1use super::{Array, BlockSizes, Error};
2use core::fmt;
3
4pub struct ReadBuffer<BS: BlockSizes> {
6 buffer: Array<u8, BS>,
10}
11
12impl<BS: BlockSizes> fmt::Debug for ReadBuffer<BS> {
13 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14 f.debug_struct("ReadBuffer")
15 .field("remaining_data", &self.remaining())
16 .finish_non_exhaustive()
17 }
18}
19
20impl<BS: BlockSizes> Default for ReadBuffer<BS> {
21 #[inline]
22 fn default() -> Self {
23 let buffer = Default::default();
24 let mut res = Self { buffer };
25 unsafe { res.set_pos_unchecked(BS::USIZE) };
27 res
28 }
29}
30
31impl<BS: BlockSizes> Clone for ReadBuffer<BS> {
32 #[inline]
33 fn clone(&self) -> Self {
34 let buffer = self.buffer.clone();
35 Self { buffer }
36 }
37}
38
39impl<BS: BlockSizes> ReadBuffer<BS> {
40 #[inline(always)]
42 pub fn get_pos(&self) -> usize {
43 let pos = self.buffer[0];
44 if pos == 0 || pos > BS::U8 {
45 debug_assert!(false);
46 unsafe {
48 core::hint::unreachable_unchecked();
49 }
50 }
51 pos as usize
52 }
53
54 #[inline(always)]
56 pub fn size(&self) -> usize {
57 BS::USIZE
58 }
59
60 #[inline(always)]
62 pub fn remaining(&self) -> usize {
63 self.size() - self.get_pos()
64 }
65
66 #[inline(always)]
71 #[allow(clippy::cast_possible_truncation)]
72 unsafe fn set_pos_unchecked(&mut self, pos: usize) {
73 debug_assert!(pos != 0 && pos <= BS::USIZE);
74 self.buffer[0] = pos as u8;
75 }
76
77 #[inline(always)]
82 pub fn read_cached(&mut self, len: usize) -> &[u8] {
83 let rem = self.remaining();
84 let new_len = core::cmp::min(rem, len);
85 let pos = self.get_pos();
86
87 unsafe { self.set_pos_unchecked(pos + new_len) };
89 &self.buffer[pos..][..new_len]
90 }
91
92 #[inline(always)]
102 pub fn write_block(
103 &mut self,
104 read_len: usize,
105 gen_block: impl FnOnce(&mut Array<u8, BS>),
106 read_fn: impl FnOnce(&[u8]),
107 ) {
108 if read_len == 0 {
109 return;
110 }
111 assert!(read_len < BS::USIZE);
112
113 gen_block(&mut self.buffer);
114 read_fn(&self.buffer[..read_len]);
115
116 unsafe { self.set_pos_unchecked(read_len) };
118 }
119
120 pub fn reset(&mut self) {
122 self.buffer[0] = BS::U8;
123 }
124
125 #[inline]
129 pub fn read(&mut self, buf: &mut [u8], mut gen_block: impl FnMut(&mut Array<u8, BS>)) {
130 let head_ks = self.read_cached(buf.len());
131 let (head, buf) = buf.split_at_mut(head_ks.len());
132 let (blocks, tail) = Array::slice_as_chunks_mut(buf);
133
134 head.copy_from_slice(head_ks);
135 for block in blocks {
136 gen_block(block);
137 }
138
139 self.write_block(tail.len(), gen_block, |tail_ks| {
140 tail.copy_from_slice(tail_ks);
141 });
142 }
143
144 #[inline]
146 pub fn serialize(&self) -> Array<u8, BS> {
147 let pos = self.get_pos();
148 let mut res = self.buffer.clone();
149 for b in &mut res[1..pos] {
151 *b = 0;
152 }
153 res
154 }
155
156 #[inline]
162 pub fn deserialize(buffer: &Array<u8, BS>) -> Result<Self, Error> {
163 let pos = usize::from(buffer[0]);
164 if pos == 0 || pos > BS::USIZE || buffer[1..pos].iter().any(|&b| b != 0) {
165 Err(Error)
166 } else {
167 let buffer = buffer.clone();
168 Ok(Self { buffer })
169 }
170 }
171}
172
173#[cfg(feature = "zeroize")]
174impl<BS: BlockSizes> Drop for ReadBuffer<BS> {
175 fn drop(&mut self) {
176 use zeroize::Zeroize;
177 self.buffer.zeroize();
178 }
179}
180
181#[cfg(feature = "zeroize")]
182impl<BS: BlockSizes> zeroize::ZeroizeOnDrop for ReadBuffer<BS> {}