1use constant_time_eq::constant_time_eq;
2
3#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop))]
7pub struct Bytes<const N: usize> {
8 bytes: [u8; N],
9 length: u16,
10}
11
12impl<const N: usize> Bytes<N> {
13 #[inline]
14 pub(crate) fn new() -> Bytes<N> {
15 assert!(N <= u16::MAX as usize);
16 return Bytes {
17 bytes: [0u8; N],
18 length: 0,
19 };
20 }
21
22 #[inline]
23 pub(crate) fn with_length(length: usize) -> Bytes<N> {
24 assert!(N <= u16::MAX as usize && length <= u16::MAX as usize);
25 assert!(length <= N, "length exceeds capacity");
26 return Bytes {
27 bytes: [0u8; N],
28 length: length as u16,
29 };
30 }
31
32 #[inline]
33 pub fn len(&self) -> usize {
34 return self.length as usize;
35 }
36
37 pub(crate) fn push(&mut self, byte: u8) {
38 assert!(self.length as usize + 1 <= N);
39 self.bytes[self.length as usize] = byte;
40 self.length += 1;
41 }
42
43 pub(crate) fn append(&mut self, data: &[u8]) {
44 assert!(self.length as usize + data.len() <= N);
45 self.bytes[self.length as usize..data.len() + self.length as usize].copy_from_slice(data);
46 self.length += data.len() as u16;
47 }
48}
49
50impl<const N: usize> PartialEq for Bytes<N> {
51 #[inline]
52 fn eq(&self, other: &Self) -> bool {
53 constant_time_eq(self.as_ref(), other.as_ref())
54 }
55}
56
57impl<const N: usize> Eq for Bytes<N> {}
58
59impl<const N: usize> AsRef<[u8]> for Bytes<N> {
60 #[inline]
61 fn as_ref(&self) -> &[u8] {
62 &self.bytes[..self.length as usize]
63 }
64}
65
66impl<const N: usize> AsMut<[u8]> for Bytes<N> {
67 #[inline]
68 fn as_mut(&mut self) -> &mut [u8] {
69 &mut self.bytes[..self.length as usize]
70 }
71}