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 bool; 22 mod cow; 23 mod map; 24 mod option; 25 mod stdint; 26 mod string; 27 mod tuple; 28 mod varint; 29 mod vec; 30 31 pub use varint::*; 32 33 pub use mls_rs_codec_derive::*; 34 35 #[derive(Debug)] 36 #[cfg_attr(feature = "std", derive(thiserror::Error))] 37 #[non_exhaustive] 38 pub 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. 58 pub trait MlsSize { mls_encoded_len(&self) -> usize59 fn mls_encoded_len(&self) -> usize; 60 } 61 62 impl<T> MlsSize for &T 63 where 64 T: MlsSize + ?Sized, 65 { 66 #[inline] mls_encoded_len(&self) -> usize67 fn mls_encoded_len(&self) -> usize { 68 (*self).mls_encoded_len() 69 } 70 } 71 72 impl<T> MlsSize for Box<T> 73 where 74 T: MlsSize + ?Sized, 75 { 76 #[inline] mls_encoded_len(&self) -> usize77 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. 83 pub trait MlsEncode: MlsSize { mls_encode(&self, writer: &mut Vec<u8>) -> Result<(), Error>84 fn mls_encode(&self, writer: &mut Vec<u8>) -> Result<(), Error>; 85 86 #[inline] mls_encode_to_vec(&self) -> Result<Vec<u8>, Error>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 100 impl<T> MlsEncode for &T 101 where 102 T: MlsEncode + ?Sized, 103 { 104 #[inline] mls_encode(&self, writer: &mut Vec<u8>) -> Result<(), Error>105 fn mls_encode(&self, writer: &mut Vec<u8>) -> Result<(), Error> { 106 (*self).mls_encode(writer) 107 } 108 } 109 110 impl<T> MlsEncode for Box<T> 111 where 112 T: MlsEncode + ?Sized, 113 { 114 #[inline] mls_encode(&self, writer: &mut Vec<u8>) -> Result<(), Error>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. 121 pub trait MlsDecode: Sized { mls_decode(reader: &mut &[u8]) -> Result<Self, Error>122 fn mls_decode(reader: &mut &[u8]) -> Result<Self, Error>; 123 } 124 125 impl<T: MlsDecode> MlsDecode for Box<T> { 126 #[inline] mls_decode(reader: &mut &[u8]) -> Result<Self, Error>127 fn mls_decode(reader: &mut &[u8]) -> Result<Self, Error> { 128 T::mls_decode(reader).map(Box::new) 129 } 130 } 131