Skip to main content

libtw2_buffer/
lib.rs

1//! `buffer` provides safe, write-only and generics-free byte buffers that can
2//! be used without initializing them first.
3//!
4//! The main trait of this library is `Buffer` that represents a type that can
5//! contain uninitialized bytes (such as `Vec`, `ArrayVec`, etc.) and can
6//! safely be read into (e.g. using `ReadBuffer`).
7//!
8//! In order to keep code sizes down, such a type implementing `Buffer` is
9//! quickly converted into the struct `BufferRef`, so this is the type
10//! receivers of types implementing `Buffer`s should work with.
11//!
12//! An example for the usage of this trait can be found with `ReadBuffer` which
13//! implements reading into a buffer without initializing it first.
14
15#![warn(missing_docs)]
16
17#[macro_use]
18extern crate mac;
19
20use std::slice;
21
22pub use impls::arrayvec::ArrayVecBuffer;
23pub use impls::buffer_ref::BufferRefBuffer;
24pub use impls::cap_at::CapAt;
25pub use impls::cap_at::CapAtBuffer;
26pub use impls::slice::SliceBuffer;
27pub use impls::slice_ref::SliceRefBuffer;
28pub use impls::vec::VecBuffer;
29pub use traits::read_buffer_ref;
30pub use traits::ReadBuffer;
31pub use traits::ReadBufferMarker;
32pub use traits::ReadBufferRef;
33
34mod impls;
35mod traits;
36
37/// An error occuring when too many bytes are being pushed into a buffer.
38#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
39pub struct CapacityError;
40
41unsafe fn wildly_unsafe<'a, 'b>(slice: &'a mut [u8]) -> &'b mut [u8] {
42    slice::from_raw_parts_mut(slice.as_mut_ptr(), slice.len())
43}
44
45/// A reference to an uninitialized or partially initialized byte buffer.
46///
47/// It keeps track of how many bytes (from the start of the buffer) are
48/// initialized.
49pub struct BufferRef<'data, 'size> {
50    buffer: &'data mut [u8],
51    initialized_: &'size mut usize,
52}
53
54impl<'d, 's> BufferRef<'d, 's> {
55    /// Creates a buffer reference from the buffer and a pointer where the
56    /// length should be written to.
57    ///
58    /// Important: `initialized` must initially be zero.
59    pub fn new(buffer: &'d mut [u8], initialized: &'s mut usize) -> BufferRef<'d, 's> {
60        debug_assert!(*initialized == 0);
61        BufferRef {
62            buffer: buffer,
63            initialized_: initialized,
64        }
65    }
66
67    /// Advances the split of initialized/uninitialized data by `num_bytes` to
68    /// the right.
69    pub unsafe fn advance(&mut self, num_bytes: usize) {
70        assert!(*self.initialized_ + num_bytes <= self.buffer.len());
71        *self.initialized_ += num_bytes;
72    }
73
74    /// Writes the bytes yielded by the `bytes` iterator into the buffer.
75    ///
76    /// If the iterator yields more bytes than the buffer can contain, a
77    /// `CapacityError` is returned.
78    pub fn extend<I>(&mut self, bytes: I) -> Result<(), CapacityError>
79    where
80        I: Iterator<Item = u8>,
81    {
82        let mut buf_iter = (&mut self.buffer[*self.initialized_..]).into_iter();
83        for b in bytes {
84            *unwrap_or_return!(buf_iter.next(), Err(CapacityError)) = b;
85            *self.initialized_ += 1;
86        }
87        Ok(())
88    }
89
90    /// Writes the byte slice into the buffer.
91    ///
92    /// If the slice contains more bytes than the buffer can contain, a
93    /// `CapacityError` is returned.
94    pub fn write(&mut self, bytes: &[u8]) -> Result<(), CapacityError> {
95        self.extend(bytes.iter().cloned())
96    }
97
98    /// Returns the uninitialized part of the buffer.
99    pub unsafe fn uninitialized_mut(&mut self) -> &mut [u8] {
100        &mut self.buffer[*self.initialized_..]
101    }
102
103    /// Consumes the (mutable) buffer reference to produce a slice of the
104    /// initialized data that is independent from the `BufferRef` instance.
105    pub fn initialized(self) -> &'d [u8] {
106        &self.buffer[..*self.initialized_]
107    }
108
109    /// Returns the amount of uninitialized bytes that are left.
110    pub fn remaining(&self) -> usize {
111        self.buffer.len() - *self.initialized_
112    }
113
114    fn cap_at(self, index: usize) -> BufferRef<'d, 's> {
115        assert!(*self.initialized_ == 0);
116        BufferRef {
117            buffer: &mut self.buffer[..index],
118            initialized_: self.initialized_,
119        }
120    }
121}
122
123/// Convenience function that converts a `T: Buffer` into a `BufferRef`.
124pub fn with_buffer<'a, T: Buffer<'a>, F, R>(buffer: T, f: F) -> R
125where
126    F: for<'b> FnOnce(BufferRef<'a, 'b>) -> R,
127{
128    let mut intermediate = buffer.to_to_buffer_ref();
129    f(intermediate.to_buffer_ref())
130}
131
132/// Trait for types that can act as buffer for bytes.
133///
134/// It should be accepted as trait bound for functions that accept buffers, and
135/// should immediately be converted to `BufferRef` using the `with_buffer`
136/// function.
137pub trait Buffer<'data> {
138    /// Intermediate result of converting the `T: Buffer` into a `BufferRef`.
139    type Intermediate: ToBufferRef<'data>;
140    /// Converts the `T: Buffer` into the intermediate step to `BufferRef`.
141    fn to_to_buffer_ref(self) -> Self::Intermediate;
142    /// Caps the buffer at the specified byte index.
143    ///
144    /// This means that no more than `len` bytes will be written to the buffer.
145    fn cap_at(self, len: usize) -> CapAt<'data, Self>
146    where
147        Self: Sized,
148    {
149        self.cap_at_impl(len)
150    }
151}
152
153/// Internal trait for the intermediate result of converting a `T: Buffer` into
154/// a `BufferRef`.
155pub trait ToBufferRef<'data> {
156    /// Second step to convert a `T: Buffer` to a `BufferRef`.
157    fn to_buffer_ref<'size>(&'size mut self) -> BufferRef<'data, 'size>;
158}
159
160trait CapAtImpl<'data>: Buffer<'data> {
161    fn cap_at_impl(self, len: usize) -> CapAt<'data, Self>
162    where
163        Self: Sized;
164}