1use crate::{
8 bytewords::{self, Style},
9 collections::Vec,
10 fountain,
11 ur::UR,
12};
13use core::{fmt, str};
14
15#[cfg(feature = "alloc")]
17pub type Decoder = BaseDecoder<Alloc>;
18
19pub type HeaplessDecoder<
23 const MAX_MESSAGE_LEN: usize,
24 const MAX_MIXED_PARTS: usize,
25 const MAX_FRAGMENT_LEN: usize,
26 const MAX_SEQUENCE_COUNT: usize,
27 const QUEUE_SIZE: usize,
28 const MAX_UR_TYPE: usize,
29> = BaseDecoder<
30 Heapless<
31 MAX_MESSAGE_LEN,
32 MAX_MIXED_PARTS,
33 MAX_FRAGMENT_LEN,
34 MAX_SEQUENCE_COUNT,
35 QUEUE_SIZE,
36 MAX_UR_TYPE,
37 >,
38>;
39
40impl<
41 const MAX_MESSAGE_LEN: usize,
42 const MAX_MIXED_PARTS: usize,
43 const MAX_FRAGMENT_LEN: usize,
44 const MAX_SEQUENCE_COUNT: usize,
45 const QUEUE_SIZE: usize,
46 const MAX_UR_TYPE: usize,
47 >
48 HeaplessDecoder<
49 MAX_MESSAGE_LEN,
50 MAX_MIXED_PARTS,
51 MAX_FRAGMENT_LEN,
52 MAX_SEQUENCE_COUNT,
53 QUEUE_SIZE,
54 MAX_UR_TYPE,
55 >
56{
57 pub const fn new() -> Self {
59 Self {
60 fountain: fountain::decoder::HeaplessDecoder::new(),
61 fragment: heapless::Vec::new(),
62 ur_type: heapless::Vec::new(),
63 }
64 }
65}
66
67#[derive(Default)]
73pub struct BaseDecoder<T: Types> {
74 fountain: fountain::decoder::BaseDecoder<T::Decoder>,
75 fragment: T::Fragment,
76 ur_type: T::URType,
77}
78
79impl<T: Types> BaseDecoder<T> {
80 pub fn receive(&mut self, ur: UR) -> Result<(), Error> {
97 if !ur.is_multi_part() {
98 return Err(Error::NotMultiPart);
99 }
100
101 if self.ur_type.is_empty() {
102 self.ur_type
103 .try_extend_from_slice(ur.as_type().as_bytes())
104 .map_err(|_| Error::URTypeTooBig {
105 size: ur.as_type().as_bytes().len(),
106 })?;
107 } else if (&self.ur_type as &[_]) != ur.as_type().as_bytes() {
108 return Err(Error::InconsistentType);
109 }
110
111 let part = if !ur.is_deserialized() {
112 let bytewords = ur
113 .as_bytewords()
114 .expect("resource shouldn't be deserialized at this point");
115
116 let size = bytewords::validate(bytewords, Style::Minimal)?;
117 self.fragment.clear();
118 self.fragment
119 .try_resize(size, 0)
120 .map_err(|_| Error::FragmentTooBig { size })?;
121
122 bytewords::decode_to_slice(bytewords, &mut self.fragment, Style::Minimal)?;
123 Some(minicbor::decode(&self.fragment[..size])?)
124 } else {
125 None
126 };
127
128 let part = part.as_ref().unwrap_or_else(|| ur.as_part().unwrap());
129 self.fountain.receive(part)?;
130 Ok(())
131 }
132
133 #[must_use]
139 #[inline]
140 pub fn is_complete(&self) -> bool {
141 self.fountain.is_complete()
142 }
143
144 pub fn ur_type(&self) -> Option<&str> {
146 if !self.ur_type.is_empty() {
147 Some(str::from_utf8(&self.ur_type).unwrap())
148 } else {
149 None
150 }
151 }
152
153 #[inline]
166 pub fn message(&self) -> Result<Option<&[u8]>, Error> {
167 self.fountain.message().map_err(Error::from)
168 }
169
170 #[inline]
172 pub fn estimated_percent_complete(&self) -> f64 {
173 self.fountain.estimated_percent_complete()
174 }
175
176 #[must_use]
189 pub fn is_empty(&self) -> bool {
190 self.fountain.is_empty()
191 }
192
193 pub fn clear(&mut self) {
195 self.fountain.clear();
196 self.fragment.clear();
197 self.ur_type.clear();
198 }
199}
200
201pub trait Types: Default {
203 type Decoder: fountain::decoder::Types;
205
206 type Fragment: Vec<u8>;
208
209 type URType: Vec<u8>;
211}
212
213#[derive(Default)]
215#[cfg(feature = "alloc")]
216pub struct Alloc;
217
218#[cfg(feature = "alloc")]
219impl Types for Alloc {
220 type Decoder = fountain::decoder::Alloc;
221
222 type Fragment = alloc::vec::Vec<u8>;
223
224 type URType = alloc::vec::Vec<u8>;
225}
226
227#[derive(Default)]
229pub struct Heapless<
230 const MAX_MESSAGE_LEN: usize,
231 const MAX_MIXED_PARTS: usize,
232 const MAX_FRAGMENT_LEN: usize,
233 const MAX_SEQUENCE_COUNT: usize,
234 const QUEUE_SIZE: usize,
235 const MAX_UR_TYPE: usize,
236>;
237
238impl<
239 const MAX_MESSAGE_LEN: usize,
240 const MAX_MIXED_PARTS: usize,
241 const MAX_FRAGMENT_LEN: usize,
242 const MAX_SEQUENCE_COUNT: usize,
243 const QUEUE_SIZE: usize,
244 const MAX_UR_TYPE: usize,
245 > Types
246 for Heapless<
247 MAX_MESSAGE_LEN,
248 MAX_MIXED_PARTS,
249 MAX_FRAGMENT_LEN,
250 MAX_SEQUENCE_COUNT,
251 QUEUE_SIZE,
252 MAX_UR_TYPE,
253 >
254{
255 type Decoder = fountain::decoder::Heapless<
256 MAX_MESSAGE_LEN,
257 MAX_MIXED_PARTS,
258 MAX_FRAGMENT_LEN,
259 MAX_SEQUENCE_COUNT,
260 QUEUE_SIZE,
261 >;
262
263 type Fragment = heapless::Vec<u8, MAX_FRAGMENT_LEN>;
264
265 type URType = heapless::Vec<u8, MAX_UR_TYPE>;
266}
267
268#[derive(Debug)]
270pub enum Error {
271 Cbor(minicbor::decode::Error),
273 Fountain(fountain::decoder::Error),
275 Bytewords(bytewords::DecodeError),
277 NotMultiPart,
279 FragmentTooBig {
281 size: usize,
283 },
284 URTypeTooBig {
286 size: usize,
288 },
289 InconsistentType,
291}
292
293#[cfg(feature = "std")]
294impl std::error::Error for Error {}
295
296impl fmt::Display for Error {
297 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
298 match self {
299 Error::Cbor(e) => write!(f, "CBOR decoding error: {e}"),
300 Error::Fountain(e) => write!(f, "Fountain decoding error: {e}"),
301 Error::Bytewords(e) => write!(f, "Bytewords decoding error: {e}"),
302 Error::NotMultiPart => write!(f, "The Uniform Resource is not multi-part"),
303 Error::FragmentTooBig { size } => write!(
304 f,
305 "The fragment size ({size} bytes) is too big for the decoder"
306 ),
307 Error::URTypeTooBig { size } => {
308 write!(f, "The UR type ({size} bytes) is too big for the decoder")
309 }
310 Error::InconsistentType => write!(
311 f,
312 "The received fragment is not consistent with the type of the previous fragments"
313 ),
314 }
315 }
316}
317
318impl From<minicbor::decode::Error> for Error {
319 fn from(e: minicbor::decode::Error) -> Self {
320 Self::Cbor(e)
321 }
322}
323
324impl From<bytewords::DecodeError> for Error {
325 fn from(e: bytewords::DecodeError) -> Self {
326 Self::Bytewords(e)
327 }
328}
329
330impl From<fountain::decoder::Error> for Error {
331 fn from(e: fountain::decoder::Error) -> Self {
332 Self::Fountain(e)
333 }
334}