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    /// Asserts that the unfilled part of the buffer is initialized.
219    ///
220    /// # Safety
221    ///
222    /// All the elements of the buffer must be initialized.
223    ///
224    /// ```
225    /// use borrowed_buf::BorrowedBuf;
226    /// use core::mem::MaybeUninit;
227    ///
228    /// let mut storage = [MaybeUninit::new(0u8); 4];
229    /// let mut buf = BorrowedBuf::<u8>::from(&mut storage[..]);
230    /// assert!(!buf.is_init());
231    /// // SAFETY: every element of `storage` was initialized above.
232    /// unsafe { buf.set_init() };
233    /// buf.unfilled().advance_checked(4);
234    /// assert_eq!(buf.filled(), &[0; 4]);
235    /// ```
236    #[inline]
237    pub unsafe fn set_init(&mut self) -> &mut Self {
238        self.init = true;
239        self
240    }
241}
242
243/// A writeable view of the unfilled portion of a [`BorrowedBuf`].
244///
245/// The unfilled portion may be uninitialized; see [`BorrowedBuf`] for details.
246///
247/// Data can be written directly to the cursor by using [`append`](BorrowedCursor::append) or
248/// indirectly by getting a slice of part or all of the cursor and writing into the slice. In the
249/// indirect case, the caller must call [`advance`](BorrowedCursor::advance) after writing to inform
250/// the cursor how many elements have been written.
251///
252/// Once elements are written to the cursor, they become part of the filled portion of the
253/// underlying `BorrowedBuf` and can no longer be accessed or re-written by the cursor. In other
254/// words, the cursor tracks the unfilled part of the underlying `BorrowedBuf`.
255///
256/// The lifetime `'a` is a bound on the lifetime of the underlying buffer (which means it is a bound
257/// on the elements in that buffer by transitivity).
258///
259/// # Examples
260///
261/// ```
262/// use borrowed_buf::{BorrowedBuf, BorrowedCursor};
263/// use core::mem::MaybeUninit;
264///
265/// // A producer that only sees the free space.
266/// fn produce(mut cursor: BorrowedCursor<'_, u32>) {
267///     let n = cursor.capacity().min(3);
268///     // SAFETY: only initialized values are written.
269///     let out = unsafe { cursor.as_mut() };
270///     for (i, slot) in out[..n].iter_mut().enumerate() {
271///         slot.write(i as u32 * 10);
272///     }
273///     // SAFETY: the first `n` elements of the cursor were just written.
274///     unsafe { cursor.advance(n) };
275/// }
276///
277/// let mut storage = [MaybeUninit::uninit(); 4];
278/// let mut buf = BorrowedBuf::from(&mut storage[..]);
279/// buf.unfilled().append(&[7]);
280/// produce(buf.unfilled());
281/// assert_eq!(buf.filled(), &[7, 0, 10, 20]);
282/// ```
283pub struct BorrowedCursor<'a, T> {
284    /// The start of the elements of the buffer this cursor was created from.
285    /// Safety invariant: this points to the start of the *whole* buffer of `*borrowed_buf` and is
286    /// valid for reads and writes of `(*borrowed_buf).buf.len()` elements, so that
287    /// `(*borrowed_buf).filled` indexes into it.
288    buf: NonNull<MaybeUninit<T>>,
289    /// The buffer this cursor was created from.
290    /// Safety invariants:
291    /// 1. `(*borrowed_buf).buf` is *never* accessed by the owner of the pointee while the `buf`
292    ///    field above is alive, because there is a `&mut` of the pointee while the cursor is alive.
293    /// 2. We promise to only access the `filled` and `init` fields and the metadata of the `buf`
294    ///    field through the `borrowed_buf` pointer, never triggering any retag of `buf`'s pointer,
295    ///    as the `buf` field above holds a reborrow of it and reaching the parent again would be a
296    ///    foreign access for that reborrow. This includes not making a reference to the whole
297    ///    pointee out of `borrowed_buf`, but only accessing those fields directly through pointer
298    ///    manipulation.
299    borrowed_buf: NonNull<BorrowedBuf<'a, T>>,
300}
301
302// SAFETY: A `BorrowedCursor<'a, T>` is a unique borrow of a `BorrowedBuf<'a, T>`, which is a
303// `&'a mut [MaybeUninit<T>]` and two `Copy` fields. The `buf` raw pointer is used like
304// `&mut [MaybeUninit<T>]` so `T: Send` -> `Send` and `T: Sync` -> `Sync`, and the
305// `borrowed_buf` only touches two `Copy` fields, without depending on `T`.
306unsafe impl<T: Send> Send for BorrowedCursor<'_, T> {}
307// SAFETY: See the `Send` impl above.
308unsafe impl<T: Sync> Sync for BorrowedCursor<'_, T> {}
309
310impl<T> Debug for BorrowedCursor<'_, T> {
311    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
312        let buf = BorrowedBufDebug {
313            init: self.is_buf_init(),
314            filled: self.filled(),
315            capacity: self.buf_len(),
316        };
317
318        f.debug_struct("BorrowedCursor").field("buf", &buf).finish()
319    }
320}
321
322// Helpers to access underlying buffer state.
323impl<'a, T> BorrowedCursor<'a, T> {
324    #[inline]
325    fn buf_mut(&mut self) -> &mut [MaybeUninit<T>] {
326        let len = self.buf_len();
327        // SAFETY: `buf` points to `len` elements that this cursor borrows exclusively.
328        unsafe { slice::from_raw_parts_mut(self.buf.as_ptr(), len) }
329    }
330
331    #[inline]
332    fn buf_len(&self) -> usize {
333        // SAFETY: We read just the metadata of `buf` and avoid retagging the reference.
334        unsafe {
335            let borrowed_buf = self.borrowed_buf.as_ptr();
336            let buf_ptr: *const &'a mut [MaybeUninit<T>] = &raw const (*borrowed_buf).buf;
337            // Same layout:
338            // https://doc.rust-lang.org/reference/type-layout.html#r-layout.pointer.intro
339            let buf_ptr: *const *const [MaybeUninit<T>] = buf_ptr.cast();
340            let buf: *const [MaybeUninit<T>] = *buf_ptr;
341            buf.len()
342        }
343    }
344
345    #[inline]
346    fn unfilled_slice(&mut self) -> &mut [MaybeUninit<T>] {
347        let filled = self.filled();
348        // SAFETY: always in bounds.
349        unsafe { self.buf_mut().get_unchecked_mut(filled..) }
350    }
351
352    #[inline]
353    fn filled(&self) -> usize {
354        // SAFETY: We access just `filled` and avoid foreign read on `buf`.
355        unsafe { (*self.borrowed_buf.as_ptr()).filled }
356    }
357
358    #[inline]
359    fn is_buf_init(&self) -> bool {
360        // SAFETY: We access just `init` and avoid foreign read on `buf`.
361        unsafe { (*self.borrowed_buf.as_ptr()).init }
362    }
363
364    /// # Safety
365    ///
366    /// In case of `true` all the elements of the cursor must be initialized.
367    #[inline]
368    unsafe fn set_buf_init(&mut self, init: bool) {
369        // SAFETY: We access just `init` and avoid foreign read on `buf`.
370        unsafe {
371            (*self.borrowed_buf.as_ptr()).init = init;
372        }
373    }
374
375    /// # Safety
376    ///
377    /// The next `n` elements of the cursor must be initialized.
378    #[inline]
379    unsafe fn add_filled(&mut self, n: usize) {
380        // SAFETY: We access just `filled` and avoid foreign read on `buf`.
381        unsafe {
382            (*self.borrowed_buf.as_ptr()).filled += n;
383        }
384    }
385}
386
387impl<'a, T: Copy> BorrowedCursor<'a, T> {
388    /// Reborrows this cursor by cloning it with a smaller lifetime.
389    ///
390    /// Since a cursor maintains unique access to its underlying buffer, the borrowed cursor is
391    /// not accessible while the new cursor exists.
392    #[inline]
393    pub fn reborrow<'this>(&'this mut self) -> BorrowedCursor<'this, T> {
394        BorrowedCursor {
395            buf: self.buf,
396            borrowed_buf: self.borrowed_buf,
397        }
398    }
399
400    /// Returns the available space in the cursor.
401    #[inline]
402    pub fn capacity(&self) -> usize {
403        self.buf_len() - self.filled()
404    }
405
406    /// Returns the number of elements written to the `BorrowedBuf` this cursor was created from.
407    ///
408    /// In particular, the count returned is shared by all reborrows of the cursor.
409    #[inline]
410    pub fn written(&self) -> usize {
411        self.filled()
412    }
413
414    /// Returns `true` if the buffer is initialized.
415    #[inline]
416    pub fn is_init(&self) -> bool {
417        self.is_buf_init()
418    }
419
420    /// Set the buffer as fully initialized.
421    ///
422    /// # Safety
423    ///
424    /// All the elements of the cursor must be initialized.
425    ///
426    /// ```
427    /// use borrowed_buf::BorrowedBuf;
428    /// use core::mem::MaybeUninit;
429    ///
430    /// let mut storage = [MaybeUninit::<u8>::uninit(); 4];
431    /// let mut buf = BorrowedBuf::from(&mut storage[..]);
432    /// let mut cursor = buf.unfilled();
433    /// // SAFETY: only initialized values are written.
434    /// unsafe { cursor.as_mut() }.fill(MaybeUninit::new(b'x'));
435    /// // SAFETY: every element of the cursor was just written.
436    /// unsafe { cursor.set_init() };
437    /// cursor.advance_checked(4);
438    /// assert_eq!(buf.filled(), b"xxxx");
439    /// ```
440    #[inline]
441    pub unsafe fn set_init(&mut self) {
442        // SAFETY: the caller guarantees that all the elements of the cursor are initialized.
443        unsafe { self.set_buf_init(true) }
444    }
445
446    /// Returns a mutable reference to the whole cursor.
447    ///
448    /// # Safety
449    ///
450    /// The caller must not uninitialize any elements of the cursor if it is initialized.
451    #[inline]
452    pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit<T>] {
453        self.unfilled_slice()
454    }
455
456    /// Advances the cursor by asserting that `n` elements have been filled.
457    ///
458    /// After advancing, the `n` elements are no longer accessible via the cursor and can only be
459    /// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements
460    /// and its unfilled portion (and the capacity of this cursor) shrinks by `n` elements.
461    ///
462    /// If less than `n` elements initialized (by the cursor's point of view), `set_init` should be
463    /// called first.
464    ///
465    /// # Panics
466    ///
467    /// Panics if there are less than `n` elements initialized.
468    #[inline]
469    #[track_caller]
470    pub fn advance_checked(&mut self, n: usize) -> &mut Self {
471        // The subtraction cannot underflow by invariant of this type.
472        let init_unfilled = if self.is_buf_init() {
473            self.buf_len() - self.filled()
474        } else {
475            0
476        };
477        assert!(
478            n <= init_unfilled,
479            "advanced past the initialized part of the buffer"
480        );
481
482        // SAFETY: the next `n` elements are initialized, as asserted above.
483        unsafe { self.advance(n) };
484        self
485    }
486
487    /// Advances the cursor by asserting that `n` elements have been filled.
488    ///
489    /// After advancing, the `n` elements are no longer accessible via the cursor and can only be
490    /// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements
491    /// and its unfilled portion (and the capacity of this cursor) shrinks by `n` elements.
492    ///
493    /// # Safety
494    ///
495    /// The caller must ensure that the first `n` elements of the cursor have been initialized.
496    #[inline]
497    pub unsafe fn advance(&mut self, n: usize) -> &mut Self {
498        // SAFETY: the caller guarantees that the first `n` elements of the cursor are initialized.
499        unsafe { self.add_filled(n) };
500        self
501    }
502
503    /// Append elements to the cursor, advancing position within its buffer.
504    ///
505    /// # Panics
506    ///
507    /// Panics if `self.capacity()` is less than `buf.len()`.
508    ///
509    /// ```
510    /// use borrowed_buf::BorrowedBuf;
511    /// use core::mem::MaybeUninit;
512    ///
513    /// let mut storage = [MaybeUninit::uninit(); 4];
514    /// let mut buf = BorrowedBuf::from(&mut storage[..]);
515    /// buf.unfilled().append(&[1u64, 2]);
516    /// buf.unfilled().append(&[3]);
517    /// assert_eq!(buf.filled(), &[1, 2, 3]);
518    /// ```
519    #[inline]
520    #[track_caller]
521    pub fn append(&mut self, buf: &[T]) {
522        assert!(
523            self.capacity() >= buf.len(),
524            "appended past the end of the buffer"
525        );
526
527        // SAFETY: we do not de-initialize any of the elements of the slice, the destination has
528        // room for `buf.len()` elements as asserted above, and `buf` can't overlap it because the
529        // cursor borrows the destination exclusively.
530        unsafe {
531            let dst = self.as_mut().as_mut_ptr().cast::<T>();
532            ptr::copy_nonoverlapping(buf.as_ptr(), dst, buf.len());
533        }
534
535        // SAFETY: these elements have just been initialized.
536        unsafe { self.advance(buf.len()) };
537    }
538
539    /// Runs the given closure with a `BorrowedBuf` containing the unfilled part
540    /// of the cursor.
541    ///
542    /// This enables inspecting what was written to the cursor.
543    ///
544    /// # Panics
545    ///
546    /// Panics if the `BorrowedBuf` given to the closure is replaced by another
547    /// one.
548    ///
549    /// ```
550    /// use borrowed_buf::BorrowedBuf;
551    /// use core::mem::MaybeUninit;
552    ///
553    /// let mut storage = [MaybeUninit::uninit(); 8];
554    /// let mut buf = BorrowedBuf::from(&mut storage[..]);
555    /// let mut cursor = buf.unfilled();
556    /// cursor.append(b"ab");
557    /// let fresh = cursor.with_unfilled_buf(|sub| {
558    ///     sub.unfilled().append(b"cd");
559    ///     sub.filled().to_vec()
560    /// });
561    /// assert_eq!(fresh, b"cd");
562    /// assert_eq!(buf.filled(), b"abcd");
563    /// ```
564    pub fn with_unfilled_buf<R>(&mut self, f: impl FnOnce(&mut BorrowedBuf<'_, T>) -> R) -> R {
565        let mut buf = BorrowedBuf::from(self.reborrow());
566        let prev_ptr = buf.buf as *const _;
567        let res = f(&mut buf);
568
569        // Check that the caller didn't replace the `BorrowedBuf`.
570        // This is necessary for the safety of the code below: if the check wasn't
571        // there, one could mark some elements as initialized even though they aren't.
572        assert!(
573            ptr::eq(prev_ptr, buf.buf),
574            "the `BorrowedBuf` given to the closure was replaced"
575        );
576
577        let filled = buf.filled;
578        let init = buf.init;
579
580        // Update `init` and `filled` fields with what was written to the buffer.
581        // `self.buf.filled` was the starting length of the `BorrowedBuf`.
582        //
583        // SAFETY: These elements were initialized/filled in the `BorrowedBuf`, and therefore they
584        // are initialized/filled in the cursor too, because the buffer wasn't replaced.
585        unsafe {
586            self.set_buf_init(init);
587            self.advance(filled);
588        }
589
590        res
591    }
592}
593
594impl<'a, T: Default + Copy> BorrowedCursor<'a, T> {
595    /// Initializes all elements in the cursor with their default value and
596    /// returns them.
597    ///
598    /// ```
599    /// use borrowed_buf::BorrowedBuf;
600    /// use core::mem::MaybeUninit;
601    ///
602    /// let mut storage = [MaybeUninit::<f32>::uninit(); 4];
603    /// let mut buf = BorrowedBuf::from(&mut storage[..]);
604    /// let mut cursor = buf.unfilled();
605    ///
606    /// let out = cursor.ensure_init();
607    /// assert_eq!(out, &[0.0; 4]);
608    /// out[0] = 1.5;
609    /// cursor.advance_checked(1);
610    /// assert_eq!(buf.filled(), &[1.5]);
611    /// ```
612    #[inline]
613    pub fn ensure_init(&mut self) -> &mut [T] {
614        if !self.is_buf_init() {
615            self.unfilled_slice().fill(MaybeUninit::new(T::default()));
616            // SAFETY: buf is now initialized.
617            unsafe { self.set_buf_init(true) };
618        }
619
620        // SAFETY: these elements have just been initialized if they weren't before.
621        unsafe { assume_init_mut(self.unfilled_slice()) }
622    }
623}
624
625/// Stable equivalent of `<[MaybeUninit<T>]>::assume_init_ref`.
626///
627/// # Safety
628///
629/// Every element of `s` must be initialized.
630#[inline(always)]
631const unsafe fn assume_init_ref<T>(s: &[MaybeUninit<T>]) -> &[T] {
632    // SAFETY: the caller guarantees `s` is initialized; the layouts are identical.
633    unsafe { &*(s as *const [MaybeUninit<T>] as *const [T]) }
634}
635
636/// Stable equivalent of `<[MaybeUninit<T>]>::assume_init_mut`.
637///
638/// # Safety
639///
640/// Every element of `s` must be initialized.
641#[inline(always)]
642const unsafe fn assume_init_mut<T>(s: &mut [MaybeUninit<T>]) -> &mut [T] {
643    // SAFETY: the caller guarantees `s` is initialized; the layouts are identical.
644    unsafe { &mut *(s as *mut [MaybeUninit<T>] as *mut [T]) }
645}
646
647/// Compile-fail checks for the soundness-relevant type properties.
648///
649/// A cursor must be invariant over `T`, or a short-lived value could be written into a buffer
650/// of longer-lived ones:
651///
652/// ```compile_fail
653/// use borrowed_buf::BorrowedCursor;
654/// fn shorten<'a, 'b>(c: BorrowedCursor<'a, &'static str>) -> BorrowedCursor<'a, &'b str> {
655///     c
656/// }
657/// ```
658///
659/// The buffer can't be accessed while a cursor over it is alive:
660///
661/// ```compile_fail,E0499
662/// use borrowed_buf::BorrowedBuf;
663/// use core::mem::MaybeUninit;
664/// let mut storage = [MaybeUninit::<u8>::uninit(); 4];
665/// let mut buf = BorrowedBuf::<u8>::from(&mut storage[..]);
666/// let mut cursor = buf.unfilled();
667/// buf.clear();
668/// cursor.append(b"a");
669/// ```
670///
671/// A buffer built from a cursor can't outlive the cursor's borrow:
672///
673/// ```compile_fail,E0499
674/// use borrowed_buf::BorrowedBuf;
675/// use core::mem::MaybeUninit;
676/// let mut storage = [MaybeUninit::<u8>::uninit(); 4];
677/// let mut buf = BorrowedBuf::<u8>::from(&mut storage[..]);
678/// let sub = BorrowedBuf::from(buf.unfilled());
679/// buf.clear();
680/// drop(sub);
681/// ```
682///
683/// A cursor is not `Send` when its elements are not:
684///
685/// ```compile_fail,E0277
686/// use borrowed_buf::BorrowedBuf;
687/// use core::mem::MaybeUninit;
688/// fn assert_send<T: Send>(_: T) {}
689/// let mut storage = [MaybeUninit::<*const u8>::uninit(); 1];
690/// let mut buf = BorrowedBuf::<*const u8>::from(&mut storage[..]);
691/// assert_send(buf.unfilled());
692/// ```
693#[cfg(doctest)]
694struct CompileFail;