musli/writer/
slice_mut_writer.rs

1use core::marker::PhantomData;
2use core::ptr::NonNull;
3
4use crate::alloc::Vec;
5use crate::Context;
6
7use super::{SliceOverflow, Writer};
8
9/// A writer into a slice.
10pub struct SliceMutWriter<'a> {
11    start: NonNull<u8>,
12    end: NonNull<u8>,
13    _marker: PhantomData<&'a mut [u8]>,
14}
15
16impl<'a> SliceMutWriter<'a> {
17    pub(super) fn new(slice: &'a mut [u8]) -> Self {
18        // SAFETY: The slice is valid for the duration of the writer.
19        unsafe {
20            let range = slice.as_mut_ptr_range();
21            let start = NonNull::new_unchecked(range.start);
22            let end = NonNull::new_unchecked(range.end);
23            Self {
24                start,
25                end,
26                _marker: PhantomData,
27            }
28        }
29    }
30
31    #[inline]
32    pub(crate) fn remaining(&self) -> usize {
33        self.end.as_ptr() as usize - self.start.as_ptr() as usize
34    }
35}
36
37impl<'a> Writer for SliceMutWriter<'a> {
38    type Ok = usize;
39
40    type Mut<'this>
41        = &'this mut SliceMutWriter<'a>
42    where
43        Self: 'this;
44
45    #[inline]
46    fn finish<C>(&mut self, _: C) -> Result<Self::Ok, C::Error>
47    where
48        C: Context,
49    {
50        Ok(self.remaining())
51    }
52
53    #[inline]
54    fn borrow_mut(&mut self) -> Self::Mut<'_> {
55        self
56    }
57
58    #[inline]
59    fn extend<C>(&mut self, cx: C, buffer: Vec<u8, C::Allocator>) -> Result<(), C::Error>
60    where
61        C: Context,
62    {
63        // SAFETY: the buffer never outlives this function call.
64        self.write_bytes(cx, buffer.as_slice())
65    }
66
67    #[inline]
68    fn write_bytes<C>(&mut self, cx: C, bytes: &[u8]) -> Result<(), C::Error>
69    where
70        C: Context,
71    {
72        let end = self.start.as_ptr().wrapping_add(bytes.len());
73
74        if end > self.end.as_ptr() || end < self.start.as_ptr() {
75            return Err(cx.message(SliceOverflow {
76                n: bytes.len(),
77                capacity: self.remaining(),
78            }));
79        }
80
81        // SAFETY: Construction of the writer ensures the range is valid.
82        unsafe {
83            self.start
84                .as_ptr()
85                .copy_from_nonoverlapping(bytes.as_ptr(), bytes.len());
86            self.start = NonNull::new_unchecked(end);
87        }
88
89        Ok(())
90    }
91
92    #[inline]
93    fn write_byte<C>(&mut self, cx: C, b: u8) -> Result<(), C::Error>
94    where
95        C: Context,
96    {
97        if self.start == self.end {
98            return Err(cx.message(format_args!(
99                "Buffer overflow, remaining is 0 while tried to write 1"
100            )));
101        }
102
103        // SAFETY: Construction of the writer ensures the range is valid.
104        unsafe {
105            self.start.write(b);
106            self.start = self.start.add(1);
107        }
108
109        Ok(())
110    }
111}