willow_data_model/entry/
builder.rs1use anyhash::Hasher;
2use ufotofu::prelude::*;
3
4use crate::prelude::*;
5
6pub struct EntryBuilder<const MCL: usize, const MCC: usize, const MPL: usize, N, S, PD> {
10 namespace_id: Option<N>,
11 subspace_id: Option<S>,
12 path: Option<Path<MCL, MCC, MPL>>,
13 timestamp: Option<Timestamp>,
14 payload_length: Option<u64>,
15 payload_digest: Option<PD>,
16}
17
18impl<const MCL: usize, const MCC: usize, const MPL: usize, N, S, PD>
19 EntryBuilder<MCL, MCC, MPL, N, S, PD>
20{
21 pub(crate) fn create_empty() -> Self {
22 Self {
23 namespace_id: None,
24 subspace_id: None,
25 path: None,
26 timestamp: None,
27 payload_length: None,
28 payload_digest: None,
29 }
30 }
31
32 pub fn namespace_id(&mut self, value: N) -> &mut Self {
34 let new = self;
35 new.namespace_id = Some(value);
36 new
37 }
38
39 pub fn subspace_id(&mut self, value: S) -> &mut Self {
41 let new = self;
42 new.subspace_id = Some(value);
43 new
44 }
45
46 pub fn path(&mut self, value: Path<MCL, MCC, MPL>) -> &mut Self {
48 let new = self;
49 new.path = Some(value);
50 new
51 }
52
53 pub fn timestamp<T: Into<Timestamp>>(&mut self, value: T) -> &mut Self {
55 let new = self;
56 new.timestamp = Some(value.into());
57 new
58 }
59
60 pub fn payload_length(&mut self, value: u64) -> &mut Self {
62 let new = self;
63 new.payload_length = Some(value);
64 new
65 }
66
67 pub fn payload_digest(&mut self, value: PD) -> &mut Self {
69 let new = self;
70 new.payload_digest = Some(value);
71 new
72 }
73
74 pub fn payload<Payload: AsRef<[u8]>, H, Digest>(&mut self, payload: Payload) -> &mut Self
78 where
79 H: Default + Hasher<Digest>,
80 Digest: Into<PD>,
81 {
82 let new = self;
83
84 let mut hasher = H::default();
85 hasher.write(payload.as_ref());
86
87 new.payload_digest = Some(hasher.finish().into());
88 new.payload_length = Some(payload.as_ref().len() as u64);
89
90 new
91 }
92
93 pub async fn payload_async<P, H, Digest>(
97 &mut self,
98 payload_producer: &mut P,
99 ) -> Result<&mut Self, P::Error>
100 where
101 H: Default + Hasher<Digest>,
102 Digest: Into<PD>,
103 P: BulkProducer<Item = u8, Final = ()>,
104 {
105 let new = self;
106
107 let mut hasher = H::default();
108 let mut payload_len = 0;
109
110 loop {
111 match payload_producer
112 .expose_items_sync(|partial_payload| {
113 hasher.write(partial_payload);
114 payload_len += partial_payload.len();
115 (partial_payload.len(), ())
116 })
117 .await?
118 {
119 Either::Left(_) => {}
120 Either::Right(_) => {
121 new.payload_digest = Some(hasher.finish().into());
122 new.payload_length = Some(payload_len as u64);
123 return Ok(new);
124 }
125 }
126 }
127 }
128
129 #[cfg(feature = "std")]
131 pub fn now(&mut self) -> Result<&mut Self, HifitimeError> {
132 let new = self;
133
134 new.timestamp = Some(Timestamp::now()?);
135
136 Ok(new)
137 }
138
139 pub fn build(&mut self) -> Result<Entry<MCL, MCC, MPL, N, S, PD>, EntryBuilderError> {
143 Ok(Entry {
144 namespace_id: self
145 .namespace_id
146 .take()
147 .ok_or(EntryBuilderError::MissingNamespaceId)?,
148 subspace_id: self
149 .subspace_id
150 .take()
151 .ok_or(EntryBuilderError::MissingSubespaceId)?,
152 path: self.path.take().ok_or(EntryBuilderError::MissingPath)?,
153 timestamp: self
154 .timestamp
155 .take()
156 .ok_or(EntryBuilderError::MissingTimestamp)?,
157 payload_length: self
158 .payload_length
159 .take()
160 .ok_or(EntryBuilderError::MissingPayloadLength)?,
161 payload_digest: self
162 .payload_digest
163 .take()
164 .ok_or(EntryBuilderError::MissingPayloadDigest)?,
165 })
166 }
167}
168
169#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
171pub enum EntryBuilderError {
172 MissingNamespaceId,
174 MissingSubespaceId,
176 MissingPath,
178 MissingTimestamp,
180 MissingPayloadLength,
182 MissingPayloadDigest,
184}