Skip to main content

jam_std_common/util/
bytes_cursor.rs

1use bytes::{Buf, Bytes};
2use codec::{Decode, Input};
3
4/// [`BytesCursor`] is a [`Bytes`] wrapper implementing [`Input`].
5///
6/// It supports zero-copy decoding of `Bytes` fields, and provides a
7/// [`read_bytes`](Self::read_bytes) method which can be used to implement zero-copy decoding of
8/// other types.
9pub struct BytesCursor {
10	bytes: Bytes,
11	position: usize,
12}
13
14impl BytesCursor {
15	/// Returns `true` iff there are no bytes left to read.
16	pub fn is_empty(&self) -> bool {
17		self.position == self.bytes.len()
18	}
19
20	/// Returns the number of bytes left to read.
21	///
22	/// Note that this is "infallible" in contrast to [`Input::remaining_len`], which can return
23	/// `Err` or `Ok(None)`.
24	pub fn infallible_remaining_len(&self) -> usize {
25		self.bytes.len() - self.position
26	}
27
28	fn align(&mut self) {
29		self.bytes.advance(self.position);
30		self.position = 0;
31	}
32
33	/// Returns a reference to a [`Bytes`] object containing the remaining bytes.
34	///
35	/// The length of the `Bytes` should match `self.infallible_remaining_len()`.
36	pub fn remaining(&mut self) -> &Bytes {
37		self.align();
38		&self.bytes
39	}
40
41	/// Read `len` bytes.
42	///
43	/// This is zero-copy; the returned `Bytes` uses the same underlying storage as the wrapped
44	/// `Bytes` object.
45	pub fn read_bytes(&mut self, len: usize) -> Result<Bytes, codec::Error> {
46		self.align();
47		if len > self.bytes.len() {
48			return Err("Not enough data".into())
49		}
50		Ok(self.bytes.split_to(len))
51	}
52
53	/// Convenience method to decode a value and ensure all bytes are consumed.
54	pub fn decode_all<T: Decode>(&mut self) -> Result<T, codec::Error> {
55		let value = T::decode(self)?;
56		if !self.is_empty() {
57			return Err("Extraneous bytes".into())
58		}
59		Ok(value)
60	}
61}
62
63impl Input for BytesCursor {
64	fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
65		Ok(Some(self.infallible_remaining_len()))
66	}
67
68	fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
69		if into.len() > self.infallible_remaining_len() {
70			return Err("Not enough data".into())
71		}
72		into.copy_from_slice(&self.bytes[self.position..self.position + into.len()]);
73		self.position += into.len();
74		Ok(())
75	}
76
77	fn scale_internal_decode_bytes(&mut self) -> Result<Bytes, codec::Error> {
78		let length = <codec::Compact<u32>>::decode(self)?.0 as usize;
79		self.read_bytes(length)
80	}
81}
82
83impl From<Bytes> for BytesCursor {
84	fn from(bytes: Bytes) -> Self {
85		Self { bytes, position: 0 }
86	}
87}
88
89impl From<Vec<u8>> for BytesCursor {
90	fn from(vec: Vec<u8>) -> Self {
91		Bytes::from(vec).into()
92	}
93}
94
95unsafe impl castaway::LifetimeFree for BytesCursor {}