binary_codec_sv2/codec/
mod.rs

1// Provides traits and utilities for encoding and decoding data at a low level,
2// prioritizing efficiency and memory safety by operating directly on slices rather than
3// relying on `Read` or `Write` streams.
4//
5// ## Overview
6//
7// Optimized for performance, this module directly manipulates byte slices, avoiding
8// the overhead of stream-based I/O. It uses memory-efficient techniques like obtaining
9// pointers to original data instead of copying it. Enums are avoided for decoding, as
10// each message type can be identified by its numeric identifier, streamlining the process.
11//
12// ### Key Components
13//
14// - **Traits**: Defines core traits (`SizeHint`, `GetSize`, `Fixed`, `Variable`) that establish a
15//   consistent interface for encoding and decoding operations.
16// - **Buffer Management**: With the `with_buffer_pool` feature enabled, the `Slice` type from
17//   `buffer_sv2` is included, supporting memory pooling and efficient slice handling for
18//   high-performance buffer management scenarios.
19//
20// ### Traits Overview
21//
22// - **`SizeHint`**: Estimates the size of a decodable type, useful for variable-length data where
23//   the size must be determined dynamically.
24// - **`GetSize`**: Provides the exact size of an encodable type in bytes, crucial for buffer
25//   allocation.
26// - **`Fixed`**: Marks types with a compile-time constant size, simplifying encoding and decoding.
27// - **`Variable`**: For types with dynamic sizes, manages size variability and calculates inner
28//   sizes.
29//
30// ## Build Options
31//
32// - **`no_std` Compatibility**: This module can be compiled without the standard library for
33//   constrained environments. Some methods and traits are conditionally available when `std` is
34//   included.
35// - **`with_buffer_pool`**: When enabled, includes the `Slice` type for managing pooled memory
36//   slices, improving memory handling and efficiency in high-performance scenarios.
37//
38// ## Detailed Trait Descriptions
39//
40// ### `SizeHint`
41// Defines methods to calculate the size of encoded data for types with variable sizes.
42// - **`size_hint`**: Returns the total size of the encoded data for raw data and an offset.
43// - **`size_hint_`**: Returns the size for a specific instance, offering flexibility.
44//
45// ### `GetSize`
46// Provides a `get_size` method that returns the exact size in bytes of an encodable type.
47//
48// ### `Fixed`
49// For types with a fixed size, this trait defines a constant `SIZE`, simplifying work with
50// fixed-size types.
51//
52// ### `Variable`
53// Types with variable sizes implement this trait, providing constants (`HEADER_SIZE`, `MAX_SIZE`)
54// and methods for size management and inner size calculation.
55//
56// ## Summary
57//
58// This module supports efficient, low-level encoding and decoding by operating directly on slices,
59// avoiding excess data copying. It offers capabilities for both fixed and variable-sized data,
60// making it versatile for a wide range of encoding tasks.
61use crate::Error;
62pub mod decodable;
63pub mod encodable;
64mod impls;
65#[cfg(feature = "with_buffer_pool")]
66use buffer_sv2::Slice;
67
68use alloc::vec::Vec;
69
70/// The `SizeHint` trait provides a mechanism to return the encoded bytes size of a decodable type.
71///
72/// It defines two methods for retrieving the size of an encoded message:
73///
74///
75/// These methods are crucial in decoding scenarios where the full size of the message
76/// is not immediately available, helping to determine how many bytes need to be read.
77pub trait SizeHint {
78    /// `size_hint` is a static method that takes the raw data and an offset and returns the total
79    /// size of the encoded message. This is particularly useful for types where the encoded size
80    /// may vary based on the contents of the data, and we need to calculate how much space is
81    /// required for decoding.
82    fn size_hint(data: &[u8], offset: usize) -> Result<usize, Error>;
83    /// `size_hint_` is an instance method that performs the same function but allows the size to be
84    /// be determined with respect to the current instance of the type.
85    fn size_hint_(&self, data: &[u8], offset: usize) -> Result<usize, Error>;
86}
87
88/// [`GetSize`] is a trait defining a single function that  calculates the total size of an
89/// encodable type.
90pub trait GetSize {
91    /// `get_size` returns total size of the type in bytes.
92    fn get_size(&self) -> usize;
93}
94
95#[cfg(feature = "with_buffer_pool")]
96impl GetSize for Slice {
97    fn get_size(&self) -> usize {
98        self.len()
99    }
100}
101/// [`Fixed`] is a trait is defining a single element representing a size of a constant.
102///
103/// This is useful for primitives with a constant fixed size
104///
105/// Types implementing this trait must define the constant `SIZE`, representing the
106/// fixed number of bytes needed to encode or decode the type. This trait is used for
107/// types that have a know size at compile time , such as integers, fixed-size arrays, etc.
108pub trait Fixed {
109    ///the constant `SIZE`, represents the fixed number of bytes needed to encode or decode the
110    /// type.
111    const SIZE: usize;
112}
113
114// Not used and will be removed during refactoring
115#[allow(dead_code)]
116pub trait Variable {
117    const HEADER_SIZE: usize;
118    //const ELEMENT_SIZE: usize;
119    const MAX_SIZE: usize;
120
121    fn inner_size(&self) -> usize;
122
123    // Retrieves the header as a byte vector. This header typically contains information
124    // about the size or type of the data that follows.
125    fn get_header(&self) -> Vec<u8>;
126}
127
128impl<T: Fixed> SizeHint for T {
129    fn size_hint(_data: &[u8], _offset: usize) -> Result<usize, Error> {
130        Ok(Self::SIZE)
131    }
132
133    fn size_hint_(&self, _: &[u8], _offset: usize) -> Result<usize, Error> {
134        Ok(Self::SIZE)
135    }
136}
137
138impl<T: Fixed> GetSize for T {
139    fn get_size(&self) -> usize {
140        Self::SIZE
141    }
142}