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//! # Cross-Language Interoperability
53//!
54//! To support foreign function interface (FFI) use cases, the module includes `CError` and `CVec`
55//! types that represent SV2 data and errors in a format suitable for cross-language compatibility.
56//!
57//! # Build Options
58//!
59//! Supports optional features like `no_std` for environments without standard library support.
60//! Error types are conditionally compiled to work with or without `std`.
61//!
62//! ## Conditional Compilation
63//! - With the `no_std` feature enabled, I/O-related errors use a simplified `IoError`
64//!   representation.
65//! - Standard I/O errors (`std::io::Error`) are used when `no_std` is disabled.
66//!
67//! # FFI Interoperability
68//!
69//! Provides utilities for FFI (Foreign Function Interface) to enable data passing between Rust and
70//! other languages. Includes:
71//! - `CVec`: Represents a byte vector for safe passing between C and Rust.
72//! - `CError`: A C-compatible error type.
73//! - `CVec2`: Manages collections of `CVec` objects across FFI boundaries.
74//!
75//! Facilitates integration of SV2 functionality into cross-language projects.
76
77#![cfg_attr(feature = "no_std", no_std)]
78
79#[cfg(not(feature = "no_std"))]
80use std::io::{Error as E, ErrorKind};
81
82mod codec;
83mod datatypes;
84pub use datatypes::{
85    PubKey, Seq0255, Seq064K, Signature, Str0255, Sv2DataType, Sv2Option, U32AsRef, B016M, B0255,
86    B032, B064K, U24, U256,
87};
88
89pub use crate::codec::{
90    decodable::{Decodable, GetMarker},
91    encodable::{Encodable, EncodableField},
92    Fixed, GetSize, SizeHint,
93};
94
95use alloc::vec::Vec;
96
97/// Converts the provided SV2 data type to a byte vector based on the SV2 encoding format.
98#[allow(clippy::wrong_self_convention)]
99pub fn to_bytes<T: Encodable + GetSize>(src: T) -> Result<Vec<u8>, Error> {
100    let mut result = vec![0_u8; src.get_size()];
101    src.to_bytes(&mut result)?;
102    Ok(result)
103}
104
105/// Encodes the SV2 data type to the provided byte slice.
106#[allow(clippy::wrong_self_convention)]
107pub fn to_writer<T: Encodable>(src: T, dst: &mut [u8]) -> Result<(), Error> {
108    src.to_bytes(dst)?;
109    Ok(())
110}
111
112/// Decodes an SV2-encoded byte slice into the specified data type.
113pub fn from_bytes<'a, T: Decodable<'a>>(data: &'a mut [u8]) -> Result<T, Error> {
114    T::from_bytes(data)
115}
116
117/// Provides an interface and implementation details for decoding complex data structures
118/// from raw bytes or I/O streams. Handles deserialization of nested and primitive data
119/// structures through traits, enums, and helper functions for managing the decoding process.
120///
121/// # Overview
122/// The [`Decodable`] trait serves as the core component, offering methods to define a type's
123/// structure, decode raw byte data, and construct instances from decoded fields. It supports both
124/// in-memory byte slices and I/O streams for flexibility across deserialization use cases.
125///
126/// # Key Concepts and Types
127/// - **[`Decodable`] Trait**: Defines methods to decode types from byte data, process individual
128///   fields, and construct complete types.
129/// - **[`FieldMarker`] and `PrimitiveMarker`**: Enums that represent data types or structures,
130///   guiding the decoding process by defining field structures and types.
131/// - **[`DecodableField`] and `DecodablePrimitive`**: Represent decoded fields as either primitives
132///   or nested structures, forming the building blocks for complex data types.
133///
134/// # Error Handling
135/// Custom error types manage issues during decoding, such as insufficient data or unsupported
136/// types. Errors are surfaced through `Result` types to ensure reliability in data parsing tasks.
137///
138/// # `no_std` Support
139/// Compatible with `no_std` environments through conditional compilation. Omits I/O-dependent
140/// methods like `from_reader` when `no_std` is enabled, ensuring lightweight builds for constrained
141/// environments.
142pub mod decodable {
143    pub use crate::codec::decodable::{Decodable, DecodableField, FieldMarker};
144    //pub use crate::codec::decodable::PrimitiveMarker;
145}
146
147/// Provides an encoding framework for serializing various data types into bytes.
148///
149/// The [`Encodable`] trait is the core of this framework, enabling types to define
150/// how they serialize data into bytes. This is essential for transmitting data
151/// between components or systems in a consistent, byte-oriented format.
152///
153/// ## Overview
154///
155/// Supports a wide variety of data types, including basic types (e.g., integers,
156/// booleans, and byte arrays) and complex structures. Each type’s encoding logic is
157/// encapsulated in enums like [`EncodablePrimitive`] and [`EncodableField`], enabling
158/// structured and hierarchical data serialization.
159///
160/// ### Key Types
161///
162/// - **[`Encodable`]**: Defines methods for converting an object into a byte array or writing it
163///   directly to an output stream. It supports both primitive types and complex structures.
164/// - **[`EncodablePrimitive`]**: Represents basic types that can be serialized directly. Includes
165///   data types like integers, booleans, and byte arrays.
166/// - **[`EncodableField`]**: Extends [`EncodablePrimitive`] to support structured and nested data,
167///   enabling recursive encoding of complex structures.
168///
169/// ### `no_std` Compatibility
170///
171/// When compiled with the `no_std` feature enabled, this module omits the `to_writer` method
172/// to support environments without the standard library. Only buffer-based encoding
173/// (`to_bytes`) is available in this mode.
174///
175/// ## Error Handling
176///
177/// Errors during encoding are handled through the [`Error`] type. Common failure scenarios include
178/// buffer overflows and type-specific serialization errors. Each encoding method returns an
179/// appropriate error if encoding fails, supporting comprehensive error management.
180///
181/// ## Trait Details
182///
183/// ### [`Encodable`]
184/// - **`to_bytes`**: Encodes the instance into a byte slice, returning the number of bytes written
185///   or an error if encoding fails.
186/// - **`to_writer`** (requires `std`): Encodes the instance into any [`Write`] implementor, such as
187///   a file or network stream.
188///
189/// ### Additional Enums and Methods
190///
191/// Includes utility types and methods for calculating sizes, encoding hierarchical data,
192/// and supporting both owned and reference-based data variants.
193///
194/// - **[`EncodablePrimitive`]**: Handles encoding logic for primitive types, addressing
195///   serialization requirements specific to each type.
196/// - **[`EncodableField`]**: Extends encoding to support composite types and structured data,
197///   enabling recursive encoding of nested structures.
198///
199/// ## Summary
200///
201/// Designed for flexibility and extensibility, this module supports a wide range of data
202/// serialization needs through customizable encoding strategies. Implementing the
203/// [`Encodable`] trait for custom types ensures efficient and consistent data serialization
204/// across applications.
205pub mod encodable {
206    pub use crate::codec::encodable::{Encodable, EncodableField, EncodablePrimitive};
207}
208
209#[macro_use]
210extern crate alloc;
211
212/// Error types used within the protocol library to indicate various failure conditions.
213#[derive(Debug, PartialEq, Eq, Clone)]
214pub enum Error {
215    /// Indicates an attempt to read beyond a valid range.
216    OutOfBound,
217
218    /// Raised when a non-binary value is interpreted as a boolean.
219    NotABool(u8),
220
221    /// Occurs when an unexpected size mismatch arises during a write operation, specifying
222    /// expected and actual sizes.
223    WriteError(usize, usize),
224
225    /// Signifies an overflow condition where a `u32` exceeds the maximum allowable `u24` value.
226    U24TooBig(u32),
227
228    /// Reports a size mismatch for a signature, such as when it does not match the expected size.
229    InvalidSignatureSize(usize),
230
231    /// Raised when a `u256` value is invalid, typically due to size discrepancies.
232    InvalidU256(usize),
233
234    /// Indicates an invalid `u24` representation.
235    InvalidU24(u32),
236
237    /// Error indicating that a byte array exceeds the maximum allowed size for `B0255`.
238    InvalidB0255Size(usize),
239
240    /// Error indicating that a byte array exceeds the maximum allowed size for `B064K`.
241    InvalidB064KSize(usize),
242
243    /// Error indicating that a byte array exceeds the maximum allowed size for `B016M`.
244    InvalidB016MSize(usize),
245
246    /// Raised when a sequence size exceeds `0255`.
247    InvalidSeq0255Size(usize),
248
249    /// Error when trying to encode a non-primitive data type.
250    NonPrimitiveTypeCannotBeEncoded,
251
252    /// Generic conversion error related to primitive types.
253    PrimitiveConversionError,
254
255    /// Error occurring during decoding due to conversion issues.
256    DecodableConversionError,
257
258    /// Error triggered when a decoder is used without initialization.
259    UnInitializedDecoder,
260
261    #[cfg(not(feature = "no_std"))]
262    /// Represents I/O-related errors, compatible with `no_std` mode where specific error types may
263    /// vary.
264    IoError(E),
265
266    #[cfg(feature = "no_std")]
267    /// Represents I/O-related errors, compatible with `no_std` mode.
268    IoError,
269
270    /// Raised when an unexpected mismatch occurs during read operations, specifying expected and
271    /// actual read sizes.
272    ReadError(usize, usize),
273
274    /// Used as a marker error for fields that should remain void or empty.
275    VoidFieldMarker,
276
277    /// Signifies a value overflow based on protocol restrictions, containing details about
278    /// fixed/variable size, maximum size allowed, and the offending value details.
279    ValueExceedsMaxSize(bool, usize, usize, usize, Vec<u8>, usize),
280
281    /// Triggered when a sequence type (`Seq0255`, `Seq064K`) exceeds its maximum allowable size.
282    SeqExceedsMaxSize,
283
284    /// Raised when no valid decodable field is provided during decoding.
285    NoDecodableFieldPassed,
286
287    /// Error for protocol-specific invalid values.
288    ValueIsNotAValidProtocol(u8),
289
290    /// Raised when an unsupported or unknown message type is encountered.
291    UnknownMessageType(u8),
292
293    /// Indicates a protocol constraint violation where `Sv2Option` unexpectedly contains multiple
294    /// elements.
295    Sv2OptionHaveMoreThenOneElement(u8),
296}
297
298#[cfg(not(feature = "no_std"))]
299impl From<E> for Error {
300    fn from(v: E) -> Self {
301        match v.kind() {
302            ErrorKind::UnexpectedEof => Error::OutOfBound,
303            _ => Error::IoError(v),
304        }
305    }
306}
307
308/// `CError` is a foreign function interface (FFI)-compatible version of the `Error` enum to
309/// facilitate cross-language compatibility.
310#[repr(C)]
311#[derive(Debug)]
312pub enum CError {
313    /// Indicates an attempt to read beyond a valid range.
314    OutOfBound,
315
316    /// Raised when a non-binary value is interpreted as a boolean.
317    NotABool(u8),
318
319    /// Occurs when an unexpected size mismatch arises during a write operation, specifying
320    /// expected and actual sizes.
321    WriteError(usize, usize),
322
323    /// Signifies an overflow condition where a `u32` exceeds the maximum allowable `u24` value.
324    U24TooBig(u32),
325
326    /// Reports a size mismatch for a signature, such as when it does not match the expected size.
327    InvalidSignatureSize(usize),
328
329    /// Raised when a `u256` value is invalid, typically due to size discrepancies.
330    InvalidU256(usize),
331
332    /// Indicates an invalid `u24` representation.
333    InvalidU24(u32),
334
335    /// Error indicating that a byte array exceeds the maximum allowed size for `B0255`.
336    InvalidB0255Size(usize),
337
338    /// Error indicating that a byte array exceeds the maximum allowed size for `B064K`.
339    InvalidB064KSize(usize),
340
341    /// Error indicating that a byte array exceeds the maximum allowed size for `B016M`.
342    InvalidB016MSize(usize),
343
344    /// Raised when a sequence size exceeds `0255`.
345    InvalidSeq0255Size(usize),
346
347    /// Error when trying to encode a non-primitive data type.
348    NonPrimitiveTypeCannotBeEncoded,
349
350    /// Generic conversion error related to primitive types.
351    PrimitiveConversionError,
352
353    /// Error occurring during decoding due to conversion issues.
354    DecodableConversionError,
355
356    /// Error triggered when a decoder is used without initialization.
357    UnInitializedDecoder,
358
359    #[cfg(not(feature = "no_std"))]
360    /// Represents I/O-related errors, compatible with `no_std` mode where specific error types may
361    /// vary.
362    IoError(E),
363
364    #[cfg(feature = "no_std")]
365    /// Represents I/O-related errors, compatible with `no_std` mode.
366    IoError,
367
368    /// Raised when an unexpected mismatch occurs during read operations, specifying expected and
369    /// actual read sizes.
370    ReadError(usize, usize),
371
372    /// Used as a marker error for fields that should remain void or empty.
373    VoidFieldMarker,
374
375    /// Signifies a value overflow based on protocol restrictions, containing details about
376    /// fixed/variable size, maximum size allowed, and the offending value details.
377    ValueExceedsMaxSize(bool, usize, usize, usize, CVec, usize),
378
379    /// Triggered when a sequence type (`Seq0255`, `Seq064K`) exceeds its maximum allowable size.
380    SeqExceedsMaxSize,
381
382    /// Raised when no valid decodable field is provided during decoding.
383    NoDecodableFieldPassed,
384
385    /// Error for protocol-specific invalid values.
386    ValueIsNotAValidProtocol(u8),
387
388    /// Raised when an unsupported or unknown message type is encountered.
389    UnknownMessageType(u8),
390
391    /// Indicates a protocol constraint violation where `Sv2Option` unexpectedly contains multiple
392    /// elements.
393    Sv2OptionHaveMoreThenOneElement(u8),
394}
395
396impl From<Error> for CError {
397    fn from(e: Error) -> CError {
398        match e {
399            Error::OutOfBound => CError::OutOfBound,
400            Error::NotABool(u) => CError::NotABool(u),
401            Error::WriteError(u1, u2) => CError::WriteError(u1, u2),
402            Error::U24TooBig(u) => CError::U24TooBig(u),
403            Error::InvalidSignatureSize(u) => CError::InvalidSignatureSize(u),
404            Error::InvalidU256(u) => CError::InvalidU256(u),
405            Error::InvalidU24(u) => CError::InvalidU24(u),
406            Error::InvalidB0255Size(u) => CError::InvalidB0255Size(u),
407            Error::InvalidB064KSize(u) => CError::InvalidB064KSize(u),
408            Error::InvalidB016MSize(u) => CError::InvalidB016MSize(u),
409            Error::InvalidSeq0255Size(u) => CError::InvalidSeq0255Size(u),
410            Error::NonPrimitiveTypeCannotBeEncoded => CError::NonPrimitiveTypeCannotBeEncoded,
411            Error::PrimitiveConversionError => CError::PrimitiveConversionError,
412            Error::DecodableConversionError => CError::DecodableConversionError,
413            Error::UnInitializedDecoder => CError::UnInitializedDecoder,
414            #[cfg(not(feature = "no_std"))]
415            Error::IoError(e) => CError::IoError(e),
416            #[cfg(feature = "no_std")]
417            Error::IoError => CError::IoError,
418            Error::ReadError(u1, u2) => CError::ReadError(u1, u2),
419            Error::VoidFieldMarker => CError::VoidFieldMarker,
420            Error::ValueExceedsMaxSize(isfixed, size, headersize, maxsize, bad_value, bad_len) => {
421                let bv1: &[u8] = bad_value.as_ref();
422                let bv: CVec = bv1.into();
423                CError::ValueExceedsMaxSize(isfixed, size, headersize, maxsize, bv, bad_len)
424            }
425            Error::SeqExceedsMaxSize => CError::SeqExceedsMaxSize,
426            Error::NoDecodableFieldPassed => CError::NoDecodableFieldPassed,
427            Error::ValueIsNotAValidProtocol(u) => CError::ValueIsNotAValidProtocol(u),
428            Error::UnknownMessageType(u) => CError::UnknownMessageType(u),
429            Error::Sv2OptionHaveMoreThenOneElement(u) => CError::Sv2OptionHaveMoreThenOneElement(u),
430        }
431    }
432}
433
434impl Drop for CError {
435    fn drop(&mut self) {
436        match self {
437            Self::OutOfBound => (),
438            Self::NotABool(_) => (),
439            Self::WriteError(_, _) => (),
440            Self::U24TooBig(_) => (),
441            Self::InvalidSignatureSize(_) => (),
442            Self::InvalidU256(_) => (),
443            Self::InvalidU24(_) => (),
444            Self::InvalidB0255Size(_) => (),
445            Self::InvalidB064KSize(_) => (),
446            Self::InvalidB016MSize(_) => (),
447            Self::InvalidSeq0255Size(_) => (),
448            Self::NonPrimitiveTypeCannotBeEncoded => (),
449            Self::PrimitiveConversionError => (),
450            Self::DecodableConversionError => (),
451            Self::UnInitializedDecoder => (),
452            #[cfg(not(feature = "no_std"))]
453            Self::IoError(_) => (),
454            #[cfg(feature = "no_std")]
455            Self::IoError => (),
456            Self::ReadError(_, _) => (),
457            Self::VoidFieldMarker => (),
458            Self::ValueExceedsMaxSize(_, _, _, _, cvec, _) => free_vec(cvec),
459            Self::SeqExceedsMaxSize => (),
460            Self::NoDecodableFieldPassed => (),
461            Self::ValueIsNotAValidProtocol(_) => (),
462            Self::UnknownMessageType(_) => (),
463            Self::Sv2OptionHaveMoreThenOneElement(_) => (),
464        };
465    }
466}
467
468/// Vec<u8> is used as the Sv2 type Bytes
469impl GetSize for Vec<u8> {
470    fn get_size(&self) -> usize {
471        self.len()
472    }
473}
474
475// Only needed for implement encodable for Frame never called
476impl From<Vec<u8>> for EncodableField<'_> {
477    fn from(_v: Vec<u8>) -> Self {
478        unreachable!()
479    }
480}
481
482#[cfg(feature = "with_buffer_pool")]
483impl From<buffer_sv2::Slice> for EncodableField<'_> {
484    fn from(_v: buffer_sv2::Slice) -> Self {
485        unreachable!()
486    }
487}
488
489/// A struct to facilitate transferring a `Vec<u8>` across FFI boundaries.
490#[repr(C)]
491#[derive(Debug, Clone, Copy)]
492pub struct CVec {
493    data: *mut u8,
494    len: usize,
495    capacity: usize,
496}
497
498impl CVec {
499    /// Returns a mutable slice of the contained data.
500    ///
501    /// # Safety
502    ///
503    /// The caller must ensure that the data pointed to by `self.data`
504    /// remains valid for the duration of the returned slice.
505    pub fn as_mut_slice(&mut self) -> &mut [u8] {
506        unsafe { core::slice::from_raw_parts_mut(self.data, self.len) }
507    }
508
509    /// Fills a buffer allocated in Rust from C.
510    ///
511    /// # Safety
512    ///
513    /// Constructs a `CVec` without taking ownership of the pointed buffer. If the owner drops the
514    /// buffer, the `CVec` will point to invalid memory.
515    #[allow(clippy::wrong_self_convention)]
516    pub fn as_shared_buffer(v: &mut [u8]) -> Self {
517        let (data, len) = (v.as_mut_ptr(), v.len());
518        Self {
519            data,
520            len,
521            capacity: len,
522        }
523    }
524}
525
526impl From<&[u8]> for CVec {
527    fn from(v: &[u8]) -> Self {
528        let mut buffer: Vec<u8> = vec![0; v.len()];
529        buffer.copy_from_slice(v);
530
531        // Get the length, first, then the pointer (doing it the other way around **currently**
532        // doesn't cause UB, but it may be unsound due to unclear (to me, at least) guarantees of
533        // the std lib)
534        let len = buffer.len();
535        let ptr = buffer.as_mut_ptr();
536        core::mem::forget(buffer);
537
538        CVec {
539            data: ptr,
540            len,
541            capacity: len,
542        }
543    }
544}
545
546/// Creates a `CVec` from a buffer that was allocated in C.
547///
548/// # Safety
549/// The caller must ensure that the buffer is valid and that
550/// the data length does not exceed the allocated size.
551#[no_mangle]
552pub unsafe extern "C" fn cvec_from_buffer(data: *const u8, len: usize) -> CVec {
553    let input = core::slice::from_raw_parts(data, len);
554
555    let mut buffer: Vec<u8> = vec![0; len];
556    buffer.copy_from_slice(input);
557
558    // Get the length, first, then the pointer (doing it the other way around **currently** doesn't
559    // cause UB, but it may be unsound due to unclear (to me, at least) guarantees of the std lib)
560    let len = buffer.len();
561    let ptr = buffer.as_mut_ptr();
562    core::mem::forget(buffer);
563
564    CVec {
565        data: ptr,
566        len,
567        capacity: len,
568    }
569}
570
571/// A struct to manage a collection of `CVec` objects across FFI boundaries.
572#[repr(C)]
573#[derive(Debug, Clone, Copy)]
574pub struct CVec2 {
575    data: *mut CVec,
576    len: usize,
577    capacity: usize,
578}
579
580impl CVec2 {
581    /// `as_mut_slice`: helps to get a mutable slice
582    pub fn as_mut_slice(&mut self) -> &mut [CVec] {
583        unsafe { core::slice::from_raw_parts_mut(self.data, self.len) }
584    }
585}
586impl From<CVec2> for Vec<CVec> {
587    fn from(v: CVec2) -> Self {
588        unsafe { Vec::from_raw_parts(v.data, v.len, v.capacity) }
589    }
590}
591
592/// Frees the underlying memory of a `CVec`.
593pub fn free_vec(buf: &mut CVec) {
594    let _: Vec<u8> = unsafe { Vec::from_raw_parts(buf.data, buf.len, buf.capacity) };
595}
596
597/// Frees the underlying memory of a `CVec2` and all its elements.
598pub fn free_vec_2(buf: &mut CVec2) {
599    let vs: Vec<CVec> = unsafe { Vec::from_raw_parts(buf.data, buf.len, buf.capacity) };
600    for mut s in vs {
601        free_vec(&mut s)
602    }
603}
604
605impl<'a, const A: bool, const B: usize, const C: usize, const D: usize>
606    From<datatypes::Inner<'a, A, B, C, D>> for CVec
607{
608    fn from(v: datatypes::Inner<'a, A, B, C, D>) -> Self {
609        let (ptr, len, cap): (*mut u8, usize, usize) = match v {
610            datatypes::Inner::Ref(inner) => {
611                // Data is copied in a vector that then will be forgetted from the allocator,
612                // cause the owner of the data is going to be dropped by rust
613                let mut inner: Vec<u8> = inner.into();
614
615                // Get the length, first, then the pointer (doing it the other way around
616                // **currently** doesn't cause UB, but it may be unsound due to unclear (to me, at
617                // least) guarantees of the std lib)
618                let len = inner.len();
619                let cap = inner.capacity();
620                let ptr = inner.as_mut_ptr();
621                core::mem::forget(inner);
622
623                (ptr, len, cap)
624            }
625            datatypes::Inner::Owned(mut inner) => {
626                // Get the length, first, then the pointer (doing it the other way around
627                // **currently** doesn't cause UB, but it may be unsound due to unclear (to me, at
628                // least) guarantees of the std lib)
629                let len = inner.len();
630                let cap = inner.capacity();
631                let ptr = inner.as_mut_ptr();
632                core::mem::forget(inner);
633
634                (ptr, len, cap)
635            }
636        };
637        Self {
638            data: ptr,
639            len,
640            capacity: cap,
641        }
642    }
643}
644
645/// Initializes an empty `CVec2`.
646///
647/// # Safety
648/// The caller is responsible for freeing the `CVec2` when it is no longer needed.
649#[no_mangle]
650pub unsafe extern "C" fn init_cvec2() -> CVec2 {
651    let mut buffer = Vec::<CVec>::new();
652
653    // Get the length, first, then the pointer (doing it the other way around **currently** doesn't
654    // cause UB, but it may be unsound due to unclear (to me, at least) guarantees of the std lib)
655    let len = buffer.len();
656    let ptr = buffer.as_mut_ptr();
657    core::mem::forget(buffer);
658
659    CVec2 {
660        data: ptr,
661        len,
662        capacity: len,
663    }
664}
665
666/// Adds a `CVec` to a `CVec2`.
667///
668/// # Safety
669/// The caller must ensure no duplicate `CVec`s are added, as duplicates may
670/// lead to double-free errors when the message is dropped.
671#[no_mangle]
672pub unsafe extern "C" fn cvec2_push(cvec2: &mut CVec2, cvec: CVec) {
673    let mut buffer: Vec<CVec> = Vec::from_raw_parts(cvec2.data, cvec2.len, cvec2.capacity);
674    buffer.push(cvec);
675
676    let len = buffer.len();
677    let ptr = buffer.as_mut_ptr();
678    core::mem::forget(buffer);
679
680    cvec2.data = ptr;
681    cvec2.len = len;
682    cvec2.capacity = len;
683}
684
685impl<'a, T: Into<CVec>> From<Seq0255<'a, T>> for CVec2 {
686    fn from(v: Seq0255<'a, T>) -> Self {
687        let mut v: Vec<CVec> = v.0.into_iter().map(|x| x.into()).collect();
688        // Get the length, first, then the pointer (doing it the other way around **currently**
689        // doesn't cause UB, but it may be unsound due to unclear (to me, at least) guarantees of
690        // the std lib)
691        let len = v.len();
692        let capacity = v.capacity();
693        let data = v.as_mut_ptr();
694        core::mem::forget(v);
695        Self {
696            data,
697            len,
698            capacity,
699        }
700    }
701}
702impl<'a, T: Into<CVec>> From<Seq064K<'a, T>> for CVec2 {
703    fn from(v: Seq064K<'a, T>) -> Self {
704        let mut v: Vec<CVec> = v.0.into_iter().map(|x| x.into()).collect();
705        // Get the length, first, then the pointer (doing it the other way around **currently**
706        // doesn't cause UB, but it may be unsound due to unclear (to me, at least) guarantees of
707        // the std lib)
708        let len = v.len();
709        let capacity = v.capacity();
710        let data = v.as_mut_ptr();
711        core::mem::forget(v);
712        Self {
713            data,
714            len,
715            capacity,
716        }
717    }
718}
719
720/// Exported FFI functions for interoperability with C code for u24
721#[no_mangle]
722pub extern "C" fn _c_export_u24(_a: U24) {}
723/// Exported FFI functions for interoperability with C code for CVec
724#[no_mangle]
725pub extern "C" fn _c_export_cvec(_a: CVec) {}
726/// Exported FFI functions for interoperability with C code for CVec2
727#[no_mangle]
728pub extern "C" fn _c_export_cvec2(_a: CVec2) {}