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