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