1#![no_std]
2#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3#![doc = include_str!("../README.md")]
4#![warn(
5 clippy::mod_module_files,
6 clippy::unwrap_used,
7 rust_2018_idioms,
8 unused_lifetimes
9)]
10
11#[macro_use]
28extern crate alloc;
29
30#[cfg(feature = "std")]
31extern crate std;
32
33use alloc::{string::String, vec::Vec};
34use core::fmt::{self, Display};
35#[cfg(feature = "std")]
36use std::io::{Read, Write};
37
38mod arrays;
39mod primitives;
40mod quic_vec;
41mod tls_vec;
42
43pub use tls_vec::{
44 SecretTlsVecU16, SecretTlsVecU24, SecretTlsVecU32, SecretTlsVecU8, TlsByteSliceU16,
45 TlsByteSliceU24, TlsByteSliceU32, TlsByteSliceU8, TlsByteVecU16, TlsByteVecU24, TlsByteVecU32,
46 TlsByteVecU8, TlsSliceU16, TlsSliceU24, TlsSliceU32, TlsSliceU8, TlsVecU16, TlsVecU24,
47 TlsVecU32, TlsVecU8,
48};
49
50#[cfg(feature = "std")]
51pub use quic_vec::{rw as vlen, SecretVLBytes};
52pub use quic_vec::{VLByteSlice, VLBytes};
53
54#[cfg(feature = "derive")]
55pub use tls_codec_derive::{
56 TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSerializeBytes, TlsSize,
57};
58
59#[cfg(feature = "conditional_deserialization")]
60pub use tls_codec_derive::conditionally_deserializable;
61
62#[derive(Debug, Eq, PartialEq, Clone)]
64pub enum Error {
65 EncodingError(String),
67
68 InvalidVectorLength,
70
71 InvalidWriteLength(String),
73
74 InvalidInput,
76
77 DecodingError(String),
79
80 EndOfStream,
82
83 TrailingData,
85
86 UnknownValue(u64),
90
91 LibraryError,
93}
94
95#[cfg(feature = "std")]
96impl std::error::Error for Error {}
97
98impl Display for Error {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 f.write_fmt(format_args!("{self:?}"))
101 }
102}
103
104#[cfg(feature = "std")]
105impl From<std::io::Error> for Error {
106 fn from(e: std::io::Error) -> Self {
107 match e.kind() {
108 std::io::ErrorKind::UnexpectedEof => Self::EndOfStream,
109 _ => Self::DecodingError(format!("io error: {e:?}")),
110 }
111 }
112}
113
114pub trait Size {
119 fn tls_serialized_len(&self) -> usize;
120}
121
122pub trait Serialize: Size {
128 #[cfg(feature = "std")]
131 fn tls_serialize<W: Write>(&self, writer: &mut W) -> Result<usize, Error>;
132
133 #[cfg(feature = "std")]
135 fn tls_serialize_detached(&self) -> Result<Vec<u8>, Error> {
136 let mut buffer = Vec::with_capacity(self.tls_serialized_len());
137 let written = self.tls_serialize(&mut buffer)?;
138 debug_assert_eq!(
139 written,
140 buffer.len(),
141 "Expected that {} bytes were written but the output holds {} bytes",
142 written,
143 buffer.len()
144 );
145 if written != buffer.len() {
146 Err(Error::EncodingError(format!(
147 "Expected that {} bytes were written but the output holds {} bytes",
148 written,
149 buffer.len()
150 )))
151 } else {
152 Ok(buffer)
153 }
154 }
155}
156
157pub trait SerializeBytes: Size {
162 fn tls_serialize(&self) -> Result<Vec<u8>, Error>;
164}
165
166pub trait Deserialize: Size {
169 #[cfg(feature = "std")]
176 fn tls_deserialize<R: Read>(bytes: &mut R) -> Result<Self, Error>
177 where
178 Self: Sized;
179
180 #[cfg(feature = "std")]
186 fn tls_deserialize_exact(bytes: impl AsRef<[u8]>) -> Result<Self, Error>
187 where
188 Self: Sized,
189 {
190 let mut bytes = bytes.as_ref();
191 let out = Self::tls_deserialize(&mut bytes)?;
192
193 if !bytes.is_empty() {
194 return Err(Error::TrailingData);
195 }
196
197 Ok(out)
198 }
199}
200
201pub trait DeserializeBytes: Size {
205 fn tls_deserialize_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), Error>
212 where
213 Self: Sized;
214
215 fn tls_deserialize_exact_bytes(bytes: &[u8]) -> Result<Self, Error>
221 where
222 Self: Sized,
223 {
224 let (out, remainder) = Self::tls_deserialize_bytes(bytes)?;
225
226 if !remainder.is_empty() {
227 return Err(Error::TrailingData);
228 }
229
230 Ok(out)
231 }
232}
233
234#[derive(Copy, Clone, Debug, Default, PartialEq)]
238pub struct U24([u8; 3]);
239
240impl U24 {
241 pub const MAX: Self = Self([255u8; 3]);
242 pub const MIN: Self = Self([0u8; 3]);
243
244 pub fn from_be_bytes(bytes: [u8; 3]) -> Self {
245 U24(bytes)
246 }
247
248 pub fn to_be_bytes(self) -> [u8; 3] {
249 self.0
250 }
251}
252
253impl From<U24> for usize {
254 fn from(value: U24) -> usize {
255 const LEN: usize = core::mem::size_of::<usize>();
256 let mut usize_bytes = [0u8; LEN];
257 usize_bytes[LEN - 3..].copy_from_slice(&value.0);
258 usize::from_be_bytes(usize_bytes)
259 }
260}
261
262impl TryFrom<usize> for U24 {
263 type Error = Error;
264
265 fn try_from(value: usize) -> Result<Self, Self::Error> {
266 const LEN: usize = core::mem::size_of::<usize>();
267 if value > (1 << 24) - 1 {
270 Err(Error::LibraryError)
271 } else {
272 Ok(U24(value.to_be_bytes()[LEN - 3..].try_into()?))
273 }
274 }
275}