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) {}