1use super::{Array, ArraySize, Error};
2use core::fmt;
3
4pub struct ReadBuffer<BS: ArraySize> {
6 buffer: Array<u8, BS>,
10}
11
12impl<BS: ArraySize> 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: ArraySize> Default for ReadBuffer<BS> {
21 #[inline]
22 fn default() -> Self {
23 assert!(
24 BS::USIZE != 0 && BS::USIZE < 256,
25 "buffer block size must be bigger than zero and smaller than 256"
26 );
27
28 let buffer = Default::default();
29 let mut res = Self { buffer };
30 unsafe { res.set_pos_unchecked(BS::USIZE) };
32 res
33 }
34}
35
36impl<BS: ArraySize> Clone for ReadBuffer<BS> {
37 #[inline]
38 fn clone(&self) -> Self {
39 let buffer = self.buffer.clone();
40 Self { buffer }
41 }
42}
43
44impl<BS: ArraySize> ReadBuffer<BS> {
45 #[inline(always)]
47 pub fn get_pos(&self) -> usize {
48 let pos = self.buffer[0];
49 if pos == 0 || pos > BS::U8 {
50 debug_assert!(false);
51 unsafe {
53 core::hint::unreachable_unchecked();
54 }
55 }
56 pos as usize
57 }
58
59 #[inline(always)]
61 pub fn size(&self) -> usize {
62 BS::USIZE
63 }
64
65 #[inline(always)]
67 pub fn remaining(&self) -> usize {
68 self.size() - self.get_pos()
69 }
70
71 #[inline(always)]
76 unsafe fn set_pos_unchecked(&mut self, pos: usize) {
77 debug_assert!(pos != 0 && pos <= BS::USIZE);
78 self.buffer[0] = pos as u8;
79 }
80
81 #[inline(always)]
86 pub fn read_cached(&mut self, len: usize) -> &[u8] {
87 let rem = self.remaining();
88 let new_len = core::cmp::min(rem, len);
89 let pos = self.get_pos();
90
91 unsafe { self.set_pos_unchecked(pos + new_len) };
93 &self.buffer[pos..][..new_len]
94 }
95
96 #[inline(always)]
106 pub fn write_block(
107 &mut self,
108 read_len: usize,
109 gen_block: impl FnOnce(&mut Array<u8, BS>),
110 read_fn: impl FnOnce(&[u8]),
111 ) {
112 if read_len == 0 {
113 return;
114 }
115 assert!(read_len < BS::USIZE);
116
117 gen_block(&mut self.buffer);
118 read_fn(&self.buffer[..read_len]);
119
120 unsafe { self.set_pos_unchecked(read_len) };
122 }
123
124 pub fn reset(&mut self) {
126 self.buffer[0] = BS::U8;
127 }
128
129 #[inline]
133 pub fn read(&mut self, buf: &mut [u8], mut gen_block: impl FnMut(&mut Array<u8, BS>)) {
134 let head_ks = self.read_cached(buf.len());
135 let (head, buf) = buf.split_at_mut(head_ks.len());
136 let (blocks, tail) = Array::slice_as_chunks_mut(buf);
137
138 head.copy_from_slice(head_ks);
139 for block in blocks {
140 gen_block(block);
141 }
142
143 self.write_block(tail.len(), gen_block, |tail_ks| {
144 tail.copy_from_slice(tail_ks)
145 });
146 }
147
148 #[inline]
150 pub fn serialize(&self) -> Array<u8, BS> {
151 let pos = self.get_pos();
152 let mut res = self.buffer.clone();
153 for b in &mut res[1..pos] {
155 *b = 0;
156 }
157 res
158 }
159
160 #[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: ArraySize> 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: ArraySize> zeroize::ZeroizeOnDrop for ReadBuffer<BS> {}