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}