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}