byteserde/des_slice.rs
1use std::fmt::{Debug, LowerHex};
2
3use crate::{
4 error::SerDesError,
5 prelude::ByteSerializerHeap,
6 utils::{
7 hex::{to_hex_line, to_hex_pretty},
8 numerics::{be_bytes::FromBeBytes, le_bytes::FromLeBytes, ne_bytes::FromNeBytes},
9 },
10};
11
12use super::ser_stack::ByteSerializerStack;
13
14/// Utility struct with a number of methods to enable deserialization of bytes into various types
15/// ```
16/// use ::byteserde::prelude::*;
17/// let bytes = &[0x01, 0x00, 0x02, 0x00, 0x00, 0x03];
18/// let mut des = ByteDeserializerSlice::new(bytes);
19/// assert_eq!(des.remaining(), 6);
20/// assert_eq!(des.idx(), 0);
21/// assert_eq!(des.len(), 6);
22///
23/// let first: u8 = des.deserialize_bytes_slice(1).unwrap()[0];
24/// assert_eq!(first , 1);
25///
26/// let second: &[u8; 2] = des.deserialize_bytes_array_ref().unwrap();
27/// assert_eq!(second, &[0x00, 0x02]);
28///
29/// let remaining: &[u8] = des.deserialize_bytes_slice_remaining();
30/// assert_eq!(remaining, &[0x00, 0x00, 0x03]);
31/// ```
32#[derive(Debug, PartialEq)]
33pub struct ByteDeserializerSlice<'slice> {
34 bytes: &'slice [u8],
35 idx: usize,
36}
37
38/// Provides a convenient way to view buffer content as both HEX and ASCII bytes where printable.
39/// supports both forms of alternate
40/// ```
41/// use byteserde::prelude::*;
42/// let mut des = ByteDeserializerSlice::new(&[0x01, 0x00, 0x02, 0x00, 0x00, 0x03]);
43/// println ! ("{:#x}", des); // up to 16 bytes per line
44/// println ! ("{:x}", des); // single line
45/// ```
46impl<'bytes> LowerHex for ByteDeserializerSlice<'bytes> {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 let bytes = match f.alternate() {
49 true => format!("\n{hex}", hex = to_hex_pretty(self.bytes)),
50 false => to_hex_line(self.bytes),
51 };
52 let len = self.bytes.len();
53 let idx = self.idx;
54 let rem = self.remaining();
55 write!(f, "ByteDeserializerSlice {{ len: {len}, idx: {idx}, remaining: {rem}, bytes: {bytes} }}",)
56 }
57}
58
59impl<'bytes> ByteDeserializerSlice<'bytes> {
60 #[inline(always)]
61 pub fn new(bytes: &[u8]) -> ByteDeserializerSlice {
62 ByteDeserializerSlice { bytes, idx: 0 }
63 }
64
65 pub fn reset(&mut self) {
66 self.idx = 0;
67 }
68
69 /// Tracks the bytes read and always set to the next unread byte in the buffer. This is an inverse of [Self::remaining()]
70 pub fn idx(&self) -> usize {
71 self.idx
72 }
73 /// Number of bytes remaining to be deserialized, this is an inverse of [Self::idx()]
74 pub fn remaining(&self) -> usize {
75 self.len() - self.idx
76 }
77
78 // Number of bytes in the buffer does not change as deserialization progresses unlike [Self::remaining()] and [Self::idx()]
79 pub fn len(&self) -> usize {
80 self.bytes.len()
81 }
82 pub fn is_empty(&self) -> bool {
83 self.remaining() == 0
84 }
85
86 #[cold]
87 fn error(&self, n: usize) -> SerDesError {
88 // moving error into a fn improves performance by 10%
89 // from_bytes - reuse ByteDeserializerSlice
90 // time: [39.251 ns 39.333 ns 39.465 ns]
91 // change: [-12.507% -11.603% -10.612%] (p = 0.00 < 0.05)
92 // Performance has improved.
93 SerDesError {
94 message: format!("Failed to get a slice size: {n} bytes from {self:x}"),
95 }
96 }
97 /// consumes all of the remaining bytes in the buffer and returns them as slice
98 pub fn deserialize_bytes_slice_remaining(&mut self) -> &'bytes [u8] {
99 let slice = &self.bytes[self.idx..];
100 self.idx += slice.len();
101 slice
102 }
103 /// consumes `len` bytes from the buffer and returns them as slice if successful.
104 /// Fails if `len` is greater then [Self::remaining()]
105 pub fn deserialize_bytes_slice(&mut self, len: usize) -> crate::error::Result<&'bytes [u8]> {
106 let res = self.peek_bytes_slice(len)?;
107 self.advance_idx(len);
108 Ok(res)
109 }
110
111 #[inline(always)]
112 pub fn deserialize_u8(&mut self) -> crate::error::Result<u8> {
113 let res = self.bytes.get(self.idx..);
114 match res {
115 Some(v) => {
116 self.idx += 1;
117 Ok(v[0])
118 }
119 None => Err(self.error(1)),
120 }
121 }
122 #[inline(always)]
123 pub fn deserialize_i8(&mut self) -> crate::error::Result<i8> {
124 let res = self.bytes.get(self.idx..);
125 match res {
126 Some(v) => {
127 self.idx += 1;
128 Ok(v[0] as i8)
129 }
130 None => Err(self.error(1)),
131 }
132 }
133 /// moves the index forward by `len` bytes, intended to be used in combination with [Self::peek_bytes_slice()]
134 #[inline(always)]
135 fn advance_idx(&mut self, len: usize) {
136 self.idx += len;
137 }
138 /// produces with out consuming `len` bytes from the buffer and returns them as slice if successful.
139 #[inline(always)]
140 pub fn peek_bytes_slice(&self, len: usize) -> crate::error::Result<&'bytes [u8]> {
141 match self.bytes.get(self.idx..self.idx + len) {
142 Some(v) => Ok(v),
143 None => Err(SerDesError {
144 message: format!("requested: {req}, bytes:\n{self:#x}", req = len,),
145 }),
146 }
147 }
148
149 #[inline]
150 pub fn deserialize_bytes_array_ref<const N: usize>(&mut self) -> crate::error::Result<&'bytes [u8; N]> {
151 match self.bytes.get(self.idx..self.idx + N) {
152 Some(v) => {
153 self.idx += N;
154 Ok(v.try_into().expect("Failed to convert &[u8] into &[u8; N]"))
155 }
156 None => Err(self.error(N)),
157 }
158 }
159 /// depletes `2` bytes for `u16`, etc. and returns after deserializing using `native` endianess
160 /// FromNeBytes trait is already implemented for all rust's numeric primitives in this crate
161 /// ```
162 /// use ::byteserde::prelude::*;
163 /// let mut des = ByteDeserializerSlice::new(&[0x00, 0x01]);
164 /// let v: u16 = des.deserialize_ne().unwrap();
165 /// // ... etc
166 /// ```
167 #[inline]
168 pub fn deserialize_ne<const N: usize, T: FromNeBytes<N, T>>(&mut self) -> crate::error::Result<T> {
169 let r = self.deserialize_bytes_array_ref::<N>()?;
170 Ok(T::from_bytes_ref(r))
171 }
172 /// depletes `2` bytes for `u16`, etc. and returns after deserializing using `little` endianess
173 /// FromLeBytes trait is already implemented for all rust's numeric primitives in this crate
174 /// ```
175 /// use ::byteserde::prelude::*;
176 /// let mut des = ByteDeserializerSlice::new(&[0x00, 0x01]);
177 /// let v: u16 = des.deserialize_le().unwrap();
178 /// // ... etc
179 /// ```
180 // #[inline]
181 pub fn deserialize_le<const N: usize, T: FromLeBytes<N, T>>(&mut self) -> crate::error::Result<T> {
182 let r = self.deserialize_bytes_array_ref::<N>()?;
183 Ok(T::from_bytes_ref(r))
184 }
185 /// depletes `2` bytes for `u16`, etc. and returns after deserializing using `big` endianess
186 /// FromBeBytes trait is already implemented for all rust's numeric primitives in this crate
187 /// ```
188 /// use ::byteserde::prelude::*;
189 /// let mut des = ByteDeserializerSlice::new(&[0x00, 0x01]);
190 /// let v: u16 = des.deserialize_be().unwrap();
191 /// // ... etc
192 /// ```
193 #[inline]
194 pub fn deserialize_be<const N: usize, T: FromBeBytes<N, T>>(&mut self) -> crate::error::Result<T> {
195 let r = self.deserialize_bytes_array_ref::<N>()?;
196 Ok(T::from_bytes_ref(r))
197 }
198 /// creates a new instance of `T` type `struct`, depleting exactly the right amount of bytes from [ByteDeserializerSlice]
199 /// `T` must implement [ByteDeserializeSlice] trait
200 pub fn deserialize<T>(&mut self) -> crate::error::Result<T>
201 where T: ByteDeserializeSlice<T> {
202 T::byte_deserialize(self)
203 }
204
205 /// creates a new instance of T type struct, depleting `exactly` `len` bytes from [ByteDeserializerSlice].
206 /// Intended for types with variable length such as Strings, Vec, etc.
207 pub fn deserialize_take<T>(&mut self, len: usize) -> crate::error::Result<T>
208 where T: ByteDeserializeSlice<T> {
209 T::byte_deserialize_take(self, len)
210 }
211}
212
213/// This trait is to be implemented by any struct, example `MyFavStruct`, to be compatible with [`ByteDeserializerSlice::deserialize<MyFavStruct>()`]
214pub trait ByteDeserializeSlice<T> {
215 /// If successful returns a new instance of T type struct, depleting exactly the right amount of bytes from [ByteDeserializerSlice]
216 /// Number of bytes depleted is determined by the struct T itself and its member types.
217 fn byte_deserialize(des: &mut ByteDeserializerSlice) -> crate::error::Result<T>;
218
219 /// if successful returns a new instance of T type struct, however ONLY depleting a maximum of `len` bytes from [ByteDeserializerSlice]
220 /// Intended for types with variable length such as Strings, Vec, etc.
221 /// No bytes will be depleted if attempt was not successful.
222 #[inline(always)]
223 fn byte_deserialize_take(des: &mut ByteDeserializerSlice, len: usize) -> crate::error::Result<T> {
224 let bytes = des.peek_bytes_slice(len)?;
225 let tmp_des = &mut ByteDeserializerSlice::new(bytes);
226 let result = Self::byte_deserialize(tmp_des);
227 match result {
228 Ok(v) => {
229 des.advance_idx(bytes.len());
230 Ok(v)
231 }
232 Err(e) => Err(e),
233 }
234 }
235}
236
237/// Greedy deserialization of the remaining byte stream into a `Vec<u8>`
238impl ByteDeserializeSlice<Vec<u8>> for Vec<u8> {
239 fn byte_deserialize(des: &mut ByteDeserializerSlice) -> crate::error::Result<Vec<u8>> {
240 Ok(des.deserialize_bytes_slice_remaining().into())
241 }
242}
243
244/// This is a short cut method that creates a new instance of [ByteDeserializerSlice] and then uses that to convert them into a T type struct.
245#[inline(always)]
246pub fn from_slice<T>(bytes: &[u8]) -> crate::error::Result<T>
247where T: ByteDeserializeSlice<T> {
248 let de = &mut ByteDeserializerSlice::new(bytes);
249 T::byte_deserialize(de)
250}
251
252/// This is a short cut method that uses [`ByteSerializerStack<CAP>::as_slice()`] method to issue a [from_slice] call.
253pub fn from_serializer_stack<const CAP: usize, T>(ser: &ByteSerializerStack<CAP>) -> crate::error::Result<T>
254where T: ByteDeserializeSlice<T> {
255 from_slice(ser.as_slice())
256}
257/// This is a short cut method that uses [`ByteSerializerHeap::as_slice()`] method to issue a [from_slice] call.
258pub fn from_serializer_heap<T>(ser: &ByteSerializerHeap) -> crate::error::Result<T>
259where T: ByteDeserializeSlice<T> {
260 from_slice(ser.as_slice())
261}