compact_encoding/
lib.rs

1#![forbid(unsafe_code, missing_docs)]
2#![cfg_attr(test, deny(warnings))]
3
4//! # Series of compact encoding schemes for building small and fast parsers and serializers
5//!
6//! Binary compatible with the
7//! [original JavaScript compact-encoding library](https://github.com/compact-encoding/compact-encoding/).
8//!
9//! ## Usage
10//!
11//! The simplest way to encoded and decode a some data is using the [`to_encoded_bytes`] and
12//! [`map_decode`] macros:
13//! ```
14//! use compact_encoding::{map_decode, to_encoded_bytes};
15//!
16//! let number = 41_u32;
17//! let word = "hi";
18//!
19//! let encoded_buffer = to_encoded_bytes!(number, word);
20//! let ((number_dec, word_dec), remaining_buffer) = map_decode!(&encoded_buffer, [u32, String]);
21//!
22//! assert!(remaining_buffer.is_empty());
23//! assert_eq!(number_dec, number);
24//! assert_eq!(word_dec, word);
25//! # Ok::<(), Box<dyn std::error::Error>>(())
26//! ```
27//! ### Manual encoding and decoding
28//!
29//! When more fine-grained control of encoding and decoding is needed you manually do each step of
30//! encoding and decoding like in the following example, where we want to use a fixed width
31//! encoding for `number` (instead of the default variable width encoding). It shows how to
32//! manually calculate the needed buffer size, create the buffer, encode data, and decode it.
33//! ```
34//! use compact_encoding::{CompactEncoding, FixedWidthEncoding, FixedWidthU32};
35//!
36//! let number = 41_u32;
37//! let word = "hi";
38//!
39//! // Use `encoded_size` to figure out how big a buffer should be
40//! let size = number.as_fixed_width().encoded_size()? + word.encoded_size()?;
41//!
42//! // Create a buffer with the calculated size
43//! let mut buffer = vec![0; size];
44//! assert_eq!(buffer.len(), 4 + 1 + 2);
45//!
46//! // Then actually encode the values
47//! let mut remaining_buffer = number.as_fixed_width().encode(&mut buffer)?;
48//! remaining_buffer = word.encode(remaining_buffer)?;
49//! assert!(remaining_buffer.is_empty());
50//! assert_eq!(buffer.to_vec(), vec![41_u8, 0, 0, 0, 2_u8, b'h', b'i']);
51//!
52//! // `buffer` now contains all the encoded data, and we can decode from it
53//! let (number_dec, remaining_buffer) = FixedWidthU32::decode(&buffer)?;
54//! let (word_dec, remaining_buffer) = String::decode(remaining_buffer)?;
55//! assert!(remaining_buffer.is_empty());
56//! assert_eq!(number_dec, number);
57//! assert_eq!(word_dec, word);
58//! # Ok::<(), Box<dyn std::error::Error>>(())
59//! ```
60//!
61//! ### Implementing CompactEncoding for custom types
62//!
63//! Here we demonstrate how to implement [`CompactEncoding`] for a custom struct.
64//! ```
65//! use compact_encoding::{
66//!     map_decode, map_encode, sum_encoded_size, to_encoded_bytes, CompactEncoding, EncodingError,
67//! };
68//!
69//! #[derive(Debug, PartialEq)]
70//! struct MyStruct {
71//!     some_flag: bool,
72//!     values: Option<Vec<[u8; 32]>>,
73//!     other: String,
74//!     stuff: u64,
75//! }
76//!
77//! impl CompactEncoding for MyStruct {
78//!     fn encoded_size(&self) -> Result<usize, EncodingError> {
79//!         Ok(1 /* flags */ + {
80//!              /* handle option values */
81//!             if let Some(values) = &self.values  {
82//!                 values.encoded_size()?
83//!             } else {
84//!                 0
85//!             }
86//!         } + sum_encoded_size!(&self.other, &self.stuff))
87//!     }
88//!
89//!     fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
90//!         let mut flags: u8 = 0;
91//!         if self.some_flag {
92//!             flags |= 1;
93//!         }
94//!         if self.values.is_some() {
95//!             flags |= 2;
96//!         }
97//!         let mut rest = flags.encode(buffer)?;
98//!         if let Some(values) = &self.values {
99//!             rest = values.encode(rest)?;
100//!         }
101//!         Ok(map_encode!(rest, self.other, self.stuff))
102//!     }
103//!
104//!     fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError> {
105//!         let (flags, rest) = u8::decode(buffer)?;
106//!         let some_flag: bool = flags & 1 != 0;
107//!         let (values, rest) = if flags & 2 != 0 {
108//!             let (vec, rest) = <Vec<[u8; 32]>>::decode(rest)?;
109//!             (Some(vec), rest)
110//!         } else {
111//!             (None, rest)
112//!         };
113//!         let ((other, stuff), rest) = map_decode!(rest, [String, u64]);
114//!         Ok((
115//!             Self {
116//!                 some_flag,
117//!                 values,
118//!                 other,
119//!                 stuff,
120//!             },
121//!             rest,
122//!         ))
123//!     }
124//! }
125//!
126//! // Test values
127//! let foo = MyStruct {
128//!     some_flag: false,
129//!     values: None,
130//!     other: "hi".to_string(),
131//!     stuff: 42,
132//! };
133//!
134//! let bar = MyStruct {
135//!     some_flag: true,
136//!     values: Some(vec![[1; 32], [2; 32]]),
137//!     other: "yo".to_string(),
138//!     stuff: 0,
139//! };
140//!
141//! // Encode `foo` and `bar` to a buffer
142//! let buffer = to_encoded_bytes!(&foo, &bar);
143//!
144//! // With the above use of a flags byte, the empty value encodes to only one byte
145//! assert_eq!(
146//!     buffer.len(),
147//!     // flags + string + u64
148//!     (1 + 3 + 1) +
149//!     // "" + (values.len().encoded_size() + (values.len() * <[u8;32]>::encoded_size()) + ""
150//!     (1 + (1 + (2 * 32)) + 3 + 1)
151//! );
152//!
153//! // And decode directly to your own struct
154//! let (foo_dec, rest) = MyStruct::decode(&buffer)?;
155//! let (bar_dec, rest) = MyStruct::decode(&rest)?;
156//! // Ensure all bytes were used
157//! assert!(rest.is_empty());
158//! assert_eq!(foo_dec, foo);
159//! assert_eq!(bar_dec, bar);
160//! # Ok::<(), Box<dyn std::error::Error>>(())
161//! ```
162mod error;
163mod fixedwidth;
164pub use fixedwidth::{FixedWidthEncoding, FixedWidthU32, FixedWidthU64, FixedWidthUint};
165use std::{
166    any::type_name,
167    net::{Ipv4Addr, Ipv6Addr},
168};
169
170pub use crate::error::{EncodingError, EncodingErrorKind};
171
172/// indicates a variable width unsigned integer fits in u16
173pub const U16_SIGNIFIER: u8 = 0xfd;
174/// indicates a variable width unsigned integer fits in u32
175pub const U32_SIGNIFIER: u8 = 0xfe;
176/// indicates a variable width unsigned integer fits in u64
177pub const U64_SIGNIFIER: u8 = 0xff;
178
179const U16_SIZE: usize = 2;
180const U32_SIZE: usize = 4;
181const U64_SIZE: usize = 8;
182
183/// A trait for building small and fast parsers and serializers.
184pub trait CompactEncoding<Decode: ?Sized = Self> {
185    /// The size in bytes required to encode `self`.
186    fn encoded_size(&self) -> Result<usize, EncodingError>;
187
188    /// Encode `self` into `buffer` returning the remainder of `buffer`.
189    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError>;
190
191    /// Decode a value from the given `buffer` of the type specified by the `Decode` type parameter
192    /// (which defaults to `Self`). Returns the decoded value and remaining undecoded bytes.
193    fn decode(buffer: &[u8]) -> Result<(Decode, &[u8]), EncodingError>
194    where
195        Decode: Sized;
196
197    /// Encode `self` into a `Vec<u8>`. This is just a helper method for creating a buffer and
198    /// encoding to it in one step.
199    /// ```
200    /// # use std::net::Ipv4Addr;
201    /// # use compact_encoding::CompactEncoding;
202    /// let foo: Ipv4Addr = "0.0.0.0".parse()?;
203    /// let mut buff = vec![0; foo.encoded_size()?];
204    /// foo.encode(&mut buff)?;
205    /// # Ok::<(), Box<dyn std::error::Error>>(())
206    /// ```
207    fn to_encoded_bytes(&self) -> Result<Box<[u8]>, EncodingError> {
208        let mut buff = self.create_buffer()?;
209        self.encode(&mut buff)?;
210        Ok(buff)
211    }
212    /// Create an empty buffer of the correct size for encoding `self` to. This is just a helper
213    /// method for: encoding to it in one step.
214    /// ```
215    /// # use std::net::Ipv4Addr;
216    /// # use compact_encoding::CompactEncoding;
217    /// let foo: Ipv4Addr = "0.0.0.0".parse()?;
218    /// vec![0; foo.encoded_size()?];
219    /// # Ok::<(), Box<dyn std::error::Error>>(())
220    /// ```
221    fn create_buffer(&self) -> Result<Box<[u8]>, EncodingError> {
222        Ok(vec![0; self.encoded_size()?].into_boxed_slice())
223    }
224
225    /// Like [`CompactEncoding::encode`] but also return the number of bytes encoded.
226    fn encode_with_len<'a>(
227        &self,
228        buffer: &'a mut [u8],
229    ) -> Result<(&'a mut [u8], usize), EncodingError> {
230        let before_len = buffer.len();
231        let rest = self.encode(buffer)?;
232        let num_encoded_bytes = before_len - rest.len();
233        Ok((rest, num_encoded_bytes))
234    }
235
236    /// Like [`CompactEncoding::decode`] but also return the number of bytes decoded.
237    fn decode_with_len(buffer: &[u8]) -> Result<(Decode, &[u8], usize), EncodingError>
238    where
239        Decode: Sized,
240    {
241        let (out, rest) = Self::decode(buffer)?;
242        Ok((out, rest, buffer.len() - rest.len()))
243    }
244}
245
246/// Implement this for type `T` to have `CompactEncoding` implemented for `Vec<T>`
247pub trait VecEncodable: CompactEncoding {
248    /// Calculate the resulting size in bytes of `vec`
249    fn vec_encoded_size(vec: &[Self]) -> Result<usize, EncodingError>
250    where
251        Self: Sized;
252
253    /// Encode `vec` to `buffer`
254    fn vec_encode<'a>(vec: &[Self], buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError>
255    where
256        Self: Sized,
257    {
258        encode_vec(vec, buffer)
259    }
260
261    /// Decode [`Vec<Self>`] from buffer
262    fn vec_decode(buffer: &[u8]) -> Result<(Vec<Self>, &[u8]), EncodingError>
263    where
264        Self: Sized,
265    {
266        decode_vec(buffer)
267    }
268}
269
270// NB: we DO want &Box<..> because we want the trait to work for boxed things, hence clippy::allow
271#[allow(clippy::borrowed_box)]
272/// Define this trait for `T` to get `impl Box<[T]> for CompactEncoding`
273pub trait BoxedSliceEncodable: CompactEncoding {
274    /// The encoded size in bytes
275    fn boxed_slice_encoded_size(boxed: &Box<[Self]>) -> Result<usize, EncodingError>
276    where
277        Self: Sized;
278
279    /// Encode `Box<[Self]>` to the buffer and return the remainder of the buffer
280    fn boxed_slice_encode<'a>(
281        vec: &Box<[Self]>,
282        buffer: &'a mut [u8],
283    ) -> Result<&'a mut [u8], EncodingError>
284    where
285        Self: Sized,
286    {
287        encode_vec(vec, buffer)
288    }
289
290    /// Decode [`Box<[Self]>`] from buffer
291    fn boxed_slice_decode(buffer: &[u8]) -> Result<(Box<[Self]>, &[u8]), EncodingError>
292    where
293        Self: Sized,
294    {
295        let (result, rest) = decode_vec(buffer)?;
296        Ok((result.into_boxed_slice(), rest))
297    }
298}
299
300#[macro_export]
301/// Given a list of [`CompactEncoding`] things, sum the result of calling
302/// [`CompactEncoding::encoded_size`] on all of them.
303/// Note this is macro is useful when your arguments have differing types.
304/// ```
305/// # use crate::compact_encoding::{sum_encoded_size, CompactEncoding};
306/// # use std::net::Ipv4Addr;
307/// let foo: Ipv4Addr = "0.0.0.0".parse()?;
308/// let bar = 42u64;
309/// let qux = "hello?";
310/// let result = sum_encoded_size!(foo, bar, qux);
311/// assert_eq!(result, 12);
312/// # Ok::<(), Box<dyn std::error::Error>>(())
313/// ```
314/// If you want to use this within a non-result context you can do
315/// ```
316/// # use crate::compact_encoding::{sum_encoded_size, CompactEncoding, EncodingError};
317/// let bar = 42u64;
318/// let result = (|| Ok::<usize, EncodingError>(sum_encoded_size!(bar)))().unwrap();
319/// assert_eq!(result, 1);
320/// ```
321macro_rules! sum_encoded_size {
322    ($($val:expr),+) => {{
323        0
324        $(
325            + $val.encoded_size()?
326        )*
327    }}
328}
329
330#[macro_export]
331/// Given a list of [`CompactEncoding`] things, create a zeroed buffer of the correct size for encoding.
332/// Note this is macro is useful when your arguments have differing types.
333/// ```
334/// # use crate::compact_encoding::{create_buffer, CompactEncoding};
335/// # use std::net::Ipv4Addr;
336/// let foo: Ipv4Addr = "0.0.0.0".parse()?;
337/// let bar = 42u64;
338/// let qux = "hello?";
339/// let buff = create_buffer!(foo, bar, qux);
340/// assert_eq!(buff.len(), 12);
341/// # Ok::<(), Box<dyn std::error::Error>>(())
342/// ```
343macro_rules! create_buffer {
344    ($($val:expr),+) => {{
345        let len = (
346            0
347            $(
348                + $val.encoded_size()?
349            )*
350        );
351        vec![0; len].into_boxed_slice()
352    }}
353}
354
355#[macro_export]
356/// Given a buffer and a list of [`CompactEncoding`] things, encode the arguments to the buffer.
357/// Note this is macro is useful when your arguments have differing types.
358/// ```
359/// # use crate::compact_encoding::{create_buffer, map_encode, CompactEncoding};
360/// let num = 42u64;
361/// let word = "yo";
362/// let mut buff = create_buffer!(num, word);
363/// let result = map_encode!(&mut buff, num, word);
364/// assert!(result.is_empty());
365/// assert_eq!(&*buff, &[42, 2, b'y', b'o']);
366/// # Ok::<(), Box<dyn std::error::Error>>(())
367/// ```
368macro_rules! map_encode {
369    ($buffer:expr$(,)*) => {
370        $buffer
371    };
372    // Base case: single field
373    ($buffer:expr, $field:expr) => {
374        $field.encode($buffer)?
375    };
376    // Recursive case: first field + rest
377    ($buffer:expr, $first:expr, $($rest:expr),+) => {{
378        let rest = $first.encode($buffer)?;
379        map_encode!(rest, $($rest),+)
380    }};
381}
382
383#[macro_export]
384/// Given a list of [`CompactEncoding`] things, encode the arguments to the buffer.
385/// Note this is macro is useful when your arguments have differing types.
386/// ```
387/// # use crate::compact_encoding::to_encoded_bytes;
388/// let result = to_encoded_bytes!(42u64, "yo");
389/// assert_eq!(&*result, &[42, 2, 121, 111]);
390/// # Ok::<(), Box<dyn std::error::Error>>(())
391/// ```
392macro_rules! to_encoded_bytes {
393    ($($val:expr),*) => {{
394        use $crate::{map_encode, create_buffer, CompactEncoding};
395        let mut buffer = create_buffer!($($val),*);
396        map_encode!(&mut buffer, $($val),*);
397        buffer
398    }}
399}
400
401#[macro_export]
402/// Decode a buffer to the list of types provided, returning the remaining buffer.
403/// It takes as arguments: `(&buffer, [type1, type2, type3, ...])`
404/// And returns: `((decoded_type1, decoded_type2, ...), remaining_buffer)`
405/// ```
406/// # use crate::compact_encoding::{to_encoded_bytes, map_decode};
407/// let buffer = to_encoded_bytes!(42u64, "yo");
408/// let ((number, word), remaining_buffer) = map_decode!(&buffer, [u64, String]);
409/// assert!(remaining_buffer.is_empty());
410/// assert_eq!(number, 42u64);
411/// assert_eq!(word, "yo");
412/// # Ok::<(), Box<dyn std::error::Error>>(())
413/// ```
414macro_rules! map_decode {
415    ($buffer:expr, [
416        $($field_type:ty),* $(,)?
417    ]) => {{
418        use $crate::CompactEncoding;
419        let mut current_buffer: &[u8] = $buffer;
420
421        // Decode each type into `result_tuple`
422        let result_tuple = (
423            $(
424                match <$field_type>::decode(&current_buffer)? {
425                    (value, new_buf) => {
426                        current_buffer = new_buf;
427                        value
428                    }
429                },
430            )*
431        );
432        (result_tuple, current_buffer)
433    }};
434}
435
436/// helper for mapping the first element of a two eleent tuple
437macro_rules! map_first {
438    ($res:expr, $f:expr) => {{
439        let (one, two) = $res;
440        let mapped = $f(one)?;
441        (mapped, two)
442    }};
443}
444
445/// Split a slice in two at `mid`. Returns encoding error when `mid` is out of bounds.
446pub fn get_slices_checked(buffer: &[u8], mid: usize) -> Result<(&[u8], &[u8]), EncodingError> {
447    buffer.split_at_checked(mid).ok_or_else(|| {
448        EncodingError::out_of_bounds(&format!(
449            "Could not split slice at [{mid}] slice.len() = [{}]",
450            buffer.len()
451        ))
452    })
453}
454
455/// Split a mutable slice into two mutable slices around `mid`.
456/// Returns encoding error when `mid` is out of bounds.
457pub fn get_slices_mut_checked(
458    buffer: &mut [u8],
459    mid: usize,
460) -> Result<(&mut [u8], &mut [u8]), EncodingError> {
461    let len = buffer.len();
462    buffer.split_at_mut_checked(mid).ok_or_else(|| {
463        EncodingError::out_of_bounds(&format!(
464            "Could not split mut slice at [{mid}] slice.len() = [{len}]"
465        ))
466    })
467}
468
469/// Get a slice as an array of size `N`. Errors when `slice.len() != N`.
470pub fn as_array<const N: usize>(buffer: &[u8]) -> Result<&[u8; N], EncodingError> {
471    let blen = buffer.len();
472    if blen != N {
473        return Err(EncodingError::out_of_bounds(&format!(
474            "Could get a [{N}] byte array from a slice of length [{blen}]"
475        )));
476    }
477    Ok(buffer.split_first_chunk::<N>().expect("checked above").0)
478}
479
480/// Get a slice as a mutable array of size `N`. Errors when `slice.len() != N`.
481pub fn as_array_mut<const N: usize>(buffer: &mut [u8]) -> Result<&mut [u8; N], EncodingError> {
482    let blen = buffer.len();
483    if blen != N {
484        return Err(EncodingError::out_of_bounds(&format!(
485            "Could get a [{N}] byte array from a slice of length [{blen}]"
486        )));
487    }
488    Ok(buffer
489        .split_first_chunk_mut::<N>()
490        .expect("checked above")
491        .0)
492}
493
494/// Write `source` to `buffer` and return the remainder of `buffer`.
495/// Errors when `N < buffer.len()`
496pub fn write_array<'a, const N: usize>(
497    source: &[u8; N],
498    buffer: &'a mut [u8],
499) -> std::result::Result<&'a mut [u8], EncodingError> {
500    let blen = buffer.len();
501    let Some((dest, rest)) = buffer.split_first_chunk_mut::<N>() else {
502        return Err(EncodingError::out_of_bounds(&format!(
503            "Could not write [{}] bytes to buffer of length [{}]",
504            N, blen
505        )));
506    };
507    dest.copy_from_slice(source);
508    Ok(rest)
509}
510
511/// split the first `N` bytes of `buffer` off and return them
512pub fn take_array<const N: usize>(
513    buffer: &[u8],
514) -> std::result::Result<([u8; N], &[u8]), EncodingError> {
515    let Some((out, rest)) = buffer.split_first_chunk::<N>() else {
516        return Err(EncodingError::out_of_bounds(&format!(
517            "Could not write [{}] bytes to buffer of length [{}]",
518            N,
519            buffer.len()
520        )));
521    };
522    Ok((*out, rest))
523}
524/// split the first `N` bytes of `buffer` off and return them
525pub fn take_array_mut<const N: usize>(
526    buffer: &mut [u8],
527) -> std::result::Result<(&mut [u8; N], &mut [u8]), EncodingError> {
528    let blen = buffer.len();
529    let Some((out, rest)) = buffer.split_first_chunk_mut::<N>() else {
530        return Err(EncodingError::out_of_bounds(&format!(
531            "Could not write [{}] bytes to buffer of length [{blen}]",
532            N,
533        )));
534    };
535    Ok((out, rest))
536}
537
538/// write `source` to `buffer` and return remaining buffer
539pub fn write_slice<'a>(source: &[u8], buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
540    let mid = source.len();
541    let (dest, rest) = get_slices_mut_checked(buffer, mid)?;
542    dest.copy_from_slice(source);
543    Ok(rest)
544}
545
546/// Helper to convert a vec to an array, and fail with an encoding error when needed
547pub fn bytes_fixed_from_vec<const N: usize>(value: &[u8]) -> Result<[u8; N], EncodingError> {
548    <[u8; N]>::try_from(value).map_err(|e| {
549        EncodingError::invalid_data(&format!(
550            "Could not covert slice with length [{}] to array of length [{}]. Error: [{e}]",
551            value.len(),
552            N
553        ))
554    })
555}
556
557fn encoded_size_str(value: &str) -> Result<usize, EncodingError> {
558    Ok(encoded_size_usize(value.len()) + value.len())
559}
560
561/// The number of bytes required to encode this number. Note this is always variable width.
562pub fn encoded_size_usize(val: usize) -> usize {
563    if val < U16_SIGNIFIER.into() {
564        1
565    } else if val <= 0xffff {
566        3
567    } else if val <= 0xffffffff {
568        5
569    } else {
570        9
571    }
572}
573
574/// The number of bytes required to encode this number.
575/// We only need this for u64 because all other uints can be converted to usize reliably.
576pub fn encoded_size_var_u64(val: u64) -> usize {
577    if val < U16_SIGNIFIER.into() {
578        1
579    } else if val <= 0xffff {
580        3
581    } else if val <= 0xffffffff {
582        5
583    } else {
584        9
585    }
586}
587
588/// Write `uint` to the start of `buffer` and return the remaining part of `buffer`.
589pub fn encode_var_u64(uint: u64, buffer: &mut [u8]) -> Result<&mut [u8], EncodingError> {
590    if uint < U16_SIGNIFIER.into() {
591        encode_u8(uint as u8, buffer)
592    } else if uint <= 0xffff {
593        let rest = write_array(&[U16_SIGNIFIER], buffer)?;
594        encode_u16(uint as u16, rest)
595    } else if uint <= 0xffffffff {
596        let rest = write_array(&[U32_SIGNIFIER], buffer)?;
597        encode_u32(uint as u32, rest)
598    } else {
599        let rest = write_array(&[U64_SIGNIFIER], buffer)?;
600        encode_u64(uint, rest)
601    }
602}
603
604/// Decode a `usize` from `buffer` and return the remaining bytes.
605/// This will fail, when we are decoding a `usize` on a usize = u32 machine for data that was originally encoded on a `usize = u64` machine whenever the value is over `u32::MAX`.
606pub fn decode_usize(buffer: &[u8]) -> Result<(usize, &[u8]), EncodingError> {
607    let ([first], rest) = take_array::<1>(buffer)?;
608    Ok(match first {
609        x if x < U16_SIGNIFIER => (x.into(), rest),
610        U16_SIGNIFIER => map_first!(decode_u16(rest)?, |x: u16| Ok(x.into())),
611        U32_SIGNIFIER => {
612            map_first!(decode_u32(rest)?, |val| usize::try_from(val).map_err(
613                |_| EncodingError::overflow("Could not convert u32 to usize")
614            ))
615        }
616        _ => {
617            map_first!(decode_u64(rest)?, |val| usize::try_from(val).map_err(
618                |_| EncodingError::overflow("Could not convert u64 to usize")
619            ))
620        }
621    })
622}
623
624/// Encoded a fixed sized array to a buffer, return the remainder of the buffer.
625/// Errors when `value.len() > buffer.len()`;
626/// ```
627/// # use compact_encoding::encode_bytes_fixed;
628/// let mut buffer = vec![0; 3];
629/// let rest = encode_bytes_fixed(&[4, 2], &mut buffer)?;
630/// assert_eq!(rest, &[0]);
631/// assert_eq!(buffer, &[4, 2, 0]);
632/// # Ok::<(), Box<dyn std::error::Error>>(())
633/// ```
634pub fn encode_bytes_fixed<'a, const N: usize>(
635    value: &[u8; N],
636    buffer: &'a mut [u8],
637) -> Result<&'a mut [u8], EncodingError> {
638    write_array(value, buffer)
639}
640
641/// Decode a fixed sized array from a buffer. Return the array and the remainder of the buffer.
642/// Errors when `buffer.len() < N`;
643/// ```
644/// # use compact_encoding::decode_bytes_fixed;
645/// let mut buffer = vec![1, 2, 3];
646/// let (arr, rest) = decode_bytes_fixed::<2>(&mut buffer)?;
647/// assert_eq!(arr, [1, 2]);
648/// assert_eq!(rest, &[3]);
649/// # Ok::<(), Box<dyn std::error::Error>>(())
650/// ```
651pub fn decode_bytes_fixed<const N: usize>(
652    buffer: &[u8],
653) -> Result<([u8; N], &[u8]), EncodingError> {
654    take_array(buffer)
655    //write_array(value, buffer)
656}
657
658fn decode_u16(buffer: &[u8]) -> Result<(u16, &[u8]), EncodingError> {
659    let (data, rest) = take_array::<2>(buffer)?;
660    Ok((u16::from_le_bytes(data), rest))
661}
662fn decode_u32(buffer: &[u8]) -> Result<(u32, &[u8]), EncodingError> {
663    let (data, rest) = take_array::<4>(buffer)?;
664    Ok((u32::from_le_bytes(data), rest))
665}
666fn decode_u64(buffer: &[u8]) -> Result<(u64, &[u8]), EncodingError> {
667    let (data, rest) = take_array::<8>(buffer)?;
668    Ok((u64::from_le_bytes(data), rest))
669}
670
671fn decode_u32_var(buffer: &[u8]) -> Result<(u32, &[u8]), EncodingError> {
672    let ([first], rest) = take_array::<1>(buffer)?;
673    Ok(match first {
674        x if x < U16_SIGNIFIER => (x.into(), rest),
675        U16_SIGNIFIER => {
676            let (val, rest) = decode_u16(rest)?;
677            (val.into(), rest)
678        }
679        _ => decode_u32(rest)?,
680    })
681}
682
683fn decode_u64_var(buffer: &[u8]) -> Result<(u64, &[u8]), EncodingError> {
684    let ([first], rest) = take_array::<1>(buffer)?;
685    Ok(match first {
686        x if x < U16_SIGNIFIER => (x.into(), rest),
687        U16_SIGNIFIER => map_first!(decode_u16(rest)?, |x: u16| Ok(x.into())),
688        U32_SIGNIFIER => map_first!(decode_u32(rest)?, |x: u32| Ok(x.into())),
689        _ => decode_u64(rest)?,
690    })
691}
692
693fn decode_buffer_vec(buffer: &[u8]) -> Result<(Vec<u8>, &[u8]), EncodingError> {
694    let (n_bytes, rest) = decode_usize(buffer)?;
695    let (out, rest) = get_slices_checked(rest, n_bytes)?;
696    Ok((out.to_vec(), rest))
697}
698
699fn decode_string(buffer: &[u8]) -> Result<(String, &[u8]), EncodingError> {
700    let (len, rest) = decode_usize(buffer)?;
701    let (str_buff, rest) = get_slices_checked(rest, len)?;
702    let out = String::from_utf8(str_buff.to_vec())
703        .map_err(|e| EncodingError::invalid_data(&format!("String is invalid UTF-8, {e}")))?;
704    Ok((out, rest))
705}
706
707fn encode_u8(val: u8, buffer: &mut [u8]) -> Result<&mut [u8], EncodingError> {
708    write_array(&val.to_le_bytes(), buffer)
709}
710fn encode_u16(val: u16, buffer: &mut [u8]) -> Result<&mut [u8], EncodingError> {
711    write_array(&val.to_le_bytes(), buffer)
712}
713fn encode_u32(val: u32, buffer: &mut [u8]) -> Result<&mut [u8], EncodingError> {
714    write_array(&val.to_le_bytes(), buffer)
715}
716fn encode_u64(val: u64, buffer: &mut [u8]) -> Result<&mut [u8], EncodingError> {
717    write_array(&val.to_le_bytes(), buffer)
718}
719
720fn encode_usize_var<'a>(
721    value: &usize,
722    buffer: &'a mut [u8],
723) -> Result<&'a mut [u8], EncodingError> {
724    if *value < U16_SIGNIFIER.into() {
725        encode_u8(*value as u8, buffer)
726    } else if *value <= 0xffff {
727        encode_u16(*value as u16, write_array(&[U16_SIGNIFIER], buffer)?)
728    } else if *value <= 0xffffffff {
729        let value = u32::try_from(*value).map_err(|e| {
730            EncodingError::overflow(&format!(
731                "count not covert usize [{value}] to u32. Error: [{e}]"
732            ))
733        })?;
734        encode_u32(value, write_array(&[U32_SIGNIFIER], buffer)?)
735    } else {
736        let value = u64::try_from(*value).map_err(|e| {
737            EncodingError::overflow(&format!(
738                "count not covert usize [{value}] to u64. Error: [{e}]"
739            ))
740        })?;
741        encode_u64(value, write_array(&[U64_SIGNIFIER], buffer)?)
742    }
743}
744
745fn encode_str<'a>(value: &str, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
746    let rest = encode_usize_var(&value.len(), buffer)?;
747    write_slice(value.as_bytes(), rest)
748}
749
750fn encode_buffer<'a>(value: &[u8], buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
751    let rest = encode_usize_var(&value.len(), buffer)?;
752    write_slice(value, rest)
753}
754
755impl<const N: usize> CompactEncoding for [u8; N] {
756    fn encoded_size(&self) -> Result<usize, EncodingError> {
757        Ok(N)
758    }
759
760    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
761        write_array(self, buffer)
762    }
763
764    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
765    where
766        Self: Sized,
767    {
768        take_array(buffer)
769    }
770}
771
772impl CompactEncoding for u8 {
773    fn encoded_size(&self) -> Result<usize, EncodingError> {
774        Ok(1)
775    }
776
777    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
778        write_array(&[*self], buffer)
779    }
780
781    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
782    where
783        Self: Sized,
784    {
785        let ([out], rest) = take_array::<1>(buffer)?;
786        Ok((out, rest))
787    }
788}
789
790impl CompactEncoding for u16 {
791    fn encoded_size(&self) -> Result<usize, EncodingError> {
792        Ok(U16_SIZE)
793    }
794
795    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
796        encode_u16(*self, buffer)
797    }
798
799    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
800    where
801        Self: Sized,
802    {
803        decode_u16(buffer)
804    }
805}
806
807// NB: we want u32 encoded and decoded as variable sized uint
808impl CompactEncoding for u32 {
809    fn encoded_size(&self) -> Result<usize, EncodingError> {
810        Ok(encoded_size_usize(*self as usize))
811    }
812
813    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
814        encode_usize_var(&(*self as usize), buffer)
815    }
816
817    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
818    where
819        Self: Sized,
820    {
821        decode_u32_var(buffer)
822    }
823}
824impl CompactEncoding for u64 {
825    fn encoded_size(&self) -> Result<usize, EncodingError> {
826        Ok(encoded_size_var_u64(*self))
827    }
828
829    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
830        encode_var_u64(*self, buffer)
831    }
832
833    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
834    where
835        Self: Sized,
836    {
837        decode_u64_var(buffer)
838    }
839}
840
841impl CompactEncoding for String {
842    fn encoded_size(&self) -> Result<usize, EncodingError> {
843        encoded_size_str(self)
844    }
845
846    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
847        encode_str(self, buffer)
848    }
849
850    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
851    where
852        Self: Sized,
853    {
854        decode_string(buffer)
855    }
856}
857
858impl CompactEncoding<String> for str {
859    fn encoded_size(&self) -> Result<usize, EncodingError> {
860        encoded_size_str(self)
861    }
862
863    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
864        encode_str(self, buffer)
865    }
866
867    fn decode(buffer: &[u8]) -> Result<(String, &[u8]), EncodingError> {
868        decode_string(buffer)
869    }
870}
871
872impl CompactEncoding for Vec<String> {
873    fn encoded_size(&self) -> Result<usize, EncodingError> {
874        let mut out = encoded_size_usize(self.len());
875        for s in self {
876            out += s.encoded_size()?;
877        }
878        Ok(out)
879    }
880
881    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
882        let mut rest = encode_usize_var(&self.len(), buffer)?;
883        for s in self {
884            rest = s.encode(rest)?;
885        }
886        Ok(rest)
887    }
888
889    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
890    where
891        Self: Sized,
892    {
893        let (len, mut rest) = decode_usize(buffer)?;
894        let mut out = Vec::with_capacity(len);
895        for _ in 0..len {
896            let result = String::decode(rest)?;
897            out.push(result.0);
898            rest = result.1;
899        }
900        Ok((out, rest))
901    }
902}
903
904impl CompactEncoding for Vec<u8> {
905    fn encoded_size(&self) -> Result<usize, EncodingError> {
906        Ok(encoded_size_usize(self.len()) + self.len())
907    }
908
909    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
910        encode_buffer(self, buffer)
911    }
912
913    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
914    where
915        Self: Sized,
916    {
917        decode_buffer_vec(buffer)
918    }
919}
920
921impl CompactEncoding for Ipv4Addr {
922    fn encoded_size(&self) -> std::result::Result<usize, EncodingError> {
923        Ok(U32_SIZE)
924    }
925
926    fn encode<'a>(&self, buffer: &'a mut [u8]) -> std::result::Result<&'a mut [u8], EncodingError> {
927        let Some((dest, rest)) = buffer.split_first_chunk_mut::<4>() else {
928            return Err(EncodingError::out_of_bounds(&format!(
929                "Colud not encode {}, not enough room in buffer",
930                type_name::<Self>()
931            )));
932        };
933        dest.copy_from_slice(&self.octets());
934        Ok(rest)
935    }
936
937    fn decode(buffer: &[u8]) -> std::result::Result<(Self, &[u8]), EncodingError>
938    where
939        Self: Sized,
940    {
941        let Some((dest, rest)) = buffer.split_first_chunk::<4>() else {
942            return Err(EncodingError::out_of_bounds(&format!(
943                "Colud not decode {}, buffer not big enough",
944                type_name::<Self>()
945            )));
946        };
947        Ok((Ipv4Addr::from(*dest), rest))
948    }
949}
950impl CompactEncoding for Ipv6Addr {
951    fn encoded_size(&self) -> std::result::Result<usize, EncodingError> {
952        Ok(4)
953    }
954
955    fn encode<'a>(&self, buffer: &'a mut [u8]) -> std::result::Result<&'a mut [u8], EncodingError> {
956        let Some((dest, rest)) = buffer.split_first_chunk_mut::<16>() else {
957            return Err(EncodingError::out_of_bounds(&format!(
958                "Colud not encode {}, not enough room in buffer",
959                type_name::<Self>()
960            )));
961        };
962        dest.copy_from_slice(&self.octets());
963        Ok(rest)
964    }
965
966    fn decode(buffer: &[u8]) -> std::result::Result<(Self, &[u8]), EncodingError>
967    where
968        Self: Sized,
969    {
970        let Some((dest, rest)) = buffer.split_first_chunk::<16>() else {
971            return Err(EncodingError::out_of_bounds(&format!(
972                "Colud not decode {}, buffer not big enough",
973                type_name::<Self>()
974            )));
975        };
976        Ok((Ipv6Addr::from(*dest), rest))
977    }
978}
979
980fn encode_vec<'a, T: CompactEncoding + Sized>(
981    vec: &[T],
982    buffer: &'a mut [u8],
983) -> Result<&'a mut [u8], EncodingError> {
984    let mut rest = encode_usize_var(&vec.len(), buffer)?;
985    for x in vec {
986        rest = <T as CompactEncoding>::encode(x, rest)?;
987    }
988    Ok(rest)
989}
990
991fn decode_vec<T: CompactEncoding + Sized>(buffer: &[u8]) -> Result<(Vec<T>, &[u8]), EncodingError> {
992    let (len, mut rest) = decode_usize(buffer)?;
993    let mut out = Vec::with_capacity(len);
994    for _ in 0..len {
995        let res = <T as CompactEncoding>::decode(rest)?;
996        out.push(res.0);
997        rest = res.1;
998    }
999    Ok((out, rest))
1000}
1001
1002impl<T: VecEncodable> CompactEncoding for Vec<T> {
1003    fn encoded_size(&self) -> Result<usize, EncodingError> {
1004        T::vec_encoded_size(self)
1005    }
1006
1007    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
1008        <T as VecEncodable>::vec_encode(self, buffer)
1009    }
1010
1011    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
1012    where
1013        Self: Sized,
1014    {
1015        <T as VecEncodable>::vec_decode(buffer)
1016    }
1017}
1018
1019impl VecEncodable for u32 {
1020    fn vec_encoded_size(vec: &[Self]) -> Result<usize, EncodingError>
1021    where
1022        Self: Sized,
1023    {
1024        Ok(encoded_size_usize(vec.len()) + (vec.len() * 4))
1025    }
1026    /// Encode `vec` to `buffer`
1027    fn vec_encode<'a>(vec: &[Self], buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError>
1028    where
1029        Self: Sized,
1030    {
1031        let mut rest = encode_usize_var(&vec.len(), buffer)?;
1032        for x in vec {
1033            rest = encode_u32(*x, rest)?;
1034        }
1035        Ok(rest)
1036    }
1037
1038    /// Decode [`Vec<Self>`] from buffer
1039    fn vec_decode(buffer: &[u8]) -> Result<(Vec<Self>, &[u8]), EncodingError>
1040    where
1041        Self: Sized,
1042    {
1043        let (len, mut rest) = decode_usize(buffer)?;
1044        let mut out = Vec::with_capacity(len);
1045
1046        for _ in 0..len {
1047            let result = decode_u32(rest)?;
1048            out.push(result.0);
1049            rest = result.1;
1050        }
1051        Ok((out, rest))
1052    }
1053}
1054
1055impl<const N: usize> VecEncodable for [u8; N] {
1056    fn vec_encoded_size(vec: &[Self]) -> Result<usize, EncodingError>
1057    where
1058        Self: Sized,
1059    {
1060        Ok(encoded_size_usize(vec.len()) + (vec.len() * N))
1061    }
1062}
1063
1064impl BoxedSliceEncodable for u8 {
1065    fn boxed_slice_encoded_size(boxed: &Box<[Self]>) -> Result<usize, EncodingError>
1066    where
1067        Self: Sized,
1068    {
1069        Ok(encoded_size_usize(boxed.len()) + boxed.len())
1070    }
1071
1072    fn boxed_slice_encode<'a>(
1073        boxed: &Box<[Self]>,
1074        buffer: &'a mut [u8],
1075    ) -> Result<&'a mut [u8], EncodingError>
1076    where
1077        Self: Sized,
1078    {
1079        let rest = encode_usize_var(&boxed.len(), buffer)?;
1080        write_slice(boxed, rest)
1081    }
1082
1083    fn boxed_slice_decode(buffer: &[u8]) -> Result<(Box<[Self]>, &[u8]), EncodingError>
1084    where
1085        Self: Sized,
1086    {
1087        let (len, rest) = decode_usize(buffer)?;
1088        let (out, rest) = get_slices_checked(rest, len)?;
1089        Ok((out.into(), rest))
1090    }
1091}
1092
1093impl<T: BoxedSliceEncodable> CompactEncoding for Box<[T]> {
1094    fn encoded_size(&self) -> Result<usize, EncodingError> {
1095        T::boxed_slice_encoded_size(self)
1096    }
1097
1098    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
1099        <T as BoxedSliceEncodable>::boxed_slice_encode(self, buffer)
1100    }
1101
1102    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
1103    where
1104        Self: Sized,
1105    {
1106        <T as BoxedSliceEncodable>::boxed_slice_decode(buffer)
1107    }
1108}
1109
1110#[cfg(test)]
1111mod test {
1112    use super::*;
1113
1114    #[test]
1115    fn decode_buff_vec() -> Result<(), EncodingError> {
1116        let buf = &[1, 1];
1117        let (a, b) = decode_buffer_vec(buf)?;
1118        assert_eq!(a, &[1]);
1119        assert_eq!(b, &[]);
1120        Ok(())
1121    }
1122    macro_rules! check_usize_var_enc_dec {
1123        ($size:expr, $value:expr) => {
1124            let mut buffer = vec![0; encoded_size_usize($value)];
1125            assert_eq!(buffer.len(), $size);
1126            let remaining = encode_usize_var(&$value, &mut buffer)?;
1127            assert!(remaining.is_empty());
1128            let (result, rest) = decode_usize(&buffer)?;
1129            assert!(rest.is_empty());
1130            assert_eq!(result, $value);
1131        };
1132    }
1133
1134    #[test]
1135    fn usize_var_enc_dec() -> Result<(), EncodingError> {
1136        check_usize_var_enc_dec!(1, 42);
1137        check_usize_var_enc_dec!(1 + 2, 256);
1138        check_usize_var_enc_dec!(1 + 4, 65536);
1139        check_usize_var_enc_dec!(1 + 8, 4294967296);
1140
1141        Ok(())
1142    }
1143}