s2n_codec/encoder/
value.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{
5    encoder::{Encoder, EncoderLenEstimator},
6    i24, i48, u24, u48, DecoderBuffer, DecoderBufferMut,
7};
8use byteorder::{ByteOrder, NetworkEndian};
9use core::mem::size_of;
10
11pub trait EncoderValue: Sized {
12    /// Encodes the value into the encoder
13    fn encode<E: Encoder>(&self, encoder: &mut E);
14
15    /// Encodes the value into the encoder, while potentially mutating the value itself
16    #[inline]
17    fn encode_mut<E: Encoder>(&mut self, encoder: &mut E) {
18        self.encode(encoder)
19    }
20
21    /// Returns the encoding size with no buffer constrains
22    #[inline]
23    fn encoding_size(&self) -> usize {
24        self.encoding_size_for_encoder(&EncoderLenEstimator::new(usize::MAX))
25    }
26
27    /// Returns the encoding size for the given encoder's capacity
28    #[inline]
29    fn encoding_size_for_encoder<E: Encoder>(&self, encoder: &E) -> usize {
30        let mut estimator = EncoderLenEstimator::new(encoder.remaining_capacity());
31        self.encode(&mut estimator);
32        estimator.len()
33    }
34
35    /// Encodes the value into the encoder with a prefix of `Len`
36    #[inline]
37    fn encode_with_len_prefix<Len: TryFrom<usize> + EncoderValue, E: Encoder>(
38        &self,
39        encoder: &mut E,
40    ) where
41        Self: Sized,
42        Len::Error: core::fmt::Debug,
43    {
44        let len = self.encoding_size_for_encoder(encoder);
45        let len: Len = Len::try_from(len).expect("invalid conversion");
46        len.encode(encoder);
47        self.encode(encoder);
48    }
49
50    #[cfg(feature = "alloc")]
51    fn encode_to_vec(&self) -> alloc::vec::Vec<u8> {
52        let len = self.encoding_size();
53        let mut buffer = alloc::vec![0u8; len];
54        self.encode(&mut crate::EncoderBuffer::new(&mut buffer));
55        buffer
56    }
57}
58
59macro_rules! encoder_value_byte {
60    ($ty:ident) => {
61        impl EncoderValue for $ty {
62            #[inline]
63            fn encode<E: Encoder>(&self, encoder: &mut E) {
64                encoder.write_sized(size_of::<Self>(), |buf| {
65                    buf[0] = *self as u8;
66                })
67            }
68
69            #[inline]
70            fn encoding_size(&self) -> usize {
71                size_of::<Self>()
72            }
73
74            #[inline]
75            fn encoding_size_for_encoder<E: Encoder>(&self, _encoder: &E) -> usize {
76                size_of::<Self>()
77            }
78        }
79    };
80}
81
82encoder_value_byte!(u8);
83encoder_value_byte!(i8);
84
85macro_rules! encoder_value_network_endian {
86    ($call:ident, $ty:ty, $size:expr) => {
87        impl EncoderValue for $ty {
88            #[inline]
89            fn encode<E: Encoder>(&self, encoder: &mut E) {
90                encoder.write_sized($size, |buf| {
91                    NetworkEndian::$call(buf, (*self).into());
92                })
93            }
94
95            #[inline]
96            fn encoding_size(&self) -> usize {
97                $size
98            }
99
100            #[inline]
101            fn encoding_size_for_encoder<E: Encoder>(&self, _encoder: &E) -> usize {
102                $size
103            }
104        }
105    };
106}
107
108encoder_value_network_endian!(write_u16, u16, size_of::<Self>());
109encoder_value_network_endian!(write_i16, i16, size_of::<Self>());
110encoder_value_network_endian!(write_u24, u24, 3);
111encoder_value_network_endian!(write_i24, i24, 3);
112encoder_value_network_endian!(write_u32, u32, size_of::<Self>());
113encoder_value_network_endian!(write_i32, i32, size_of::<Self>());
114encoder_value_network_endian!(write_u48, u48, 6);
115encoder_value_network_endian!(write_i48, i48, 6);
116encoder_value_network_endian!(write_u64, u64, size_of::<Self>());
117encoder_value_network_endian!(write_i64, i64, size_of::<Self>());
118encoder_value_network_endian!(write_u128, u128, size_of::<Self>());
119encoder_value_network_endian!(write_i128, i128, size_of::<Self>());
120encoder_value_network_endian!(write_f32, f32, size_of::<Self>());
121encoder_value_network_endian!(write_f64, f64, size_of::<Self>());
122
123macro_rules! encoder_value_slice {
124    ($ty:ty, |$self:ident| $value:expr) => {
125        impl EncoderValue for $ty {
126            #[inline]
127            fn encode<E: Encoder>(&$self, encoder: &mut E) {
128                encoder.write_slice($value)
129            }
130
131            #[inline]
132            fn encoding_size(&self) -> usize {
133                self.len()
134            }
135
136            #[inline]
137            fn encoding_size_for_encoder<E: Encoder>(&self, _encoder: &E) -> usize {
138                self.len()
139            }
140        }
141    };
142}
143
144encoder_value_slice!(&[u8], |self| self);
145encoder_value_slice!(&mut [u8], |self| self);
146encoder_value_slice!(DecoderBuffer<'_>, |self| self.as_less_safe_slice());
147encoder_value_slice!(DecoderBufferMut<'_>, |self| self.as_less_safe_slice());
148
149impl EncoderValue for &'_ [&'_ [u8]] {
150    #[inline]
151    fn encode<E: Encoder>(&self, encoder: &mut E) {
152        for slice in self.iter() {
153            encoder.write_slice(slice)
154        }
155    }
156
157    #[inline]
158    fn encoding_size(&self) -> usize {
159        self.iter().map(|s| s.len()).sum()
160    }
161
162    #[inline]
163    fn encoding_size_for_encoder<E: Encoder>(&self, _encoder: &E) -> usize {
164        self.iter().map(|s| s.len()).sum()
165    }
166}
167
168impl EncoderValue for () {
169    #[inline]
170    fn encode<E: Encoder>(&self, _encoder: &mut E) {}
171
172    #[inline]
173    fn encoding_size(&self) -> usize {
174        0
175    }
176
177    #[inline]
178    fn encoding_size_for_encoder<E: Encoder>(&self, _encoder: &E) -> usize {
179        0
180    }
181}
182
183impl<A: EncoderValue, B: EncoderValue> EncoderValue for (A, B) {
184    #[inline]
185    fn encode<E: Encoder>(&self, encoder: &mut E) {
186        self.0.encode(encoder);
187        self.1.encode(encoder);
188    }
189
190    #[inline]
191    fn encoding_size(&self) -> usize {
192        self.0.encoding_size() + self.1.encoding_size()
193    }
194
195    #[inline]
196    fn encoding_size_for_encoder<E: Encoder>(&self, encoder: &E) -> usize {
197        self.0.encoding_size_for_encoder(encoder) + self.1.encoding_size_for_encoder(encoder)
198    }
199}
200
201impl<T: EncoderValue> EncoderValue for Option<T> {
202    #[inline]
203    fn encode<E: Encoder>(&self, buffer: &mut E) {
204        if let Some(value) = self.as_ref() {
205            value.encode(buffer);
206        }
207    }
208
209    #[inline]
210    fn encode_mut<E: Encoder>(&mut self, buffer: &mut E) {
211        if let Some(value) = self.as_mut() {
212            value.encode_mut(buffer);
213        }
214    }
215}
216
217#[cfg(feature = "bytes")]
218impl EncoderValue for bytes::Bytes {
219    #[inline]
220    fn encode<E: Encoder>(&self, encoder: &mut E) {
221        if E::SPECIALIZES_BYTES {
222            encoder.write_bytes(self.clone())
223        } else {
224            encoder.write_slice(self)
225        }
226    }
227
228    #[inline]
229    fn encoding_size(&self) -> usize {
230        self.len()
231    }
232
233    #[inline]
234    fn encoding_size_for_encoder<E: Encoder>(&self, _encoder: &E) -> usize {
235        self.len()
236    }
237}
238
239#[cfg(feature = "bytes")]
240impl EncoderValue for &bytes::Bytes {
241    #[inline]
242    fn encode<E: Encoder>(&self, encoder: &mut E) {
243        if E::SPECIALIZES_BYTES {
244            encoder.write_bytes((*self).clone())
245        } else {
246            encoder.write_slice(self)
247        }
248    }
249
250    #[inline]
251    fn encoding_size(&self) -> usize {
252        self.len()
253    }
254
255    #[inline]
256    fn encoding_size_for_encoder<E: Encoder>(&self, _encoder: &E) -> usize {
257        self.len()
258    }
259}
260
261#[cfg(test)]
262mod tests {
263
264    use super::*;
265
266    #[test]
267    #[cfg_attr(kani, kani::proof)]
268    fn u8_encoding_size() {
269        bolero::check!()
270            .with_type()
271            .cloned()
272            .for_each(|callee: u8| Some(callee.encoding_size()));
273    }
274
275    #[test]
276    #[cfg_attr(kani, kani::proof)]
277    fn i8_encoding_size() {
278        bolero::check!()
279            .with_type()
280            .cloned()
281            .for_each(|callee: i8| Some(callee.encoding_size()));
282    }
283
284    #[test]
285    #[cfg_attr(kani, kani::proof)]
286    fn u16_encoding_size() {
287        bolero::check!()
288            .with_type()
289            .cloned()
290            .for_each(|callee: u16| Some(callee.encoding_size()));
291    }
292
293    #[test]
294    #[cfg_attr(kani, kani::proof)]
295    fn i16_encoding_size() {
296        bolero::check!()
297            .with_type()
298            .cloned()
299            .for_each(|callee: i16| Some(callee.encoding_size()));
300    }
301
302    #[test]
303    #[cfg_attr(kani, kani::proof)]
304    fn u24_encoding_size() {
305        bolero::check!()
306            .with_type()
307            .cloned()
308            .for_each(|callee: u24| Some(callee.encoding_size()));
309    }
310
311    #[test]
312    #[cfg_attr(kani, kani::proof)]
313    fn i24_encoding_size() {
314        bolero::check!()
315            .with_type()
316            .cloned()
317            .for_each(|callee: i24| Some(callee.encoding_size()));
318    }
319
320    #[test]
321    #[cfg_attr(kani, kani::proof)]
322    fn u32_encoding_size() {
323        bolero::check!()
324            .with_type()
325            .cloned()
326            .for_each(|callee: u32| Some(callee.encoding_size()));
327    }
328
329    #[test]
330    #[cfg_attr(kani, kani::proof)]
331    fn i32_encoding_size() {
332        bolero::check!()
333            .with_type()
334            .cloned()
335            .for_each(|callee: i32| Some(callee.encoding_size()));
336    }
337
338    #[test]
339    #[cfg_attr(kani, kani::proof)]
340    fn u48_encoding_size() {
341        bolero::check!()
342            .with_type()
343            .cloned()
344            .for_each(|callee: u48| Some(callee.encoding_size()));
345    }
346
347    #[test]
348    #[cfg_attr(kani, kani::proof)]
349    fn i48_encoding_size() {
350        bolero::check!()
351            .with_type()
352            .cloned()
353            .for_each(|callee: i48| Some(callee.encoding_size()));
354    }
355
356    #[test]
357    #[cfg_attr(kani, kani::proof)]
358    fn u64_encoding_size() {
359        bolero::check!()
360            .with_type()
361            .cloned()
362            .for_each(|callee: u64| Some(callee.encoding_size()));
363    }
364
365    #[test]
366    #[cfg_attr(kani, kani::proof)]
367    fn i64_encoding_size() {
368        bolero::check!()
369            .with_type()
370            .cloned()
371            .for_each(|callee: i64| Some(callee.encoding_size()));
372    }
373
374    #[test]
375    #[cfg_attr(kani, kani::proof)]
376    fn u128_encoding_size() {
377        bolero::check!()
378            .with_type()
379            .cloned()
380            .for_each(|callee: u128| Some(callee.encoding_size()));
381    }
382
383    #[test]
384    #[cfg_attr(kani, kani::proof)]
385    fn i128_encoding_size() {
386        bolero::check!()
387            .with_type()
388            .cloned()
389            .for_each(|callee: i128| Some(callee.encoding_size()));
390    }
391
392    #[test]
393    #[cfg_attr(kani, kani::proof)]
394    fn f32_encoding_size() {
395        bolero::check!()
396            .with_type()
397            .cloned()
398            .for_each(|callee: f32| Some(callee.encoding_size()));
399    }
400
401    #[test]
402    #[cfg_attr(kani, kani::proof)]
403    fn f64_encoding_size() {
404        bolero::check!()
405            .with_type()
406            .cloned()
407            .for_each(|callee: f64| Some(callee.encoding_size()));
408    }
409
410    #[test]
411    #[cfg_attr(kani, kani::proof)]
412    fn empty_encoding_size() {
413        bolero::check!()
414            .with_type()
415            .cloned()
416            .for_each(|callee: ()| Some(callee.encoding_size()));
417    }
418}