bitvec/boxed.rs
1#![cfg(feature = "alloc")]
2#![doc = include_str!("../doc/boxed.md")]
3
4use alloc::boxed::Box;
5use core::{
6 mem::ManuallyDrop,
7 slice,
8};
9
10use tap::{
11 Pipe,
12 Tap,
13};
14use wyz::comu::Mut;
15
16use 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
33mod api;
34mod iter;
35mod ops;
36mod tests;
37mod traits;
38
39pub use self::iter::IntoIter;
40
41#[repr(transparent)]
42#[doc = include_str!("../doc/boxed/BitBox.md")]
43pub struct BitBox<T = usize, O = Lsb0>
44where
45 T: BitStore,
46 O: BitOrder,
47{
48 /// Describes the region that the box owns.
49 bitspan: BitSpan<Mut, T, O>,
50}
51
52impl<T, O> BitBox<T, O>
53where
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 pub fn from_bitslice(slice: &BitSlice<T, O>) -> Self {
89 BitVec::from_bitslice(slice).into_boxed_bitslice()
90 }
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 pub fn from_boxed_slice(boxed: Box<[T]>) -> Self {
115 Self::try_from_boxed_slice(boxed)
116 .expect("slice was too long to be converted into a `BitBox`")
117 }
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 pub fn try_from_boxed_slice(boxed: Box<[T]>) -> Result<Self, Box<[T]>> {
145 let mut boxed = ManuallyDrop::new(boxed);
146
147 BitPtr::from_mut_slice(boxed.as_mut())
148 .span(boxed.len() * mem::bits_of::<T::Mem>())
149 .map(|bitspan| Self { bitspan })
150 .map_err(|_| ManuallyDrop::into_inner(boxed))
151 }
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 pub fn into_boxed_slice(self) -> Box<[T]> {
171 self.pipe(ManuallyDrop::new)
172 .as_raw_mut_slice()
173 .pipe(|slice| unsafe { Box::from_raw(slice) })
174 }
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 pub fn into_bitvec(self) -> BitVec<T, O> {
209 let bitspan = self.bitspan;
210 /* This pipeline converts the underlying `Box<[T]>` into a `Vec<T>`,
211 * then converts that into a `BitVec`. This handles any changes that
212 * may occur in the allocator. Once done, the original head/span
213 * values need to be written into the `BitVec`, since the conversion
214 * from `Vec` always fully spans the live elements.
215 */
216 self.pipe(ManuallyDrop::new)
217 .with_box(|b| unsafe { ManuallyDrop::take(b) })
218 .into_vec()
219 .pipe(BitVec::from_vec)
220 .tap_mut(|bv| unsafe {
221 // len first! Otherwise, the descriptor might briefly go out of
222 // bounds.
223 bv.set_len_unchecked(bitspan.len());
224 bv.set_head(bitspan.head());
225 })
226 }
227
228 /// Explicitly views the bit-box as a bit-slice.
229 #[inline]
230 pub fn as_bitslice(&self) -> &BitSlice<T, O> {
231 unsafe { self.bitspan.into_bitslice_ref() }
232 }
233
234 /// Explicitly views the bit-box as a mutable bit-slice.
235 #[inline]
236 pub fn as_mut_bitslice(&mut self) -> &mut BitSlice<T, O> {
237 unsafe { self.bitspan.into_bitslice_mut() }
238 }
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 pub fn as_raw_slice(&self) -> &[T] {
246 let (data, len) =
247 (self.bitspan.address().to_const(), self.bitspan.elements());
248 unsafe { slice::from_raw_parts(data, len) }
249 }
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 pub fn as_raw_mut_slice(&mut self) -> &mut [T] {
257 let (data, len) =
258 (self.bitspan.address().to_mut(), self.bitspan.elements());
259 unsafe { slice::from_raw_parts_mut(data, len) }
260 }
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 pub fn fill_uninitialized(&mut self, value: bool) {
295 let (_, head, bits) = self.bitspan.raw_parts();
296 let head = head.into_inner() as usize;
297 let tail = head + bits;
298 let all = self.as_raw_mut_slice().view_bits_mut::<O>();
299 unsafe {
300 all.get_unchecked_mut(.. head).fill(value);
301 all.get_unchecked_mut(tail ..).fill(value);
302 }
303 }
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 pub fn force_align(&mut self) {
339 let head = self.bitspan.head();
340 if head == BitIdx::MIN {
341 return;
342 }
343 let head = head.into_inner() as usize;
344 let last = self.len() + head;
345 unsafe {
346 self.bitspan.set_head(BitIdx::MIN);
347 self.copy_within_unchecked(head .. last, 0);
348 }
349 }
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 fn with_box<F, R>(&mut self, func: F) -> R
359 where F: FnOnce(&mut ManuallyDrop<Box<[T]>>) -> R {
360 self.as_raw_mut_slice()
361 .pipe(|raw| unsafe { Box::from_raw(raw) })
362 .pipe(ManuallyDrop::new)
363 .pipe_ref_mut(func)
364 }
365}