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