musli/
writer.rs

1//! Trait governing how to write bytes.
2//!
3//! To adapt [`std::io::Write`] types, see the [`wrap`] function.
4//!
5//! [`wrap`]: crate::wrap::wrap
6
7mod slice_mut_writer;
8pub use self::slice_mut_writer::SliceMutWriter;
9
10use core::fmt;
11
12use crate::alloc::Vec;
13use crate::{Allocator, Context};
14
15mod sealed {
16    use super::Writer;
17
18    pub trait Sealed {}
19    impl<W> Sealed for &mut W where W: ?Sized + Writer {}
20    #[cfg(feature = "std")]
21    impl<W> Sealed for crate::wrap::Wrap<W> where W: std::io::Write {}
22    impl Sealed for &mut [u8] {}
23}
24
25/// Coerce a type into a [`Writer`].
26///
27/// # Examples
28///
29/// ```
30/// use musli::{Context, IntoWriter, Writer};
31/// use musli::context;
32///
33/// let mut buffer = Vec::new();
34/// let mut writer = (&mut buffer).into_writer();
35/// let cx = context::new();
36///
37/// writer.write_bytes(&cx, b"Hello")?;
38/// writer.finish(&cx)?;
39///
40/// assert_eq!(buffer, b"Hello");
41/// # Ok::<_, musli::context::ErrorMarker>(())
42/// ```
43pub trait IntoWriter
44where
45    Self: self::sealed::Sealed,
46{
47    /// The output of the writer which will be returned after writing.
48    type Ok;
49
50    /// The writer type.
51    type Writer: Writer<Ok = Self::Ok>;
52
53    /// Convert the type into a writer.
54    fn into_writer(self) -> Self::Writer;
55}
56
57/// The trait governing how a writer works.
58///
59/// # Examples
60///
61/// ```
62/// use musli::{Context, Writer};
63/// use musli::context;
64///
65/// // Example using Writer as a trait bound
66/// fn write_greeting<W, C>(mut writer: W, cx: C) -> Result<W::Ok, C::Error>
67/// where
68///     W: Writer,
69///     C: Context,
70/// {
71///     writer.write_bytes(cx, b"Hello")?;
72///     writer.write_byte(cx, b' ')?;
73///     writer.write_bytes(cx, b"World")?;
74///     writer.finish(cx)
75/// }
76///
77/// let mut writer = Vec::new();
78/// let cx = context::new();
79///
80/// write_greeting(&mut writer, &cx)?;
81/// assert_eq!(writer, b"Hello World");
82/// # Ok::<_, context::ErrorMarker>(())
83/// ```
84pub trait Writer {
85    /// The value returned from writing the value.
86    type Ok;
87
88    /// Reborrowed type.
89    ///
90    /// Why oh why would we want to do this over having a simple `&'this mut T`?
91    ///
92    /// We want to avoid recursive types, which will blow up the compiler. And
93    /// the above is a typical example of when that can go wrong. This ensures
94    /// that each call to `borrow_mut` dereferences the [`Reader`] at each step to
95    /// avoid constructing a large muted type, like `&mut &mut &mut VecWriter`.
96    ///
97    /// [`Reader`]: crate::reader::Reader
98    type Mut<'this>: Writer
99    where
100        Self: 'this;
101
102    /// Finalize the writer and return the output.
103    fn finish<C>(&mut self, cx: C) -> Result<Self::Ok, C::Error>
104    where
105        C: Context;
106
107    /// Reborrow the current type.
108    ///
109    /// # Examples
110    ///
111    /// ```
112    /// use musli::{Context, Writer};
113    /// use musli::context;
114    ///
115    /// let mut writer = Vec::new();
116    /// let cx = context::new();
117    ///
118    /// {
119    ///     let mut borrowed = writer.borrow_mut();
120    ///     borrowed.write_bytes(&cx, b"Hello")?;
121    /// }
122    ///
123    /// writer.write_bytes(&cx, b" World")?;
124    /// writer.finish(&cx)?;
125    /// assert_eq!(writer, b"Hello World");
126    /// # Ok::<_, musli::context::ErrorMarker>(())
127    /// ```
128    fn borrow_mut(&mut self) -> Self::Mut<'_>;
129
130    /// Write a buffer to the current writer.
131    ///
132    /// This method is used internally to write a musli Vec buffer to the writer.
133    /// Most users will use [`write_bytes`] instead.
134    ///
135    /// [`write_bytes`]: Writer::write_bytes
136    fn extend<C>(&mut self, cx: C, buffer: Vec<u8, C::Allocator>) -> Result<(), C::Error>
137    where
138        C: Context;
139
140    /// Write bytes to the current writer.
141    ///
142    /// # Examples
143    ///
144    /// ```
145    /// use musli::{Context, Writer};
146    /// use musli::context;
147    ///
148    /// let mut writer = Vec::new();
149    /// let cx = context::new();
150    ///
151    /// writer.write_bytes(&cx, b"Hello")?;
152    /// writer.write_bytes(&cx, b" ")?;
153    /// writer.write_bytes(&cx, b"World")?;
154    /// writer.finish(&cx)?;
155    /// assert_eq!(writer, b"Hello World");
156    /// # Ok::<_, musli::context::ErrorMarker>(())
157    /// ```
158    fn write_bytes<C>(&mut self, cx: C, bytes: &[u8]) -> Result<(), C::Error>
159    where
160        C: Context;
161
162    /// Write a single byte.
163    #[inline]
164    fn write_byte<C>(&mut self, cx: C, b: u8) -> Result<(), C::Error>
165    where
166        C: Context,
167    {
168        self.write_bytes(cx, &[b])
169    }
170}
171
172impl<'a, W> IntoWriter for &'a mut W
173where
174    W: ?Sized + Writer,
175{
176    type Ok = W::Ok;
177    type Writer = &'a mut W;
178
179    #[inline]
180    fn into_writer(self) -> Self::Writer {
181        self
182    }
183}
184
185impl<W> Writer for &mut W
186where
187    W: ?Sized + Writer,
188{
189    type Ok = W::Ok;
190    type Mut<'this>
191        = &'this mut W
192    where
193        Self: 'this;
194
195    #[inline]
196    fn finish<C>(&mut self, cx: C) -> Result<Self::Ok, C::Error>
197    where
198        C: Context,
199    {
200        (*self).finish(cx)
201    }
202
203    #[inline]
204    fn borrow_mut(&mut self) -> Self::Mut<'_> {
205        self
206    }
207
208    #[inline]
209    fn extend<C>(&mut self, cx: C, buffer: Vec<u8, C::Allocator>) -> Result<(), C::Error>
210    where
211        C: Context,
212    {
213        (*self).extend(cx, buffer)
214    }
215
216    #[inline]
217    fn write_bytes<C>(&mut self, cx: C, bytes: &[u8]) -> Result<(), C::Error>
218    where
219        C: Context,
220    {
221        (*self).write_bytes(cx, bytes)
222    }
223
224    #[inline]
225    fn write_byte<C>(&mut self, cx: C, b: u8) -> Result<(), C::Error>
226    where
227        C: Context,
228    {
229        (*self).write_byte(cx, b)
230    }
231}
232
233#[cfg(feature = "alloc")]
234impl Writer for rust_alloc::vec::Vec<u8> {
235    type Ok = ();
236    type Mut<'this>
237        = &'this mut Self
238    where
239        Self: 'this;
240
241    #[inline]
242    fn finish<C>(&mut self, _: C) -> Result<Self::Ok, C::Error>
243    where
244        C: Context,
245    {
246        Ok(())
247    }
248
249    #[inline]
250    fn borrow_mut(&mut self) -> Self::Mut<'_> {
251        self
252    }
253
254    #[inline]
255    fn extend<C>(&mut self, cx: C, buffer: Vec<u8, C::Allocator>) -> Result<(), C::Error>
256    where
257        C: Context,
258    {
259        // SAFETY: the buffer never outlives this function call.
260        self.write_bytes(cx, buffer.as_slice())
261    }
262
263    #[inline]
264    fn write_bytes<C>(&mut self, cx: C, bytes: &[u8]) -> Result<(), C::Error>
265    where
266        C: Context,
267    {
268        self.extend_from_slice(bytes);
269        cx.advance(bytes.len());
270        Ok(())
271    }
272
273    #[inline]
274    fn write_byte<C>(&mut self, cx: C, b: u8) -> Result<(), C::Error>
275    where
276        C: Context,
277    {
278        self.push(b);
279        cx.advance(1);
280        Ok(())
281    }
282}
283
284impl<'a> IntoWriter for &'a mut [u8] {
285    type Ok = usize;
286    type Writer = SliceMutWriter<'a>;
287
288    #[inline]
289    fn into_writer(self) -> Self::Writer {
290        SliceMutWriter::new(self)
291    }
292}
293
294/// A writer that writes against an underlying [`Vec`].
295pub struct BufWriter<A>
296where
297    A: Allocator,
298{
299    buf: Vec<u8, A>,
300}
301
302impl<A> BufWriter<A>
303where
304    A: Allocator,
305{
306    /// Construct a new buffer writer.
307    ///
308    /// # Examples
309    ///
310    /// ```
311    /// use musli::alloc::Global;
312    /// use musli::writer::BufWriter;
313    ///
314    /// let writer = BufWriter::new(Global::new());
315    /// ```
316    pub fn new(alloc: A) -> Self {
317        Self {
318            buf: Vec::new_in(alloc),
319        }
320    }
321
322    /// Coerce into inner buffer.
323    ///
324    /// # Examples
325    ///
326    /// ```
327    /// use musli::alloc::Global;
328    /// use musli::writer::BufWriter;
329    ///
330    /// let writer = BufWriter::new(Global::new());
331    /// let buffer = writer.into_inner();
332    /// assert!(buffer.is_empty());
333    /// ```
334    pub fn into_inner(self) -> Vec<u8, A> {
335        self.buf
336    }
337}
338
339impl<A> Writer for BufWriter<A>
340where
341    A: Allocator,
342{
343    type Ok = ();
344    type Mut<'this>
345        = &'this mut Self
346    where
347        Self: 'this;
348
349    #[inline]
350    fn finish<C>(&mut self, _: C) -> Result<Self::Ok, C::Error>
351    where
352        C: Context,
353    {
354        Ok(())
355    }
356
357    #[inline]
358    fn borrow_mut(&mut self) -> Self::Mut<'_> {
359        self
360    }
361
362    #[inline]
363    fn extend<C>(&mut self, cx: C, buffer: Vec<u8, C::Allocator>) -> Result<(), C::Error>
364    where
365        C: Context,
366    {
367        self.buf
368            .extend_from_slice(buffer.as_slice())
369            .map_err(cx.map())?;
370        Ok(())
371    }
372
373    #[inline]
374    fn write_bytes<C>(&mut self, cx: C, bytes: &[u8]) -> Result<(), C::Error>
375    where
376        C: Context,
377    {
378        self.buf.extend_from_slice(bytes).map_err(cx.map())?;
379        Ok(())
380    }
381}
382
383/// Overflow when trying to write to a slice.
384#[derive(Debug)]
385struct SliceOverflow {
386    n: usize,
387    capacity: usize,
388}
389
390impl fmt::Display for SliceOverflow {
391    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
392        let SliceOverflow { n, capacity } = self;
393
394        write!(
395            f,
396            "Tried to write {n} bytes to slice, with a remaining capacity of {capacity}"
397        )
398    }
399}