Skip to main content

substrate_data/wire/
stream.rs

1//! [`Stream`]: a list kept in the binary form: its items written as they
2//! come (no `Vec` of them on the way), cut out whole when the stream is
3//! decoded and read back one at a time, when asked. For the big ones: a
4//! table's rows, a picture's pixels, a log.
5//!
6//! Decoding a stream checks its framing only (its byte length and its item
7//! count against the bytes there are), so it costs a copy, not a pass over
8//! the items. An item is read when it is asked for, and
9//! [`Stream::iter`] yields a `Result` for each: a bad item is an
10//! [`ItemError`](crate::ItemError) naming its index and byte.
11//!
12//! ```
13//! use substrate_data::{Schema, Stream};
14//!
15//! #[derive(Schema)]
16//! struct Sheet {
17//!     name: String,
18//!     cells: Stream<u16>,
19//! }
20//!
21//! let sheet = Sheet { name: "q3".into(), cells: (0..1000u16).map(|i| i % 3).collect() };
22//! let back: Sheet = substrate_data::read_bytes(&substrate_data::to_bytes(&sheet)).unwrap();
23//! assert_eq!(back.cells.len(), 1000);
24//! let twos = back.cells.iter().filter(|c| matches!(c, Ok(2))).count();
25//! assert_eq!(twos, 333);
26//! // All of them, or the first that cannot be read:
27//! let cells: Vec<u16> = back.cells.iter().collect::<Result<_, _>>().unwrap();
28//! assert_eq!(cells.len(), 1000);
29//! ```
30
31use std::fmt;
32use std::marker::PhantomData;
33
34use super::item_error::ItemError;
35use super::items::Items;
36use super::stream_writer::StreamWriter;
37use crate::binary::{Decoder, Writer};
38use crate::frame::{Packer, Unpacker};
39use crate::model::borrowed::ValueRef;
40use crate::model::value::{Seg, Value};
41use crate::schema::{Reader, Schema, Shape};
42
43/// A list of `T` kept written: its body in the binary form, its strings its own.
44///
45/// A stream that was built here (`collect`, `From<Vec<T>>`, a
46/// [`StreamWriter`]) always reads. A decoded one has had its framing checked
47/// and nothing more, so an item can fail when it is read: see [`Stream::iter`].
48///
49/// Two streams are equal when they have the same count and the same bytes,
50/// not when their items are equal: the same items written by another encoder
51/// (a different but valid spelling of an int, say) are not equal, and a
52/// stream with an unreadable item equals only a copy of itself. Compare
53/// [`Stream::to_vec`] to compare items.
54pub struct Stream<T> {
55    /// The items, written one after another.
56    items: Vec<u8>,
57    len: usize,
58    item: PhantomData<fn() -> T>,
59}
60
61impl<T> Stream<T> {
62    pub(super) fn from_written(items: Vec<u8>, len: usize) -> Self {
63        Stream {
64            items,
65            len,
66            item: PhantomData,
67        }
68    }
69
70    /// How many items it says it has (a decoded stream's are not read yet).
71    #[must_use]
72    pub fn len(&self) -> usize {
73        self.len
74    }
75
76    /// Whether it says it has none.
77    #[must_use]
78    pub fn is_empty(&self) -> bool {
79        self.len == 0
80    }
81
82    /// How many bytes it takes.
83    #[must_use]
84    pub fn bytes_len(&self) -> usize {
85        self.items.len()
86    }
87}
88
89impl<T: Schema> Stream<T> {
90    /// Writes items one by one ([`StreamWriter::push`]).
91    #[must_use]
92    pub fn writer() -> StreamWriter<T> {
93        StreamWriter {
94            w: Writer::body(),
95            len: 0,
96            item: PhantomData,
97        }
98    }
99
100    /// The items, each read as it's asked for.
101    ///
102    /// An item that cannot be read (a newer item type, a corrupt byte) is an
103    /// `Err` naming its index and byte, and the iterator ends there; so does
104    /// a stream with bytes left after its counted items, with an `Err` at
105    /// index [`len`](Stream::len). `iter().collect::<Result<Vec<_>, _>>()`
106    /// reads them all or stops at the first bad one.
107    #[must_use]
108    pub fn iter(&self) -> Items<'_, T> {
109        Items::new(&self.items, self.len)
110    }
111
112    /// Every item, read now: the first that cannot be read is the error.
113    ///
114    /// # Errors
115    ///
116    /// An [`ItemError`] for the first unreadable item.
117    pub fn to_vec(&self) -> Result<Vec<T>, ItemError> {
118        self.iter().collect()
119    }
120
121    /// Reads every item and drops it: whether the whole stream reads.
122    ///
123    /// # Errors
124    ///
125    /// An [`ItemError`] for the first unreadable item.
126    pub fn validate(&self) -> Result<(), ItemError> {
127        self.iter().try_for_each(|item| item.map(drop))
128    }
129}
130
131impl<'a, T: Schema> IntoIterator for &'a Stream<T> {
132    type Item = Result<T, ItemError>;
133    type IntoIter = Items<'a, T>;
134
135    fn into_iter(self) -> Items<'a, T> {
136        self.iter()
137    }
138}
139
140impl<T: Schema> FromIterator<T> for Stream<T> {
141    fn from_iter<I: IntoIterator<Item = T>>(items: I) -> Self {
142        let mut w = Stream::writer();
143        for item in items {
144            w.push(&item);
145        }
146        w.finish()
147    }
148}
149
150impl<T: Schema> From<Vec<T>> for Stream<T> {
151    fn from(items: Vec<T>) -> Self {
152        items.into_iter().collect()
153    }
154}
155
156impl<T> Clone for Stream<T> {
157    fn clone(&self) -> Self {
158        Stream::from_written(self.items.clone(), self.len)
159    }
160}
161
162impl<T> PartialEq for Stream<T> {
163    fn eq(&self, other: &Self) -> bool {
164        self.len == other.len && self.items == other.items
165    }
166}
167
168impl<T> Default for Stream<T> {
169    fn default() -> Self {
170        Stream::from_written(Vec::new(), 0)
171    }
172}
173
174impl<T> fmt::Debug for Stream<T> {
175    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176        write!(f, "Stream({} items, {} bytes)", self.len, self.items.len())
177    }
178}
179
180impl<T: Schema> Schema for Stream<T> {
181    fn shape() -> Shape {
182        Shape::List(T::shape)
183    }
184    /// The slow way (a text file, a value): read whole, then written.
185    fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<Self> {
186        let ValueRef::List(items) = v else {
187            cx.expected(crate::schema::Expected::List, v);
188            return None;
189        };
190        let mut w = Stream::writer();
191        let mut ok = true;
192        for (i, item) in items.iter().enumerate() {
193            match cx.at(Seg::Index(i), |cx| T::read(item, cx)) {
194                Some(x) => w.push(&x),
195                None => ok = false,
196            }
197        }
198        ok.then(|| w.finish())
199    }
200    /// The items that read, up to the first that does not: a `Value` has no
201    /// place for an error, so check a decoded stream with [`Stream::validate`].
202    fn write(&self) -> Value {
203        Value::List(
204            self.iter()
205                .map_while(Result::ok)
206                .map(|item| item.write())
207                .collect(),
208        )
209    }
210    fn encode(&self, w: &mut Writer) {
211        w.stream_body(self.len, &self.items);
212    }
213    /// Checks the framing only: the byte length, and that the count fits the
214    /// bytes (each item takes one at least, so a hostile count allocates
215    /// nothing). The items are read by [`Stream::iter`].
216    fn decode(d: &mut Decoder<'_>) -> Option<Self> {
217        let mut body = Decoder::body(d.stream()?);
218        let len = body.stream_count()?;
219        Some(Stream::from_written(body.rest().to_vec(), len))
220    }
221    /// In a frame it's a list, as its shape says (the items that read, as
222    /// in [`Stream::write`]).
223    fn pack(&self, p: &mut Packer) {
224        let items: Vec<T> = self.iter().map_while(Result::ok).collect();
225        T::pack_list(&items, p);
226    }
227    fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
228        T::unpack_list(u).map(Stream::from)
229    }
230}