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;