Skip to main content

rings_core/dht/
subring.rs

1#![warn(missing_docs)]
2
3use serde::Deserialize;
4use serde::Serialize;
5
6use super::entry::Entry;
7use super::entry::EntryCrdt;
8use super::entry::EntryKind;
9use super::FingerTable;
10use crate::dht::Did;
11use crate::error::Error;
12use crate::error::Result;
13use crate::message::Encoder;
14
15/// A lightweight ring descriptor stored as an [`Entry`].
16///
17/// The entry key of a subring is the hash of its name.
18#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
19pub struct Subring {
20    /// name of subring
21    pub name: String,
22    /// finger table
23    pub finger: FingerTable,
24    /// creator
25    pub creator: Did,
26}
27
28impl Subring {
29    /// Create a new Subring
30    pub fn new(name: &str, creator: Did) -> Result<Self> {
31        let did = Entry::gen_did(name)?;
32        Ok(Self {
33            name: name.to_string(),
34            finger: FingerTable::new(did, 1),
35            creator,
36        })
37    }
38}
39
40impl TryFrom<Subring> for Entry {
41    type Error = Error;
42    fn try_from(ring: Subring) -> Result<Self> {
43        let data = serde_json::to_string(&ring).map_err(|_| Error::SerializeToString)?;
44        Ok(Self {
45            did: Self::gen_did(&ring.name)?,
46            data: vec![data.encode()?],
47            kind: EntryKind::Subring,
48            crdt: EntryCrdt::default(),
49        })
50    }
51}
52
53impl TryFrom<Entry> for Subring {
54    type Error = Error;
55    fn try_from(entry: Entry) -> Result<Self> {
56        match &entry.kind {
57            EntryKind::Subring => {
58                let data = entry.data.first().ok_or_else(|| {
59                    Error::InvalidMessage("subring entry has no encoded payload".to_string())
60                })?;
61                let decoded: String = data.decode()?;
62                let subring: Subring =
63                    serde_json::from_str(&decoded).map_err(Error::Deserialize)?;
64                Ok(subring)
65            }
66            _ => Err(Error::InvalidEntryKind),
67        }
68    }
69}