leaf_protocol_types/
lib.rs

1//! Core types in the Leaf specification
2
3use borsh::{BorshDeserialize, BorshSerialize};
4
5mod borsh_schema;
6mod digest;
7
8pub use borsh_schema::*;
9pub use digest::*;
10
11pub type NamespaceId = [u8; 32];
12pub type SubspaceId = [u8; 32];
13pub type SubspaceSecretKey = [u8; 32];
14pub type NamespaceSecretKey = [u8; 32];
15
16/// An entity path.
17#[derive(
18    borsh::BorshDeserialize,
19    borsh::BorshSerialize,
20    Debug,
21    Clone,
22    PartialEq,
23    Eq,
24    PartialOrd,
25    Ord,
26    Hash,
27    Default,
28)]
29pub struct EntityPath(pub Vec<PathSegment>);
30impl AsRef<[PathSegment]> for EntityPath {
31    fn as_ref(&self) -> &[PathSegment] {
32        &self.0
33    }
34}
35impl From<()> for EntityPath {
36    fn from(_: ()) -> Self {
37        EntityPath(Vec::default())
38    }
39}
40impl<T: Into<PathSegment>, const N: usize> From<[T; N]> for EntityPath {
41    fn from(value: [T; N]) -> Self {
42        EntityPath(value.into_iter().map(|x| x.into()).collect())
43    }
44}
45
46#[derive(borsh::BorshDeserialize, borsh::BorshSerialize, Debug, Clone, Default)]
47pub struct Entity {
48    pub components: Vec<ComponentEntry>,
49}
50
51impl Entity {
52    pub fn sort_components(&mut self) {
53        self.components.sort();
54    }
55
56    pub fn compute_digest(&self) -> Digest {
57        let is_sorted = self.components.windows(2).all(|w| w[0] <= w[1]);
58        assert!(is_sorted, "Components must be sorted to compute digest");
59        let mut buf = Vec::new();
60        self.serialize(&mut buf).unwrap();
61        Digest::new(&buf)
62    }
63}
64
65#[derive(
66    borsh::BorshDeserialize,
67    borsh::BorshSerialize,
68    Debug,
69    Clone,
70    Copy,
71    PartialEq,
72    PartialOrd,
73    Ord,
74    Eq,
75)]
76pub struct ComponentEntry {
77    // The schema ID may not be set if the component is encrypted.
78    pub schema_id: Option<Digest>,
79    pub component_id: Digest,
80}
81
82/// A segment in an entity Path.
83#[derive(
84    borsh::BorshDeserialize, borsh::BorshSerialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
85)]
86pub enum PathSegment {
87    Null,
88    Bool(bool),
89    Uint(u64),
90    Int(i64),
91    String(String),
92    Bytes(Vec<u8>),
93}
94impl std::fmt::Debug for PathSegment {
95    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96        match self {
97            Self::Null => write!(f, "Null"),
98            Self::Bool(arg0) => write!(f, "{arg0}"),
99            Self::Uint(arg0) => write!(f, "{arg0}_u64"),
100            Self::Int(arg0) => write!(f, "{arg0}_i64"),
101            Self::String(arg0) => write!(f, "\"{arg0}\""),
102            Self::Bytes(arg0) => write!(f, "base32:{}", &iroh_base::base32::fmt(arg0)),
103        }
104    }
105}
106impl From<()> for PathSegment {
107    fn from(_: ()) -> Self {
108        Self::Null
109    }
110}
111impl From<bool> for PathSegment {
112    fn from(value: bool) -> Self {
113        Self::Bool(value)
114    }
115}
116impl From<u64> for PathSegment {
117    fn from(value: u64) -> Self {
118        Self::Uint(value)
119    }
120}
121impl From<i64> for PathSegment {
122    fn from(value: i64) -> Self {
123        Self::Int(value)
124    }
125}
126impl<'a> From<&'a str> for PathSegment {
127    fn from(value: &'a str) -> Self {
128        Self::String(value.into())
129    }
130}
131impl From<String> for PathSegment {
132    fn from(value: String) -> Self {
133        Self::String(value)
134    }
135}
136impl From<Vec<u8>> for PathSegment {
137    fn from(value: Vec<u8>) -> Self {
138        Self::Bytes(value)
139    }
140}
141
142/// The kind of component data.
143#[derive(borsh::BorshDeserialize, borsh::BorshSerialize, Debug, Clone)]
144pub enum ComponentKind {
145    /// Unencrypted data
146    Unencrypted(ComponentData),
147    /// Encrypted data with an associated key ID and encryption algorithm.
148    Encrypted {
149        algorithm: EncryptionAlgorithm,
150        key_id: [u8; 32],
151        encrypted_data: Vec<u8>,
152    },
153}
154
155impl ComponentKind {
156    pub fn unencrypted(&self) -> Option<&ComponentData> {
157        match self {
158            ComponentKind::Unencrypted(u) => Some(u),
159            _ => None,
160        }
161    }
162}
163
164/// The data that makes up a component.
165#[derive(borsh::BorshDeserialize, borsh::BorshSerialize, Debug, Clone)]
166pub struct ComponentData {
167    /// The Schema ID of the component data.
168    pub schema: Digest,
169    /// The data of the component, to be parsed according to it's [`Schema`]'s [`BorshSchema`].
170    pub data: Vec<u8>,
171}
172
173/// A [`Component`][crate::Component] schema.
174#[derive(borsh::BorshDeserialize, borsh::BorshSerialize, Debug, Clone)]
175pub struct Schema {
176    /// The name of the schema.
177    pub name: String,
178    /// The [`BorshSchema`] describing the component's data.
179    pub format: BorshSchema,
180    /// The collection ID containing the components that document this schema.
181    pub specification: Digest,
182}
183
184/// A [`borsh`] schema describing the data format of a [`Component`][crate::Component].
185#[derive(borsh::BorshDeserialize, borsh::BorshSerialize, Debug, Clone)]
186pub enum BorshSchema {
187    Null,
188    Bool,
189    U8,
190    U16,
191    U32,
192    U64,
193    U128,
194    I8,
195    I16,
196    I32,
197    I64,
198    I128,
199    F32,
200    F64,
201    String,
202    Option {
203        schema: Box<BorshSchema>,
204    },
205    Array {
206        schema: Box<BorshSchema>,
207        len: u32,
208    },
209    Struct {
210        fields: Vec<(String, BorshSchema)>,
211    },
212    Enum {
213        variants: Vec<(String, BorshSchema)>,
214    },
215    Vector {
216        schema: Box<BorshSchema>,
217    },
218    Map {
219        key: Box<BorshSchema>,
220        value: Box<BorshSchema>,
221    },
222    Set {
223        schema: Box<BorshSchema>,
224    },
225    Blob,
226    Snapshot,
227    Link,
228}
229
230#[derive(borsh::BorshDeserialize, borsh::BorshSerialize, Debug, Clone)]
231pub struct Link {
232    namespace: KeyResolverKind,
233    subspace: KeyResolverKind,
234    path: Vec<PathSegment>,
235    snapshot: Option<Digest>,
236}
237impl HasBorshSchema for Link {
238    fn borsh_schema() -> BorshSchema {
239        BorshSchema::Link
240    }
241}
242
243/// Similar to a [`types::Link`], but with a resolved namespace and subspace.
244#[derive(
245    Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, BorshDeserialize, BorshSerialize, Default,
246)]
247pub struct ExactLink {
248    pub namespace: NamespaceId,
249    pub subspace: SubspaceId,
250    pub path: EntityPath,
251}
252
253impl<P: Into<EntityPath>> From<(NamespaceId, SubspaceId, P)> for ExactLink {
254    fn from((n, s, p): (NamespaceId, SubspaceId, P)) -> Self {
255        Self {
256            namespace: n,
257            subspace: s,
258            path: p.into(),
259        }
260    }
261}
262
263#[derive(
264    borsh::BorshDeserialize,
265    borsh::BorshSerialize,
266    Debug,
267    Clone,
268    Hash,
269    Eq,
270    PartialEq,
271    Ord,
272    PartialOrd,
273)]
274pub struct Blob(pub Digest);
275impl HasBorshSchema for Blob {
276    fn borsh_schema() -> BorshSchema {
277        BorshSchema::Blob
278    }
279}
280
281#[derive(
282    borsh::BorshDeserialize,
283    borsh::BorshSerialize,
284    Debug,
285    Clone,
286    Hash,
287    Eq,
288    PartialEq,
289    Ord,
290    PartialOrd,
291)]
292pub struct Snapshot(pub Digest);
293impl HasBorshSchema for Snapshot {
294    fn borsh_schema() -> BorshSchema {
295        BorshSchema::Snapshot
296    }
297}
298
299/// A key-resolver algorithm.
300#[derive(borsh::BorshDeserialize, borsh::BorshSerialize, Debug, Clone)]
301pub enum KeyResolverKind {
302    /// The key is stored inline and may be used directly.
303    Inline([u8; 32]),
304    /// The key must be resolved using the key resolver with the given digest. The `data` is passed
305    /// to the key resolver algorithm.
306    Custom { id: Digest, data: Vec<u8> },
307}
308
309/// A key-resolver algorithm.
310#[derive(borsh::BorshDeserialize, borsh::BorshSerialize, Debug, Clone)]
311pub struct KeyResolver {
312    pub name: String,
313    pub specification: Digest,
314}
315
316/// An encryption algorithm.
317#[derive(borsh::BorshDeserialize, borsh::BorshSerialize, Debug, Clone)]
318pub struct EncryptionAlgorithm {
319    pub name: String,
320    pub specification: Digest,
321}