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