Skip to main content

substrate_data/wire/
items.rs

1//! [`Items`]: the items of a [`Stream`](crate::Stream), read one at a time.
2
3use std::iter::FusedIterator;
4use std::marker::PhantomData;
5
6use super::item_error::ItemError;
7use crate::binary::Decoder;
8use crate::schema::Schema;
9
10/// The items of a [`Stream`](crate::Stream), each read when asked for
11/// ([`Stream::iter`](crate::Stream::iter)).
12///
13/// An item that cannot be read is an `Err` naming its index and byte; the
14/// iterator ends there, since the items after it cannot be told apart.
15#[derive(Debug)]
16pub struct Items<'a, T> {
17    d: Decoder<'a>,
18    index: usize,
19    len: usize,
20    done: bool,
21    item: PhantomData<fn() -> T>,
22}
23
24impl<'a, T> Items<'a, T> {
25    pub(super) fn new(items: &'a [u8], len: usize) -> Self {
26        Items {
27            d: Decoder::body(items),
28            index: 0,
29            len,
30            done: false,
31            item: PhantomData,
32        }
33    }
34
35    /// Ends the iteration on the fault at `offset`.
36    fn fault(&mut self, offset: usize) -> ItemError {
37        self.done = true;
38        ItemError {
39            index: self.index,
40            offset,
41        }
42    }
43}
44
45impl<T: Schema> Iterator for Items<'_, T> {
46    type Item = Result<T, ItemError>;
47
48    fn next(&mut self) -> Option<Self::Item> {
49        if self.done {
50            return None;
51        }
52        let offset = self.d.offset();
53        if self.index == self.len {
54            // Past the last item: bytes left over are a fault, once.
55            if self.d.at_end() {
56                self.done = true;
57                return None;
58            }
59            return Some(Err(self.fault(offset)));
60        }
61        match T::decode(&mut self.d) {
62            Some(item) => {
63                self.index += 1;
64                Some(Ok(item))
65            }
66            None => Some(Err(self.fault(offset))),
67        }
68    }
69
70    fn size_hint(&self) -> (usize, Option<usize>) {
71        if self.done {
72            return (0, Some(0));
73        }
74        // Each item may be the one that fails, and so is the leftover check.
75        (0, Some(self.len - self.index + 1))
76    }
77}
78
79impl<T: Schema> FusedIterator for Items<'_, T> {}