1use core::cell::Cell;
2use core::cell::RefCell;
3use core::fmt;
4use core::mem;
5use core::mem::ManuallyDrop;
6use core::ops::Range;
7
8use alloc::vec::Vec;
9use musli::Encode;
10use musli::mode::Binary;
11
12use crate::api::{EncodeBody, Format};
13use crate::format;
14
15#[derive(Debug)]
16#[cfg_attr(test, derive(PartialEq))]
17enum InvalidFrameWhat {
18 ReadPosition(usize),
19 LengthPrefix,
20 LengthPrefixOverflow(u32),
21 InsufficientLength(usize),
22 InsufficientFrame(usize),
23}
24
25impl fmt::Display for InvalidFrameWhat {
26 #[inline]
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 match self {
29 Self::ReadPosition(pos) => write!(f, "read position ({pos}) out of bounds"),
30 Self::LengthPrefix => write!(f, "4 byte length prefix out of bounds"),
31 Self::LengthPrefixOverflow(len) => write!(f, "length prefix {len} overflowed usize"),
32 Self::InsufficientLength(len) => {
33 write!(f, "insufficient data for length (needed {len} bytes)")
34 }
35 Self::InsufficientFrame(len) => {
36 write!(f, "insufficient data for frame (needed {len} bytes)")
37 }
38 }
39 }
40}
41
42#[derive(Debug)]
43#[cfg_attr(test, derive(PartialEq))]
44pub(crate) struct InvalidFrame {
45 what: InvalidFrameWhat,
46 range: Range<usize>,
47 size: usize,
48}
49
50impl fmt::Display for InvalidFrame {
51 #[inline]
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 write!(
54 f,
55 "{} {}-{} (has {} bytes)",
56 self.what, self.range.start, self.range.end, self.size
57 )
58 }
59}
60
61#[must_use = "Writer must be consumed with Writer::flush to have an effect on the underlying buffer"]
62pub(crate) struct Writer<'a> {
63 start: usize,
64 buf: &'a mut Buf,
65}
66
67impl Writer<'_> {
68 #[inline]
75 pub(crate) fn envelope<T>(&mut self, value: &T) -> Result<(), format::Error>
76 where
77 T: ?Sized + Encode<Binary>,
78 {
79 format::encode_envelope(&mut self.buf.buffer, value)
80 }
81
82 #[inline]
84 pub(crate) fn body<T>(&mut self, format: Format, value: &T) -> Result<(), format::Error>
85 where
86 T: ?Sized + EncodeBody,
87 {
88 format.encode(&mut self.buf.buffer, value)
89 }
90
91 #[inline]
93 pub(crate) fn flush(self) {
94 let mut this = ManuallyDrop::new(self);
95 let start = this.start;
96 this.buf.done(start);
97 }
98}
99
100impl Drop for Writer<'_> {
101 #[inline]
102 fn drop(&mut self) {
103 self.buf.reset(self.start);
104 }
105}
106
107#[derive(Default)]
110pub(crate) struct Buf {
111 buffer: Vec<u8>,
112 read: Cell<usize>,
113}
114
115impl Buf {
116 pub(crate) fn writer(&mut self) -> Writer<'_> {
118 if self.read.get() == self.buffer.len() {
119 self.buffer.clear();
120 self.read.set(0);
121 }
122
123 let start = self.buffer.len();
124 self.buffer.extend_from_slice(&[0; mem::size_of::<u32>()]);
125 Writer { start, buf: self }
126 }
127
128 #[inline]
129 #[cfg(test)]
130 pub(crate) fn is_empty(&self) -> bool {
131 debug_assert!(self.read.get() <= self.buffer.len());
133 self.read.get() >= self.buffer.len()
134 }
135
136 fn len_at_mut(&mut self, at: usize) -> Option<&mut [u8; 4]> {
137 let bytes = self.buffer.get_mut(at..at + mem::size_of::<u32>())?;
138 Some(unsafe { &mut *bytes.as_mut_ptr().cast() })
139 }
140
141 #[inline]
145 fn done(&mut self, start: usize) {
146 let delta = self
147 .buffer
148 .len()
149 .saturating_sub(start)
150 .saturating_sub(mem::size_of::<u32>());
151
152 let l = u32::try_from(delta).unwrap_or(u32::MAX).to_le_bytes();
153
154 let Some(len) = self.len_at_mut(start) else {
155 return;
156 };
157
158 *len = l;
159 }
160
161 #[inline]
165 fn reset(&mut self, start: usize) {
166 self.buffer.truncate(start);
167 }
168
169 #[inline]
170 pub(crate) fn clear(&mut self) {
171 self.buffer.clear();
172 self.read.set(0);
173 }
174
175 #[inline]
180 pub(crate) fn shrink_to(&mut self, capacity: usize) {
181 self.buffer.shrink_to(capacity);
182 }
183
184 #[inline]
186 pub(crate) fn read(&self) -> Result<Option<&[u8]>, InvalidFrame> {
187 let read = self.read.get();
188
189 if self.buffer.len() == read {
190 return Ok(None);
191 }
192
193 let Some(tail) = self.buffer.get(read..) else {
194 return Err(InvalidFrame {
195 what: InvalidFrameWhat::ReadPosition(read),
196 range: 0..read,
197 size: self.buffer.len(),
198 });
199 };
200
201 let Some((head, tail)) = tail.split_at_checked(mem::size_of::<u32>()) else {
202 return Err(InvalidFrame {
203 what: InvalidFrameWhat::InsufficientLength(mem::size_of::<u32>()),
204 range: 0..read,
205 size: self.buffer.len(),
206 });
207 };
208
209 let frame = read..read + mem::size_of::<u32>();
210
211 let &[a, b, c, d] = head else {
212 return Err(InvalidFrame {
213 what: InvalidFrameWhat::LengthPrefix,
214 range: frame.clone(),
215 size: self.buffer.len(),
216 });
217 };
218
219 let len = u32::from_le_bytes([a, b, c, d]);
220
221 let Ok(len) = usize::try_from(len) else {
222 return Err(InvalidFrame {
223 what: InvalidFrameWhat::LengthPrefixOverflow(len),
224 range: frame.clone(),
225 size: self.buffer.len(),
226 });
227 };
228
229 let Some(out) = tail.get(..len) else {
230 return Err(InvalidFrame {
231 what: InvalidFrameWhat::InsufficientFrame(len),
232 range: frame.start..frame.end + len,
233 size: self.buffer.len(),
234 });
235 };
236
237 let next = read
238 .saturating_add(mem::size_of::<u32>())
239 .saturating_add(len);
240
241 self.read.set(next);
242 Ok(Some(out))
243 }
244}
245
246pub(crate) struct BufPool {
247 pool: RefCell<Vec<Buf>>,
248 max_capacity: usize,
252}
253
254impl BufPool {
255 #[inline]
257 pub(crate) fn new(max_capacity: usize) -> Self {
258 Self {
259 pool: RefCell::new(Vec::new()),
260 max_capacity,
261 }
262 }
263
264 #[inline]
268 pub(crate) fn with<E>(&self, f: impl FnOnce(&mut Buf) -> Result<(), E>) -> Result<Buf, E> {
269 let mut buf = self.get();
270 let result = f(&mut buf);
271
272 match result {
273 Ok(()) => Ok(buf),
274 Err(err) => {
275 self.put(buf);
276 Err(err)
277 }
278 }
279 }
280
281 #[inline]
282 pub(crate) fn get(&self) -> Buf {
283 self.pool.borrow_mut().pop().unwrap_or_default()
284 }
285
286 #[inline]
287 pub(crate) fn put(&self, mut buf: Buf) {
288 buf.clear();
289 buf.shrink_to(self.max_capacity);
290 self.pool.borrow_mut().push(buf);
291 }
292}
293
294#[cfg(test)]
295mod tests {
296 use alloc::string::{String, ToString};
297
298 use musli::Encode;
299
300 use super::{Buf, BufPool};
301 use crate::api::Format;
302
303 #[test]
307 fn test_pool_shrinks_returned_buffers() {
308 let pool = BufPool::new(16);
309
310 let mut buf = pool.get();
311 buf.buffer.extend_from_slice(&[0; 1024]);
312 assert!(buf.buffer.capacity() >= 1024);
313
314 pool.put(buf);
315
316 let buf = pool.get();
317 assert!(buf.buffer.is_empty());
318
319 assert!(
320 buf.buffer.capacity() <= 16,
321 "Expected the allocation to be released, got {}",
322 buf.buffer.capacity()
323 );
324 }
325
326 #[test]
327 fn test_empty_buf() {
328 let buf = Buf::default();
329 assert!(buf.is_empty());
330 assert_eq!(buf.read(), Ok(None));
331 }
332
333 #[derive(Encode, musli::Decode)]
334 struct Message {
335 a: u32,
336 b: String,
337 }
338
339 #[test]
340 fn test_two_elements() {
341 let mut buf = Buf::default();
342
343 assert!(buf.is_empty());
344 assert_eq!(buf.read(), Ok(None));
345
346 buf.writer()
348 .body(
349 Format::DEFAULT,
350 &Message {
351 a: 42,
352 b: "hello".to_string(),
353 },
354 )
355 .unwrap();
356
357 assert!(buf.is_empty());
358 assert_eq!(buf.read(), Ok(None));
359
360 let mut writer = buf.writer();
362 writer
363 .body(
364 Format::DEFAULT,
365 &Message {
366 a: 42,
367 b: "hello".to_string(),
368 },
369 )
370 .unwrap();
371
372 writer.flush();
373
374 assert!(!buf.is_empty());
375 assert!(matches!(buf.read(), Ok(Some(..))));
376
377 assert!(buf.is_empty());
378 assert_eq!(buf.read(), Ok(None));
379 }
380}