22
33use crate :: fmt:: { self , Debug , Formatter } ;
44use 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
3735impl Debug for BorrowedBuf < ' _ > {
@@ -48,24 +46,20 @@ impl Debug for BorrowedBuf<'_> {
4846impl < ' 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.
6559impl < ' 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.
7569impl < ' 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