• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use core::fmt;
2 use core::mem::MaybeUninit;
3 use core::ops::{
4     Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
5 };
6 
7 /// Uninitialized byte slice.
8 ///
9 /// Returned by `BufMut::chunk_mut()`, the referenced byte slice may be
10 /// uninitialized. The wrapper provides safe access without introducing
11 /// undefined behavior.
12 ///
13 /// The safety invariants of this wrapper are:
14 ///
15 ///  1. Reading from an `UninitSlice` is undefined behavior.
16 ///  2. Writing uninitialized bytes to an `UninitSlice` is undefined behavior.
17 ///
18 /// The difference between `&mut UninitSlice` and `&mut [MaybeUninit<u8>]` is
19 /// that it is possible in safe code to write uninitialized bytes to an
20 /// `&mut [MaybeUninit<u8>]`, which this type prohibits.
21 #[repr(transparent)]
22 pub struct UninitSlice([MaybeUninit<u8>]);
23 
24 impl UninitSlice {
25     /// Create a `&mut UninitSlice` from a pointer and a length.
26     ///
27     /// # Safety
28     ///
29     /// The caller must ensure that `ptr` references a valid memory region owned
30     /// by the caller representing a byte slice for the duration of `'a`.
31     ///
32     /// # Examples
33     ///
34     /// ```
35     /// use bytes::buf::UninitSlice;
36     ///
37     /// let bytes = b"hello world".to_vec();
38     /// let ptr = bytes.as_ptr() as *mut _;
39     /// let len = bytes.len();
40     ///
41     /// let slice = unsafe { UninitSlice::from_raw_parts_mut(ptr, len) };
42     /// ```
43     #[inline]
from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice44     pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice {
45         let maybe_init: &mut [MaybeUninit<u8>] =
46             core::slice::from_raw_parts_mut(ptr as *mut _, len);
47         &mut *(maybe_init as *mut [MaybeUninit<u8>] as *mut UninitSlice)
48     }
49 
50     /// Write a single byte at the specified offset.
51     ///
52     /// # Panics
53     ///
54     /// The function panics if `index` is out of bounds.
55     ///
56     /// # Examples
57     ///
58     /// ```
59     /// use bytes::buf::UninitSlice;
60     ///
61     /// let mut data = [b'f', b'o', b'o'];
62     /// let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) };
63     ///
64     /// slice.write_byte(0, b'b');
65     ///
66     /// assert_eq!(b"boo", &data[..]);
67     /// ```
68     #[inline]
write_byte(&mut self, index: usize, byte: u8)69     pub fn write_byte(&mut self, index: usize, byte: u8) {
70         assert!(index < self.len());
71 
72         unsafe { self[index..].as_mut_ptr().write(byte) }
73     }
74 
75     /// Copies bytes  from `src` into `self`.
76     ///
77     /// The length of `src` must be the same as `self`.
78     ///
79     /// # Panics
80     ///
81     /// The function panics if `src` has a different length than `self`.
82     ///
83     /// # Examples
84     ///
85     /// ```
86     /// use bytes::buf::UninitSlice;
87     ///
88     /// let mut data = [b'f', b'o', b'o'];
89     /// let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) };
90     ///
91     /// slice.copy_from_slice(b"bar");
92     ///
93     /// assert_eq!(b"bar", &data[..]);
94     /// ```
95     #[inline]
copy_from_slice(&mut self, src: &[u8])96     pub fn copy_from_slice(&mut self, src: &[u8]) {
97         use core::ptr;
98 
99         assert_eq!(self.len(), src.len());
100 
101         unsafe {
102             ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
103         }
104     }
105 
106     /// Return a raw pointer to the slice's buffer.
107     ///
108     /// # Safety
109     ///
110     /// The caller **must not** read from the referenced memory and **must not**
111     /// write **uninitialized** bytes to the slice either.
112     ///
113     /// # Examples
114     ///
115     /// ```
116     /// use bytes::BufMut;
117     ///
118     /// let mut data = [0, 1, 2];
119     /// let mut slice = &mut data[..];
120     /// let ptr = BufMut::chunk_mut(&mut slice).as_mut_ptr();
121     /// ```
122     #[inline]
as_mut_ptr(&mut self) -> *mut u8123     pub fn as_mut_ptr(&mut self) -> *mut u8 {
124         self.0.as_mut_ptr() as *mut _
125     }
126 
127     /// Returns the number of bytes in the slice.
128     ///
129     /// # Examples
130     ///
131     /// ```
132     /// use bytes::BufMut;
133     ///
134     /// let mut data = [0, 1, 2];
135     /// let mut slice = &mut data[..];
136     /// let len = BufMut::chunk_mut(&mut slice).len();
137     ///
138     /// assert_eq!(len, 3);
139     /// ```
140     #[inline]
len(&self) -> usize141     pub fn len(&self) -> usize {
142         self.0.len()
143     }
144 }
145 
146 impl fmt::Debug for UninitSlice {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result147     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
148         fmt.debug_struct("UninitSlice[...]").finish()
149     }
150 }
151 
152 macro_rules! impl_index {
153     ($($t:ty),*) => {
154         $(
155             impl Index<$t> for UninitSlice {
156                 type Output = UninitSlice;
157 
158                 #[inline]
159                 fn index(&self, index: $t) -> &UninitSlice {
160                     let maybe_uninit: &[MaybeUninit<u8>] = &self.0[index];
161                     unsafe { &*(maybe_uninit as *const [MaybeUninit<u8>] as *const UninitSlice) }
162                 }
163             }
164 
165             impl IndexMut<$t> for UninitSlice {
166                 #[inline]
167                 fn index_mut(&mut self, index: $t) -> &mut UninitSlice {
168                     let maybe_uninit: &mut [MaybeUninit<u8>] = &mut self.0[index];
169                     unsafe { &mut *(maybe_uninit as *mut [MaybeUninit<u8>] as *mut UninitSlice) }
170                 }
171             }
172         )*
173     };
174 }
175 
176 impl_index!(
177     Range<usize>,
178     RangeFrom<usize>,
179     RangeFull,
180     RangeInclusive<usize>,
181     RangeTo<usize>,
182     RangeToInclusive<usize>
183 );
184