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     /// ```
from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice43     pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice {
44         let maybe_init: &mut [MaybeUninit<u8>] =
45             core::slice::from_raw_parts_mut(ptr as *mut _, len);
46         &mut *(maybe_init as *mut [MaybeUninit<u8>] as *mut UninitSlice)
47     }
48 
49     /// Write a single byte at the specified offset.
50     ///
51     /// # Panics
52     ///
53     /// The function panics if `index` is out of bounds.
54     ///
55     /// # Examples
56     ///
57     /// ```
58     /// use bytes::buf::UninitSlice;
59     ///
60     /// let mut data = [b'f', b'o', b'o'];
61     /// let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) };
62     ///
63     /// slice.write_byte(0, b'b');
64     ///
65     /// assert_eq!(b"boo", &data[..]);
66     /// ```
write_byte(&mut self, index: usize, byte: u8)67     pub fn write_byte(&mut self, index: usize, byte: u8) {
68         assert!(index < self.len());
69 
70         unsafe { self[index..].as_mut_ptr().write(byte) }
71     }
72 
73     /// Copies bytes  from `src` into `self`.
74     ///
75     /// The length of `src` must be the same as `self`.
76     ///
77     /// # Panics
78     ///
79     /// The function panics if `src` has a different length than `self`.
80     ///
81     /// # Examples
82     ///
83     /// ```
84     /// use bytes::buf::UninitSlice;
85     ///
86     /// let mut data = [b'f', b'o', b'o'];
87     /// let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) };
88     ///
89     /// slice.copy_from_slice(b"bar");
90     ///
91     /// assert_eq!(b"bar", &data[..]);
92     /// ```
copy_from_slice(&mut self, src: &[u8])93     pub fn copy_from_slice(&mut self, src: &[u8]) {
94         use core::ptr;
95 
96         assert_eq!(self.len(), src.len());
97 
98         unsafe {
99             ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
100         }
101     }
102 
103     /// Return a raw pointer to the slice's buffer.
104     ///
105     /// # Safety
106     ///
107     /// The caller **must not** read from the referenced memory and **must not**
108     /// write **uninitialized** bytes to the slice either.
109     ///
110     /// # Examples
111     ///
112     /// ```
113     /// use bytes::BufMut;
114     ///
115     /// let mut data = [0, 1, 2];
116     /// let mut slice = &mut data[..];
117     /// let ptr = BufMut::chunk_mut(&mut slice).as_mut_ptr();
118     /// ```
as_mut_ptr(&mut self) -> *mut u8119     pub fn as_mut_ptr(&mut self) -> *mut u8 {
120         self.0.as_mut_ptr() as *mut _
121     }
122 
123     /// Returns the number of bytes in the slice.
124     ///
125     /// # Examples
126     ///
127     /// ```
128     /// use bytes::BufMut;
129     ///
130     /// let mut data = [0, 1, 2];
131     /// let mut slice = &mut data[..];
132     /// let len = BufMut::chunk_mut(&mut slice).len();
133     ///
134     /// assert_eq!(len, 3);
135     /// ```
len(&self) -> usize136     pub fn len(&self) -> usize {
137         self.0.len()
138     }
139 }
140 
141 impl fmt::Debug for UninitSlice {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result142     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
143         fmt.debug_struct("UninitSlice[...]").finish()
144     }
145 }
146 
147 macro_rules! impl_index {
148     ($($t:ty),*) => {
149         $(
150             impl Index<$t> for UninitSlice {
151                 type Output = UninitSlice;
152 
153                 fn index(&self, index: $t) -> &UninitSlice {
154                     let maybe_uninit: &[MaybeUninit<u8>] = &self.0[index];
155                     unsafe { &*(maybe_uninit as *const [MaybeUninit<u8>] as *const UninitSlice) }
156                 }
157             }
158 
159             impl IndexMut<$t> for UninitSlice {
160                 fn index_mut(&mut self, index: $t) -> &mut UninitSlice {
161                     let maybe_uninit: &mut [MaybeUninit<u8>] = &mut self.0[index];
162                     unsafe { &mut *(maybe_uninit as *mut [MaybeUninit<u8>] as *mut UninitSlice) }
163                 }
164             }
165         )*
166     };
167 }
168 
169 impl_index!(
170     Range<usize>,
171     RangeFrom<usize>,
172     RangeFull,
173     RangeInclusive<usize>,
174     RangeTo<usize>,
175     RangeToInclusive<usize>
176 );
177