1use iroh_db_core::{BlobHash, DomainId, FieldState, RecordError};
2
3#[derive(
5 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, minicbor::Encode, minicbor::Decode,
6)]
7#[cbor(array)]
8pub struct BlobRef {
9 #[n(0)]
10 domain_id: DomainId,
11 #[n(1)]
12 epoch: u64,
13 #[n(2)]
14 manifest_hash: BlobHash,
15}
16
17impl BlobRef {
18 pub const fn new(domain_id: DomainId, epoch: u64, manifest_hash: BlobHash) -> Self {
20 Self {
21 domain_id,
22 epoch,
23 manifest_hash,
24 }
25 }
26
27 pub const fn domain_id(self) -> DomainId {
29 self.domain_id
30 }
31
32 pub const fn epoch(self) -> u64 {
34 self.epoch
35 }
36
37 pub const fn manifest_hash(self) -> BlobHash {
39 self.manifest_hash
40 }
41}
42
43impl FieldState for BlobRef {
44 type Value = Self;
45
46 const CRDT_KIND: iroh_db_core::CrdtKind = iroh_db_core::CrdtKind::Immutable;
47
48 fn encode_state(&self) -> Result<Vec<u8>, RecordError> {
49 minicbor::to_vec(self).map_err(|error| RecordError::Encode(error.to_string()))
50 }
51
52 fn decode_state(bytes: &[u8]) -> Result<Self, RecordError> {
53 let mut decoder = minicbor::Decoder::new(bytes);
54 let value = decoder
55 .decode::<Self>()
56 .map_err(|error| RecordError::Decode(error.to_string()))?;
57 if decoder.position() != bytes.len() {
58 return Err(RecordError::TrailingData);
59 }
60 if value.encode_state()? != bytes {
61 return Err(RecordError::NonCanonicalEncoding);
62 }
63 Ok(value)
64 }
65
66 fn visible_values(&self) -> Result<Vec<Vec<u8>>, RecordError> {
67 Ok(vec![self.encode_state()?])
68 }
69
70 fn merge_state(&mut self, other: &Self) -> Result<(), RecordError> {
71 if self == other {
72 Ok(())
73 } else {
74 Err(iroh_db_core::CrdtError::ImmutableAlreadySet.into())
75 }
76 }
77
78 fn canonicalize_for_commit(
79 &self,
80 _author: iroh_db_core::AuthorId,
81 _sequence: u64,
82 _context: &iroh_db_core::VersionVector,
83 _next_operation: &mut u32,
84 ) -> Result<Self, RecordError> {
85 Ok(*self)
86 }
87}
88
89#[derive(Debug, Clone, PartialEq, Eq, minicbor::Encode, minicbor::Decode)]
90#[cbor(array)]
91pub(crate) struct ManifestEnvelope {
92 #[n(0)]
93 pub(crate) version: u16,
94 #[n(1)]
95 pub(crate) domain_id: DomainId,
96 #[n(2)]
97 pub(crate) epoch: u64,
98 #[n(3)]
99 pub(crate) salt: [u8; 32],
100 #[n(4)]
101 pub(crate) nonce: [u8; 24],
102 #[n(5)]
103 pub(crate) ciphertext: Vec<u8>,
104}
105
106#[derive(Debug, Clone, PartialEq, Eq, minicbor::Encode, minicbor::Decode)]
107#[cbor(array)]
108pub(crate) struct ManifestBody {
109 #[n(0)]
110 pub(crate) plaintext_len: u64,
111 #[n(1)]
112 pub(crate) plaintext_hash: [u8; 32],
113 #[n(2)]
114 pub(crate) chunk_size: u32,
115 #[n(3)]
116 pub(crate) chunks: Vec<ChunkDescriptor>,
117 #[n(4)]
118 pub(crate) media_type: Option<String>,
119}
120
121#[derive(Debug, Clone, PartialEq, Eq, minicbor::Encode, minicbor::Decode)]
122#[cbor(array)]
123pub(crate) struct ChunkDescriptor {
124 #[n(0)]
125 pub(crate) index: u32,
126 #[n(1)]
127 pub(crate) plaintext_len: u32,
128 #[n(2)]
129 pub(crate) ciphertext_hash: BlobHash,
130 #[n(3)]
131 pub(crate) nonce: [u8; 24],
132}