binary_codec_sv2/
lib.rs

1//! Defines types, encodings, and conversions between custom datatype and standard Rust type,
2//! providing abstractions for encoding, decoding, and error handling of SV2 data types.
3//!
4//! # Overview
5//!
6//! Enables conversion between various Rust types and SV2-specific data formats for efficient
7//! network communication. Provides utilities to encode and decode data types according to the SV2
8//! specifications.
9//!
10//! ## Type Mappings
11//! The following table illustrates how standard Rust types map to their SV2 counterparts:
12//!
13//! ```txt
14//! bool     <-> BOOL
15//! u8       <-> U8
16//! u16      <-> U16
17//! U24      <-> U24
18//! u32      <-> U32
19//! f32      <-> F32     // Not in the spec, but used
20//! u64      <-> U64     
21//! U256     <-> U256
22//! Str0255  <-> STRO_255
23//! Signature<-> SIGNATURE
24//! B032     <-> B0_32   
25//! B0255    <-> B0_255
26//! B064K    <-> B0_64K
27//! B016M    <-> B0_16M
28//! [u8]     <-> BYTES
29//! Pubkey   <-> PUBKEY
30//! Seq0255  <-> SEQ0_255[T]
31//! Seq064K  <-> SEQ0_64K[T]
32//! ```
33//!
34//! # Encoding & Decoding
35//!
36//! Enables conversion between various Rust types and SV2-specific data formats for efficient
37//! network communication. Provides utilities to encode and decode data types according to the SV2
38//! specifications.
39//!
40//! - **to_bytes**: Encodes an SV2 data type into a byte vector.
41//! - **to_writer**: Encodes an SV2 data type into a byte slice.
42//! - **from_bytes**: Decodes an SV2-encoded byte slice into the specified data type.
43//!
44//! # Error Handling
45//!
46//! Defines an `Error` enum for handling failure conditions during encoding, decoding, and data
47//! manipulation. Common errors include:
48//! - Out-of-bounds accesses
49//! - Size mismatches during encoding/decoding
50//! - Invalid data representations, such as non-boolean values interpreted as booleans.
51//!
52//! # Build Options
53//!
54//! Supports optional features like `no_std` for environments without standard library support.
55//! Error types are conditionally compiled to work with or without `std`.
56//!
57//! ## Conditional Compilation
58//! - With the `no_std` feature enabled, I/O-related errors use a simplified `IoError`
59//!   representation.
60//! - Standard I/O errors (`std::io::Error`) are used when `no_std` is disabled.
61
62#![cfg_attr(feature = "no_std", no_std)]
63
64#[cfg(not(feature = "no_std"))]
65use std::io::{Error as E, ErrorKind};
66
67mod codec;
68mod datatypes;
69pub use datatypes::{
70    PubKey, Seq0255, Seq064K, Signature, Str0255, Sv2DataType, Sv2Option, U32AsRef, B016M, B0255,
71    B032, B064K, U24, U256,
72};
73
74pub use crate::codec::{
75    decodable::{Decodable, GetMarker},
76    encodable::{Encodable, EncodableField},
77    Fixed, GetSize, SizeHint,
78};
79
80use alloc::vec::Vec;
81
82/// Converts the provided SV2 data type to a byte vector based on the SV2 encoding format.
83#[allow(clippy::wrong_self_convention)]
84pub fn to_bytes<T: Encodable + GetSize>(src: T) -> Result<Vec<u8>, Error> {
85    let mut result = vec![0_u8; src.get_size()];
86    src.to_bytes(&mut result)?;
87    Ok(result)
88}
89
90/// Encodes the SV2 data type to the provided byte slice.
91#[allow(clippy::wrong_self_convention)]
92pub fn to_writer<T: Encodable>(src: T, dst: &mut [u8]) -> Result<(), Error> {
93    src.to_bytes(dst)?;
94    Ok(())
95}
96
97/// Decodes an SV2-encoded byte slice into the specified data type.
98pub fn from_bytes<'a, T: Decodable<'a>>(data: &'a mut [u8]) -> Result<T, Error> {
99    T::from_bytes(data)
100}
101
102/// Provides an interface and implementation details for decoding complex data structures
103/// from raw bytes or I/O streams. Handles deserialization of nested and primitive data
104/// structures through traits, enums, and helper functions for managing the decoding process.
105///
106/// # Overview
107/// The [`Decodable`] trait serves as the core component, offering methods to define a type's
108/// structure, decode raw byte data, and construct instances from decoded fields. It supports both
109/// in-memory byte slices and I/O streams for flexibility across deserialization use cases.
110///
111/// # Key Concepts and Types
112/// - **[`Decodable`] Trait**: Defines methods to decode types from byte data, process individual
113///   fields, and construct complete types.
114/// - **[`FieldMarker`] and `PrimitiveMarker`**: Enums that represent data types or structures,
115///   guiding the decoding process by defining field structures and types.
116/// - **[`DecodableField`] and `DecodablePrimitive`**: Represent decoded fields as either primitives
117///   or nested structures, forming the building blocks for complex data types.
118///
119/// # Error Handling
120/// Custom error types manage issues during decoding, such as insufficient data or unsupported
121/// types. Errors are surfaced through `Result` types to ensure reliability in data parsing tasks.
122///
123/// # `no_std` Support
124/// Compatible with `no_std` environments through conditional compilation. Omits I/O-dependent
125/// methods like `from_reader` when `no_std` is enabled, ensuring lightweight builds for constrained
126/// environments.
127pub mod decodable {
128    pub use crate::codec::decodable::{Decodable, DecodableField, FieldMarker};
129    //pub use crate::codec::decodable::PrimitiveMarker;
130}
131
132/// Provides an encoding framework for serializing various data types into bytes.
133///
134/// The [`Encodable`] trait is the core of this framework, enabling types to define
135/// how they serialize data into bytes. This is essential for transmitting data
136/// between components or systems in a consistent, byte-oriented format.
137///
138/// ## Overview
139///
140/// Supports a wide variety of data types, including basic types (e.g., integers,
141/// booleans, and byte arrays) and complex structures. Each type’s encoding logic is
142/// encapsulated in enums like [`EncodablePrimitive`] and [`EncodableField`], enabling
143/// structured and hierarchical data serialization.
144///
145/// ### Key Types
146///
147/// - **[`Encodable`]**: Defines methods for converting an object into a byte array or writing it
148///   directly to an output stream. It supports both primitive types and complex structures.
149/// - **[`EncodablePrimitive`]**: Represents basic types that can be serialized directly. Includes
150///   data types like integers, booleans, and byte arrays.
151/// - **[`EncodableField`]**: Extends [`EncodablePrimitive`] to support structured and nested data,
152///   enabling recursive encoding of complex structures.
153///
154/// ### `no_std` Compatibility
155///
156/// When compiled with the `no_std` feature enabled, this module omits the `to_writer` method
157/// to support environments without the standard library. Only buffer-based encoding
158/// (`to_bytes`) is available in this mode.
159///
160/// ## Error Handling
161///
162/// Errors during encoding are handled through the [`Error`] type. Common failure scenarios include
163/// buffer overflows and type-specific serialization errors. Each encoding method returns an
164/// appropriate error if encoding fails, supporting comprehensive error management.
165///
166/// ## Trait Details
167///
168/// ### [`Encodable`]
169/// - **`to_bytes`**: Encodes the instance into a byte slice, returning the number of bytes written
170///   or an error if encoding fails.
171/// - **`to_writer`** (requires `std`): Encodes the instance into any [`Write`] implementor, such as
172///   a file or network stream.
173///
174/// ### Additional Enums and Methods
175///
176/// Includes utility types and methods for calculating sizes, encoding hierarchical data,
177/// and supporting both owned and reference-based data variants.
178///
179/// - **[`EncodablePrimitive`]**: Handles encoding logic for primitive types, addressing
180///   serialization requirements specific to each type.
181/// - **[`EncodableField`]**: Extends encoding to support composite types and structured data,
182///   enabling recursive encoding of nested structures.
183///
184/// ## Summary
185///
186/// Designed for flexibility and extensibility, this module supports a wide range of data
187/// serialization needs through customizable encoding strategies. Implementing the
188/// [`Encodable`] trait for custom types ensures efficient and consistent data serialization
189/// across applications.
190pub mod encodable {
191    pub use crate::codec::encodable::{Encodable, EncodableField, EncodablePrimitive};
192}
193
194#[macro_use]
195extern crate alloc;
196
197/// Error types used within the protocol library to indicate various failure conditions.
198#[derive(Debug, PartialEq, Eq, Clone)]
199pub enum Error {
200    /// Indicates an attempt to read beyond a valid range.
201    OutOfBound,
202
203    /// Raised when a non-binary value is interpreted as a boolean.
204    NotABool(u8),
205
206    /// Occurs when an unexpected size mismatch arises during a write operation, specifying
207    /// expected and actual sizes.
208    WriteError(usize, usize),
209
210    /// Signifies an overflow condition where a `u32` exceeds the maximum allowable `u24` value.
211    U24TooBig(u32),
212
213    /// Reports a size mismatch for a signature, such as when it does not match the expected size.
214    InvalidSignatureSize(usize),
215
216    /// Raised when a `u256` value is invalid, typically due to size discrepancies.
217    InvalidU256(usize),
218
219    /// Indicates an invalid `u24` representation.
220    InvalidU24(u32),
221
222    /// Error indicating that a byte array exceeds the maximum allowed size for `B0255`.
223    InvalidB0255Size(usize),
224
225    /// Error indicating that a byte array exceeds the maximum allowed size for `B064K`.
226    InvalidB064KSize(usize),
227
228    /// Error indicating that a byte array exceeds the maximum allowed size for `B016M`.
229    InvalidB016MSize(usize),
230
231    /// Raised when a sequence size exceeds `0255`.
232    InvalidSeq0255Size(usize),
233
234    /// Error when trying to encode a non-primitive data type.
235    NonPrimitiveTypeCannotBeEncoded,
236
237    /// Generic conversion error related to primitive types.
238    PrimitiveConversionError,
239
240    /// Error occurring during decoding due to conversion issues.
241    DecodableConversionError,
242
243    /// Error triggered when a decoder is used without initialization.
244    UnInitializedDecoder,
245
246    #[cfg(not(feature = "no_std"))]
247    /// Represents I/O-related errors, compatible with `no_std` mode where specific error types may
248    /// vary.
249    IoError(E),
250
251    #[cfg(feature = "no_std")]
252    /// Represents I/O-related errors, compatible with `no_std` mode.
253    IoError,
254
255    /// Raised when an unexpected mismatch occurs during read operations, specifying expected and
256    /// actual read sizes.
257    ReadError(usize, usize),
258
259    /// Used as a marker error for fields that should remain void or empty.
260    VoidFieldMarker,
261
262    /// Signifies a value overflow based on protocol restrictions, containing details about
263    /// fixed/variable size, maximum size allowed, and the offending value details.
264    ValueExceedsMaxSize(bool, usize, usize, usize, Vec<u8>, usize),
265
266    /// Triggered when a sequence type (`Seq0255`, `Seq064K`) exceeds its maximum allowable size.
267    SeqExceedsMaxSize,
268
269    /// Raised when no valid decodable field is provided during decoding.
270    NoDecodableFieldPassed,
271
272    /// Error for protocol-specific invalid values.
273    ValueIsNotAValidProtocol(u8),
274
275    /// Raised when an unsupported or unknown message type is encountered.
276    UnknownMessageType(u8),
277
278    /// Indicates a protocol constraint violation where `Sv2Option` unexpectedly contains multiple
279    /// elements.
280    Sv2OptionHaveMoreThenOneElement(u8),
281}
282
283#[cfg(not(feature = "no_std"))]
284impl From<E> for Error {
285    fn from(v: E) -> Self {
286        match v.kind() {
287            ErrorKind::UnexpectedEof => Error::OutOfBound,
288            _ => Error::IoError(v),
289        }
290    }
291}
292
293/// Vec<u8> is used as the Sv2 type Bytes
294impl GetSize for Vec<u8> {
295    fn get_size(&self) -> usize {
296        self.len()
297    }
298}
299
300// Only needed for implement encodable for Frame never called
301impl From<Vec<u8>> for EncodableField<'_> {
302    fn from(_v: Vec<u8>) -> Self {
303        unreachable!()
304    }
305}
306
307#[cfg(feature = "with_buffer_pool")]
308impl From<buffer_sv2::Slice> for EncodableField<'_> {
309    fn from(_v: buffer_sv2::Slice) -> Self {
310        unreachable!()
311    }
312}