musli_common/
writer.rs

1use core::fmt;
2use core::mem::take;
3
4use musli::{Buf, Context};
5
6#[cfg(feature = "alloc")]
7use alloc::vec::Vec;
8
9/// Maximum size used by a fixed length [`Buf`].
10pub const MAX_FIXED_BYTES_LEN: usize = 128;
11
12/// Overflow when trying to write to a slice.
13#[derive(Debug)]
14pub(crate) struct SliceOverflow {
15    n: usize,
16    capacity: usize,
17}
18
19impl fmt::Display for SliceOverflow {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21        let SliceOverflow { n, capacity } = self;
22
23        write!(
24            f,
25            "Tried to write {n} bytes to slice, with a remaining capacity of {capacity}"
26        )
27    }
28}
29
30/// The trait governing how a writer works.
31pub trait Writer {
32    /// Reborrowed type.
33    ///
34    /// Why oh why would we want to do this over having a simple `&'this mut T`?
35    ///
36    /// We want to avoid recursive types, which will blow up the compiler. And
37    /// the above is a typical example of when that can go wrong. This ensures
38    /// that each call to `borrow_mut` dereferences the [Reader] at each step to
39    /// avoid constructing a large muted type, like `&mut &mut &mut VecWriter`.
40    ///
41    /// [Reader]: crate::reader::Reader
42    type Mut<'this>: Writer
43    where
44        Self: 'this;
45
46    /// Reborrow the current type.
47    fn borrow_mut(&mut self) -> Self::Mut<'_>;
48
49    /// Write a buffer to the current writer.
50    fn write_buffer<C, B>(&mut self, cx: &C, buffer: B) -> Result<(), C::Error>
51    where
52        C: ?Sized + Context,
53        B: Buf;
54
55    /// Write bytes to the current writer.
56    fn write_bytes<C>(&mut self, cx: &C, bytes: &[u8]) -> Result<(), C::Error>
57    where
58        C: ?Sized + Context;
59
60    /// Write a single byte.
61    #[inline]
62    fn write_byte<C>(&mut self, cx: &C, b: u8) -> Result<(), C::Error>
63    where
64        C: ?Sized + Context,
65    {
66        self.write_bytes(cx, &[b])
67    }
68}
69
70impl<W> Writer for &mut W
71where
72    W: ?Sized + Writer,
73{
74    type Mut<'this> = &'this mut W where Self: 'this;
75
76    #[inline]
77    fn borrow_mut(&mut self) -> Self::Mut<'_> {
78        self
79    }
80
81    #[inline]
82    fn write_buffer<C, B>(&mut self, cx: &C, buffer: B) -> Result<(), C::Error>
83    where
84        C: ?Sized + Context,
85        B: Buf,
86    {
87        (*self).write_buffer(cx, buffer)
88    }
89
90    #[inline]
91    fn write_bytes<C>(&mut self, cx: &C, bytes: &[u8]) -> Result<(), C::Error>
92    where
93        C: ?Sized + Context,
94    {
95        (*self).write_bytes(cx, bytes)
96    }
97
98    #[inline]
99    fn write_byte<C>(&mut self, cx: &C, b: u8) -> Result<(), C::Error>
100    where
101        C: ?Sized + Context,
102    {
103        (*self).write_byte(cx, b)
104    }
105}
106
107#[cfg(feature = "alloc")]
108impl Writer for Vec<u8> {
109    type Mut<'this> = &'this mut Self where Self: 'this;
110
111    #[inline]
112    fn borrow_mut(&mut self) -> Self::Mut<'_> {
113        self
114    }
115
116    #[inline]
117    fn write_buffer<C, B>(&mut self, cx: &C, buffer: B) -> Result<(), C::Error>
118    where
119        C: ?Sized + Context,
120        B: Buf,
121    {
122        // SAFETY: the buffer never outlives this function call.
123        self.write_bytes(cx, buffer.as_slice())
124    }
125
126    #[inline]
127    fn write_bytes<C>(&mut self, cx: &C, bytes: &[u8]) -> Result<(), C::Error>
128    where
129        C: ?Sized + Context,
130    {
131        self.extend_from_slice(bytes);
132        cx.advance(bytes.len());
133        Ok(())
134    }
135
136    #[inline]
137    fn write_byte<C>(&mut self, cx: &C, b: u8) -> Result<(), C::Error>
138    where
139        C: ?Sized + Context,
140    {
141        self.push(b);
142        cx.advance(1);
143        Ok(())
144    }
145}
146
147impl Writer for &mut [u8] {
148    type Mut<'this> = &'this mut Self where Self: 'this;
149
150    #[inline]
151    fn borrow_mut(&mut self) -> Self::Mut<'_> {
152        self
153    }
154
155    #[inline]
156    fn write_buffer<C, B>(&mut self, cx: &C, buffer: B) -> Result<(), C::Error>
157    where
158        C: ?Sized + Context,
159        B: Buf,
160    {
161        // SAFETY: the buffer never outlives this function call.
162        self.write_bytes(cx, buffer.as_slice())
163    }
164
165    #[inline]
166    fn write_bytes<C>(&mut self, cx: &C, bytes: &[u8]) -> Result<(), C::Error>
167    where
168        C: ?Sized + Context,
169    {
170        if self.len() < bytes.len() {
171            return Err(cx.message(SliceOverflow {
172                n: bytes.len(),
173                capacity: self.len(),
174            }));
175        }
176
177        let next = take(self);
178        let (this, next) = next.split_at_mut(bytes.len());
179        this.copy_from_slice(bytes);
180        *self = next;
181        Ok(())
182    }
183
184    #[inline]
185    fn write_byte<C>(&mut self, cx: &C, b: u8) -> Result<(), C::Error>
186    where
187        C: ?Sized + Context,
188    {
189        if self.is_empty() {
190            return Err(cx.message(format_args!(
191                "Buffer overflow, remaining is {} while tried to write 1",
192                self.len()
193            )));
194        }
195
196        self[0] = b;
197        *self = &mut take(self)[1..];
198        Ok(())
199    }
200}
201
202/// A writer that writes against an underlying [`Buf`].
203pub struct BufWriter<T> {
204    buf: T,
205}
206
207impl<T> BufWriter<T> {
208    /// Construct a new buffer writer.
209    pub fn new(buf: T) -> Self {
210        Self { buf }
211    }
212
213    /// Coerce into inner buffer.
214    pub fn into_inner(self) -> T {
215        self.buf
216    }
217}
218
219impl<T> Writer for BufWriter<T>
220where
221    T: Buf,
222{
223    type Mut<'this> = &'this mut Self
224    where
225        Self: 'this;
226
227    #[inline(always)]
228    fn borrow_mut(&mut self) -> Self::Mut<'_> {
229        self
230    }
231
232    #[inline(always)]
233    fn write_buffer<C, B>(&mut self, cx: &C, buffer: B) -> Result<(), C::Error>
234    where
235        C: ?Sized + Context,
236        B: Buf,
237    {
238        if !self.buf.write(buffer.as_slice()) {
239            return Err(cx.message("Buffer overflow"));
240        }
241
242        Ok(())
243    }
244
245    #[inline(always)]
246    fn write_bytes<C>(&mut self, cx: &C, bytes: &[u8]) -> Result<(), C::Error>
247    where
248        C: ?Sized + Context,
249    {
250        if !self.buf.write(bytes) {
251            return Err(cx.message("Buffer overflow"));
252        }
253
254        Ok(())
255    }
256}