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;