1use constant_time_eq::constant_time_eq;
2
3#[derive(Copy, Clone)]
7pub(crate) struct Bytes<const N: usize> {
8 pub(crate) bytes: [u8; N],
9 pub(crate) 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 fn len(&self) -> usize {
24 return self.length as usize;
25 }
26
27 #[inline]
28 pub(crate) fn with_length(length: usize) -> Bytes<N> {
29 assert!(N <= u16::MAX as usize && length <= u16::MAX as usize);
30 assert!(length <= N, "length exceeds capacity");
31 return Bytes {
32 bytes: [0u8; N],
33 length: length as u16,
34 };
35 }
36
37 #[inline]
38 pub(crate) fn push(&mut self, byte: u8) {
39 assert!(self.length as usize + 1 <= N);
40 self.bytes[self.length as usize] = byte;
41 self.length += 1;
42 }
43
44 #[inline]
45 pub(crate) fn append(&mut self, data: &[u8]) {
46 assert!(self.length as usize + data.len() <= N);
47 self.bytes[self.length as usize..data.len() + self.length as usize].copy_from_slice(data);
48 self.length += data.len() as u16;
49 }
50}
51
52impl<const N: usize, const L: usize> From<[u8; L]> for Bytes<N> {
53 #[inline]
54 fn from(data: [u8; L]) -> Self {
55 const {
56 assert!(L <= N);
57 }
58
59 let mut bytes = [0u8; N];
60 bytes[..L].copy_from_slice(&data);
61
62 Bytes {
63 bytes,
64 length: L as u16,
65 }
66 }
67}
68
69impl<const N: usize, const L: usize> From<&[u8; L]> for Bytes<N> {
70 #[inline]
71 fn from(data: &[u8; L]) -> Self {
72 const {
73 assert!(L <= N);
74 }
75
76 let mut bytes = [0u8; N];
77 bytes[..L].copy_from_slice(data);
78
79 Bytes {
80 bytes,
81 length: L as u16,
82 }
83 }
84}
85
86impl<const N: usize> PartialEq for Bytes<N> {
87 #[inline]
88 fn eq(&self, other: &Self) -> bool {
89 constant_time_eq(&self, &other)
90 }
91}
92
93impl<const N: usize> Eq for Bytes<N> {}
94
95impl<const N: usize> core::ops::Deref for Bytes<N> {
96 type Target = [u8];
97 fn deref(&self) -> &[u8] {
98 &self.bytes[..self.length as usize]
99 }
100}
101
102impl<const N: usize> AsMut<[u8]> for Bytes<N> {
103 #[inline]
104 fn as_mut(&mut self) -> &mut [u8] {
105 &mut self.bytes[..self.length as usize]
106 }
107}
108
109#[derive(Copy, Clone)]
113#[repr(transparent)]
114pub struct Hash(pub(crate) Bytes<64>);
115
116macro_rules! impl_bytes {
118 ($name:ident($inner:ty)) => {
119 impl $name {
120 #[inline]
121 pub fn len(&self) -> usize {
122 self.0.len()
123 }
124 }
125
126 impl AsRef<[u8]> for $name {
127 #[inline]
128 fn as_ref(&self) -> &[u8] {
129 self.0.as_ref()
130 }
131 }
132
133 impl core::ops::Deref for $name {
134 type Target = [u8];
135 fn deref(&self) -> &[u8] {
136 &self.0
137 }
138 }
139
140 impl AsMut<[u8]> for $name {
141 #[inline]
142 fn as_mut(&mut self) -> &mut [u8] {
143 self.0.as_mut()
144 }
145 }
146
147 impl PartialEq for $name {
148 #[inline]
149 fn eq(&self, other: &Self) -> bool {
150 self.0 == other.0
151 }
152 }
153
154 impl Eq for $name {}
155 };
156}
157
158impl_bytes!(Hash(Bytes<64>));