bincode_next/enc/
write.rs

1//! This module contains writer-based structs and traits.
2//!
3//! Because `std::io::Write` is only limited to `std` and not `core`, we provide our own [Writer].
4
5use crate::error::EncodeError;
6
7/// Trait that indicates that a struct can be used as a destination to encode data too. This is used by [Encode]
8///
9/// [Encode]: ../trait.Encode.html
10pub trait Writer {
11    /// Write `bytes` to the underlying writer. Exactly `bytes.len()` bytes must be written, or else an error should be returned.
12    ///
13    /// # Errors
14    ///
15    /// Returns `EncodeError::UnexpectedEnd` if the writer does not have enough space.
16    fn write(&mut self, bytes: &[u8]) -> Result<(), EncodeError>;
17}
18
19impl<T: Writer> Writer for &mut T {
20    #[inline]
21    fn write(&mut self, bytes: &[u8]) -> Result<(), EncodeError> {
22        (**self).write(bytes)
23    }
24}
25
26/// A helper struct that implements `Writer` for a `&[u8]` slice.
27///
28/// ```
29/// use bincode_next::enc::write::{Writer, SliceWriter};
30///
31/// let destination = &mut [0u8; 100];
32/// let mut writer = SliceWriter::new(destination);
33/// writer.write(&[1, 2, 3, 4, 5]).unwrap();
34///
35/// assert_eq!(writer.bytes_written(), 5);
36/// assert_eq!(destination[0..6], [1, 2, 3, 4, 5, 0]);
37/// ```
38pub struct SliceWriter<'storage> {
39    slice: &'storage mut [u8],
40    original_length: usize,
41}
42
43impl<'storage> SliceWriter<'storage> {
44    /// Create a new instance of `SliceWriter` with the given byte array.
45    pub const fn new(bytes: &'storage mut [u8]) -> Self {
46        let original = bytes.len();
47        Self {
48            slice: bytes,
49            original_length: original,
50        }
51    }
52
53    /// Return the amount of bytes written so far.
54    #[must_use]
55    pub const fn bytes_written(&self) -> usize {
56        self.original_length - self.slice.len()
57    }
58}
59
60impl Writer for SliceWriter<'_> {
61    #[inline(always)]
62    fn write(&mut self, bytes: &[u8]) -> Result<(), EncodeError> {
63        if bytes.len() > self.slice.len() {
64            return Err(EncodeError::UnexpectedEnd);
65        }
66        let (a, b) = core::mem::take(&mut self.slice).split_at_mut(bytes.len());
67        a.copy_from_slice(bytes);
68        self.slice = b;
69
70        Ok(())
71    }
72}
73
74/// A writer that counts how many bytes were written. This is useful for e.g. pre-allocating buffers before writing to them.
75#[derive(Default)]
76pub struct SizeWriter {
77    /// the amount of bytes that were written so far
78    pub bytes_written: usize,
79}
80impl Writer for SizeWriter {
81    #[inline(always)]
82    fn write(&mut self, bytes: &[u8]) -> Result<(), EncodeError> {
83        self.bytes_written += bytes.len();
84
85        Ok(())
86    }
87}