/rust/registry/src/index.crates.io-6f17d22bba15001f/bitvec-1.0.1/src/boxed.rs
Line | Count | Source (jump to first uncovered line) |
1 | | #![cfg(feature = "alloc")] |
2 | | #![doc = include_str!("../doc/boxed.md")] |
3 | | |
4 | | use alloc::boxed::Box; |
5 | | use core::{ |
6 | | mem::ManuallyDrop, |
7 | | slice, |
8 | | }; |
9 | | |
10 | | use tap::{ |
11 | | Pipe, |
12 | | Tap, |
13 | | }; |
14 | | use wyz::comu::Mut; |
15 | | |
16 | | use crate::{ |
17 | | index::BitIdx, |
18 | | mem, |
19 | | order::{ |
20 | | BitOrder, |
21 | | Lsb0, |
22 | | }, |
23 | | ptr::{ |
24 | | BitPtr, |
25 | | BitSpan, |
26 | | }, |
27 | | slice::BitSlice, |
28 | | store::BitStore, |
29 | | vec::BitVec, |
30 | | view::BitView, |
31 | | }; |
32 | | |
33 | | mod api; |
34 | | mod iter; |
35 | | mod ops; |
36 | | mod tests; |
37 | | mod traits; |
38 | | |
39 | | pub use self::iter::IntoIter; |
40 | | |
41 | | #[repr(transparent)] |
42 | | #[doc = include_str!("../doc/boxed/BitBox.md")] |
43 | | pub struct BitBox<T = usize, O = Lsb0> |
44 | | where |
45 | | T: BitStore, |
46 | | O: BitOrder, |
47 | | { |
48 | | /// Describes the region that the box owns. |
49 | | bitspan: BitSpan<Mut, T, O>, |
50 | | } |
51 | | |
52 | | impl<T, O> BitBox<T, O> |
53 | | where |
54 | | T: BitStore, |
55 | | O: BitOrder, |
56 | | { |
57 | | /// Copies a bit-slice region into a new bit-box allocation. |
58 | | /// |
59 | | /// The referent memory is `memcpy`d into the heap, exactly preserving the |
60 | | /// original bit-slice’s memory layout and contents. This allows the |
61 | | /// function to run as fast as possible, but misaligned source bit-slices |
62 | | /// may result in decreased performance or unexpected layout behavior during |
63 | | /// use. You can use [`.force_align()`] to ensure that the referent |
64 | | /// bit-slice is aligned in memory. |
65 | | /// |
66 | | /// ## Notes |
67 | | /// |
68 | | /// Bits in the allocation of the source bit-slice, but outside its own |
69 | | /// description of that memory, have an **unspecified**, but initialized, |
70 | | /// value. You may not rely on their contents in any way, and you *should* |
71 | | /// call [`.force_align()`] and/or [`.fill_uninitialized()`] if you are |
72 | | /// going to inspect the underlying memory of the new allocation. |
73 | | /// |
74 | | /// ## Examples |
75 | | /// |
76 | | /// ```rust |
77 | | /// use bitvec::prelude::*; |
78 | | /// |
79 | | /// let data = 0b0101_1011u8; |
80 | | /// let bits = data.view_bits::<Msb0>(); |
81 | | /// let bb = BitBox::from_bitslice(&bits[2 ..]); |
82 | | /// assert_eq!(bb, bits[2 ..]); |
83 | | /// ``` |
84 | | /// |
85 | | /// [`.fill_uninitialized()`]: Self::fill_uninitialized |
86 | | /// [`.force_align()`]: Self::force_align |
87 | | #[inline] |
88 | 0 | pub fn from_bitslice(slice: &BitSlice<T, O>) -> Self { |
89 | 0 | BitVec::from_bitslice(slice).into_boxed_bitslice() |
90 | 0 | } |
91 | | |
92 | | /// Converts a `Box<[T]>` into a `BitBox<T, O>`, in place. |
93 | | /// |
94 | | /// This does not affect the referent buffer, and only transforms the |
95 | | /// handle. |
96 | | /// |
97 | | /// ## Panics |
98 | | /// |
99 | | /// This panics if the provided `boxed` slice is too long to view as a |
100 | | /// bit-slice region. |
101 | | /// |
102 | | /// ## Examples |
103 | | /// |
104 | | /// ```rust |
105 | | /// use bitvec::prelude::*; |
106 | | /// |
107 | | /// let boxed: Box<[u8]> = Box::new([0; 40]); |
108 | | /// let addr = boxed.as_ptr(); |
109 | | /// let bb = BitBox::<u8>::from_boxed_slice(boxed); |
110 | | /// assert_eq!(bb, bits![0; 320]); |
111 | | /// assert_eq!(addr, bb.as_raw_slice().as_ptr()); |
112 | | /// ``` |
113 | | #[inline] |
114 | 0 | pub fn from_boxed_slice(boxed: Box<[T]>) -> Self { |
115 | 0 | Self::try_from_boxed_slice(boxed) |
116 | 0 | .expect("slice was too long to be converted into a `BitBox`") |
117 | 0 | } |
118 | | |
119 | | /// Attempts to convert an ordinary boxed slice into a boxed bit-slice. |
120 | | /// |
121 | | /// This does not perform a copy or reällocation; it only attempts to |
122 | | /// transform the handle. Because `Box<[T]>` can be longer than `BitBox`es, |
123 | | /// it may fail, and will return the original handle if it does. |
124 | | /// |
125 | | /// It is unlikely that you have a single `Box<[_]>` that is too large to |
126 | | /// convert into a bit-box. You can find the length restrictions as the |
127 | | /// bit-slice associated constants [`MAX_BITS`] and [`MAX_ELTS`]. |
128 | | /// |
129 | | /// ## Examples |
130 | | /// |
131 | | /// ```rust |
132 | | /// use bitvec::prelude::*; |
133 | | /// |
134 | | /// let boxed: Box<[u8]> = Box::new([0u8; 40]); |
135 | | /// let addr = boxed.as_ptr(); |
136 | | /// let bb = BitBox::<u8>::try_from_boxed_slice(boxed).unwrap(); |
137 | | /// assert_eq!(bb, bits![0; 320]); |
138 | | /// assert_eq!(addr, bb.as_raw_slice().as_ptr()); |
139 | | /// ``` |
140 | | /// |
141 | | /// [`MAX_BITS`]: crate::slice::BitSlice::MAX_BITS |
142 | | /// [`MAX_ELTS`]: crate::slice::BitSlice::MAX_ELTS |
143 | | #[inline] |
144 | 0 | pub fn try_from_boxed_slice(boxed: Box<[T]>) -> Result<Self, Box<[T]>> { |
145 | 0 | let mut boxed = ManuallyDrop::new(boxed); |
146 | 0 |
|
147 | 0 | BitPtr::from_mut_slice(boxed.as_mut()) |
148 | 0 | .span(boxed.len() * mem::bits_of::<T::Mem>()) |
149 | 0 | .map(|bitspan| Self { bitspan }) |
150 | 0 | .map_err(|_| ManuallyDrop::into_inner(boxed)) |
151 | 0 | } |
152 | | |
153 | | /// Converts the bit-box back into an ordinary boxed element slice. |
154 | | /// |
155 | | /// This does not touch the allocator or the buffer contents; it is purely a |
156 | | /// handle transform. |
157 | | /// |
158 | | /// ## Examples |
159 | | /// |
160 | | /// ```rust |
161 | | /// use bitvec::prelude::*; |
162 | | /// |
163 | | /// let bb = bitbox![0; 5]; |
164 | | /// let addr = bb.as_raw_slice().as_ptr(); |
165 | | /// let boxed = bb.into_boxed_slice(); |
166 | | /// assert_eq!(boxed[..], [0][..]); |
167 | | /// assert_eq!(addr, boxed.as_ptr()); |
168 | | /// ``` |
169 | | #[inline] |
170 | 0 | pub fn into_boxed_slice(self) -> Box<[T]> { |
171 | 0 | self.pipe(ManuallyDrop::new) |
172 | 0 | .as_raw_mut_slice() |
173 | 0 | .pipe(|slice| unsafe { Box::from_raw(slice) }) |
174 | 0 | } |
175 | | |
176 | | /// Converts the bit-box into a bit-vector. |
177 | | /// |
178 | | /// This uses the Rust allocator API, and does not guarantee whether or not |
179 | | /// a reällocation occurs internally. |
180 | | /// |
181 | | /// The resulting bit-vector can be converted back into a bit-box via |
182 | | /// [`BitBox::into_boxed_bitslice`][0]. |
183 | | /// |
184 | | /// ## Original |
185 | | /// |
186 | | /// [`slice::into_vec`](https://doc.rust-lang.org/std/primitive.slice.html#method.into_vec) |
187 | | /// |
188 | | /// ## API Differences |
189 | | /// |
190 | | /// The original function is implemented in an `impl<T> [T]` block, despite |
191 | | /// taking a `Box<[T]>` receiver. Since `BitBox` cannot be used as an |
192 | | /// explicit receiver outside its own `impl` blocks, the method is relocated |
193 | | /// here. |
194 | | /// |
195 | | /// ## Examples |
196 | | /// |
197 | | /// ```rust |
198 | | /// use bitvec::prelude::*; |
199 | | /// |
200 | | /// let bb = bitbox![0, 1, 0, 0, 1]; |
201 | | /// let bv = bb.into_bitvec(); |
202 | | /// |
203 | | /// assert_eq!(bv, bitvec![0, 1, 0, 0, 1]); |
204 | | /// ``` |
205 | | /// |
206 | | /// [0]: crate::vec::BitVec::into_boxed_bitslice |
207 | | #[inline] |
208 | 0 | pub fn into_bitvec(self) -> BitVec<T, O> { |
209 | 0 | let bitspan = self.bitspan; |
210 | 0 | /* This pipeline converts the underlying `Box<[T]>` into a `Vec<T>`, |
211 | 0 | * then converts that into a `BitVec`. This handles any changes that |
212 | 0 | * may occur in the allocator. Once done, the original head/span |
213 | 0 | * values need to be written into the `BitVec`, since the conversion |
214 | 0 | * from `Vec` always fully spans the live elements. |
215 | 0 | */ |
216 | 0 | self.pipe(ManuallyDrop::new) |
217 | 0 | .with_box(|b| unsafe { ManuallyDrop::take(b) }) |
218 | 0 | .into_vec() |
219 | 0 | .pipe(BitVec::from_vec) |
220 | 0 | .tap_mut(|bv| unsafe { |
221 | 0 | // len first! Otherwise, the descriptor might briefly go out of |
222 | 0 | // bounds. |
223 | 0 | bv.set_len_unchecked(bitspan.len()); |
224 | 0 | bv.set_head(bitspan.head()); |
225 | 0 | }) |
226 | 0 | } |
227 | | |
228 | | /// Explicitly views the bit-box as a bit-slice. |
229 | | #[inline] |
230 | 0 | pub fn as_bitslice(&self) -> &BitSlice<T, O> { |
231 | 0 | unsafe { self.bitspan.into_bitslice_ref() } |
232 | 0 | } |
233 | | |
234 | | /// Explicitly views the bit-box as a mutable bit-slice. |
235 | | #[inline] |
236 | 0 | pub fn as_mut_bitslice(&mut self) -> &mut BitSlice<T, O> { |
237 | 0 | unsafe { self.bitspan.into_bitslice_mut() } |
238 | 0 | } |
239 | | |
240 | | /// Views the bit-box as a slice of its underlying memory elements. |
241 | | /// |
242 | | /// Because bit-boxes uniquely own their buffer, they can safely view the |
243 | | /// underlying buffer without dealing with contending neighbors. |
244 | | #[inline] |
245 | 0 | pub fn as_raw_slice(&self) -> &[T] { |
246 | 0 | let (data, len) = |
247 | 0 | (self.bitspan.address().to_const(), self.bitspan.elements()); |
248 | 0 | unsafe { slice::from_raw_parts(data, len) } |
249 | 0 | } |
250 | | |
251 | | /// Views the bit-box as a mutable slice of its underlying memory elements. |
252 | | /// |
253 | | /// Because bit-boxes uniquely own their buffer, they can safely view the |
254 | | /// underlying buffer without dealing with contending neighbors. |
255 | | #[inline] |
256 | 0 | pub fn as_raw_mut_slice(&mut self) -> &mut [T] { |
257 | 0 | let (data, len) = |
258 | 0 | (self.bitspan.address().to_mut(), self.bitspan.elements()); |
259 | 0 | unsafe { slice::from_raw_parts_mut(data, len) } |
260 | 0 | } |
261 | | |
262 | | /// Sets the unused bits outside the `BitBox` buffer to a fixed value. |
263 | | /// |
264 | | /// This method modifies all bits that the allocated buffer owns but which |
265 | | /// are outside the `self.as_bitslice()` view. `bitvec` guarantees that all |
266 | | /// owned bits are initialized to *some* value, but does not guarantee |
267 | | /// *which* value. This method can be used to make all such unused bits have |
268 | | /// a known value after the call, so that viewing the underlying memory |
269 | | /// directly has consistent results. |
270 | | /// |
271 | | /// Note that the crate implementation guarantees that all bits owned by its |
272 | | /// handles are stably initialized according to the language and compiler |
273 | | /// rules! `bitvec` will never cause UB by using uninitialized memory. |
274 | | /// |
275 | | /// ## Examples |
276 | | /// |
277 | | /// ```rust |
278 | | /// use bitvec::prelude::*; |
279 | | /// |
280 | | /// let bits = 0b1011_0101u8.view_bits::<Msb0>(); |
281 | | /// let mut bb = BitBox::from_bitslice(&bits[2 .. 6]); |
282 | | /// assert_eq!(bb.count_ones(), 3); |
283 | | /// // Remember, the two bits on each edge are unspecified, and cannot be |
284 | | /// // observed! They must be masked away for the test to be meaningful. |
285 | | /// assert_eq!(bb.as_raw_slice()[0] & 0x3C, 0b00_1101_00u8); |
286 | | /// |
287 | | /// bb.fill_uninitialized(false); |
288 | | /// assert_eq!(bb.as_raw_slice(), &[0b00_1101_00u8]); |
289 | | /// |
290 | | /// bb.fill_uninitialized(true); |
291 | | /// assert_eq!(bb.as_raw_slice(), &[0b11_1101_11u8]); |
292 | | /// ``` |
293 | | #[inline] |
294 | 0 | pub fn fill_uninitialized(&mut self, value: bool) { |
295 | 0 | let (_, head, bits) = self.bitspan.raw_parts(); |
296 | 0 | let head = head.into_inner() as usize; |
297 | 0 | let tail = head + bits; |
298 | 0 | let all = self.as_raw_mut_slice().view_bits_mut::<O>(); |
299 | 0 | unsafe { |
300 | 0 | all.get_unchecked_mut(.. head).fill(value); |
301 | 0 | all.get_unchecked_mut(tail ..).fill(value); |
302 | 0 | } |
303 | 0 | } |
304 | | |
305 | | /// Ensures that the allocated buffer has no dead bits between the start of |
306 | | /// the buffer and the start of the live bit-slice. |
307 | | /// |
308 | | /// This is useful for ensuring a consistent memory layout in bit-boxes |
309 | | /// created by cloning an arbitrary bit-slice into the heap. As bit-slices |
310 | | /// can begin and end anywhere in memory, the [`::from_bitslice()`] function |
311 | | /// does not attempt to normalize them and only does a fast element-wise |
312 | | /// copy when creating the bit-box. |
313 | | /// |
314 | | /// The value of dead bits that are in the allocation but not in the live |
315 | | /// region are *initialized*, but do not have a *specified* value. After |
316 | | /// calling this method, you should use [`.fill_uninitialized()`] to set the |
317 | | /// excess bits in the buffer to a fixed value. |
318 | | /// |
319 | | /// ## Examples |
320 | | /// |
321 | | /// ```rust |
322 | | /// use bitvec::prelude::*; |
323 | | /// |
324 | | /// let bits = &0b10_1101_01u8.view_bits::<Msb0>()[2 .. 6]; |
325 | | /// let mut bb = BitBox::from_bitslice(bits); |
326 | | /// // Remember, the two bits on each edge are unspecified, and cannot be |
327 | | /// // observed! They must be masked away for the test to be meaningful. |
328 | | /// assert_eq!(bb.as_raw_slice()[0] & 0x3C, 0b00_1101_00u8); |
329 | | /// |
330 | | /// bb.force_align(); |
331 | | /// bb.fill_uninitialized(false); |
332 | | /// assert_eq!(bb.as_raw_slice(), &[0b1101_0000u8]); |
333 | | /// ``` |
334 | | /// |
335 | | /// [`::from_bitslice()`]: Self::from_bitslice |
336 | | /// [`.fill_uninitialized()`]: Self::fill_uninitialized |
337 | | #[inline] |
338 | 0 | pub fn force_align(&mut self) { |
339 | 0 | let head = self.bitspan.head(); |
340 | 0 | if head == BitIdx::MIN { |
341 | 0 | return; |
342 | 0 | } |
343 | 0 | let head = head.into_inner() as usize; |
344 | 0 | let last = self.len() + head; |
345 | 0 | unsafe { |
346 | 0 | self.bitspan.set_head(BitIdx::MIN); |
347 | 0 | self.copy_within_unchecked(head .. last, 0); |
348 | 0 | } |
349 | 0 | } |
350 | | |
351 | | /// Permits a function to modify the `Box` backing storage of a `BitBox` |
352 | | /// handle. |
353 | | /// |
354 | | /// This produces a temporary `Box` view of the bit-box’s buffer and allows |
355 | | /// a function to have mutable access to it. After the callback returns, the |
356 | | /// `Box` is written back into `self` and forgotten. |
357 | | #[inline] |
358 | 0 | fn with_box<F, R>(&mut self, func: F) -> R |
359 | 0 | where F: FnOnce(&mut ManuallyDrop<Box<[T]>>) -> R { |
360 | 0 | self.as_raw_mut_slice() |
361 | 0 | .pipe(|raw| unsafe { Box::from_raw(raw) }) |
362 | 0 | .pipe(ManuallyDrop::new) |
363 | 0 | .pipe_ref_mut(func) |
364 | 0 | } |
365 | | } |