mls_rs_codec/
lib.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// Copyright by contributors to this project.
3// SPDX-License-Identifier: (Apache-2.0 OR MIT)
4
5#![cfg_attr(not(feature = "std"), no_std)]
6extern crate alloc;
7
8use alloc::boxed::Box;
9
10pub use alloc::vec::Vec;
11
12mod array;
13
14/// Optimized encoding and decoding for types that can be represented by `Vec<u8>`.
15///
16/// Compatible with derive macros by using `mls_codec(with = "mls_rs_codec::byte_vec")`
17pub mod byte_vec;
18
19pub mod iter;
20
21mod bool;
22mod cow;
23mod map;
24mod option;
25mod stdint;
26mod string;
27mod tuple;
28mod varint;
29mod vec;
30
31pub use varint::*;
32
33pub use mls_rs_codec_derive::*;
34
35#[derive(Debug)]
36#[cfg_attr(feature = "std", derive(thiserror::Error))]
37#[non_exhaustive]
38pub enum Error {
39    #[cfg_attr(feature = "std", error("Integer out of range for VarInt"))]
40    VarIntOutOfRange,
41    #[cfg_attr(feature = "std", error("Invalid varint prefix {0}"))]
42    InvalidVarIntPrefix(u8),
43    #[cfg_attr(feature = "std", error("VarInt does not use the min-length encoding"))]
44    VarIntMinimumLengthEncoding,
45    #[cfg_attr(feature = "std", error("UnexpectedEOF"))]
46    UnexpectedEOF,
47    #[cfg_attr(feature = "std", error("Option marker out of range: {0}"))]
48    OptionOutOfRange(u8),
49    #[cfg_attr(feature = "std", error("Unsupported enum discriminant"))]
50    UnsupportedEnumDiscriminant,
51    #[cfg_attr(feature = "std", error("Expected UTF-8 string"))]
52    Utf8,
53    #[cfg_attr(feature = "std", error("mls codec error: {0}"))]
54    Custom(u8),
55}
56
57/// Trait that determines the encoded length in MLS encoding.
58pub trait MlsSize {
59    fn mls_encoded_len(&self) -> usize;
60}
61
62impl<T> MlsSize for &T
63where
64    T: MlsSize + ?Sized,
65{
66    #[inline]
67    fn mls_encoded_len(&self) -> usize {
68        (*self).mls_encoded_len()
69    }
70}
71
72impl<T> MlsSize for Box<T>
73where
74    T: MlsSize + ?Sized,
75{
76    #[inline]
77    fn mls_encoded_len(&self) -> usize {
78        self.as_ref().mls_encoded_len()
79    }
80}
81
82/// Trait to support serializing a type with MLS encoding.
83pub trait MlsEncode: MlsSize {
84    fn mls_encode(&self, writer: &mut Vec<u8>) -> Result<(), Error>;
85
86    #[inline]
87    fn mls_encode_to_vec(&self) -> Result<Vec<u8>, Error> {
88        #[cfg(feature = "preallocate")]
89        let mut vec = Vec::with_capacity(self.mls_encoded_len());
90
91        #[cfg(not(feature = "preallocate"))]
92        let mut vec = Vec::new();
93
94        self.mls_encode(&mut vec)?;
95
96        Ok(vec)
97    }
98}
99
100impl<T> MlsEncode for &T
101where
102    T: MlsEncode + ?Sized,
103{
104    #[inline]
105    fn mls_encode(&self, writer: &mut Vec<u8>) -> Result<(), Error> {
106        (*self).mls_encode(writer)
107    }
108}
109
110impl<T> MlsEncode for Box<T>
111where
112    T: MlsEncode + ?Sized,
113{
114    #[inline]
115    fn mls_encode(&self, writer: &mut Vec<u8>) -> Result<(), Error> {
116        self.as_ref().mls_encode(writer)
117    }
118}
119
120/// Trait to support deserialzing to a type using MLS encoding.
121pub trait MlsDecode: Sized {
122    fn mls_decode(reader: &mut &[u8]) -> Result<Self, Error>;
123}
124
125impl<T: MlsDecode> MlsDecode for Box<T> {
126    #[inline]
127    fn mls_decode(reader: &mut &[u8]) -> Result<Self, Error> {
128        T::mls_decode(reader).map(Box::new)
129    }
130}