1use core::cell::Cell;
2use core::fmt;
3use core::mem;
4use core::num::NonZeroUsize;
5use core::ops::Range;
6
7use alloc::vec::Vec;
8use musli::mode::Binary;
9use musli::{Encode, storage};
10
11#[derive(Debug)]
12enum InvalidFrameWhat {
13 ReadPosition(usize),
14 LengthPrefix,
15 LengthPrefixOverflow(u32),
16 InsufficientLength(usize),
17 InsufficientFrame(usize),
18}
19
20impl fmt::Display for InvalidFrameWhat {
21 #[inline]
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 Self::ReadPosition(pos) => write!(f, "read position ({pos}) out of bounds"),
25 Self::LengthPrefix => write!(f, "4 byte length prefix out of bounds"),
26 Self::LengthPrefixOverflow(len) => write!(f, "length prefix {len} overflowed usize"),
27 Self::InsufficientLength(len) => {
28 write!(f, "insufficient data for length (needed {len} bytes)")
29 }
30 Self::InsufficientFrame(len) => {
31 write!(f, "insufficient data for frame (needed {len} bytes)")
32 }
33 }
34 }
35}
36
37#[derive(Debug)]
38pub(crate) struct InvalidFrame {
39 what: InvalidFrameWhat,
40 range: Range<usize>,
41 size: usize,
42}
43
44impl fmt::Display for InvalidFrame {
45 #[inline]
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 write!(
48 f,
49 "{} {}-{} (has {} bytes)",
50 self.what, self.range.start, self.range.end, self.size
51 )
52 }
53}
54
55#[derive(Default)]
58pub(crate) struct Buf {
59 start: Option<NonZeroUsize>,
60 buffer: Vec<u8>,
61 read: Cell<usize>,
62}
63
64impl Buf {
65 #[inline]
73 pub(crate) fn write<T>(&mut self, value: T) -> Result<(), storage::Error>
74 where
75 T: Encode<Binary>,
76 {
77 if self.start.is_none() {
78 let bytes = 0u32.to_le_bytes();
79 self.buffer.extend_from_slice(&bytes);
80 self.start = NonZeroUsize::new(self.buffer.len());
81 }
82
83 storage::to_writer(&mut self.buffer, &value)?;
84 Ok(())
85 }
86
87 #[inline]
89 pub(crate) fn is_empty(&self) -> bool {
90 debug_assert!(self.read.get() <= self.buffer.len());
92 self.read.get() >= self.buffer.len()
93 }
94
95 fn len_at_mut(&mut self, at: usize) -> Option<&mut [u8; 4]> {
96 match self.buffer.get_mut(at..at + mem::size_of::<u32>())? {
97 bytes if bytes.len() == mem::size_of::<u32>() => {
98 Some(unsafe { &mut *bytes.as_mut_ptr().cast() })
99 }
100 _ => None,
101 }
102 }
103
104 #[inline]
108 pub(crate) fn done(&mut self) {
109 if let Some(start) = self.start.take() {
110 let l = u32::try_from(self.buffer.len().saturating_sub(start.get()))
111 .unwrap_or(u32::MAX)
112 .to_le_bytes();
113
114 let Some(len) = self.len_at_mut(start.get().saturating_sub(mem::size_of::<u32>()))
115 else {
116 return;
117 };
118
119 *len = l;
120 }
121 }
122
123 #[inline]
127 pub(crate) fn reset(&mut self) {
128 if let Some(start) = self.start {
129 self.buffer.truncate(start.get());
130 }
131 }
132
133 #[inline]
134 pub(crate) fn clear(&mut self) {
135 self.start = None;
136 self.buffer.clear();
137 self.read.set(0);
138 }
139
140 #[inline]
142 pub(crate) fn read(&self) -> Result<Option<&[u8]>, InvalidFrame> {
143 let read = self.read.get();
144
145 if self.buffer.len() == read {
146 return Ok(None);
147 }
148
149 let Some(tail) = self.buffer.get(read..) else {
150 return Err(InvalidFrame {
151 what: InvalidFrameWhat::ReadPosition(read),
152 range: 0..read,
153 size: self.buffer.len(),
154 });
155 };
156
157 let Some((head, tail)) = tail.split_at_checked(mem::size_of::<u32>()) else {
158 return Err(InvalidFrame {
159 what: InvalidFrameWhat::InsufficientLength(mem::size_of::<u32>()),
160 range: 0..read,
161 size: self.buffer.len(),
162 });
163 };
164
165 let frame = read..read + mem::size_of::<u32>();
166
167 let &[a, b, c, d] = head else {
168 return Err(InvalidFrame {
169 what: InvalidFrameWhat::LengthPrefix,
170 range: frame.clone(),
171 size: self.buffer.len(),
172 });
173 };
174
175 let len = u32::from_le_bytes([a, b, c, d]);
176
177 let Ok(len) = usize::try_from(len) else {
178 return Err(InvalidFrame {
179 what: InvalidFrameWhat::LengthPrefixOverflow(len),
180 range: frame.clone(),
181 size: self.buffer.len(),
182 });
183 };
184
185 let Some(out) = tail.get(..len) else {
186 return Err(InvalidFrame {
187 what: InvalidFrameWhat::InsufficientFrame(len),
188 range: frame.start..frame.end + len,
189 size: self.buffer.len(),
190 });
191 };
192
193 let next = read
194 .saturating_add(mem::size_of::<u32>())
195 .saturating_add(len);
196
197 self.read.set(next);
198 Ok(Some(out))
199 }
200}