1use crate::{ArenaView, PrefixArena};
2use core::fmt;
3use core::mem::MaybeUninit;
4
5#[inline(always)]
6const unsafe fn bytes_as_uninit(slice: &[u8]) -> &[MaybeUninit<u8>] {
7 unsafe { core::mem::transmute::<&[u8], &[MaybeUninit<u8>]>(slice) }
8}
9
10#[inline(always)]
11const unsafe fn uninit_as_bytes(slice: &[MaybeUninit<u8>]) -> &[u8] {
12 unsafe { core::mem::transmute::<&[MaybeUninit<u8>], &[u8]>(slice) }
13}
14
15#[inline(always)]
16const unsafe fn uninit_as_bytes_mut(slice: &mut [MaybeUninit<u8>]) -> &mut [u8] {
17 unsafe { core::mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(slice) }
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub struct StagingBufferError;
22
23impl fmt::Display for StagingBufferError {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 f.write_str("staging buffer capacity exceeded")
26 }
27}
28
29pub struct StagingBuffer<'arena, 'b> {
35 inner: ArenaView<'arena, 'b>,
36 used: usize,
37}
38
39impl<'arena, 'b> StagingBuffer<'arena, 'b>
40where
41 'b: 'arena,
42{
43 pub const fn new(arena: &'arena mut PrefixArena<'b>) -> Self {
45 Self {
46 inner: arena.view(),
47 used: 0,
48 }
49 }
50
51 pub fn push_byte(&mut self, byte: u8) -> Result<(), StagingBufferError> {
55 if self.used >= self.inner.len() {
56 return Err(StagingBufferError);
57 }
58 self.inner.as_slice_mut()[self.used].write(byte);
59 self.used += 1;
60 Ok(())
61 }
62
63 pub fn extend_from_slice(&mut self, slice: &[u8]) -> Result<(), StagingBufferError> {
67 if self.used + slice.len() > self.inner.len() {
68 return Err(StagingBufferError);
69 }
70 self.inner.as_slice_mut()[self.used..self.used + slice.len()]
71 .copy_from_slice(unsafe { bytes_as_uninit(slice) });
72 self.used += slice.len();
73 Ok(())
74 }
75
76 pub fn extend_from_slice_capped(&mut self, slice: &[u8]) -> usize {
78 let to_fill = core::cmp::min(self.spare_capacity(), slice.len());
79 self.inner.as_slice_mut()[self.used..self.used + to_fill]
80 .copy_from_slice(unsafe { bytes_as_uninit(&slice[..to_fill]) });
81 self.used += to_fill;
82 to_fill
83 }
84
85 pub fn written(&self) -> &[u8] {
87 unsafe { uninit_as_bytes(&self.inner.as_slice()[..self.used]) }
88 }
89
90 pub fn written_mut(&mut self) -> &mut [u8] {
92 unsafe { uninit_as_bytes_mut(&mut self.inner.as_slice_mut()[..self.used]) }
93 }
94
95 pub const fn len(&self) -> usize {
97 self.used
98 }
99
100 pub const fn is_empty(&self) -> bool {
102 self.used == 0
103 }
104
105 pub const fn capacity(&self) -> usize {
107 self.inner.len()
108 }
109
110 pub const fn spare_capacity(&self) -> usize {
112 self.inner.len() - self.used
113 }
114
115 pub fn clear(&mut self) {
117 self.used = 0;
118 }
119
120 pub fn into_written_slice(self) -> &'b mut [u8] {
122 unsafe { uninit_as_bytes_mut(self.inner.take_prefix(self.used)) }
123 }
124}
125#[cfg(test)]
126pub mod tests {
127 use super::*;
128 use crate::PrefixArena as HeadArena;
129
130 #[test]
131 fn test_basic_push() {
132 let mut buffer = [0u8; 5];
133 let mut allocator = HeadArena::new(&mut buffer);
134 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
135
136 assert_eq!(borrowed_buffer.len(), 0);
137 assert_eq!(borrowed_buffer.capacity(), 5);
138 assert_eq!(borrowed_buffer.spare_capacity(), 5);
139
140 borrowed_buffer.push_byte(42).unwrap();
141 assert_eq!(borrowed_buffer.len(), 1);
142 assert_eq!(borrowed_buffer.written(), &[42]);
143 assert_eq!(borrowed_buffer.spare_capacity(), 4);
144 }
145
146 #[test]
147 fn test_push_until_full() {
148 let mut buffer = [0u8; 3];
149 let mut allocator = HeadArena::new(&mut buffer);
150 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
151
152 borrowed_buffer.push_byte(1).unwrap();
153 borrowed_buffer.push_byte(2).unwrap();
154 borrowed_buffer.push_byte(3).unwrap();
155
156 assert_eq!(borrowed_buffer.written(), &[1, 2, 3]);
157 assert_eq!(borrowed_buffer.spare_capacity(), 0);
158 assert!(borrowed_buffer.push_byte(4).is_err());
159 }
160
161 #[test]
162 fn test_clear() {
163 let mut buffer = [0u8; 5];
164 let mut allocator = HeadArena::new(&mut buffer);
165 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
166
167 borrowed_buffer.extend_from_slice(&[1, 2, 3]).unwrap();
168 assert_eq!(borrowed_buffer.len(), 3);
169
170 borrowed_buffer.clear();
171 assert_eq!(borrowed_buffer.len(), 0);
172 assert_eq!(borrowed_buffer.spare_capacity(), 5);
173 assert_eq!(borrowed_buffer.written(), &[]);
174 }
175
176 #[test]
177 fn test_as_mut_slice() {
178 let mut buffer = [0u8; 5];
179 let mut allocator = HeadArena::new(&mut buffer);
180 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
181
182 borrowed_buffer.extend_from_slice(&[1, 2, 3]).unwrap();
183
184 let mut_slice = borrowed_buffer.written_mut();
185 mut_slice[1] = 99;
186
187 assert_eq!(borrowed_buffer.written(), &[1, 99, 3]);
188 }
189
190 #[test]
191 fn test_empty_buffer() {
192 let mut buffer = [0u8; 0];
193 let mut allocator = HeadArena::new(&mut buffer);
194 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
195
196 assert_eq!(borrowed_buffer.len(), 0);
197 assert_eq!(borrowed_buffer.capacity(), 0);
198 assert_eq!(borrowed_buffer.spare_capacity(), 0);
199 assert!(borrowed_buffer.push_byte(1).is_err());
200 assert!(borrowed_buffer.extend_from_slice(&[1]).is_err());
201 assert_eq!(borrowed_buffer.written(), &[]);
202 }
203
204 #[test]
205 fn test_single_byte_buffer() {
206 let mut buffer = [0u8; 1];
207 let mut allocator = HeadArena::new(&mut buffer);
208 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
209
210 assert_eq!(borrowed_buffer.capacity(), 1);
211 assert_eq!(borrowed_buffer.spare_capacity(), 1);
212
213 borrowed_buffer.push_byte(42).unwrap();
214 assert_eq!(borrowed_buffer.written(), &[42]);
215 assert_eq!(borrowed_buffer.spare_capacity(), 0);
216
217 assert!(borrowed_buffer.push_byte(1).is_err());
218 assert!(borrowed_buffer.extend_from_slice(&[1]).is_err());
219 }
220
221 #[test]
222 fn test_clear_and_reuse() {
223 let mut buffer = [0u8; 5];
224 let mut allocator = HeadArena::new(&mut buffer);
225 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
226
227 borrowed_buffer.extend_from_slice(&[1, 2, 3]).unwrap();
228 assert_eq!(borrowed_buffer.len(), 3);
229
230 borrowed_buffer.clear();
231 borrowed_buffer.extend_from_slice(&[4, 5, 6, 7, 8]).unwrap();
232 assert_eq!(borrowed_buffer.written(), &[4, 5, 6, 7, 8]);
233 assert_eq!(borrowed_buffer.spare_capacity(), 0);
234 }
235
236 #[test]
237 fn test_extend_at_exact_capacity() {
238 let mut buffer = [0u8; 3];
239 let mut allocator = HeadArena::new(&mut buffer);
240 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
241
242 assert!(borrowed_buffer.extend_from_slice(&[1, 2, 3]).is_ok());
243 assert_eq!(borrowed_buffer.len(), 3);
244 assert_eq!(borrowed_buffer.spare_capacity(), 0);
245
246 assert!(borrowed_buffer.extend_from_slice(&[]).is_ok());
247 assert_eq!(borrowed_buffer.len(), 3);
248 }
249
250 #[test]
251 fn test_take_used() {
252 let mut buffer = [0u8; 5];
253 let mut allocator = HeadArena::new(&mut buffer);
254 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
255
256 borrowed_buffer.extend_from_slice(&[10, 20, 30]).unwrap();
257 let used = borrowed_buffer.into_written_slice();
258
259 assert_eq!(used, &[10, 20, 30]);
260 used[0] = 255;
261 assert_eq!(used, &[255, 20, 30]);
262 }
263
264 #[test]
265 fn test_extend_empty_slice() {
266 let mut buffer = [0u8; 5];
267 let mut allocator = HeadArena::new(&mut buffer);
268 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
269
270 borrowed_buffer.extend_from_slice(&[]).unwrap();
271 assert_eq!(borrowed_buffer.len(), 0);
272 assert_eq!(borrowed_buffer.written(), &[]);
273 }
274
275 #[test]
276 fn test_capacity_overflow() {
277 let mut buffer = [0u8; 2];
278 let mut allocator = HeadArena::new(&mut buffer);
279 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
280
281 assert!(borrowed_buffer.extend_from_slice(&[1, 2, 3]).is_err());
282 assert_eq!(borrowed_buffer.len(), 0);
283
284 borrowed_buffer.extend_from_slice(&[1, 2]).unwrap();
285 assert!(borrowed_buffer.push_byte(3).is_err());
286 assert_eq!(borrowed_buffer.written(), &[1, 2]);
287 }
288
289 #[test]
290 fn test_multiple_extension() {
291 let mut buffer = [0u8; 10];
292 let mut allocator = HeadArena::new(&mut buffer);
293 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
294
295 borrowed_buffer.extend_from_slice(&[1, 2, 3]).unwrap();
296 assert_eq!(borrowed_buffer.written(), &[1, 2, 3]);
297
298 borrowed_buffer.extend_from_slice(&[4, 5]).unwrap();
299 assert_eq!(borrowed_buffer.written(), &[1, 2, 3, 4, 5]);
300
301 borrowed_buffer
302 .extend_from_slice(&[6, 7, 8, 9, 10])
303 .unwrap();
304 assert_eq!(borrowed_buffer.written(), &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
305
306 assert!(borrowed_buffer.extend_from_slice(&[11]).is_err());
307 }
308
309 #[test]
310 fn test_append_from_slice() {
311 let mut buffer = [0u8; 5];
312 let mut allocator = HeadArena::new(&mut buffer);
313 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
314
315 let filled = borrowed_buffer.extend_from_slice_capped(&[1, 2, 3, 4, 5, 6, 7]);
317 assert_eq!(filled, 5);
318 assert_eq!(borrowed_buffer.written(), &[1, 2, 3, 4, 5]);
319 assert_eq!(borrowed_buffer.spare_capacity(), 0);
320
321 let filled = borrowed_buffer.extend_from_slice_capped(&[8, 9]);
323 assert_eq!(filled, 0);
324 assert_eq!(borrowed_buffer.written(), &[1, 2, 3, 4, 5]);
325 }
326
327 #[test]
328 fn test_append_from_slice_partial() {
329 let mut buffer = [0u8; 10];
330 let mut allocator = HeadArena::new(&mut buffer);
331 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
332
333 borrowed_buffer.extend_from_slice(&[1, 2, 3]).unwrap();
335 assert_eq!(borrowed_buffer.spare_capacity(), 7);
336
337 let filled = borrowed_buffer.extend_from_slice_capped(&[4, 5]);
339 assert_eq!(filled, 2);
340 assert_eq!(borrowed_buffer.written(), &[1, 2, 3, 4, 5]);
341 assert_eq!(borrowed_buffer.spare_capacity(), 5);
342
343 let filled = borrowed_buffer.extend_from_slice_capped(&[6, 7, 8, 9, 10]);
345 assert_eq!(filled, 5);
346 assert_eq!(borrowed_buffer.written(), &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
347 assert_eq!(borrowed_buffer.spare_capacity(), 0);
348 }
349
350 #[test]
351 fn test_fill_remaining_empty_slice() {
352 let mut buffer = [0u8; 5];
353 let mut allocator = HeadArena::new(&mut buffer);
354 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
355
356 let filled = borrowed_buffer.extend_from_slice_capped(&[]);
357 assert_eq!(filled, 0);
358 assert_eq!(borrowed_buffer.len(), 0);
359 }
360
361 #[test]
362 fn test_as_slice_lifetime() {
363 let mut buffer = [1, 2, 3, 4, 5];
364 let mut allocator = HeadArena::new(&mut buffer);
365 let mut borrowed_buffer = StagingBuffer::new(&mut allocator);
366 borrowed_buffer.extend_from_slice(&[1, 2, 3]).unwrap();
367
368 let slice1 = borrowed_buffer.written();
369 let slice2 = borrowed_buffer.written();
370
371 assert_eq!(slice1, slice2);
372 assert_eq!(slice1, &[1, 2, 3]);
373 }
374}