musli/writer/
slice_mut_writer.rs1use core::marker::PhantomData;
2use core::ptr::NonNull;
3
4use crate::alloc::Vec;
5use crate::Context;
6
7use super::{SliceOverflow, Writer};
8
9pub 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 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 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 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 unsafe {
105 self.start.write(b);
106 self.start = self.start.add(1);
107 }
108
109 Ok(())
110 }
111}