p2p_chat/storage/
friends.rs

1//! This module defines the storage interface and implementation for managing friends.
2use crate::crypto::StorageEncryption;
3use crate::types::Friend;
4use anyhow::Result;
5use async_trait::async_trait;
6use libp2p::PeerId;
7use sled::Db;
8
9/// A trait for managing friends.
10#[async_trait]
11pub trait FriendsStore {
12    /// Adds a new friend to the store.
13    ///
14    /// # Arguments
15    ///
16    /// * `friend` - The `Friend` to add.
17    ///
18    /// # Errors
19    ///
20    /// This function will return an error if the friend cannot be added.
21    async fn add_friend(&self, friend: Friend) -> Result<()>;
22
23    /// Retrieves a friend from the store by their `PeerId`.
24    ///
25    /// # Arguments
26    ///
27    /// * `peer_id` - The `PeerId` of the friend to retrieve.
28    ///
29    /// # Returns
30    ///
31    /// An `Option` containing the `Friend` if found, otherwise `None`.
32    ///
33    /// # Errors
34    ///
35    /// This function will return an error if the friend cannot be retrieved.
36    async fn get_friend(&self, peer_id: &PeerId) -> Result<Option<Friend>>;
37
38    /// Lists all friends in the store.
39    ///
40    /// # Returns
41    ///
42    /// A `Vec` containing all `Friend`s in the store.
43    ///
44    /// # Errors
45    ///
46    /// This function will return an error if the friends cannot be listed.
47    async fn list_friends(&self) -> Result<Vec<Friend>>;
48}
49
50/// A `FriendsStore` implementation using `sled` for storage.
51pub struct SledFriendsStore {
52    tree: sled::Tree,
53    encryption: Option<StorageEncryption>,
54}
55
56impl SledFriendsStore {
57    /// Creates a new `SledFriendsStore`.
58    ///
59    /// # Arguments
60    ///
61    /// * `db` - The `sled::Db` instance to use for storage.
62    /// * `encryption` - The optional `StorageEncryption` to use for encrypting friend data.
63    ///
64    /// # Errors
65    ///
66    /// This function will return an error if the `friends` tree cannot be opened.
67    pub fn new(db: Db, encryption: Option<StorageEncryption>) -> Result<Self> {
68        let tree = db.open_tree("friends")?;
69        Ok(Self { tree, encryption })
70    }
71
72    /// Serializes a `Friend` and encrypts it if encryption is enabled.
73    fn serialize_friend(&self, friend: &Friend) -> Result<Vec<u8>> {
74        let serialized = serde_json::to_vec(friend)?;
75
76        if let Some(ref encryption) = self.encryption {
77            encryption.encrypt_value(&serialized)
78        } else {
79            Ok(serialized)
80        }
81    }
82
83    /// Decrypts and deserializes a `Friend`.
84    fn deserialize_friend(&self, data: &[u8]) -> Result<Friend> {
85        let decrypted = if let Some(ref encryption) = self.encryption {
86            encryption.decrypt_value(data)?
87        } else {
88            data.to_vec()
89        };
90
91        Ok(serde_json::from_slice(&decrypted)?)
92    }
93}
94
95#[async_trait]
96impl FriendsStore for SledFriendsStore {
97    async fn add_friend(&self, friend: Friend) -> Result<()> {
98        let key = friend.peer_id.to_bytes();
99        let value = self.serialize_friend(&friend)?;
100        self.tree.insert(key, value)?;
101        self.tree.flush_async().await?;
102        Ok(())
103    }
104
105    async fn get_friend(&self, peer_id: &PeerId) -> Result<Option<Friend>> {
106        let key = peer_id.to_bytes();
107        match self.tree.get(key)? {
108            Some(data) => Ok(Some(self.deserialize_friend(&data)?)),
109            None => Ok(None),
110        }
111    }
112
113    async fn list_friends(&self) -> Result<Vec<Friend>> {
114        let mut friends = Vec::new();
115
116        for result in self.tree.iter() {
117            let (_key, value) = result?;
118            friends.push(self.deserialize_friend(&value)?);
119        }
120
121        Ok(friends)
122    }
123}