Skip to content

Commit af38757

Browse files
committed
core: Make BorrowedBuf::init a boolean
1 parent 5631c01 commit af38757

File tree

14 files changed

+134
-181
lines changed

14 files changed

+134
-181
lines changed

library/core/src/io/borrowed_buf.rs

Lines changed: 56 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,18 @@
22

33
use crate::fmt::{self, Debug, Formatter};
44
use crate::mem::{self, MaybeUninit};
5-
use crate::{cmp, ptr};
5+
use crate::ptr;
66

7-
/// A borrowed byte buffer which is incrementally filled and initialized.
7+
/// A borrowed byte buffer which is incrementally filled.
88
///
9-
/// This type is a sort of "double cursor". It tracks three regions in the buffer: a region at the beginning of the
10-
/// buffer that has been logically filled with data, a region that has been initialized at some point but not yet
11-
/// logically filled, and a region at the end that is fully uninitialized. The filled region is guaranteed to be a
12-
/// subset of the initialized region.
9+
/// This type makes it safer to work with `MaybeUninit` buffers, such as to read into a buffer
10+
/// without having to initialize it first. It tracks the region of bytes that have been filled and
11+
/// whether the unfilled region was initialized.
1312
///
1413
/// In summary, the contents of the buffer can be visualized as:
1514
/// ```not_rust
16-
/// [ capacity ]
17-
/// [ filled | unfilled ]
18-
/// [ initialized | uninitialized ]
15+
/// [ capacity ]
16+
/// [ filled | unfilled (may be initialized) ]
1917
/// ```
2018
///
2119
/// A `BorrowedBuf` is created around some existing data (or capacity for data) via a unique reference
@@ -30,8 +28,8 @@ pub struct BorrowedBuf<'data> {
3028
buf: &'data mut [MaybeUninit<u8>],
3129
/// The length of `self.buf` which is known to be filled.
3230
filled: usize,
33-
/// The length of `self.buf` which is known to be initialized.
34-
init: usize,
31+
/// Whether the entire unfilled part of `self.buf` has explicitly been initialized.
32+
init: bool,
3533
}
3634

3735
impl Debug for BorrowedBuf<'_> {
@@ -48,24 +46,20 @@ impl Debug for BorrowedBuf<'_> {
4846
impl<'data> From<&'data mut [u8]> for BorrowedBuf<'data> {
4947
#[inline]
5048
fn from(slice: &'data mut [u8]) -> BorrowedBuf<'data> {
51-
let len = slice.len();
52-
5349
BorrowedBuf {
5450
// SAFETY: initialized data never becoming uninitialized is an invariant of BorrowedBuf
55-
buf: unsafe { (slice as *mut [u8]).as_uninit_slice_mut().unwrap() },
51+
buf: unsafe { &mut *(slice as *mut [u8] as *mut [MaybeUninit<u8>]) },
5652
filled: 0,
57-
init: len,
53+
init: true,
5854
}
5955
}
6056
}
6157

6258
/// Creates a new `BorrowedBuf` from an uninitialized buffer.
63-
///
64-
/// Use `set_init` if part of the buffer is known to be already initialized.
6559
impl<'data> From<&'data mut [MaybeUninit<u8>]> for BorrowedBuf<'data> {
6660
#[inline]
6761
fn from(buf: &'data mut [MaybeUninit<u8>]) -> BorrowedBuf<'data> {
68-
BorrowedBuf { buf, filled: 0, init: 0 }
62+
BorrowedBuf { buf, filled: 0, init: false }
6963
}
7064
}
7165

@@ -74,14 +68,13 @@ impl<'data> From<&'data mut [MaybeUninit<u8>]> for BorrowedBuf<'data> {
7468
/// Use `BorrowedCursor::with_unfilled_buf` instead for a safer alternative.
7569
impl<'data> From<BorrowedCursor<'data>> for BorrowedBuf<'data> {
7670
#[inline]
77-
fn from(mut buf: BorrowedCursor<'data>) -> BorrowedBuf<'data> {
78-
let init = buf.init_mut().len();
71+
fn from(buf: BorrowedCursor<'data>) -> BorrowedBuf<'data> {
7972
BorrowedBuf {
8073
// SAFETY: no initialized byte is ever uninitialized as per
8174
// `BorrowedBuf`'s invariant
8275
buf: unsafe { buf.buf.buf.get_unchecked_mut(buf.buf.filled..) },
8376
filled: 0,
84-
init,
77+
init: buf.buf.init,
8578
}
8679
}
8780
}
@@ -100,8 +93,9 @@ impl<'data> BorrowedBuf<'data> {
10093
}
10194

10295
/// Returns the length of the initialized part of the buffer.
96+
#[unstable(feature = "borrowed_buf_init", issue = "78485")]
10397
#[inline]
104-
pub fn init_len(&self) -> usize {
98+
pub fn is_init(&self) -> bool {
10599
self.init
106100
}
107101

@@ -159,32 +153,29 @@ impl<'data> BorrowedBuf<'data> {
159153

160154
/// Clears the buffer, resetting the filled region to empty.
161155
///
162-
/// The number of initialized bytes is not changed, and the contents of the buffer are not modified.
156+
/// The contents of the buffer are not modified.
163157
#[inline]
164158
pub fn clear(&mut self) -> &mut Self {
165159
self.filled = 0;
166160
self
167161
}
168162

169-
/// Asserts that the first `n` bytes of the buffer are initialized.
170-
///
171-
/// `BorrowedBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer
172-
/// bytes than are already known to be initialized.
163+
/// Asserts that the unfilled part of the buffer is initialized.
173164
///
174165
/// # Safety
175166
///
176-
/// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized.
167+
/// All the bytes of the buffer must be initialized.
168+
#[unstable(feature = "borrowed_buf_init", issue = "78485")]
177169
#[inline]
178-
pub unsafe fn set_init(&mut self, n: usize) -> &mut Self {
179-
self.init = cmp::max(self.init, n);
170+
pub unsafe fn set_init(&mut self) -> &mut Self {
171+
self.init = true;
180172
self
181173
}
182174
}
183175

184176
/// A writeable view of the unfilled portion of a [`BorrowedBuf`].
185177
///
186-
/// The unfilled portion consists of an initialized and an uninitialized part; see [`BorrowedBuf`]
187-
/// for details.
178+
/// The unfilled portion may be uninitialized; see [`BorrowedBuf`] for details.
188179
///
189180
/// Data can be written directly to the cursor by using [`append`](BorrowedCursor::append) or
190181
/// indirectly by getting a slice of part or all of the cursor and writing into the slice. In the
@@ -238,21 +229,29 @@ impl<'a> BorrowedCursor<'a> {
238229
self.buf.filled
239230
}
240231

241-
/// Returns a mutable reference to the initialized portion of the cursor.
232+
/// Returns `true` if the buffer is initialized.
233+
#[unstable(feature = "borrowed_buf_init", issue = "78485")]
242234
#[inline]
243-
pub fn init_mut(&mut self) -> &mut [u8] {
244-
// SAFETY: We only slice the initialized part of the buffer, which is always valid
245-
unsafe {
246-
let buf = self.buf.buf.get_unchecked_mut(self.buf.filled..self.buf.init);
247-
buf.assume_init_mut()
248-
}
235+
pub fn is_init(&self) -> bool {
236+
self.buf.init
237+
}
238+
239+
/// Set the buffer as fully initialized.
240+
///
241+
/// # Safety
242+
///
243+
/// All the bytes of the cursor must be initialized.
244+
#[unstable(feature = "borrowed_buf_init", issue = "78485")]
245+
#[inline]
246+
pub unsafe fn set_init(&mut self) {
247+
self.buf.init = true;
249248
}
250249

251250
/// Returns a mutable reference to the whole cursor.
252251
///
253252
/// # Safety
254253
///
255-
/// The caller must not uninitialize any bytes in the initialized portion of the cursor.
254+
/// The caller must not uninitialize any bytes of the cursor if it is initialized.
256255
#[inline]
257256
pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit<u8>] {
258257
// SAFETY: always in bounds
@@ -271,10 +270,12 @@ impl<'a> BorrowedCursor<'a> {
271270
/// # Panics
272271
///
273272
/// Panics if there are less than `n` bytes initialized.
273+
#[unstable(feature = "borrowed_buf_init", issue = "78485")]
274274
#[inline]
275275
pub fn advance(&mut self, n: usize) -> &mut Self {
276276
// The subtraction cannot underflow by invariant of this type.
277-
assert!(n <= self.buf.init - self.buf.filled);
277+
let init_unfilled = if self.buf.init { self.buf.buf.len() - self.buf.filled } else { 0 };
278+
assert!(n <= init_unfilled);
278279

279280
self.buf.filled += n;
280281
self
@@ -293,38 +294,27 @@ impl<'a> BorrowedCursor<'a> {
293294
#[inline]
294295
pub unsafe fn advance_unchecked(&mut self, n: usize) -> &mut Self {
295296
self.buf.filled += n;
296-
self.buf.init = cmp::max(self.buf.init, self.buf.filled);
297297
self
298298
}
299299

300300
/// Initializes all bytes in the cursor and returns them.
301+
#[unstable(feature = "borrowed_buf_init", issue = "78485")]
301302
#[inline]
302303
pub fn ensure_init(&mut self) -> &mut [u8] {
303304
// SAFETY: always in bounds and we never uninitialize these bytes.
304-
let uninit = unsafe { self.buf.buf.get_unchecked_mut(self.buf.init..) };
305-
306-
// SAFETY: 0 is a valid value for MaybeUninit<u8> and the length matches the allocation
307-
// since it is comes from a slice reference.
308-
unsafe {
309-
ptr::write_bytes(uninit.as_mut_ptr(), 0, uninit.len());
305+
let unfilled = unsafe { self.buf.buf.get_unchecked_mut(self.buf.filled..) };
306+
307+
if !self.buf.init {
308+
// SAFETY: 0 is a valid value for MaybeUninit<u8> and the length matches the allocation
309+
// since it is comes from a slice reference.
310+
unsafe {
311+
ptr::write_bytes(unfilled.as_mut_ptr(), 0, unfilled.len());
312+
}
313+
self.buf.init = true;
310314
}
311-
self.buf.init = self.buf.capacity();
312-
313-
self.init_mut()
314-
}
315315

316-
/// Asserts that the first `n` unfilled bytes of the cursor are initialized.
317-
///
318-
/// `BorrowedBuf` assumes that bytes are never de-initialized, so this method does nothing when
319-
/// called with fewer bytes than are already known to be initialized.
320-
///
321-
/// # Safety
322-
///
323-
/// The caller must ensure that the first `n` bytes of the buffer have already been initialized.
324-
#[inline]
325-
pub unsafe fn set_init(&mut self, n: usize) -> &mut Self {
326-
self.buf.init = cmp::max(self.buf.init, self.buf.filled + n);
327-
self
316+
// SAFETY: these bytes have just been initialized if they weren't before
317+
unsafe { unfilled.assume_init_mut() }
328318
}
329319

330320
/// Appends data to the cursor, advancing position within its buffer.
@@ -341,10 +331,6 @@ impl<'a> BorrowedCursor<'a> {
341331
self.as_mut()[..buf.len()].write_copy_of_slice(buf);
342332
}
343333

344-
// SAFETY: We just added the entire contents of buf to the filled section.
345-
unsafe {
346-
self.set_init(buf.len());
347-
}
348334
self.buf.filled += buf.len();
349335
}
350336

@@ -365,7 +351,7 @@ impl<'a> BorrowedCursor<'a> {
365351
// Check that the caller didn't replace the `BorrowedBuf`.
366352
// This is necessary for the safety of the code below: if the check wasn't
367353
// there, one could mark some bytes as initialized even though there aren't.
368-
assert!(core::ptr::addr_eq(prev_ptr, buf.buf));
354+
assert!(core::ptr::eq(prev_ptr, buf.buf));
369355

370356
let filled = buf.filled;
371357
let init = buf.init;
@@ -376,7 +362,7 @@ impl<'a> BorrowedCursor<'a> {
376362
// SAFETY: These amounts of bytes were initialized/filled in the `BorrowedBuf`,
377363
// and therefore they are initialized/filled in the cursor too, because the
378364
// buffer wasn't replaced.
379-
self.buf.init = self.buf.filled + init;
365+
self.buf.init = init;
380366
self.buf.filled += filled;
381367

382368
res

0 commit comments

Comments
 (0)