femtopb/
repeated.rs

1//! `Repeated` scalar or composite values.
2use crate::{encoding, error, item_encoding, list};
3use core::marker;
4use core::{fmt, slice};
5
6/// A sparse encoding of a sequence of scalar values.
7///
8/// Use `.iter()` to iterate through the elements of this `Repeated`.
9#[repr(transparent)]
10pub struct Repeated<'a, A, E>(list::List<'a, A>, marker::PhantomData<E>)
11where
12    E: item_encoding::ItemEncoding<'a, A>;
13
14/// An iterator for a `Repeated`.
15#[derive(Clone, Debug, Default)]
16pub struct Iter<'a, A, E>(IterRepr<'a, A, E>)
17where
18    E: item_encoding::ItemEncoding<'a, A>;
19
20#[derive(Clone, Debug, Default)]
21enum IterRepr<'a, A, E>
22where
23    E: item_encoding::ItemEncoding<'a, A>,
24{
25    #[default]
26    Empty,
27    MessageBuffer {
28        msg_buf: list::MessageBuffer<'a>,
29        phantom: marker::PhantomData<E>,
30    },
31    Slice(slice::Iter<'a, A>),
32}
33
34impl<'a, A, E> Repeated<'a, A, E>
35where
36    E: item_encoding::ItemEncoding<'a, A>,
37{
38    /// Creates a new, empty `Repeated` with minimal memory footprint.
39    pub const fn empty() -> Self {
40        Self(list::List::empty(), marker::PhantomData)
41    }
42
43    /// Creates a `Repeated` that uses the specified slice as its storage.
44    ///
45    /// The slice must live as long as this `Repeated` does.
46    pub const fn from_slice(slice: &'a [A]) -> Self {
47        Self(list::List::from_slice(slice), marker::PhantomData)
48    }
49
50    // Used internally by the runtime during decoding
51    pub const fn from_msg_buf(tag: u32, data: &'a [u8]) -> Self {
52        Self(list::List::from_msg_buf(tag, data), marker::PhantomData)
53    }
54
55    /// Whether the field has been populated from either deserialization or by the user.
56    ///
57    /// Used by the decoding runtime logic for avoiding populating the same field twice for multiple
58    /// occurrences of the same field; since `from_msg_buf` takes the entire message buffer as an
59    /// argument anyway, there's no sense in populating the field multiple times.
60    pub(crate) fn is_unpopulated(&self) -> bool {
61        matches!(self.0, list::List::Empty)
62    }
63}
64
65impl<'a, A, E> Repeated<'a, A, E>
66where
67    A: Clone,
68    E: item_encoding::ItemEncoding<'a, A>,
69{
70    pub fn iter(&self) -> Iter<'a, A, E> {
71        self.into_iter()
72    }
73
74    pub fn is_empty(&self) -> bool {
75        // This is different from `self.is_unpopulated()`, because the other reprs
76        // (e.g. empty slice, or message buffer without an occurrence of the right tag) might also
77        // be empty.
78        self.iter().next().is_none() // TODO: optimization potential?
79    }
80
81    pub fn len(&self) -> usize {
82        self.iter().count() // TODO: optimization potential?
83    }
84}
85
86impl<'a, A, E> Iter<'a, A, E>
87where
88    E: item_encoding::ItemEncoding<'a, A>,
89{
90    fn from_list(lst: list::List<'a, A>) -> Self {
91        let repr = match lst {
92            list::List::Empty => IterRepr::Empty,
93            list::List::MessageBuffer(msg_buf) => IterRepr::MessageBuffer {
94                msg_buf,
95                phantom: marker::PhantomData,
96            },
97            list::List::Slice(slice) => IterRepr::Slice(slice.into_iter()),
98        };
99        Self(repr)
100    }
101}
102
103impl<'a, A, E> PartialEq for Repeated<'a, A, E>
104where
105    A: Clone + PartialEq,
106    E: item_encoding::ItemEncoding<'a, A>,
107{
108    fn eq(&self, other: &Self) -> bool {
109        self.iter().eq(other.iter())
110    }
111}
112
113impl<'a, A, E> Clone for Repeated<'a, A, E>
114where
115    E: item_encoding::ItemEncoding<'a, A>,
116{
117    fn clone(&self) -> Self {
118        Repeated(self.0, self.1)
119    }
120}
121
122impl<'a, A, E> Copy for Repeated<'a, A, E> where E: item_encoding::ItemEncoding<'a, A> {}
123
124impl<'a, A, E> Default for Repeated<'a, A, E>
125where
126    E: item_encoding::ItemEncoding<'a, A>,
127{
128    fn default() -> Self {
129        Self::empty()
130    }
131}
132
133impl<'a, A, E> fmt::Debug for Repeated<'a, A, E>
134where
135    A: Clone + fmt::Debug,
136    E: item_encoding::ItemEncoding<'a, A>,
137{
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        let mut list_fmt = f.debug_list();
140        for ref item in self.iter() {
141            list_fmt.entry(item);
142        }
143        list_fmt.finish()
144    }
145}
146
147#[cfg(feature = "defmt")]
148impl<'a, A, E> defmt::Format for Repeated<'a, A, E>
149where
150    A: Clone + defmt::Format,
151    E: item_encoding::ItemEncoding<'a, A>,
152{
153    fn format(&self, fmt: defmt::Formatter) {
154        defmt::write!(fmt, "[");
155        for ref item in self.iter() {
156            match item {
157                Ok(item) => {
158                    defmt::write!(fmt, "{:?}", item);
159                }
160                Err(e) => {
161                    defmt::write!(fmt, "...error: {:?}", e);
162                    break;
163                }
164            }
165        }
166        defmt::write!(fmt, "]");
167    }
168}
169
170impl<'a, A, E> IntoIterator for Repeated<'a, A, E>
171where
172    A: Clone,
173    E: item_encoding::ItemEncoding<'a, A>,
174{
175    type Item = Result<A, error::DecodeError>;
176    type IntoIter = Iter<'a, A, E>;
177
178    fn into_iter(self) -> Self::IntoIter {
179        Iter::from_list(self.0)
180    }
181}
182
183impl<'a, 'b, A, E> IntoIterator for &'b Repeated<'a, A, E>
184where
185    A: Clone,
186    E: item_encoding::ItemEncoding<'a, A>,
187{
188    type Item = Result<A, error::DecodeError>;
189    type IntoIter = Iter<'a, A, E>;
190
191    fn into_iter(self) -> Self::IntoIter {
192        Iter::from_list(self.0)
193    }
194}
195
196impl<'a, A, E> Iterator for Iter<'a, A, E>
197where
198    A: Clone,
199    E: item_encoding::ItemEncoding<'a, A>,
200{
201    type Item = Result<A, error::DecodeError>;
202
203    #[cfg_attr(feature = "assert-no-panic", no_panic::no_panic)]
204    fn next(&mut self) -> Option<Self::Item> {
205        match self.0 {
206            IterRepr::Empty => None,
207            IterRepr::MessageBuffer {
208                ref mut msg_buf,
209                phantom: _,
210            } => {
211                let result = next_item::<A, E>(msg_buf);
212                if result.is_err() {
213                    // If an error has occurred, we are in a bad state, so prevent further iteration
214                    self.0 = IterRepr::Empty;
215                }
216                result.transpose()
217            }
218            IterRepr::Slice(ref mut iter) => iter.next().cloned().map(|v| Ok(v)),
219        }
220    }
221}
222
223impl<'a, A, E> From<&'a [A]> for Repeated<'a, A, E>
224where
225    E: item_encoding::ItemEncoding<'a, A>,
226{
227    fn from(value: &'a [A]) -> Self {
228        Self::from_slice(value)
229    }
230}
231
232#[cfg_attr(feature = "assert-no-panic", no_panic::no_panic)]
233fn next_item<'a, A, E>(
234    msg_buf: &mut list::MessageBuffer<'a>,
235) -> Result<Option<A>, error::DecodeError>
236where
237    A: 'a,
238    E: item_encoding::ItemEncoding<'a, A>,
239{
240    let cursor = &mut msg_buf.data;
241    while !cursor.is_empty() {
242        let (tag, wire_type) = encoding::decode_key(cursor)?;
243        if tag == msg_buf.tag {
244            // At this point, we know for sure that this is a field tag occurrence that concerns
245            // us, but which encoding/wire type was used?
246            if wire_type == E::WIRE_TYPE {
247                // Decode this single value
248                return Ok(Some(E::decode_single_value(cursor)?));
249            } else {
250                return Err(error::DecodeError::UnexpectedWireTypeValue {
251                    actual: wire_type,
252                    expected: E::WIRE_TYPE,
253                });
254            }
255        } else {
256            encoding::skip_field(wire_type, tag, cursor)?;
257        }
258    }
259    // We consumed the entire message buffer; there can't be any further occurrences
260    Ok(None)
261}