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);