owned_buf/
lib.rs

1//! An owned, fixed length buffer of bytes (`u8`s) and helper types.
2//!
3//! The primary type is [`OwnedBuf`] which is a sort-of abstract wrapper type for an owned
4//! sequence of bytes. [`OwnedSlice`] and [`OwnedCursor`] give read access to the filled
5//! part of an `OwnedBuf` and write access to the unfilled part of an `OwnedBuf`, respectively.
6//!
7//! An `OwnedBuf` is primarily useful where an IO operation takes ownership of supplied buffers, for
8//! example [`async OwnedRead`](TODO).
9//!
10//! An `OwnedBuf`'s data can be in either filled (i.e., data has been written to a byte) or unfilled.
11//! Unfilled data may be with initialized or uninitialized. An `OwnedBuf` may contain all three
12//! kinds of data at the same time and tracks the state of bytes.
13//!
14//! ## Lifecycle
15//!
16//! An `OwnedBuf` is never directly created. Instead, an existing sequence of bytes (e.g., a
17//! `Vec<u8>`) is transformed into an `OwnedBuf`. Unlike when taking a slice, the previous sequence
18//! type is consumed and ownership of its memory is transferred to the `OwnedBuf` (the memory itself
19//! does not move).
20//!
21//! The `OwnedBuf` is then used. It is transformed into an `OwnedCursor` to write to it and into an
22//! `OwnedSlice` to read from it. These types can be transformed back into an `OwnedBuf` as needed.
23//! With each transformation, ownership is passed to the new type. If needed the `OwnedBuf` can be
24//! reset.
25//!
26//! An `OwnedBuf` can be transformed back into the original sequence type. Any data written to the
27//! `OwnedBuf` can be read. The sequence type can be used in the usual way, including its
28//! destruction. If an `OwnedBuf` is not transformed back into the previous type, then its destructor
29//! calls a function supplied when the buffer is created. Typically, that converts the buffer into
30//! the original sequence type and calls it destructor.
31//!
32//! ### Destructor safety
33//!
34//! An `OwnedBuf` takes a destructor as a function pointer and calls it from the `OwnedBuf`'s
35//! destructor. The function pointer is marked as `unsafe` and the safety invariant is that the
36//! `OwnedBuf` was created from the collection type expected by the destructor function. This
37//! invariant must be ensured when the `OwnedBuf` is created, thus `OwnedBuf::new` is `unsafe`.
38//!
39//! ## Conversion from user types
40//!
41//! This module includes functionality to transform an `OwnedBuf` from and to a `Vec<u8>` or
42//! `Vec<MaybeUninit<u8>>`. `OwnedBuf` is designed to be usable with any owned sequence of bytes. To
43//! create an `OwnedBuf` use [`OwnedBuf::new`], you'll supply a data pointer, some metadata, and a
44//! destructor function (see below). To transform from an `OwnedBuf`, you use `into_raw_parts` to
45//! get the internal state of the `OwnedBuf` and then create the sequence type in the usual way.
46//!
47//! An `OwnedBuf`'s destructor function has type `&'static dyn Fn(&mut OwnedBuf<A>)`, it passes a
48//! mutable reference to the destructor, however, it is guaranteed that the `OwnedBuf` will not be
49//! accessed after calling the destructor function. Typically, the destructor function will use
50//! [`std::ptr::read`] to get the `OwnedBuf` by value, transform it into the original sequence type,
51//! and (implicitly) call its destructor.
52//!
53//! ## Fields
54//!
55//! The fields of an `OwnedBuf` are private and cannot be modified directly to help ensure safety
56//! invariants. However, creating an `OwnedBuf` using `new` or calling `into_raw_parts` exposes all
57//! its fields. These fields are only intended to be used for implementing conversions from and to
58//! other collection types, not for end users. We'll summarise the fields here rather than across
59//! multiple functions.
60//!
61//! * `data: *mut MaybeUninit<u8>` a pointer to the data in the buffer
62//! * `dtor: unsafe fn(&mut OwnedBuf)` a function pointer to the backing-buffer-dependent destructor
63//! function
64//! * `user_data: *const ()` a pointer to any data, intended to be used by `self.dtor`
65//! * `capacity: usize` the total size of the buffer
66//! * `filled: usize` the number of bytes in the buffer known to be filled
67//! * `init: usize` the number of bytes in the buffer known to be initialized
68//!
69//! # Examples
70//!
71//! Creating an `OwnedBuf` from a `Vec`.
72//!
73//! ```
74//! # use owned_buf::OwnedBuf;
75//! let vec = vec![1u8, 2, 3];
76//! let buf: OwnedBuf = vec.into();
77//!
78//! // Use `filled` to view `buf` as an `OwnedSlice` to read from it.
79//! assert_eq!(1, buf.filled()[0]);
80//!
81//! // `Vec`'s destructor will be called via `OwnedBuf`'s.
82//! ```
83//!
84//! Writing into an `OwnedBuf` and converting it back into a `Vec`.
85//!
86//! ```
87//! # use owned_buf::OwnedBuf;
88//! let vec: Vec<u8> = Vec::with_capacity(8);
89//! let buf: OwnedBuf = vec.into();
90//! assert_eq!(0, buf.filled_len());
91//! assert_eq!(8, buf.capacity());
92//!
93//! // Get a cursor to write into the `OwnedBuf`.
94//! let mut cursor = buf.unfilled();
95//! cursor.write_slice(&[0, 1, 2, 3]);
96//!
97//! // Convert the cursor back into an `OwnedBuf`.
98//! let buf = cursor.into_buf();
99//! assert_eq!(4, buf.filled_len());
100//!
101//! let vec = unsafe { buf.into_vec() };
102//! assert_eq!(4, vec.len());
103//! assert_eq!(8, vec.capacity());
104//! assert_eq!(3, vec[3]);
105//! ```
106
107#![feature(maybe_uninit_slice)]
108#![feature(maybe_uninit_write_slice)]
109#![feature(vec_into_raw_parts)]
110
111use core::{
112    cmp::{max, min},
113    mem::{ManuallyDrop, MaybeUninit},
114    ops, ptr, slice,
115};
116use std::io::{Result, Write};
117
118/// An owned, fixed length buffer of bytes.
119///
120/// An `OwnedBuf` is created from an existing collection type, it is an abstract
121/// wrapper of sorts. See the [module docs](self) for details and examples.
122///
123/// This type is a sort of "double cursor". It tracks three regions in the buffer: a region at the beginning of the
124/// buffer that has been logically filled with data, a region that has been initialized at some point but not yet
125/// logically filled, and a region at the end that is fully uninitialized. The filled region is guaranteed to be a
126/// subset of the initialized region. The filled part can grow or shrink, the initialized part can
127/// only grow, and capacity of the buffer (i.e., its total length) is fixed.
128///
129/// In summary, the contents of the buffer can be visualized as:
130/// ```not_rust
131/// [             capacity              ]
132/// [ filled |         unfilled         ]
133/// [    initialized    | uninitialized ]
134/// ```
135///
136/// The API of `OwnedBuf` is focussed on creation and destruction. To read from the filled part,
137/// get a view of the buffer using an `OwnedSlice`. To write into the unfilled part, get a view of
138/// the buffer using and `OwnedCursor`. Both of these types can be converted back into an `OwnedBuf`.
139pub struct OwnedBuf {
140    data: *mut MaybeUninit<u8>,
141    dtor: unsafe fn(&mut OwnedBuf),
142    user_data: *const (),
143    capacity: usize,
144    /// The length of `self.data` which is known to be filled.
145    filled: usize,
146    /// The length of `self.data` which is known to be initialized.
147    init: usize,
148}
149
150impl Into<OwnedSlice> for OwnedBuf {
151    fn into(self) -> OwnedSlice {
152        self.filled()
153    }
154}
155
156impl Into<OwnedCursor> for OwnedBuf {
157    fn into(self) -> OwnedCursor {
158        self.unfilled()
159    }
160}
161
162impl OwnedBuf {
163    /// Create a new OwnedBuf.
164    ///
165    /// # Safety
166    ///
167    /// See module docs for safety requirements.
168    #[inline]
169    pub unsafe fn new(
170        data: *mut MaybeUninit<u8>,
171        dtor: unsafe fn(&mut OwnedBuf),
172        user_data: *const (),
173        capacity: usize,
174        filled: usize,
175        init: usize,
176    ) -> OwnedBuf {
177        OwnedBuf {
178            data,
179            dtor,
180            user_data,
181            capacity,
182            filled,
183            init,
184        }
185    }
186
187    /// Convert this buffer into a `Vec` of `u8`.
188    ///
189    /// # Safety
190    ///
191    /// It is only safe to use this method if the buffer was created from a `Vec<u8>`.
192    #[inline]
193    pub unsafe fn into_vec(self) -> Vec<u8> {
194        let (data, _, _, filled, _, capacity) = self.into_raw_parts();
195        Vec::from_raw_parts(data as *mut u8, filled, capacity)
196    }
197
198    /// Convert this buffer into a `Vec` of `MaybeUninit<u8>`.
199    ///
200    /// # Safety
201    ///
202    /// It is only safe to use this method if the buffer was created from a `Vec<MaybeUninit<u8>>`.
203    #[inline]
204    pub unsafe fn into_maybe_uninit_vec(self) -> Vec<MaybeUninit<u8>> {
205        let (data, _, _, filled, _, capacity) = self.into_raw_parts();
206        Vec::from_raw_parts(data, filled, capacity)
207    }
208
209    /// Returns the total size of the buffer.
210    #[inline]
211    pub fn capacity(&self) -> usize {
212        self.capacity
213    }
214
215    /// Returns the length of the filled part of the buffer.
216    #[inline]
217    pub fn filled_len(&self) -> usize {
218        self.filled
219    }
220
221    /// Returns the length of the initialized part of the buffer.
222    #[inline]
223    pub fn init_len(&self) -> usize {
224        self.init
225    }
226
227    /// Returns an `OwnedSlice` covering the filled part of this buffer.
228    #[inline]
229    pub fn filled(self) -> OwnedSlice {
230        OwnedSlice {
231            start: 0,
232            end: self.filled,
233            buf: self,
234        }
235    }
236
237    /// Returns an `OwnedSlice` covering a slice of the filled part of this buffer.
238    ///
239    /// The supplied range must be within the filled part of the buffer.
240    ///
241    /// # Panics
242    ///
243    /// This function will panic if `range` is outside the bounds of the filled part of the buffer.
244    #[inline]
245    pub fn filled_slice(self, range: impl UsizeRange) -> OwnedSlice {
246        let (start, end) = range.absolute_indices(0, self.filled);
247        OwnedSlice {
248            start,
249            end,
250            buf: self,
251        }
252    }
253
254    /// Returns a cursor over the unfilled part of the buffer.
255    #[inline]
256    pub fn unfilled(self) -> OwnedCursor {
257        OwnedCursor {
258            end: self.capacity,
259            buf: self,
260        }
261    }
262
263    /// Returns a cursor over a slice of the unfilled part of the buffer.
264    ///
265    /// The supplied range covers the whole buffer, not just the unfilled part. The upper bound
266    /// of the range must be within the unfilled part.
267    ///
268    /// # Examples
269    ///
270    /// Where `buf` has a capacity (total length) of 16 bytes and the first 4 bytes are filled,
271    /// `buf.unfilled_slice(..8)` will return a cursor over the first 4 unfilled bytes.
272    #[inline]
273    pub fn unfilled_slice(self, range: ops::RangeTo<usize>) -> OwnedCursor {
274        assert!(range.end >= self.filled && range.end <= self.capacity);
275        OwnedCursor {
276            end: range.end,
277            buf: self,
278        }
279    }
280
281    /// Clears the buffer, resetting the filled region to empty.
282    ///
283    /// The number of initialized bytes is not changed, and the contents of the buffer are not modified.
284    #[inline]
285    pub fn clear(&mut self) -> &mut Self {
286        self.filled = 0;
287        self
288    }
289
290    /// Asserts that the first `n` bytes of the buffer are initialized.
291    ///
292    /// `OwnedBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer
293    /// bytes than are already known to be initialized.
294    ///
295    /// # Safety
296    ///
297    /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized.
298    #[inline]
299    pub unsafe fn set_init(&mut self, n: usize) -> &mut Self {
300        self.init = max(self.init, n);
301        self
302    }
303
304    /// Decomposes this `OwnedBuf` into its raw components.
305    ///
306    /// Returns `(data, dtor, filled, init, capacity)` where `data` is a pointer to the buffer's
307    /// data in memory, `dtor` is the buffer's destructor function, `filled` is the number of bytes
308    /// which are filled with data, `init` is the number of bytes which have been initialised (i.e.,
309    /// which are safe to treat as `u8` rather than `MaybeUninit<u8>`), and `capacity` is the total
310    /// length of the buffer. `filled <= init <= capacity`.
311    ///
312    /// # Safety
313    ///
314    /// See module docs for safety requirements on the returned destructor function.
315    #[inline]
316    pub fn into_raw_parts(
317        self,
318    ) -> (
319        *mut MaybeUninit<u8>,
320        unsafe fn(&mut OwnedBuf),
321        *const (),
322        usize,
323        usize,
324        usize,
325    ) {
326        let this = ManuallyDrop::new(self);
327        (
328            this.data,
329            this.dtor,
330            this.user_data,
331            this.filled,
332            this.init,
333            this.capacity,
334        )
335    }
336}
337
338impl Drop for OwnedBuf {
339    fn drop(&mut self) {
340        unsafe { (self.dtor)(self) }
341    }
342}
343
344unsafe fn drop_vec(buf: &mut OwnedBuf) {
345    let (data, _, _, filled, _, capacity) = unsafe { ptr::read(buf) }.into_raw_parts();
346    let _vec = Vec::from_raw_parts(data, filled, capacity);
347}
348
349impl From<Vec<MaybeUninit<u8>>> for OwnedBuf {
350    fn from(v: Vec<MaybeUninit<u8>>) -> OwnedBuf {
351        let (data, len, capacity) = v.into_raw_parts();
352        OwnedBuf {
353            data,
354            dtor: drop_vec,
355            user_data: ptr::null(),
356            capacity,
357            filled: len,
358            init: len,
359        }
360    }
361}
362
363impl From<Vec<u8>> for OwnedBuf {
364    fn from(v: Vec<u8>) -> OwnedBuf {
365        let (data, len, capacity) = v.into_raw_parts();
366        OwnedBuf {
367            data: data as *mut MaybeUninit<u8>,
368            dtor: drop_vec,
369            user_data: ptr::null(),
370            capacity,
371            filled: len,
372            init: len,
373        }
374    }
375}
376
377/// An owned slice of an `OwnedBuf`.
378///
379/// Like a regular slice, an `OwnedSlice` may be a view of the whole buffer or
380/// a subslice of it. An `OwnedSlice` can be further shrunk. An `OwnedSlice` is
381/// always immutable. An `OwnedSlice` takes ownership of the `OwnedBuf` and its
382/// underlying data when it is created, it can always be converted back into an
383/// `OwnedBuf` (which will be the full, original buffer, not a subslice of it).
384///
385/// The primary way to read an `OwnedSlice` is as a `&[u8]` via dereferencing. E.g.,
386///
387/// ```
388/// # use owned_buf::OwnedBuf;
389/// let buf: OwnedBuf = vec![1u8, 2, 3, 4].into();
390/// let slice = buf.filled();
391/// assert_eq!(slice[1], 2);
392/// ```
393pub struct OwnedSlice {
394    buf: OwnedBuf,
395    // Invariant: start <= buf.filled
396    start: usize,
397    // Invariant: end >= start && end <= buf.filled
398    end: usize,
399}
400
401impl OwnedSlice {
402    /// Take an (owned) subslice of this `OwnedSlice`.
403    #[inline]
404    pub fn slice(self, range: impl UsizeRange) -> Self {
405        let (start, end) = range.absolute_indices(self.start, self.end);
406        OwnedSlice {
407            buf: self.buf,
408            start,
409            end,
410        }
411    }
412
413    /// Convert this slice back into an `OwnedBuf`.
414    #[inline]
415    pub fn into_buf(self) -> OwnedBuf {
416        self.buf
417    }
418}
419
420impl ops::Deref for OwnedSlice {
421    type Target = [u8];
422
423    fn deref(&self) -> &[u8] {
424        // SAFETY: We only slice the filled part of the buffer, which is always valid
425        unsafe {
426            MaybeUninit::slice_assume_init_ref(slice::from_raw_parts(self.buf.data, self.end))
427        }
428    }
429}
430
431/// A write-only cursor over an `OwnedBuf`.
432///
433/// Created via `OwnedBuf::unfilled` or using `Into`.
434///
435/// An `OwnedCursor` represents the unfilled portion of an `OwnedBuf`, as data is filled it becomes
436/// inaccessible via the cursor, so the start of the cursor (or current position, if you think of it
437/// that way) is always the first unfilled byte of the underlying buffer. An `OwnedCursor` can contain
438/// both initialized and uninitialized bytes.
439///
440/// An `OwnedCursor` takes ownership of the `OwnedBuf` when it is created. It can always be converted
441/// back into and `OwnedBuf`.
442pub struct OwnedCursor {
443    buf: OwnedBuf,
444    // Invariant: end >= buf.filled && end <= buf.capacity
445    end: usize,
446}
447
448impl OwnedCursor {
449    /// Convert this cursor back into its underlying buffer.
450    #[inline]
451    pub fn into_buf(self) -> OwnedBuf {
452        self.buf
453    }
454
455    /// Returns the available space in the cursor.
456    #[inline]
457    pub fn capacity(&self) -> usize {
458        self.end - self.buf.filled
459    }
460
461    /// Returns a mutable reference to the initialized portion of the cursor.
462    #[inline]
463    pub fn init_mut(&mut self) -> &mut [u8] {
464        let start = self.buf.filled;
465        let end = min(self.end, self.buf.init);
466
467        // SAFETY: We only slice the initialized part of the buffer, which is always valid
468        unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf_as_bytes()[start..end]) }
469    }
470
471    /// Returns a mutable reference to the uninitialized part of the cursor.
472    ///
473    /// It is safe to uninitialize any of these bytes.
474    #[inline]
475    pub fn uninit_mut(&mut self) -> &mut [MaybeUninit<u8>] {
476        let start = self.buf.init;
477        let end = max(self.end, self.buf.init);
478        unsafe { &mut self.buf_as_bytes()[start..end] }
479    }
480
481    /// Returns a mutable reference to the whole cursor.
482    ///
483    /// # Safety
484    ///
485    /// The caller must not uninitialize any bytes in the initialized portion of the cursor.
486    #[inline]
487    pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit<u8>] {
488        let start = self.buf.filled;
489        let end = self.end;
490        &mut self.buf_as_bytes()[start..end]
491    }
492
493    #[inline]
494    unsafe fn buf_as_bytes(&mut self) -> &mut [MaybeUninit<u8>] {
495        slice::from_raw_parts_mut(self.buf.data, self.buf.capacity)
496    }
497
498    /// Advance the cursor by asserting that `n` bytes have been filled.
499    ///
500    /// After advancing, the `n` bytes are no longer accessible via the cursor and can only be
501    /// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements
502    /// and its unfilled portion (and the capacity of this cursor) shrinks by `n` elements.
503    ///
504    /// # Safety
505    ///
506    /// The caller must ensure that the first `n` bytes of the cursor have been properly
507    /// initialised.
508    #[inline]
509    pub unsafe fn advance(&mut self, n: usize) -> &mut Self {
510        self.buf.filled += n;
511        self.buf.init = max(self.buf.init, self.buf.filled);
512        self
513    }
514
515    /// Initializes all bytes in the cursor.
516    #[inline]
517    pub fn ensure_init(&mut self) -> &mut Self {
518        for byte in self.uninit_mut() {
519            byte.write(0);
520        }
521        self.buf.init = max(self.end, self.buf.init);
522
523        self
524    }
525
526    /// Asserts that the first `n` unfilled bytes of the cursor are initialized.
527    ///
528    /// `OwnedBuf` assumes that bytes are never de-initialized, so this method does nothing when
529    /// called with fewer bytes than are already known to be initialized.
530    ///
531    /// # Safety
532    ///
533    /// The caller must ensure that the first `n` bytes of the cursor have already been initialized.
534    #[inline]
535    pub unsafe fn set_init(&mut self, n: usize) -> &mut Self {
536        self.buf.init = max(self.buf.init, self.buf.filled + n);
537        self
538    }
539
540    /// Copies `data` to the start of the cursor and advances the cursor.
541    ///
542    /// # Panics
543    ///
544    /// Panics if `self.capacity()` is less than `data.len()`.
545    #[inline]
546    pub fn write_slice(&mut self, data: &[u8]) {
547        assert!(self.capacity() >= data.len());
548
549        // SAFETY: we do not de-initialize any of the elements of the slice
550        unsafe {
551            MaybeUninit::write_slice(&mut self.as_mut()[..data.len()], data);
552        }
553
554        // SAFETY: We just added the entire contents of data.
555        unsafe {
556            self.advance(data.len());
557        }
558    }
559}
560
561impl Write for OwnedCursor {
562    fn write(&mut self, buf: &[u8]) -> Result<usize> {
563        let len = min(self.capacity(), buf.len());
564        self.write_slice(&buf[..len]);
565        Ok(len)
566    }
567
568    fn flush(&mut self) -> Result<()> {
569        Ok(())
570    }
571}
572
573/// Any range with `usize` bounds.
574pub trait UsizeRange {
575    fn absolute_indices(&self, start: usize, end: usize) -> (usize, usize);
576}
577
578impl UsizeRange for ops::Range<usize> {
579    #[inline]
580    fn absolute_indices(&self, start: usize, end: usize) -> (usize, usize) {
581        assert!(start + self.start <= end);
582        assert!(start + self.end <= end);
583        (start + self.start, start + self.end)
584    }
585}
586
587impl UsizeRange for ops::RangeFrom<usize> {
588    #[inline]
589    fn absolute_indices(&self, start: usize, end: usize) -> (usize, usize) {
590        assert!(start + self.start <= end);
591        (start + self.start, end)
592    }
593}
594
595impl UsizeRange for ops::RangeFull {
596    #[inline]
597    fn absolute_indices(&self, start: usize, end: usize) -> (usize, usize) {
598        (start, end)
599    }
600}
601
602impl UsizeRange for ops::RangeInclusive<usize> {
603    #[inline]
604    fn absolute_indices(&self, start: usize, end: usize) -> (usize, usize) {
605        assert!(start + self.start() <= end);
606        assert!(start + self.end() + 1 <= end);
607        (start + self.start(), start + self.end() + 1)
608    }
609}
610
611impl UsizeRange for ops::RangeTo<usize> {
612    #[inline]
613    fn absolute_indices(&self, start: usize, end: usize) -> (usize, usize) {
614        assert!(start + self.end <= end);
615        (start, start + self.end)
616    }
617}
618
619impl UsizeRange for ops::RangeToInclusive<usize> {
620    #[inline]
621    fn absolute_indices(&self, start: usize, end: usize) -> (usize, usize) {
622        assert!(start + self.end + 1 <= end);
623        (start, start + self.end + 1)
624    }
625}
626
627#[cfg(test)]
628mod tests {
629    use super::*;
630
631    #[test]
632    fn owned_buf_smoke() {
633        let v: Vec<u8> = vec![1, 2, 3];
634        let buf: OwnedBuf = v.into();
635        let filled = buf.filled();
636        assert_eq!(&*filled, &[1, 2, 3]);
637        let mut buf = filled.into_buf();
638        buf.clear();
639        let slice = buf.filled();
640        assert_eq!(slice.len(), 0);
641        let mut cursor = slice.into_buf().unfilled();
642        cursor.write_slice(&[6, 5, 4]);
643        let v = unsafe { cursor.into_buf().into_vec() };
644        assert_eq!(&*v, &[6, 5, 4]);
645    }
646}