aws_kms_tls_auth/
codec.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4//! The `codec` module contains traits that are used for serializing and deserializing
5//! various structs.
6//!
7//! ### Compare To
8//! [`s2n_codec`](https://crates.io/crates/s2n-codec) provides much richer functionality,
9//! but that richer functionality comes at the cost of generic lifetimes, non-std
10//! structs, and more generics. For example, s2n-codec requires a specialized
11//! `DecoderBuffer<'a>`, but this codec module just uses a plain byte slice `&[u8]`.
12//!
13//! [`binary_serde`](https://crates.io/crates/binary_serde) doesn't support dynamically
14//! sized types like `Vec<T>`, which makes it a no-go for TLS use cases, because
15//! TLS is _filled_ with lists of items.
16//!
17//! ### Future Development
18//! Ideally all of the codec stuff would be moved to a different crate, and we'd
19//! have proc macros to derive the `EncodeValue` and `DecodeValue` traits.
20
21use byteorder::{BigEndian, ReadBytesExt};
22use std::io::{self, ErrorKind, Read, Write};
23
24/// This trait defines a source that values can be decoded from.
25pub trait DecodeByteSource<T: DecodeValue>: Sized {
26    fn decode_value(&self) -> io::Result<(T, Self)>;
27}
28
29/// This trait defines a sink that values can be encoded to. Currently this is
30/// only implemented for `Vec<u8>`.
31///
32/// This is less efficient than relying on buffers, because encode calls might
33/// result in allocations. But the benefit is that it's much more ergonomic.
34pub trait EncodeBytesSink<T: EncodeValue>: Sized {
35    fn encode_value(&mut self, value: &T) -> io::Result<()>;
36}
37
38/// This trait defines a type that can be decoded from bytes.
39pub trait DecodeValue: Sized {
40    fn decode_from(buffer: &[u8]) -> std::io::Result<(Self, &[u8])>;
41
42    /// decode a value from `buffer`, using all of the bytes.
43    ///
44    /// If buffer was not entirely consumed, an error is returned.
45    fn decode_from_exact(buffer: &[u8]) -> std::io::Result<Self> {
46        let (value, buffer) = Self::decode_from(buffer)?;
47        if !buffer.is_empty() {
48            Err(std::io::Error::new(
49                ErrorKind::InvalidData,
50                "unexpected data left over",
51            ))
52        } else {
53            Ok(value)
54        }
55    }
56}
57
58/// This trait defines a type that can be encoded into bytes.
59pub trait EncodeValue: Sized {
60    fn encode_to(&self, buffer: &mut Vec<u8>) -> std::io::Result<()>;
61
62    fn encode_to_vec(&self) -> std::io::Result<Vec<u8>> {
63        let mut buffer = Vec::new();
64        self.encode_to(&mut buffer)?;
65        Ok(buffer)
66    }
67}
68
69//////////////////////////// Source + Sink Impls ///////////////////////////////
70
71impl<T: DecodeValue> DecodeByteSource<T> for &[u8] {
72    fn decode_value(&self) -> io::Result<(T, Self)> {
73        T::decode_from(self)
74    }
75}
76
77impl<T: EncodeValue> EncodeBytesSink<T> for Vec<u8> {
78    fn encode_value(&mut self, value: &T) -> io::Result<()> {
79        value.encode_to(self)
80    }
81}
82
83//////////////////////////// Primitive Impls ///////////////////////////////////
84
85impl DecodeValue for u8 {
86    fn decode_from(mut buffer: &[u8]) -> std::io::Result<(Self, &[u8])> {
87        let value = buffer.read_u8()?;
88        Ok((value, buffer))
89    }
90}
91
92impl DecodeValue for u16 {
93    fn decode_from(mut buffer: &[u8]) -> std::io::Result<(Self, &[u8])> {
94        let value = buffer.read_u16::<BigEndian>()?;
95        Ok((value, buffer))
96    }
97}
98
99impl DecodeValue for u32 {
100    fn decode_from(mut buffer: &[u8]) -> std::io::Result<(Self, &[u8])> {
101        let value = buffer.read_u32::<BigEndian>()?;
102        Ok((value, buffer))
103    }
104}
105
106impl DecodeValue for u64 {
107    fn decode_from(mut buffer: &[u8]) -> std::io::Result<(Self, &[u8])> {
108        let value = buffer.read_u64::<BigEndian>()?;
109        Ok((value, buffer))
110    }
111}
112
113impl EncodeValue for u8 {
114    fn encode_to(&self, buffer: &mut Vec<u8>) -> std::io::Result<()> {
115        buffer.write_all(&[*self])?;
116        Ok(())
117    }
118}
119
120impl EncodeValue for u16 {
121    fn encode_to(&self, buffer: &mut Vec<u8>) -> std::io::Result<()> {
122        buffer.write_all(&self.to_be_bytes())?;
123        Ok(())
124    }
125}
126
127impl EncodeValue for u32 {
128    fn encode_to(&self, buffer: &mut Vec<u8>) -> std::io::Result<()> {
129        buffer.write_all(&self.to_be_bytes())?;
130        Ok(())
131    }
132}
133
134impl EncodeValue for u64 {
135    fn encode_to(&self, buffer: &mut Vec<u8>) -> std::io::Result<()> {
136        buffer.write_all(&self.to_be_bytes())?;
137        Ok(())
138    }
139}
140
141// Implement Decode and Encode for byte arrays
142
143impl<const L: usize> DecodeValue for [u8; L] {
144    fn decode_from(mut buffer: &[u8]) -> std::io::Result<(Self, &[u8])> {
145        let mut value = [0; L];
146        buffer.read_exact(&mut value)?;
147        Ok((value, buffer))
148    }
149}
150
151impl<const L: usize> EncodeValue for [u8; L] {
152    fn encode_to(&self, buffer: &mut Vec<u8>) -> std::io::Result<()> {
153        buffer.write_all(self)?;
154        Ok(())
155    }
156}