Skip to main content

borrowed_buf/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3#![deny(missing_docs, unsafe_op_in_unsafe_fn)]
4
5#[cfg(feature = "std")]
6extern crate std;
7
8#[cfg(feature = "std")]
9pub mod io;
10
11use core::fmt::{self, Debug, Formatter};
12use core::mem::MaybeUninit;
13use core::ptr::{self, NonNull};
14use core::slice;
15
16/// A borrowed buffer of initially uninitialized elements, which is incrementally filled.
17///
18/// This type makes it safer to work with `MaybeUninit` buffers, such as to read into a buffer
19/// without having to initialize it first. It tracks the region of elements that have been filled
20/// and whether the unfilled region was initialized.
21///
22/// In summary, the contents of the buffer can be visualized as:
23///
24/// ```text
25/// [                capacity                ]
26/// [ filled | unfilled (may be initialized) ]
27/// ```
28///
29/// A `BorrowedBuf` is created around some existing elements (or capacity for elements) via a unique
30/// reference (`&mut`). The `BorrowedBuf` can be configured (e.g., using [`clear`](Self::clear) or
31/// [`set_init`](Self::set_init)), but cannot be directly written. To write into the buffer, use
32/// [`unfilled`](Self::unfilled) to create a [`BorrowedCursor`]. The cursor has write-only access to
33/// the unfilled portion of the buffer (you can think of it as a write-only iterator).
34///
35/// The lifetime `'data` is a bound on the lifetime of the underlying elements.
36///
37/// The type is most commonly used to manage bytes, but can manage any type of elements.
38///
39/// # Examples
40///
41/// ```
42/// use borrowed_buf::BorrowedBuf;
43/// use core::mem::MaybeUninit;
44///
45/// let mut storage = [MaybeUninit::<u8>::uninit(); 8];
46/// let mut buf = BorrowedBuf::from(&mut storage[..]);
47///
48/// buf.unfilled().append(b"abc");
49/// assert_eq!(buf.filled(), b"abc");
50///
51/// buf.clear();
52/// assert_eq!(buf.len(), 0);
53/// ```
54pub struct BorrowedBuf<'data, T> {
55    /// The buffer's underlying elements.
56    buf: &'data mut [MaybeUninit<T>],
57    /// The number of elements of `self.buf` that are known to be filled.
58    filled: usize,
59    /// Whether the entire unfilled part of `self.buf` has explicitly been initialized.
60    init: bool,
61}
62
63impl<T> Debug for BorrowedBuf<'_, T> {
64    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
65        BorrowedBufDebug {
66            init: self.init,
67            filled: self.filled,
68            capacity: self.capacity(),
69        }
70        .fmt(f)
71    }
72}
73
74struct BorrowedBufDebug {
75    init: bool,
76    filled: usize,
77    capacity: usize,
78}
79
80impl Debug for BorrowedBufDebug {
81    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
82        f.debug_struct("BorrowedBuf")
83            .field("init", &self.init)
84            .field("filled", &self.filled)
85            .field("capacity", &self.capacity)
86            .finish()
87    }
88}
89
90/// Creates a new `BorrowedBuf` from a fully initialized slice.
91impl<'data, T: Copy> From<&'data mut [T]> for BorrowedBuf<'data, T> {
92    #[inline]
93    fn from(slice: &'data mut [T]) -> BorrowedBuf<'data, T> {
94        BorrowedBuf {
95            // SAFETY: `T` and `MaybeUninit<T>` have the same layout, and no initialized element is
96            // ever uninitialized as per `BorrowedBuf`'s invariant.
97            buf: unsafe { &mut *(slice as *mut [T] as *mut [MaybeUninit<T>]) },
98            filled: 0,
99            init: true,
100        }
101    }
102}
103
104/// Creates a new `BorrowedBuf` from an uninitialized buffer.
105impl<'data, T: Copy> From<&'data mut [MaybeUninit<T>]> for BorrowedBuf<'data, T> {
106    #[inline]
107    fn from(buf: &'data mut [MaybeUninit<T>]) -> BorrowedBuf<'data, T> {
108        BorrowedBuf {
109            buf,
110            filled: 0,
111            init: false,
112        }
113    }
114}
115
116/// Creates a new `BorrowedBuf` from a cursor.
117///
118/// Use [`BorrowedCursor::with_unfilled_buf`] instead for a safer alternative.
119impl<'data, T: Copy> From<BorrowedCursor<'data, T>> for BorrowedBuf<'data, T> {
120    #[inline]
121    fn from(buf: BorrowedCursor<'data, T>) -> BorrowedBuf<'data, T> {
122        let filled = buf.filled();
123        let init = buf.is_buf_init();
124        let len = buf.buf_len();
125        BorrowedBuf {
126            // SAFETY: no initialized element is ever uninitialized as per `BorrowedBuf`'s
127            // invariant, and the cursor holds the unique access to those elements for `'data`.
128            buf: unsafe { slice::from_raw_parts_mut(buf.buf.as_ptr().add(filled), len - filled) },
129            filled: 0,
130            init,
131        }
132    }
133}
134
135impl<'data, T> BorrowedBuf<'data, T> {
136    /// Returns the total capacity of the buffer.
137    #[inline]
138    pub fn capacity(&self) -> usize {
139        self.buf.len()
140    }
141
142    /// Returns the length of the filled part of the buffer.
143    #[inline]
144    #[allow(clippy::len_without_is_empty)] // Mirrors `core::io::BorrowedBuf`.
145    pub fn len(&self) -> usize {
146        self.filled
147    }
148
149    /// Returns `true` if the buffer is initialized.
150    #[inline]
151    pub fn is_init(&self) -> bool {
152        self.init
153    }
154}
155
156impl<'data, T: Copy> BorrowedBuf<'data, T> {
157    /// Returns a shared reference to the filled portion of the buffer.
158    #[inline]
159    pub fn filled(&self) -> &[T] {
160        // SAFETY: We only slice the filled part of the buffer, which is always valid.
161        unsafe { assume_init_ref(self.buf.get_unchecked(..self.filled)) }
162    }
163
164    /// Returns a mutable reference to the filled portion of the buffer.
165    #[inline]
166    pub fn filled_mut(&mut self) -> &mut [T] {
167        // SAFETY: We only slice the filled part of the buffer, which is always valid.
168        unsafe { assume_init_mut(self.buf.get_unchecked_mut(..self.filled)) }
169    }
170
171    /// Returns a shared reference to the filled portion of the buffer with its original lifetime.
172    #[inline]
173    pub fn into_filled(self) -> &'data [T] {
174        // SAFETY: We only slice the filled part of the buffer, which is always valid.
175        unsafe { assume_init_ref(self.buf.get_unchecked(..self.filled)) }
176    }
177
178    /// Returns a mutable reference to the filled portion of the buffer with its original lifetime.
179    ///
180    /// ```
181    /// use borrowed_buf::BorrowedBuf;
182    /// use core::mem::MaybeUninit;
183    ///
184    /// fn fill(storage: &mut [MaybeUninit<u8>]) -> &mut [u8] {
185    ///     let mut buf = BorrowedBuf::from(storage);
186    ///     buf.unfilled().append(b"done");
187    ///     buf.into_filled_mut()
188    /// }
189    ///
190    /// let mut storage = [MaybeUninit::uninit(); 8];
191    /// assert_eq!(fill(&mut storage), b"done");
192    /// ```
193    #[inline]
194    pub fn into_filled_mut(self) -> &'data mut [T] {
195        // SAFETY: We only slice the filled part of the buffer, which is always valid.
196        unsafe { assume_init_mut(self.buf.get_unchecked_mut(..self.filled)) }
197    }
198
199    /// Returns a cursor over the unfilled part of the buffer.
200    #[inline]
201    pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this, T> {
202        let borrowed_buf = NonNull::from(&mut *self);
203        BorrowedCursor {
204            buf: NonNull::from(&mut *self.buf).cast(),
205            borrowed_buf,
206        }
207    }
208
209    /// Clears the buffer, resetting the filled region to empty.
210    ///
211    /// The contents of the buffer are not modified.
212    #[inline]
213    pub fn clear(&mut self) -> &mut Self {
214        self.filled = 0;
215        self
216    }
217
218    /// Shortens the filled region to `len` elements.
219    ///
220    /// If `len` is greater than or equal to [`len`](Self::len), this has no effect. The contents
221    /// of the buffer are not modified, and the elements cut off stay initialized, so
222    /// [`is_init`](Self::is_init) is unchanged.
223    ///
224    /// This is not part of `core::io::BorrowedBuf`.
225    ///
226    /// ```
227    /// use borrowed_buf::BorrowedBuf;
228    /// use core::mem::MaybeUninit;
229    ///
230    /// let mut storage = [MaybeUninit::uninit(); 8];
231    /// let mut buf = BorrowedBuf::<u8>::from(&mut storage[..]);
232    /// buf.unfilled().append(b"abcdef");
233    /// buf.truncate(2);
234    /// assert_eq!(buf.filled(), b"ab");
235    /// buf.unfilled().append(b"!");
236    /// assert_eq!(buf.filled(), b"ab!");
237    /// ```
238    #[inline]
239    pub fn truncate(&mut self, len: usize) -> &mut Self {
240        if len < self.filled {
241            self.filled = len;
242        }
243        self
244    }
245
246    /// Asserts that the unfilled part of the buffer is initialized.
247    ///
248    /// # Safety
249    ///
250    /// All the elements of the buffer must be initialized.
251    ///
252    /// ```
253    /// use borrowed_buf::BorrowedBuf;
254    /// use core::mem::MaybeUninit;
255    ///
256    /// let mut storage = [MaybeUninit::new(0u8); 4];
257    /// let mut buf = BorrowedBuf::<u8>::from(&mut storage[..]);
258    /// assert!(!buf.is_init());
259    /// // SAFETY: every element of `storage` was initialized above.
260    /// unsafe { buf.set_init() };
261    /// buf.unfilled().advance_checked(4);
262    /// assert_eq!(buf.filled(), &[0; 4]);
263    /// ```
264    #[inline]
265    pub unsafe fn set_init(&mut self) -> &mut Self {
266        self.init = true;
267        self
268    }
269}
270
271/// A writeable view of the unfilled portion of a [`BorrowedBuf`].
272///
273/// The unfilled portion may be uninitialized; see [`BorrowedBuf`] for details.
274///
275/// Data can be written directly to the cursor by using [`append`](BorrowedCursor::append) or
276/// indirectly by getting a slice of part or all of the cursor and writing into the slice. In the
277/// indirect case, the caller must call [`advance`](BorrowedCursor::advance) after writing to inform
278/// the cursor how many elements have been written.
279///
280/// Once elements are written to the cursor, they become part of the filled portion of the
281/// underlying `BorrowedBuf` and can no longer be accessed or re-written by the cursor. In other
282/// words, the cursor tracks the unfilled part of the underlying `BorrowedBuf`.
283///
284/// The lifetime `'a` is a bound on the lifetime of the underlying buffer (which means it is a bound
285/// on the elements in that buffer by transitivity).
286///
287/// # Examples
288///
289/// ```
290/// use borrowed_buf::{BorrowedBuf, BorrowedCursor};
291/// use core::mem::MaybeUninit;
292///
293/// // A producer that only sees the free space.
294/// fn produce(mut cursor: BorrowedCursor<'_, u32>) {
295///     let n = cursor.capacity().min(3);
296///     // SAFETY: only initialized values are written.
297///     let out = unsafe { cursor.as_mut() };
298///     for (i, slot) in out[..n].iter_mut().enumerate() {
299///         slot.write(i as u32 * 10);
300///     }
301///     // SAFETY: the first `n` elements of the cursor were just written.
302///     unsafe { cursor.advance(n) };
303/// }
304///
305/// let mut storage = [MaybeUninit::uninit(); 4];
306/// let mut buf = BorrowedBuf::from(&mut storage[..]);
307/// buf.unfilled().append(&[7]);
308/// produce(buf.unfilled());
309/// assert_eq!(buf.filled(), &[7, 0, 10, 20]);
310/// ```
311pub struct BorrowedCursor<'a, T> {
312    /// The start of the elements of the buffer this cursor was created from.
313    /// Safety invariant: this points to the start of the *whole* buffer of `*borrowed_buf` and is
314    /// valid for reads and writes of `(*borrowed_buf).buf.len()` elements, so that
315    /// `(*borrowed_buf).filled` indexes into it.
316    buf: NonNull<MaybeUninit<T>>,
317    /// The buffer this cursor was created from.
318    /// Safety invariants:
319    /// 1. `(*borrowed_buf).buf` is *never* accessed by the owner of the pointee while the `buf`
320    ///    field above is alive, because there is a `&mut` of the pointee while the cursor is alive.
321    /// 2. We promise to only access the `filled` and `init` fields and the metadata of the `buf`
322    ///    field through the `borrowed_buf` pointer, never triggering any retag of `buf`'s pointer,
323    ///    as the `buf` field above holds a reborrow of it and reaching the parent again would be a
324    ///    foreign access for that reborrow. This includes not making a reference to the whole
325    ///    pointee out of `borrowed_buf`, but only accessing those fields directly through pointer
326    ///    manipulation.
327    borrowed_buf: NonNull<BorrowedBuf<'a, T>>,
328}
329
330// SAFETY: A `BorrowedCursor<'a, T>` is a unique borrow of a `BorrowedBuf<'a, T>`, which is a
331// `&'a mut [MaybeUninit<T>]` and two `Copy` fields. The `buf` raw pointer is used like
332// `&mut [MaybeUninit<T>]` so `T: Send` -> `Send` and `T: Sync` -> `Sync`, and the
333// `borrowed_buf` only touches two `Copy` fields, without depending on `T`.
334unsafe impl<T: Send> Send for BorrowedCursor<'_, T> {}
335// SAFETY: See the `Send` impl above.
336unsafe impl<T: Sync> Sync for BorrowedCursor<'_, T> {}
337
338impl<T> Debug for BorrowedCursor<'_, T> {
339    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
340        let buf = BorrowedBufDebug {
341            init: self.is_buf_init(),
342            filled: self.filled(),
343            capacity: self.buf_len(),
344        };
345
346        f.debug_struct("BorrowedCursor").field("buf", &buf).finish()
347    }
348}
349
350// Helpers to access underlying buffer state.
351impl<'a, T> BorrowedCursor<'a, T> {
352    #[inline]
353    fn buf_mut(&mut self) -> &mut [MaybeUninit<T>] {
354        let len = self.buf_len();
355        // SAFETY: `buf` points to `len` elements that this cursor borrows exclusively.
356        unsafe { slice::from_raw_parts_mut(self.buf.as_ptr(), len) }
357    }
358
359    #[inline]
360    fn buf_len(&self) -> usize {
361        // SAFETY: We read just the metadata of `buf` and avoid retagging the reference.
362        unsafe {
363            let borrowed_buf = self.borrowed_buf.as_ptr();
364            let buf_ptr: *const &'a mut [MaybeUninit<T>] = &raw const (*borrowed_buf).buf;
365            // Same layout:
366            // https://doc.rust-lang.org/reference/type-layout.html#r-layout.pointer.intro
367            let buf_ptr: *const *const [MaybeUninit<T>] = buf_ptr.cast();
368            let buf: *const [MaybeUninit<T>] = *buf_ptr;
369            buf.len()
370        }
371    }
372
373    #[inline]
374    fn unfilled_slice(&mut self) -> &mut [MaybeUninit<T>] {
375        let filled = self.filled();
376        // SAFETY: always in bounds.
377        unsafe { self.buf_mut().get_unchecked_mut(filled..) }
378    }
379
380    #[inline]
381    fn filled(&self) -> usize {
382        // SAFETY: We access just `filled` and avoid foreign read on `buf`.
383        unsafe { (*self.borrowed_buf.as_ptr()).filled }
384    }
385
386    #[inline]
387    fn is_buf_init(&self) -> bool {
388        // SAFETY: We access just `init` and avoid foreign read on `buf`.
389        unsafe { (*self.borrowed_buf.as_ptr()).init }
390    }
391
392    /// # Safety
393    ///
394    /// In case of `true` all the elements of the cursor must be initialized.
395    #[inline]
396    unsafe fn set_buf_init(&mut self, init: bool) {
397        // SAFETY: We access just `init` and avoid foreign read on `buf`.
398        unsafe {
399            (*self.borrowed_buf.as_ptr()).init = init;
400        }
401    }
402
403    /// # Safety
404    ///
405    /// The next `n` elements of the cursor must be initialized.
406    #[inline]
407    unsafe fn add_filled(&mut self, n: usize) {
408        // SAFETY: We access just `filled` and avoid foreign read on `buf`.
409        unsafe {
410            (*self.borrowed_buf.as_ptr()).filled += n;
411        }
412    }
413}
414
415impl<'a, T: Copy> BorrowedCursor<'a, T> {
416    /// Reborrows this cursor by cloning it with a smaller lifetime.
417    ///
418    /// Since a cursor maintains unique access to its underlying buffer, the borrowed cursor is
419    /// not accessible while the new cursor exists.
420    #[inline]
421    pub fn reborrow<'this>(&'this mut self) -> BorrowedCursor<'this, T> {
422        BorrowedCursor {
423            buf: self.buf,
424            borrowed_buf: self.borrowed_buf,
425        }
426    }
427
428    /// Returns the available space in the cursor.
429    #[inline]
430    pub fn capacity(&self) -> usize {
431        self.buf_len() - self.filled()
432    }
433
434    /// Returns the number of elements written to the `BorrowedBuf` this cursor was created from.
435    ///
436    /// In particular, the count returned is shared by all reborrows of the cursor.
437    #[inline]
438    pub fn written(&self) -> usize {
439        self.filled()
440    }
441
442    /// Returns `true` if the buffer is initialized.
443    #[inline]
444    pub fn is_init(&self) -> bool {
445        self.is_buf_init()
446    }
447
448    /// Set the buffer as fully initialized.
449    ///
450    /// # Safety
451    ///
452    /// All the elements of the cursor must be initialized.
453    ///
454    /// ```
455    /// use borrowed_buf::BorrowedBuf;
456    /// use core::mem::MaybeUninit;
457    ///
458    /// let mut storage = [MaybeUninit::<u8>::uninit(); 4];
459    /// let mut buf = BorrowedBuf::from(&mut storage[..]);
460    /// let mut cursor = buf.unfilled();
461    /// // SAFETY: only initialized values are written.
462    /// unsafe { cursor.as_mut() }.fill(MaybeUninit::new(b'x'));
463    /// // SAFETY: every element of the cursor was just written.
464    /// unsafe { cursor.set_init() };
465    /// cursor.advance_checked(4);
466    /// assert_eq!(buf.filled(), b"xxxx");
467    /// ```
468    #[inline]
469    pub unsafe fn set_init(&mut self) {
470        // SAFETY: the caller guarantees that all the elements of the cursor are initialized.
471        unsafe { self.set_buf_init(true) }
472    }
473
474    /// Returns a mutable reference to the whole cursor.
475    ///
476    /// # Safety
477    ///
478    /// The caller must not uninitialize any elements of the cursor if it is initialized.
479    #[inline]
480    pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit<T>] {
481        self.unfilled_slice()
482    }
483
484    /// Advances the cursor by asserting that `n` elements have been filled.
485    ///
486    /// After advancing, the `n` elements are no longer accessible via the cursor and can only be
487    /// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements
488    /// and its unfilled portion (and the capacity of this cursor) shrinks by `n` elements.
489    ///
490    /// If less than `n` elements initialized (by the cursor's point of view), `set_init` should be
491    /// called first.
492    ///
493    /// # Panics
494    ///
495    /// Panics if there are less than `n` elements initialized.
496    #[inline]
497    #[track_caller]
498    pub fn advance_checked(&mut self, n: usize) -> &mut Self {
499        // The subtraction cannot underflow by invariant of this type.
500        let init_unfilled = if self.is_buf_init() {
501            self.buf_len() - self.filled()
502        } else {
503            0
504        };
505        assert!(
506            n <= init_unfilled,
507            "advanced past the initialized part of the buffer"
508        );
509
510        // SAFETY: the next `n` elements are initialized, as asserted above.
511        unsafe { self.advance(n) };
512        self
513    }
514
515    /// Advances the cursor by asserting that `n` elements have been filled.
516    ///
517    /// After advancing, the `n` elements are no longer accessible via the cursor and can only be
518    /// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements
519    /// and its unfilled portion (and the capacity of this cursor) shrinks by `n` elements.
520    ///
521    /// # Safety
522    ///
523    /// The caller must ensure that the first `n` elements of the cursor have been initialized.
524    #[inline]
525    pub unsafe fn advance(&mut self, n: usize) -> &mut Self {
526        // SAFETY: the caller guarantees that the first `n` elements of the cursor are initialized.
527        unsafe { self.add_filled(n) };
528        self
529    }
530
531    /// Append elements to the cursor, advancing position within its buffer.
532    ///
533    /// # Panics
534    ///
535    /// Panics if `self.capacity()` is less than `buf.len()`.
536    ///
537    /// ```
538    /// use borrowed_buf::BorrowedBuf;
539    /// use core::mem::MaybeUninit;
540    ///
541    /// let mut storage = [MaybeUninit::uninit(); 4];
542    /// let mut buf = BorrowedBuf::from(&mut storage[..]);
543    /// buf.unfilled().append(&[1u64, 2]);
544    /// buf.unfilled().append(&[3]);
545    /// assert_eq!(buf.filled(), &[1, 2, 3]);
546    /// ```
547    #[inline]
548    #[track_caller]
549    pub fn append(&mut self, buf: &[T]) {
550        assert!(
551            self.capacity() >= buf.len(),
552            "appended past the end of the buffer"
553        );
554
555        // SAFETY: we do not de-initialize any of the elements of the slice, the destination has
556        // room for `buf.len()` elements as asserted above, and `buf` can't overlap it because the
557        // cursor borrows the destination exclusively.
558        unsafe {
559            let dst = self.as_mut().as_mut_ptr().cast::<T>();
560            ptr::copy_nonoverlapping(buf.as_ptr(), dst, buf.len());
561        }
562
563        // SAFETY: these elements have just been initialized.
564        unsafe { self.advance(buf.len()) };
565    }
566
567    /// Appends `n` copies of `value` to the cursor, advancing position within its buffer.
568    ///
569    /// Like [`append`](Self::append), this writes each element once and leaves the rest of the
570    /// cursor untouched. It does not need a source slice of `n` elements.
571    ///
572    /// This is not part of `core::io::BorrowedCursor`.
573    ///
574    /// # Panics
575    ///
576    /// Panics if `self.capacity()` is less than `n`.
577    ///
578    /// ```
579    /// use borrowed_buf::BorrowedBuf;
580    /// use core::mem::MaybeUninit;
581    ///
582    /// let mut storage = [MaybeUninit::uninit(); 8];
583    /// let mut buf = BorrowedBuf::<u8>::from(&mut storage[..]);
584    /// let mut cursor = buf.unfilled();
585    /// cursor.append(b"ab");
586    /// cursor.append_fill(3, b'-');
587    /// assert_eq!(buf.filled(), b"ab---");
588    /// assert!(!buf.is_init());
589    /// ```
590    #[inline]
591    #[track_caller]
592    pub fn append_fill(&mut self, n: usize, value: T) {
593        assert!(self.capacity() >= n, "appended past the end of the buffer");
594
595        // Writing initialized values never de-initializes an element.
596        self.unfilled_slice()[..n].fill(MaybeUninit::new(value));
597
598        // SAFETY: these elements have just been initialized.
599        unsafe { self.advance(n) };
600    }
601
602    /// Runs the given closure with a `BorrowedBuf` containing the unfilled part
603    /// of the cursor.
604    ///
605    /// This enables inspecting what was written to the cursor.
606    ///
607    /// # Panics
608    ///
609    /// Panics if the `BorrowedBuf` given to the closure is replaced by another
610    /// one.
611    ///
612    /// ```
613    /// use borrowed_buf::BorrowedBuf;
614    /// use core::mem::MaybeUninit;
615    ///
616    /// let mut storage = [MaybeUninit::uninit(); 8];
617    /// let mut buf = BorrowedBuf::from(&mut storage[..]);
618    /// let mut cursor = buf.unfilled();
619    /// cursor.append(b"ab");
620    /// let fresh = cursor.with_unfilled_buf(|sub| {
621    ///     sub.unfilled().append(b"cd");
622    ///     sub.filled().to_vec()
623    /// });
624    /// assert_eq!(fresh, b"cd");
625    /// assert_eq!(buf.filled(), b"abcd");
626    /// ```
627    pub fn with_unfilled_buf<R>(&mut self, f: impl FnOnce(&mut BorrowedBuf<'_, T>) -> R) -> R {
628        let mut buf = BorrowedBuf::from(self.reborrow());
629        let prev_ptr = buf.buf as *const _;
630        let res = f(&mut buf);
631
632        // Check that the caller didn't replace the `BorrowedBuf`.
633        // This is necessary for the safety of the code below: if the check wasn't
634        // there, one could mark some elements as initialized even though they aren't.
635        assert!(
636            ptr::eq(prev_ptr, buf.buf),
637            "the `BorrowedBuf` given to the closure was replaced"
638        );
639
640        let filled = buf.filled;
641        let init = buf.init;
642
643        // Update `init` and `filled` fields with what was written to the buffer.
644        // `self.buf.filled` was the starting length of the `BorrowedBuf`.
645        //
646        // SAFETY: These elements were initialized/filled in the `BorrowedBuf`, and therefore they
647        // are initialized/filled in the cursor too, because the buffer wasn't replaced.
648        unsafe {
649            self.set_buf_init(init);
650            self.advance(filled);
651        }
652
653        res
654    }
655}
656
657impl<'a, T: Default + Copy> BorrowedCursor<'a, T> {
658    /// Initializes all elements in the cursor with their default value and
659    /// returns them.
660    ///
661    /// ```
662    /// use borrowed_buf::BorrowedBuf;
663    /// use core::mem::MaybeUninit;
664    ///
665    /// let mut storage = [MaybeUninit::<f32>::uninit(); 4];
666    /// let mut buf = BorrowedBuf::from(&mut storage[..]);
667    /// let mut cursor = buf.unfilled();
668    ///
669    /// let out = cursor.ensure_init();
670    /// assert_eq!(out, &[0.0; 4]);
671    /// out[0] = 1.5;
672    /// cursor.advance_checked(1);
673    /// assert_eq!(buf.filled(), &[1.5]);
674    /// ```
675    #[inline]
676    pub fn ensure_init(&mut self) -> &mut [T] {
677        if !self.is_buf_init() {
678            self.unfilled_slice().fill(MaybeUninit::new(T::default()));
679            // SAFETY: buf is now initialized.
680            unsafe { self.set_buf_init(true) };
681        }
682
683        // SAFETY: these elements have just been initialized if they weren't before.
684        unsafe { assume_init_mut(self.unfilled_slice()) }
685    }
686}
687
688/// Stable equivalent of `<[MaybeUninit<T>]>::assume_init_ref`.
689///
690/// # Safety
691///
692/// Every element of `s` must be initialized.
693#[inline(always)]
694const unsafe fn assume_init_ref<T>(s: &[MaybeUninit<T>]) -> &[T] {
695    // SAFETY: the caller guarantees `s` is initialized; the layouts are identical.
696    unsafe { &*(s as *const [MaybeUninit<T>] as *const [T]) }
697}
698
699/// Stable equivalent of `<[MaybeUninit<T>]>::assume_init_mut`.
700///
701/// # Safety
702///
703/// Every element of `s` must be initialized.
704#[inline(always)]
705const unsafe fn assume_init_mut<T>(s: &mut [MaybeUninit<T>]) -> &mut [T] {
706    // SAFETY: the caller guarantees `s` is initialized; the layouts are identical.
707    unsafe { &mut *(s as *mut [MaybeUninit<T>] as *mut [T]) }
708}
709
710/// Compile-fail checks for the soundness-relevant type properties.
711///
712/// A cursor must be invariant over `T`, or a short-lived value could be written into a buffer
713/// of longer-lived ones:
714///
715/// ```compile_fail
716/// use borrowed_buf::BorrowedCursor;
717/// fn shorten<'a, 'b>(c: BorrowedCursor<'a, &'static str>) -> BorrowedCursor<'a, &'b str> {
718///     c
719/// }
720/// ```
721///
722/// The buffer can't be accessed while a cursor over it is alive:
723///
724/// ```compile_fail,E0499
725/// use borrowed_buf::BorrowedBuf;
726/// use core::mem::MaybeUninit;
727/// let mut storage = [MaybeUninit::<u8>::uninit(); 4];
728/// let mut buf = BorrowedBuf::<u8>::from(&mut storage[..]);
729/// let mut cursor = buf.unfilled();
730/// buf.clear();
731/// cursor.append(b"a");
732/// ```
733///
734/// A buffer built from a cursor can't outlive the cursor's borrow:
735///
736/// ```compile_fail,E0499
737/// use borrowed_buf::BorrowedBuf;
738/// use core::mem::MaybeUninit;
739/// let mut storage = [MaybeUninit::<u8>::uninit(); 4];
740/// let mut buf = BorrowedBuf::<u8>::from(&mut storage[..]);
741/// let sub = BorrowedBuf::from(buf.unfilled());
742/// buf.clear();
743/// drop(sub);
744/// ```
745///
746/// A cursor is not `Send` when its elements are not:
747///
748/// ```compile_fail,E0277
749/// use borrowed_buf::BorrowedBuf;
750/// use core::mem::MaybeUninit;
751/// fn assert_send<T: Send>(_: T) {}
752/// let mut storage = [MaybeUninit::<*const u8>::uninit(); 1];
753/// let mut buf = BorrowedBuf::<*const u8>::from(&mut storage[..]);
754/// assert_send(buf.unfilled());
755/// ```
756#[cfg(doctest)]
757struct CompileFail;