s2n_codec/encoder/
estimator.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::encoder::Encoder;
5
6/// Estimates the `encoding_size` of an `EncoderValue`
7#[cfg_attr(test, derive(Clone, Debug, bolero::TypeGenerator))]
8pub struct EncoderLenEstimator {
9    capacity: usize,
10    len: usize,
11}
12
13impl EncoderLenEstimator {
14    /// Create a new estimator with a given buffer `capacity`
15    #[inline]
16    pub const fn new(capacity: usize) -> Self {
17        Self { capacity, len: 0 }
18    }
19
20    /// Returns true when the estimated len is greater than
21    /// the allocated buffer capacity.
22    #[inline]
23    pub const fn overflowed(&self) -> bool {
24        self.len > self.capacity
25    }
26}
27
28impl Encoder for EncoderLenEstimator {
29    #[inline]
30    fn write_sized<F: FnOnce(&mut [u8])>(&mut self, len: usize, _write: F) {
31        self.len += len;
32    }
33
34    #[inline]
35    fn write_slice(&mut self, slice: &[u8]) {
36        self.len += slice.len();
37    }
38
39    #[inline]
40    fn write_repeated(&mut self, count: usize, _value: u8) {
41        self.len += count;
42    }
43
44    #[inline]
45    fn write_zerocopy<T: zerocopy::FromBytes + zerocopy::Unaligned, F: FnOnce(&mut T)>(
46        &mut self,
47        _write: F,
48    ) {
49        self.len += core::mem::size_of::<T>();
50    }
51
52    #[inline]
53    fn capacity(&self) -> usize {
54        self.capacity
55    }
56
57    #[inline]
58    fn len(&self) -> usize {
59        self.len
60    }
61}
62
63#[cfg(test)]
64mod tests {
65
66    use super::*;
67
68    #[test]
69    #[cfg_attr(kani, kani::proof)]
70    fn encoder_len_estimator_new() {
71        bolero::check!()
72            .with_type()
73            .cloned()
74            .for_each(|capacity: usize| Some(EncoderLenEstimator::new(capacity)));
75    }
76
77    #[test]
78    #[cfg_attr(kani, kani::proof)]
79    fn encoder_len_estimator_overflowed() {
80        bolero::check!()
81            .with_type()
82            .for_each(|callee: &EncoderLenEstimator| Some(callee.overflowed()));
83    }
84
85    #[test]
86    #[cfg_attr(kani, kani::proof)]
87    fn encoder_len_estimator_write_repeated() {
88        bolero::check!()
89            .with_type()
90            .cloned()
91            .filter(|(callee, count, _): &(EncoderLenEstimator, usize, u8)| {
92                count <= &(usize::MAX - callee.len)
93            })
94            .for_each(
95                |(mut callee, count, value): (EncoderLenEstimator, usize, u8)| {
96                    callee.write_repeated(count, value);
97                    Some(())
98                },
99            );
100    }
101
102    #[test]
103    #[cfg_attr(kani, kani::proof)]
104    fn encoder_len_estimator_capacity() {
105        bolero::check!()
106            .with_type()
107            .for_each(|callee: &EncoderLenEstimator| Some(callee.capacity()));
108    }
109
110    #[test]
111    #[cfg_attr(kani, kani::proof)]
112    fn encoder_len_estimator_len() {
113        bolero::check!()
114            .with_type()
115            .for_each(|callee: &EncoderLenEstimator| Some(callee.len()));
116    }
117}