• 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 {
from_slice(slice: &mut [MaybeUninit<u8>]) -> &mut UninitSlice25     pub(crate) fn from_slice(slice: &mut [MaybeUninit<u8>]) -> &mut UninitSlice {
26         unsafe { &mut *(slice as *mut [MaybeUninit<u8>] as *mut UninitSlice) }
27     }
28 
29     /// Create a `&mut UninitSlice` from a pointer and a length.
30     ///
31     /// # Safety
32     ///
33     /// The caller must ensure that `ptr` references a valid memory region owned
34     /// by the caller representing a byte slice for the duration of `'a`.
35     ///
36     /// # Examples
37     ///
38     /// ```
39     /// use bytes::buf::UninitSlice;
40     ///
41     /// let bytes = b"hello world".to_vec();
42     /// let ptr = bytes.as_ptr() as *mut _;
43     /// let len = bytes.len();
44     ///
45     /// let slice = unsafe { UninitSlice::from_raw_parts_mut(ptr, len) };
46     /// ```
47     #[inline]
from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice48     pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice {
49         let maybe_init: &mut [MaybeUninit<u8>] =
50             core::slice::from_raw_parts_mut(ptr as *mut _, len);
51         Self::from_slice(maybe_init)
52     }
53 
54     /// Write a single byte at the specified offset.
55     ///
56     /// # Panics
57     ///
58     /// The function panics if `index` is out of bounds.
59     ///
60     /// # Examples
61     ///
62     /// ```
63     /// use bytes::buf::UninitSlice;
64     ///
65     /// let mut data = [b'f', b'o', b'o'];
66     /// let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) };
67     ///
68     /// slice.write_byte(0, b'b');
69     ///
70     /// assert_eq!(b"boo", &data[..]);
71     /// ```
72     #[inline]
write_byte(&mut self, index: usize, byte: u8)73     pub fn write_byte(&mut self, index: usize, byte: u8) {
74         assert!(index < self.len());
75 
76         unsafe { self[index..].as_mut_ptr().write(byte) }
77     }
78 
79     /// Copies bytes  from `src` into `self`.
80     ///
81     /// The length of `src` must be the same as `self`.
82     ///
83     /// # Panics
84     ///
85     /// The function panics if `src` has a different length than `self`.
86     ///
87     /// # Examples
88     ///
89     /// ```
90     /// use bytes::buf::UninitSlice;
91     ///
92     /// let mut data = [b'f', b'o', b'o'];
93     /// let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) };
94     ///
95     /// slice.copy_from_slice(b"bar");
96     ///
97     /// assert_eq!(b"bar", &data[..]);
98     /// ```
99     #[inline]
copy_from_slice(&mut self, src: &[u8])100     pub fn copy_from_slice(&mut self, src: &[u8]) {
101         use core::ptr;
102 
103         assert_eq!(self.len(), src.len());
104 
105         unsafe {
106             ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
107         }
108     }
109 
110     /// Return a raw pointer to the slice's buffer.
111     ///
112     /// # Safety
113     ///
114     /// The caller **must not** read from the referenced memory and **must not**
115     /// write **uninitialized** bytes to the slice either.
116     ///
117     /// # Examples
118     ///
119     /// ```
120     /// use bytes::BufMut;
121     ///
122     /// let mut data = [0, 1, 2];
123     /// let mut slice = &mut data[..];
124     /// let ptr = BufMut::chunk_mut(&mut slice).as_mut_ptr();
125     /// ```
126     #[inline]
as_mut_ptr(&mut self) -> *mut u8127     pub fn as_mut_ptr(&mut self) -> *mut u8 {
128         self.0.as_mut_ptr() as *mut _
129     }
130 
131     /// Return a `&mut [MaybeUninit<u8>]` to this slice's buffer.
132     ///
133     /// # Safety
134     ///
135     /// The caller **must not** read from the referenced memory and **must not** write
136     /// **uninitialized** bytes to the slice either. This is because `BufMut` implementation
137     /// that created the `UninitSlice` knows which parts are initialized. Writing uninitalized
138     /// bytes to the slice may cause the `BufMut` to read those bytes and trigger undefined
139     /// behavior.
140     ///
141     /// # Examples
142     ///
143     /// ```
144     /// use bytes::BufMut;
145     ///
146     /// let mut data = [0, 1, 2];
147     /// let mut slice = &mut data[..];
148     /// unsafe {
149     ///     let uninit_slice = BufMut::chunk_mut(&mut slice).as_uninit_slice_mut();
150     /// };
151     /// ```
152     #[inline]
as_uninit_slice_mut<'a>(&'a mut self) -> &'a mut [MaybeUninit<u8>]153     pub unsafe fn as_uninit_slice_mut<'a>(&'a mut self) -> &'a mut [MaybeUninit<u8>] {
154         &mut *(self as *mut _ as *mut [MaybeUninit<u8>])
155     }
156 
157     /// Returns the number of bytes in the slice.
158     ///
159     /// # Examples
160     ///
161     /// ```
162     /// use bytes::BufMut;
163     ///
164     /// let mut data = [0, 1, 2];
165     /// let mut slice = &mut data[..];
166     /// let len = BufMut::chunk_mut(&mut slice).len();
167     ///
168     /// assert_eq!(len, 3);
169     /// ```
170     #[inline]
len(&self) -> usize171     pub fn len(&self) -> usize {
172         self.0.len()
173     }
174 }
175 
176 impl fmt::Debug for UninitSlice {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result177     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
178         fmt.debug_struct("UninitSlice[...]").finish()
179     }
180 }
181 
182 macro_rules! impl_index {
183     ($($t:ty),*) => {
184         $(
185             impl Index<$t> for UninitSlice {
186                 type Output = UninitSlice;
187 
188                 #[inline]
189                 fn index(&self, index: $t) -> &UninitSlice {
190                     let maybe_uninit: &[MaybeUninit<u8>] = &self.0[index];
191                     unsafe { &*(maybe_uninit as *const [MaybeUninit<u8>] as *const UninitSlice) }
192                 }
193             }
194 
195             impl IndexMut<$t> for UninitSlice {
196                 #[inline]
197                 fn index_mut(&mut self, index: $t) -> &mut UninitSlice {
198                     let maybe_uninit: &mut [MaybeUninit<u8>] = &mut self.0[index];
199                     unsafe { &mut *(maybe_uninit as *mut [MaybeUninit<u8>] as *mut UninitSlice) }
200                 }
201             }
202         )*
203     };
204 }
205 
206 impl_index!(
207     Range<usize>,
208     RangeFrom<usize>,
209     RangeFull,
210     RangeInclusive<usize>,
211     RangeTo<usize>,
212     RangeToInclusive<usize>
213 );
214