wire_rs/
reader.rs

1// Copyright (c) 2022 Nathaniel Bennett
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use crate::WireError;
10use core::{mem, str};
11
12#[cfg(feature = "ioslice")]
13use std::io;
14
15const UTF8_DECODE_ERROR: &str = "failed to decode UTF8--invalid character sequence";
16const NONCONTIGUOUS_SEGMENT: &str =
17    "could not get contiguous slice--data split in 2 or more segments";
18
19#[cfg(feature = "ioslice")]
20pub type VectoredBuf<'a> = &'a [io::IoSlice<'a>];
21#[cfg(not(feature = "ioslice"))]
22pub type VectoredBuf<'a> = &'a [&'a [u8]];
23
24/// Deserialization to an owned data type from the wire.
25///
26/// A type that implements this trait guarantees that it can be constructed using a
27/// number of bytes from the provided [`WireCursor`]. If the bytes contained on the wire
28/// would lead to the construction of an invalid instance of the object, an error will
29/// be returned instead of the object.
30pub trait WireRead: Sized {
31    /// Consumes a number of bytes from `curs` and returns an owned instance of the specified type,
32    /// or returns a [`WireError`] on failure.
33    ///
34    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
35    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
36    /// in little endian.
37    ///
38    /// ## Errors
39    ///
40    /// [`WireError::InsufficientBytes`] - not enough bytes remained on the cursor to construct the type.
41    ///
42    /// [`WireError::InvalidData`] - the bytes retrieved from `curs` could not be used to construct a valid instance
43    /// of the type.
44    ///
45    /// [`WireError::Internal`] - an internal error occurred in the `wire-rs` library
46    fn read_wire<const E: bool>(curs: &mut WireCursor<'_>) -> Result<Self, WireError>;
47
48    // Add once try_from_fn is stabilized
49    /*
50    fn array_from_wire<const L: usize, const E: bool>(curs: &mut WireCursor<'_>) -> Result<[Self; L], WireError> {
51        std::array::try_from_fn(|_| { Self::from_wire::<E>(curs) })
52    }
53    */
54}
55
56/// Deserialization to a composite data type (i.e. containing both owned structures and
57/// references) from the wire.
58///
59/// A type that implements this trait guarantees that it can be constructed using a
60/// number of bytes from the provided [`WireCursor`]. If the bytes contained on the wire
61/// would lead to the construction of an invalid instance of the object, an error will
62/// be returned instead of the object.
63pub trait WireReadComp<'a>: Sized {
64    /// Consumes a number of bytes from `curs` and returns an instance of the specified type,
65    /// or returns a [`WireError`] on failure.
66    ///
67    /// The returned instance must not outlive the lifetime of the buffer that it was constructed from,
68    /// though it may outlive the `WireReader` used to construct it.
69    ///
70    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
71    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
72    /// in little endian.
73    ///
74    /// ## Errors
75    ///
76    /// [`WireError::InsufficientBytes`] - not enough bytes remained on the cursor to construct the type.
77    ///
78    /// [`WireError::InvalidData`] - the bytes retrieved from `curs` could not be used to construct a valid instance
79    /// of the type.
80    ///
81    /// [`WireError::Internal`] - an internal error occurred in the `wire-rs` library
82    fn read_wire_comp<const E: bool>(curs: &mut WireCursor<'a>) -> Result<Self, WireError>;
83
84    // Add once try_from_fn is stabilized
85    /*
86    fn array_from_wire<const L: usize, const E: bool>(curs: &mut WireCursor<'_>) -> Result<[Self; L], WireError> {
87        std::array::try_from_fn(|_| { Self::from_wire::<E>(curs) })
88    }
89    */
90}
91
92/// Deserialization to an owned data type from a portion of the wire smaller than what the data type would normally consume.
93///
94/// A type that implements this trait guarantees that it can be constructed using a specified
95/// number of bytes (greater than zero but less than the size of the type) from the provided
96/// [`WireCursor`]. If the bytes contained on the wire would lead to the construction of an
97/// invalid instance of the object, an error will be returned instead of the object.
98///
99/// This trait is most useful for reading integer values from the wire that are represented in fewer bytes than the data type,
100/// such as reading in 3 bytes to form a u32 or 5 bytes to form a u64.
101///
102/// Types implementing this trait should additionally implement [`WireRead`] for
103/// the case where `L` is equal to the size of the type.
104pub trait WireReadPart: Sized {
105    /// Consumes exactly `L` bytes (where 0 < `L` < size_of(type)) from `curs` and returns an owned
106    /// instance of the specified type, or returns a [`WireError`] on failure.
107    ///
108    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
109    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
110    /// in little endian.
111    ///
112    /// ## Errors
113    ///
114    /// [`WireError::InsufficientBytes`] - not enough bytes remained on the cursor to construct the type.
115    ///
116    /// [`WireError::InvalidData`] - the bytes retrieved from `curs` could not be used to construct a
117    /// valid instance of the type.
118    ///
119    /// [`WireError::Internal`] - an internal error occurred in the `wire-rs` library
120    fn read_wire_part<const L: usize, const E: bool>(
121        curs: &mut WireCursor<'_>,
122    ) -> Result<Self, WireError>;
123}
124
125/// Deserialization to an immutable reference of a data type from the wire.
126///
127/// A type that implements this trait guarantees that it can be constructed using a given
128/// number of bytes from the provided [`WireCursor`]. If the bytes contained on the wire
129/// cannot be converted into a reference of a valid instance of the object, an error will
130/// be returned instead of the reference.
131pub trait WireReadRef {
132    /// Consumes exactly `size` bytes from `curs` and returns an immutable reference of the specified type,
133    /// or returns a [`WireError`] on failure.
134    ///
135    /// The returned reference must not outlive the lifetime of the buffer that it references,
136    /// though it may outlive the [`WireReader`] used to construct it.
137    ///
138    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
139    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
140    /// in little endian.
141    ///
142    /// ## Errors
143    ///
144    /// [`WireError::InsufficientBytes`] - less than `size` bytes remained on the cursor.
145    ///
146    /// [`WireError::InvalidData`] - the bytes retrieved from `curs` could not be used to construct a valid
147    /// reference of the type.
148    ///
149    /// [`WireError::Internal`] - an internal error occurred in the `wire-rs` library
150    fn read_wire_ref<'a>(curs: &mut WireCursor<'a>, size: usize) -> Result<&'a Self, WireError>;
151}
152
153/// Deserialization to an owned data type from the vectored wire.
154///
155/// A type that implements this trait guarantees that it can be constructed using a
156/// number of bytes from the provided [`VectoredCursor`]. If the bytes contained on the
157/// vectored wire would lead to the construction of an invalid instance of the object,
158/// an error will be returned instead of the object.
159pub trait VectoredRead: Sized {
160    /// Consumes a number of bytes from `curs` and returns an owned instance of the specified type,
161    /// or returns a [`WireError`] on failure.
162    ///
163    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
164    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
165    /// in little endian.
166    ///
167    /// ## Errors
168    ///
169    /// [`WireError::InsufficientBytes`] - not enough bytes remained on the vectored cursor to construct
170    /// the type.
171    ///
172    /// [`WireError::InvalidData`] - the bytes retrieved from `curs` could not be used to construct a
173    /// valid instance of the type.
174    ///
175    /// [`WireError::Internal`] - an internal error occurred in the `wire-rs` library
176    fn read_vectored<const E: bool>(curs: &mut VectoredCursor<'_>) -> Result<Self, WireError>;
177
178    /*
179    fn array_from_vectored<const L: usize, const E: bool>(curs: &mut VectoredCursor<'_>) -> Result<[Self; L], WireError> {
180        std::array::try_from_fn(|_| { Self::from_vectored::<E>(curs) })
181    }
182    */
183}
184
185/// Deserialization to an owned data type from a portion of the vectored wire smaller than what
186/// the data type would normally consume.
187///
188/// A type that implements this trait guarantees that it can be constructed using a specified
189/// number of bytes (greater than zero but less than the size of the type) from the provided
190/// [`VectoredCursor`]. If the bytes contained on the vectored wire would lead to the construction of an
191/// invalid instance of the object, an error will be returned instead of the object.
192///
193/// This trait is most useful for reading integer values from the vectored wire that are represented in fewer bytes than the data type,
194/// such as reading in 3 bytes to form a u32 or 5 bytes to form a u64.
195///
196/// Types implementing this trait should additionally implement [`VectoredRead`] for
197/// the case where `L` is equal to the size of the type.
198pub trait VectoredReadPart: Sized {
199    /// Consumes exactly `L` bytes (where 0 < `L` < size_of(`type`)) from `curs` and returns an owned
200    /// instance of the specified type, or returns a [`WireError`] on failure.
201    ///
202    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
203    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
204    /// in little endian.
205    ///
206    /// ## Errors
207    ///
208    /// [`WireError::InsufficientBytes`] - not enough bytes remained on the cursor to construct the type.
209    ///
210    /// [`WireError::InvalidData`] - the bytes retrieved from `curs` could not be used to construct a
211    /// valid instance of the type.
212    ///
213    /// [`WireError::Internal`] - an internal error occurred in the `wire-rs` library
214    fn read_vectored_part<const L: usize, const E: bool>(
215        curs: &mut VectoredCursor<'_>,
216    ) -> Result<Self, WireError>;
217}
218
219/// Deserialization to a composite data type (i.e. containing both owned structures and
220/// references) from the vectored wire.
221///
222/// A type that implements this trait guarantees that it can be constructed using a
223/// number of bytes from the provided [`VectoredCursor`]. If the bytes contained on the
224/// vectored wire would lead to the construction of an invalid instance of the object,
225/// an error will be returned instead of the object.
226pub trait VectoredReadComp<'a>: Sized {
227    /// Consumes a number of bytes from `curs` and returns an owned instance of the specified
228    /// type, or returns a [`WireError`] on failure.
229    ///
230    /// The returned instance must not outlive the lifetime of the vectored buffer that it was
231    /// constructed from, though it may outlive the `VectoredReader` used to construct it.
232    ///
233    /// The generic boolean `E` designates the intended endianness of the data being read. If
234    /// `E` is set to `true`, then the data will be deserialized in big endian format; if
235    /// `false`, it will be deserialized in little endian.
236    ///
237    /// ## Errors
238    ///
239    /// [`WireError::InsufficientBytes`] - not enough bytes remained on the cursor to construct
240    /// the type.
241    ///
242    /// [`WireError::InvalidData`] - the bytes retrieved from `curs` could not be used to
243    /// construct a valid instance of the type.
244    ///
245    /// [`WireError::Internal`] - an internal error occurred in the `wire-rs` library
246    fn read_vectored_comp<const E: bool>(curs: &mut VectoredCursor<'a>) -> Result<Self, WireError>;
247
248    // Add once try_from_fn is stabilized
249    /*
250    fn array_from_wire<const L: usize, const E: bool>(curs: &mut WireCursor<'_>) -> Result<[Self; L], WireError> {
251        std::array::try_from_fn(|_| { Self::from_wire::<E>(curs) })
252    }
253    */
254}
255
256/// Deserialization to an immutable reference of a data type from the vectored wire.
257///
258/// A type that implements this trait guarantees that it can be constructed using a given
259/// number of bytes from the provided [`VectoredCursor`]. If the bytes contained on the
260/// vectored wire cannot be converted into a reference of a valid instance of the object,
261/// an error will be returned instead of the reference.
262pub trait VectoredReadRef {
263    /// Consumes exactly `size` bytes from `curs` and returns an immutable reference of the specified type,
264    /// or returns a [`WireError`] on failure.
265    ///
266    /// The returned reference must not outlive the lifetime of the vectored buffer that it references,
267    /// though it may outlive the [`VectoredReader`] used to construct it.
268    ///
269    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
270    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
271    /// in little endian.
272    ///
273    /// ## Errors
274    ///
275    /// [`WireError::InsufficientBytes`] - less than `size` bytes remained on the cursor.
276    ///
277    /// [`WireError::InvalidData`] - the bytes retrieved from `curs` could not be used to construct a
278    /// valid reference of the type.
279    ///
280    /// [`WireError::Internal`] - an internal error occurred in the `wire-rs` library
281    fn read_vectored_ref<'a>(
282        curs: &mut VectoredCursor<'a>,
283        size: usize,
284    ) -> Result<&'a Self, WireError>;
285}
286
287/// A cursor that acts as an index over a contiguous immutable slice and provides operations
288/// to sequentially read data from it.
289///
290/// When implementing the [`WireRead`] trait or one of its variants, this cursor provides an
291/// interface for reading data from the wire. When an error is returned by the cursor, it
292/// should be returned by the trait method being implemented. This can be easily accomplished
293/// using the `?` operator.
294///
295/// NOTE: this is an internal structure, and is NOT meant to be used to read data from a wire
296/// in the same manner as a [`WireReader`]. A `WireReader` is guaranteed to maintain the index
297/// of its last succesful read if any of its methods return an error, while this cursor may move
298/// its internal index forward by some unspecified amount when an error is encountered.
299#[derive(Clone, Copy)]
300pub struct WireCursor<'a> {
301    wire: &'a [u8],
302}
303
304impl<'a> WireCursor<'a> {
305    /// Create a `WireCursor` that reads from the given slice `wire`.
306    fn new(wire: &'a [u8]) -> Self {
307        WireCursor { wire }
308    }
309
310    /// Advance the cursor's index by the given amount, returning an error if there are
311    /// insufficient bytes on the wire.
312    pub fn advance(&mut self, amount: usize) -> Result<(), WireError> {
313        self.wire = match self.wire.get(amount..) {
314            Some(w) => w,
315            None => return Err(WireError::InsufficientBytes),
316        };
317        Ok(())
318    }
319
320    /// Advance the cursor's index by the given amount, or to the end of the wire if
321    /// the amount exceeds the number of remaining bytes.
322    pub fn advance_up_to(&mut self, amount: usize) {
323        self.wire = match self.wire.get(amount..) {
324            Some(w) => w,
325            None => &[],
326        };
327    }
328
329    /// Retrieve a reference to an array of bytes of size `L` from the wire.
330    pub fn get_array<const L: usize>(&mut self) -> Result<&'a [u8; L], WireError> {
331        //self.wire.try_split_array_ref() would be cleaner, but doesn't exist as an API yet...
332        match (self.wire.get(0..L), self.wire.get(L..)) {
333            (Some(r), Some(w)) => {
334                self.wire = w;
335                r.try_into().map_err(|_| WireError::Internal)
336            }
337            _ => Err(WireError::InsufficientBytes),
338        }
339    }
340
341    /// Deserialize a given type `T` that implements the [`WireRead`] trait from the wire, and
342    /// return an owned instance of it.
343    ///
344    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
345    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
346    /// in little endian.
347    pub fn get_readable<T, const E: bool>(&mut self) -> Result<T, WireError>
348    where
349        T: WireRead,
350    {
351        T::read_wire::<E>(self)
352    }
353
354    /// Deserialize `L` bytes from the wire into a given type `T` that implements the [`WireReadPart`]
355    /// trait, and return an owned instance of it.
356    ///
357    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
358    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
359    /// in little endian.
360    pub fn get_readable_part<T, const L: usize, const E: bool>(&mut self) -> Result<T, WireError>
361    where
362        T: WireReadPart,
363    {
364        T::read_wire_part::<L, E>(self)
365    }
366
367    /// Deserialize a given type `T` that implements the [`WireReadRef`] trait from the wire, and return a
368    /// reference to it.
369    ///
370    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
371    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
372    /// in little endian.
373    pub fn get_readable_ref<T, const E: bool>(&mut self, length: usize) -> Result<&'a T, WireError>
374    where
375        T: WireReadRef + ?Sized,
376    {
377        T::read_wire_ref(self, length)
378    }
379
380    /// Deserialize a given type `T` that implements the [`WireReadComp`] trait from the wire, and return
381    /// an owned instance of it.
382    ///
383    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
384    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
385    /// in little endian.
386    pub fn get_readable_comp<T, const E: bool>(&mut self) -> Result<T, WireError>
387    where
388        T: WireReadComp<'a> + ?Sized,
389    {
390        T::read_wire_comp::<E>(self)
391    }
392
393    /// Retrieve a slice of bytes from the wire.
394    pub fn get_slice(&mut self, amount: usize) -> Result<&'a [u8], WireError> {
395        // self.wire.try_split_at() would be cleaner, but doesn't exist as an API yet...
396        match (self.wire.get(0..amount), self.wire.get(amount..)) {
397            (Some(r), Some(w)) => {
398                self.wire = w;
399                Ok(r)
400            }
401            _ => Err(WireError::InsufficientBytes),
402        }
403    }
404
405    /// Check whether the wire has any remaining bytes that can be read by the cursor.
406    pub fn is_empty(&self) -> bool {
407        self.wire.is_empty()
408    }
409
410    /// Get the number of bytes remaining on the wire for the given cursor.
411    pub fn remaining(&self) -> usize {
412        self.wire.len()
413    }
414}
415
416/// A cursor that acts as an index over a set of vectored immutable slices and provides
417/// operations to sequentially read data from the slices.
418///
419/// When implementing the [`VectoredRead`] trait or one of its variants, this cursor provides an
420/// interface for reading data from the vectored wire. When an error is returned by the cursor, it
421/// should be returned by the trait method being implemented. This can be easily accomplished
422/// using the `?` operator.
423///
424/// NOTE: this is an internal structure, and is NOT meant to be used to read data from a wire
425/// in the same manner as a [`WireReader`]. A `WireReader` is guaranteed to maintain the index
426/// of its last succesful read if any of its methods return an error, while this cursor may move its
427/// internal index forward by some unspecified amount when an error is encountered.
428#[derive(Clone, Copy)]
429pub struct VectoredCursor<'a> {
430    wire: VectoredBuf<'a>,
431    idx: usize,
432}
433
434impl<'a> VectoredCursor<'a> {
435    /// Create a `VectoredCursor` that reads from the given set of vectored slices `wire`.
436    fn new(wire: VectoredBuf<'a>) -> Self {
437        VectoredCursor { wire, idx: 0 }
438    }
439
440    /// Advance the cursor's index by the given amount, returning an error if there are insufficient bytes
441    /// on the vectored wire.
442    pub fn advance(&mut self, mut amount: usize) -> Result<(), WireError> {
443        while let Some((first, next_slices)) = self.wire.split_first() {
444            let remaining_slice_len = match first.len().checked_sub(self.idx) {
445                None | Some(0) => {
446                    // Invariant: None should never occur, as the index should never exceed the bound of the first slice
447                    if next_slices.is_empty() {
448                        return Err(WireError::InsufficientBytes);
449                    }
450
451                    self.wire = next_slices;
452                    self.idx = 0;
453                    continue;
454                }
455                Some(l) => l,
456            };
457
458            match amount.checked_sub(remaining_slice_len) {
459                None | Some(0) => {
460                    self.idx += amount; // Invariant: cannot overflow (as you cannot have a slice greater than `usize::MAX`)
461                    return Ok(());
462                }
463                Some(new_amount) => {
464                    self.wire = next_slices;
465                    self.idx = 0;
466                    amount = new_amount;
467                }
468            }
469        }
470
471        Err(WireError::InsufficientBytes)
472    }
473
474    /// Advance the cursor's index by the given amount, or to the end of the vectored wire if the amount
475    /// exceeds the number of remaining bytes.
476    pub fn advance_up_to(&mut self, mut amount: usize) {
477        while let Some((first, next_slices)) = self.wire.split_first() {
478            let remaining_slice_len = match first.len().checked_sub(self.idx) {
479                None | Some(0) if next_slices.is_empty() => return,
480                None | Some(0) => {
481                    // Invariant: None should never occur, as the index should never exceed the bound of the first slice
482                    self.wire = next_slices;
483                    self.idx = 0;
484                    continue;
485                }
486                Some(l) => l,
487            };
488
489            match amount.checked_sub(remaining_slice_len) {
490                Some(0) | None => {
491                    self.idx += amount; // Invariant: cannot overflow (as you cannot have a slice greater than `usize::MAX`)
492                    return;
493                }
494                Some(_) if next_slices.is_empty() => {
495                    self.idx = first.len();
496                    return;
497                }
498                Some(new_amount) => {
499                    self.wire = next_slices;
500                    self.idx = 0;
501                    amount = new_amount;
502                }
503            }
504        }
505    }
506
507    /// Check whether the vectored wire has any remaining bytes that can be read by the cursor.
508    pub fn is_empty(&self) -> bool {
509        let mut tmp_wire = self.wire;
510        let mut tmp_idx = self.idx;
511        while let Some((first, next_slices)) = tmp_wire.split_first() {
512            if tmp_idx < first.len() {
513                return false;
514            } else if next_slices.is_empty() {
515                // tmp_idx is already first.len()
516                return true;
517            } else {
518                tmp_idx = 0;
519                tmp_wire = next_slices;
520            }
521        }
522
523        true
524    }
525
526    /// Retrieve a the next available byte from the wire.
527    pub fn get_next(&mut self) -> Result<u8, WireError> {
528        while let Some((first, next_slices)) = self.wire.split_first() {
529            match first.get(self.idx) {
530                Some(val) => {
531                    self.idx += 1;
532                    return Ok(*val);
533                }
534                None if next_slices.is_empty() => return Err(WireError::InsufficientBytes),
535                None => {
536                    self.idx = 0;
537                    self.wire = next_slices;
538                }
539            }
540        }
541
542        Err(WireError::InsufficientBytes)
543    }
544
545    /// Deserialize a given type `T` that implements the [`VectoredRead`] trait from the vectored wire,
546    /// and return an owned instance of it.
547    ///
548    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
549    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
550    /// in little endian.
551    pub fn get_readable<T, const E: bool>(&mut self) -> Result<T, WireError>
552    where
553        T: VectoredRead,
554    {
555        T::read_vectored::<E>(self)
556    }
557
558    /// Deserialize `L` bytes from the vectored wire into a given type `T` that implements the
559    /// [`VectoredReadPart`] trait, and return an owned instance of it.
560    ///
561    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
562    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
563    /// in little endian.
564    pub fn get_readable_part<T, const L: usize, const E: bool>(&mut self) -> Result<T, WireError>
565    where
566        T: VectoredReadPart,
567    {
568        T::read_vectored_part::<L, E>(self)
569    }
570
571    /// Deserialize a given type `T` that implements the [`VectoredReadRef`] trait from the vectored
572    /// wire, and return a reference to it.
573    ///
574    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
575    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
576    /// in little endian.
577    pub fn get_readable_ref<T, const E: bool>(&mut self, length: usize) -> Result<&'a T, WireError>
578    where
579        T: VectoredReadRef + ?Sized,
580    {
581        T::read_vectored_ref(self, length)
582    }
583
584    /// Deserialize a given type `T` that implements the [`VectoredReadComp`] trait from the wire, and return
585    /// an owned instance of it.
586    ///
587    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
588    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
589    /// in little endian.
590    pub fn get_readable_comp<T, const E: bool>(&mut self) -> Result<T, WireError>
591    where
592        T: VectoredReadComp<'a> + ?Sized,
593    {
594        T::read_vectored_comp::<E>(self)
595    }
596
597    /// Get the number of bytes remaining on the vectored wire for the given cursor.
598    pub fn remaining(&self) -> usize {
599        self.wire
600            .iter()
601            .map(|s| s.len())
602            .sum::<usize>()
603            .saturating_sub(self.idx)
604    }
605
606    /// Attempt to retrieve a contiguous slice of bytes from the wire, returning `None`
607    /// if the next `amount` bytes are not all located on the same slice.
608    pub fn try_get(&mut self, amount: usize) -> Option<&'a [u8]> {
609        while let Some((first, next_slices)) = self.wire.split_first() {
610            if self.idx >= first.len() && !next_slices.is_empty() {
611                self.idx = 0;
612                self.wire = next_slices;
613                continue;
614            }
615
616            let end_idx = match self.idx.checked_add(amount) {
617                Some(i) => i,
618                None => return None, // Can't have a slice of length greater than `usize::MAX`
619            };
620
621            return match first.get(self.idx..end_idx) {
622                Some(slice) => {
623                    self.idx += amount;
624                    Some(slice)
625                }
626                None => None,
627            };
628        }
629
630        None
631    }
632
633    /// Attempt to retrieve a reference to a contiguous array of bytes of size `L` from the wire,
634    /// returning `None` if the next `L` bytes are not all located on the same slice.
635    pub fn try_get_array<const L: usize>(&mut self) -> Option<&'a [u8; L]> {
636        match self.try_get(L) {
637            Some(arr) => arr.try_into().ok(), // Invariant: should always be Ok
638            None => None,
639        }
640    }
641}
642
643/// A wrapper around a `&[u8]` slice that provides an easy interface for reading data types
644/// from the slice.
645#[derive(Clone, Copy)]
646pub struct WireReader<'a, const E: bool = true> {
647    curs: WireCursor<'a>,
648    initial_len: usize,
649}
650
651impl<'a, const E: bool> WireReader<'a, E> {
652    /// Create a `WireReader` that can read data types sequentially from the `bytes` slice.
653    ///
654    /// The generic boolean `E` designates the intended endianness of the data being read. If `E` is set to
655    /// `true`, then the data will be deserialized in big endian format; if `false`, it will be deserialized
656    /// in little endian. If unset, this will default to `true`, or big endian.
657    pub fn new(bytes: &'a [u8]) -> Self {
658        WireReader {
659            curs: WireCursor::new(bytes),
660            initial_len: bytes.len(),
661        }
662    }
663
664    /// Advance the reader's index forward by the given amount of bytes, returning an error if there are insufficient
665    /// bytes on the wire to do so.
666    pub fn advance(&mut self, amount: usize) -> Result<(), WireError> {
667        let mut temp_curs = self.curs;
668        let res = temp_curs.advance(amount);
669        if res.is_ok() {
670            self.curs = temp_curs;
671        }
672        res
673    }
674
675    /// Advance the reader's index forward by the given number of bytes, or to the end of the wire if the amount
676    /// exceeds the number of remaining bytes.
677    pub fn advance_up_to(&mut self, amount: usize) {
678        self.curs.advance_up_to(amount);
679    }
680
681    /// Check if the reader has no more bytes left on the wire that can be read. If any
682    /// bytes remain, return [`WireError::ExtraBytes`]; otherwise, return Ok().
683    pub fn finalize(&self) -> Result<(), WireError> {
684        if !self.is_empty() {
685            Err(WireError::ExtraBytes)
686        } else {
687            Ok(())
688        }
689    }
690
691    /// Check if the reader has no more bytes left on the wire that can be read after
692    /// the given action. If any bytes remain, return [`WireError::ExtraBytes`]; otherwise, return Ok().
693    pub fn finalize_after<T>(action: Result<T, WireError>, reader: &Self) -> Result<T, WireError> {
694        if action.is_ok() {
695            reader.finalize()?;
696        }
697        action
698    }
699
700    /// Check whether the reader has any remaining bytes to be read.
701    pub fn is_empty(&self) -> bool {
702        self.curs.is_empty()
703    }
704
705    /// Read the given data type `T` from the wire without advancing the
706    /// index of the reader.
707    pub fn peek<T>(&self) -> Result<T, WireError>
708    where
709        T: WireRead,
710    {
711        let mut temp_curs = self.curs;
712        T::read_wire::<E>(&mut temp_curs)
713    }
714
715    /// Read the given data type `T` from the wire without advancing the
716    /// index of the reader.
717    pub fn peek_comp<T>(&self) -> Result<T, WireError>
718    where
719        T: WireReadComp<'a>,
720    {
721        let mut temp_curs = self.curs;
722        T::read_wire_comp::<E>(&mut temp_curs)
723    }
724
725    /// Read the given data type `T` from `L` bytes on the wire without
726    /// advancing the index of the reader.
727    pub fn peek_part<T, const L: usize>(&mut self) -> Result<T, WireError>
728    where
729        T: WireReadPart,
730    {
731        let mut temp_curs = self.curs;
732        T::read_wire_part::<L, E>(&mut temp_curs)
733    }
734
735    /// Read the given data type `T` from `size` bytes on the wire without
736    /// advancing the index of the reader.
737    pub fn peek_ref<T>(&mut self, size: usize) -> Result<&'a T, WireError>
738    where
739        T: WireReadRef + ?Sized,
740    {
741        let mut temp_curs = self.curs;
742        T::read_wire_ref(&mut temp_curs, size)
743    }
744
745    /// Read the given data type `T` from the wire.
746    pub fn read<T>(&mut self) -> Result<T, WireError>
747    where
748        T: WireRead,
749    {
750        let mut temp_curs = self.curs;
751        let res = T::read_wire::<E>(&mut temp_curs);
752        if res.is_ok() {
753            self.curs = temp_curs;
754        }
755        res
756    }
757
758    /// Read the given data type `T` from the wire.
759    pub fn read_comp<T>(&mut self) -> Result<T, WireError>
760    where
761        T: WireReadComp<'a>,
762    {
763        let mut temp_curs = self.curs;
764        let res = T::read_wire_comp::<E>(&mut temp_curs);
765        if res.is_ok() {
766            self.curs = temp_curs;
767        }
768        res
769    }
770
771    /// Read the given data type `T` from `size`
772    /// bytes on the wire.
773    pub fn read_part<T, const L: usize>(&mut self) -> Result<T, WireError>
774    where
775        T: WireReadPart,
776    {
777        let mut temp_curs = self.curs;
778        let res = T::read_wire_part::<L, E>(&mut temp_curs);
779        if res.is_ok() {
780            self.curs = temp_curs;
781        }
782        res
783    }
784
785    /// Read the given data type `T` from the wire.
786    pub fn read_ref<T>(&mut self, size: usize) -> Result<&'a T, WireError>
787    where
788        T: WireReadRef + ?Sized,
789    {
790        let mut temp_curs = self.curs;
791        let res = T::read_wire_ref(&mut temp_curs, size);
792        if res.is_ok() {
793            self.curs = temp_curs;
794        }
795        res
796    }
797
798    /// Read the given data type `T` from the
799    /// remaining data on the wire. Note that this operation may succeed even
800    /// if there are no bytes remaining on the wire for the given reader.
801    pub fn read_remaining<T>(&mut self) -> Result<&'a T, WireError>
802    where
803        T: WireReadRef + ?Sized,
804    {
805        self.read_ref(self.curs.remaining())
806    }
807}
808
809impl<'a, const E: bool> core::convert::From<WireReader<'a, E>> for &'a [u8] {
810    fn from(value: WireReader<'a, E>) -> Self {
811        value.curs.wire
812    }
813}
814
815pub fn _internal_wirereader_consumed(reader: &WireReader<'_>) -> usize {
816    reader.initial_len - reader.curs.remaining()
817}
818
819/// A wrapper around a slice of `&[u8]` slices that provides an easy interface for
820/// reading data types from the vectored slices.
821#[derive(Clone, Copy)]
822pub struct VectoredReader<'a, const E: bool = true> {
823    curs: VectoredCursor<'a>,
824    initial_slice_cnt: usize,
825}
826
827impl<'a, const E: bool> VectoredReader<'a, E> {
828    /// Create a `VectoredReader` that can read data types sequentially from the vectored
829    /// slices `bytes`.
830    pub fn new(bytes: VectoredBuf<'a>) -> Self {
831        VectoredReader {
832            curs: VectoredCursor::new(bytes),
833            initial_slice_cnt: bytes.len(),
834        }
835    }
836
837    /// Advance the reader's index forward by the given amount of bytes, returning an error if there
838    /// are insufficient bytes on the wire to do so.
839    pub fn advance(&mut self, amount: usize) -> Result<(), WireError> {
840        let mut temp_curs = self.curs;
841        let res = temp_curs.advance(amount);
842        if res.is_ok() {
843            self.curs = temp_curs;
844        }
845        res
846    }
847
848    /// Advance the reader's index forward by the given number of bytes, or to the end of the wire if the amount
849    /// exceeds the number of remaining bytes.
850    pub fn advance_up_to(&mut self, index: usize) {
851        self.curs.advance_up_to(index);
852    }
853
854    /// Check if the reader has no more bytes left on the vectored wire that can be read. If any
855    /// bytes remain, return [`WireError::ExtraBytes`]; otherwise, return Ok().
856    pub fn finalize(&self) -> Result<(), WireError> {
857        if self.is_empty() {
858            Ok(())
859        } else {
860            Err(WireError::ExtraBytes)
861        }
862    }
863
864    /// Check if the reader has no more bytes left on the vectored wire that can be read after
865    /// the given action. If any bytes remain, return [`WireError::ExtraBytes`]; otherwise, return Ok().
866    pub fn finalize_after<T>(action: Result<T, WireError>, reader: &Self) -> Result<T, WireError> {
867        if action.is_ok() {
868            reader.finalize()?;
869        }
870        action
871    }
872
873    /// Check whether the reader has any remaining bytes to be read.
874    pub fn is_empty(&self) -> bool {
875        self.curs.is_empty()
876    }
877
878    /// Read the given data type `T` from the vectored wire without advancing the
879    /// index of the reader.
880    pub fn peek<T>(&self) -> Result<T, WireError>
881    where
882        T: VectoredRead,
883    {
884        let mut temp_curs = self.curs; // Cheap and easy to just copy cursor and discard
885        T::read_vectored::<E>(&mut temp_curs)
886    }
887
888    /// Read the given data type `T` from the vectored wire without advancing the
889    /// index of the reader.
890    pub fn peek_comp<T>(&mut self) -> Result<T, WireError>
891    where
892        T: VectoredReadComp<'a>,
893    {
894        let mut temp_curs = self.curs;
895        T::read_vectored_comp::<E>(&mut temp_curs)
896    }
897
898    /// Read the given data type `T` from `L` bytes on the vectored wire without
899    /// advancing the index of the reader.
900    pub fn peek_part<T, const L: usize>(&mut self) -> Result<T, WireError>
901    where
902        T: VectoredReadPart,
903    {
904        let mut temp_curs = self.curs;
905        T::read_vectored_part::<L, E>(&mut temp_curs)
906    }
907
908    /// Read the given data type `T` from `size` bytes on the vectored wire without
909    /// advancing the index of the reader.
910    pub fn peek_ref<T>(&self, size: usize) -> Result<&'a T, WireError>
911    where
912        T: VectoredReadRef + ?Sized,
913    {
914        let mut temp_curs = self.curs;
915        T::read_vectored_ref(&mut temp_curs, size)
916    }
917
918    /// Read the given data type `T` from the vectored wire.
919    pub fn read<T>(&mut self) -> Result<T, WireError>
920    where
921        T: VectoredRead,
922    {
923        let mut temp_curs = self.curs;
924        let res = T::read_vectored::<E>(&mut temp_curs);
925        if res.is_ok() {
926            self.curs = temp_curs;
927        }
928        res
929    }
930
931    /// Read the given data type `T` from the vectored wire.
932    pub fn read_comp<T>(&mut self) -> Result<T, WireError>
933    where
934        T: VectoredReadComp<'a>,
935    {
936        let mut temp_curs = self.curs;
937        let res = T::read_vectored_comp::<E>(&mut temp_curs);
938        if res.is_ok() {
939            self.curs = temp_curs;
940        }
941        res
942    }
943
944    /// Read the given data type `T` from `size` bytes on the
945    /// vectored wire.
946    pub fn red_part<T, const L: usize>(&mut self) -> Result<T, WireError>
947    where
948        T: VectoredReadPart,
949    {
950        let mut temp_curs = self.curs;
951        let res = T::read_vectored_part::<L, E>(&mut temp_curs);
952        if res.is_ok() {
953            self.curs = temp_curs;
954        }
955        res
956    }
957
958    /// Read the given data type `T` from the vectored wire.
959    pub fn read_ref<T>(&mut self, size: usize) -> Result<&'a T, WireError>
960    where
961        T: VectoredReadRef + ?Sized,
962    {
963        let mut temp_curs = self.curs;
964        let res = T::read_vectored_ref(&mut temp_curs, size);
965        if res.is_ok() {
966            self.curs = temp_curs;
967        }
968        res
969    }
970
971    /// Read the given data type `T` from the remaining data on the vectored wire.
972    /// Note that this operation may succeed even if there are no bytes remaining
973    /// on the vectored wire for the given reader.
974    pub fn read_remaining<T>(&mut self) -> Result<&'a T, WireError>
975    where
976        T: VectoredReadRef + ?Sized,
977    {
978        self.read_ref(self.curs.remaining())
979    }
980}
981
982pub fn _internal_vectoredreader_vec_index(reader: &VectoredReader<'_>) -> usize {
983    reader.initial_slice_cnt - reader.curs.wire.len()
984}
985
986pub fn _internal_vectoredreader_slice_index(reader: &VectoredReader<'_>) -> usize {
987    reader.curs.idx
988}
989
990// Implementations of RefWireReadable for base types
991
992impl WireReadRef for [u8] {
993    fn read_wire_ref<'a>(curs: &mut WireCursor<'a>, size: usize) -> Result<&'a Self, WireError> {
994        curs.get_slice(size)
995    }
996}
997
998impl WireReadRef for str {
999    fn read_wire_ref<'a>(curs: &mut WireCursor<'a>, size: usize) -> Result<&'a Self, WireError> {
1000        curs.get_slice(size).and_then(|bytes| {
1001            str::from_utf8(bytes).map_err(|_| WireError::InvalidData(UTF8_DECODE_ERROR))
1002        })
1003    }
1004}
1005
1006impl VectoredReadRef for [u8] {
1007    fn read_vectored_ref<'a>(
1008        curs: &mut VectoredCursor<'a>,
1009        size: usize,
1010    ) -> Result<&'a Self, WireError> {
1011        curs.try_get(size)
1012            .ok_or(WireError::InvalidData(NONCONTIGUOUS_SEGMENT))
1013    }
1014}
1015
1016macro_rules! derive_wire_readable {
1017    ($int:ty)=> {
1018        impl WireRead for $int {
1019            fn read_wire<const E: bool>(curs: &mut WireCursor<'_>) -> Result<Self, WireError> {
1020                if E {
1021                    Ok(<$int>::from_be_bytes(*curs.get_array::<{ mem::size_of::<$int>() }>()?))
1022                } else {
1023                    Ok(<$int>::from_le_bytes(*curs.get_array::<{ mem::size_of::<$int>() }>()?))
1024                }
1025            }
1026        }
1027    };
1028
1029    ($i1:ty, $($i2:ty),+) => {
1030        derive_wire_readable! { $i1 }
1031        derive_wire_readable! { $($i2),+ }
1032    };
1033}
1034
1035macro_rules! derive_wire_partreadable {
1036    ($int:ty)=> {
1037        impl WireReadPart for $int {
1038            fn read_wire_part<const L: usize, const E: bool>(curs: &mut WireCursor<'_>) -> Result<Self, WireError> {
1039                assert!(L > 0 && L < mem::size_of::<$int>()); // TODO: once more powerful const generic expressions are in rust, use them
1040                let mut res = [0; mem::size_of::<$int>()];
1041                let bytes = curs.get_array::<L>()?;
1042
1043                if E {
1044                    for (i, b) in bytes.iter().rev().enumerate() {
1045                        res[i] = *b; // Fill first L bytes in reverse order (be -> le)
1046                    }
1047                } else {
1048                    for (i, b) in bytes.iter().enumerate() {
1049                        res[i] = *b;
1050                    }
1051                }
1052
1053                Ok(<$int>::from_le_bytes(res)) // Most computers are natively little-endian, so this will be a slightly faster transmutate
1054            }
1055        }
1056    };
1057
1058    ($i1:ty, $($i2:ty),+) => {
1059        derive_wire_partreadable! { $i1 }
1060        derive_wire_partreadable! { $($i2),+ }
1061    };
1062}
1063
1064macro_rules! derive_vectored_readable {
1065    ($int:ty)=> {
1066        impl VectoredRead for $int {
1067            fn read_vectored<const E: bool>(curs: &mut VectoredCursor<'_>) -> Result<Self, WireError> {
1068                // Try the more efficient try_get_array; fall back to getting byte by byte on failure
1069                let arr = match curs.try_get_array::<{ mem::size_of::<$int>() }>() {
1070                    Some(a) => *a,
1071                    None => {
1072                        let mut tmp_arr = [0; mem::size_of::<$int>()];
1073                        for b in tmp_arr.iter_mut() {
1074                            *b = curs.get_next()?;
1075                        }
1076
1077                        tmp_arr
1078                    },
1079                };
1080
1081                if E {
1082                    Ok(<$int>::from_be_bytes(arr))
1083                } else {
1084                    Ok(<$int>::from_le_bytes(arr))
1085                }
1086            }
1087        }
1088    };
1089
1090    ($i1:ty, $($i2:ty),+) => {
1091        derive_vectored_readable! { $i1 }
1092        derive_vectored_readable! { $($i2),+ }
1093    };
1094}
1095
1096macro_rules! derive_vectored_partreadable {
1097    ($int:ty)=> {
1098        impl VectoredReadPart for $int {
1099            fn read_vectored_part<const L: usize, const E: bool>(curs: &mut VectoredCursor<'_>) -> Result<Self, WireError> {
1100                assert!(L > 0 && L < mem::size_of::<$int>()); // TODO: once more powerful const generic expressions are in rust, use them
1101                let mut res = [0; mem::size_of::<$int>()];
1102
1103                // Try the more efficient try_get_array; fall back to getting byte by byte on failure
1104                let bytes = match curs.try_get_array::<L>() {
1105                    Some(a) => *a,
1106                    None => {
1107                        let mut tmp_arr = [0; L];
1108                        for b in tmp_arr.iter_mut() {
1109                            *b = curs.get_next()?;
1110                        }
1111
1112                        tmp_arr
1113                    },
1114                };
1115
1116                if E {
1117                    for (i, b) in bytes.iter().rev().enumerate() {
1118                        res[i] = *b; // Fill first L bytes in reverse order (be -> le)
1119                    }
1120                } else {
1121                    for (i, b) in bytes.iter().enumerate() {
1122                        res[i] = *b;
1123                    }
1124                }
1125
1126                Ok(<$int>::from_le_bytes(res)) // Most computers are natively little-endian, so this will be a slightly faster transmutate
1127            }
1128        }
1129    };
1130
1131    ($i1:ty, $($i2:ty),+) => {
1132        derive_vectored_partreadable! { $i1 }
1133        derive_vectored_partreadable! { $($i2),+ }
1134    };
1135}
1136
1137derive_wire_readable!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, f32, f64, isize, usize);
1138derive_vectored_readable!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, f32, f64, isize, usize);
1139
1140// No floats or signed integers--their implementations aren't conducive to chopping off bytes at will
1141derive_wire_partreadable!(u16, u32, u64, u128, usize);
1142derive_vectored_partreadable!(u16, u32, u64, u128, usize);