Skip to main content

typhoon_utility/bytes/
writer.rs

1use {
2    core::{mem::MaybeUninit, ptr},
3    typhoon_errors::ErrorCode,
4};
5
6pub struct MaybeUninitWriter<'a> {
7    buffer: &'a mut [MaybeUninit<u8>],
8    position: usize,
9}
10
11impl<'a> MaybeUninitWriter<'a> {
12    #[inline(always)]
13    pub fn new(buffer: &'a mut [MaybeUninit<u8>], position: usize) -> Self {
14        Self { buffer, position }
15    }
16
17    #[inline(always)]
18    pub fn initialized(&self) -> &[u8] {
19        unsafe { core::slice::from_raw_parts(self.buffer.as_ptr() as *const u8, self.position) }
20    }
21
22    #[inline(always)]
23    pub fn write_bytes(&mut self, data: &[u8]) -> Result<usize, ErrorCode> {
24        if data.is_empty() {
25            return Ok(0);
26        }
27
28        if self.position >= self.buffer.len() {
29            return Err(buffer_full());
30        }
31
32        let to_write = data.len().min(self.buffer.len() - self.position);
33
34        if to_write == 0 {
35            return Err(buffer_full());
36        }
37
38        // SAFETY: We're writing to `MaybeUninit` and ensuring the data is valid.
39        unsafe {
40            let dst_ptr = self.buffer.as_mut_ptr().add(self.position);
41            ptr::copy_nonoverlapping(data.as_ptr(), dst_ptr as *mut u8, to_write);
42        }
43
44        self.position += to_write;
45
46        Ok(to_write)
47    }
48}
49
50#[cold]
51#[inline(never)]
52fn buffer_full() -> ErrorCode {
53    ErrorCode::BufferFull
54}