1 /*! A dynamically-sized view into individual bits of a memory region.
2
3 You can read the language’s [`slice` module documentation][std] here.
4
5 This module defines the [`BitSlice`] region, and all of its associated support
6 code.
7
8 `BitSlice` is the primary working type of this crate. It is a wrapper type over
9 `[T]` which enables you to view, manipulate, and take the address of individual
10 bits in memory. It behaves in every possible respect exactly like an ordinary
11 slice: it is dynamically-sized, and must be held by `&` or `&mut` reference,
12 just like `[T]`, and implements every inherent method and trait that `[T]` does,
13 to the absolute limits of what Rust permits.
14
15 The key to `BitSlice`’s powerful capability is that references to it use a
16 special encoding that store, in addition to the address of the base element and
17 the bit length, the index of the starting bit in the base element. This custom
18 reference encoding has some costs in what APIs are possible – for instance, Rust
19 forbids it from supporting `&mut BitSlice[index] = bool` write indexing – but in
20 exchange, enables it to be *far* more capable than any other bit-slice crate in
21 existence.
22
23 Because of the volume of code that must be written to match the `[T]` standard
24 API, this module is organized very differently than the slice implementation in
25 the `core` and `std` distribution libraries.
26
27 - the root module `slice` contains new APIs that have no counterpart in `[T]`
28 - `slice/api` contains reïmplementations of the `[T]` inherent methods
29 - `slice/iter` implements all of the iteration capability
30 - `slice/ops` implements the traits in `core::ops`
31 - `slice/proxy` implements the proxy reference used in place of `&mut bool`
32 - `slice/traits` implements all other traits not in `core::ops`
33 - lastly, `slice/tests` contains all the unit tests.
34
35 [`BitSlice`]: struct.BitSlice.html
36 [std]: https://doc.rust-lang.org/std/slice
37 !*/
38
39 use crate::{
40 access::BitAccess,
41 devel as dvl,
42 domain::{
43 BitDomain,
44 BitDomainMut,
45 Domain,
46 DomainMut,
47 },
48 index::{
49 BitIdx,
50 BitMask,
51 BitRegister,
52 },
53 mem::BitMemory,
54 order::{
55 BitOrder,
56 Lsb0,
57 },
58 pointer::BitPtr,
59 store::BitStore,
60 };
61
62 use core::{
63 cmp,
64 marker::PhantomData,
65 ops::RangeBounds,
66 ptr,
67 slice,
68 };
69
70 use funty::IsInteger;
71
72 use radium::Radium;
73
74 use tap::pipe::Pipe;
75
76 /** A slice of individual bits, anywhere in memory.
77
78 This is the main working type of the crate. It is analagous to `[bool]`, and is
79 written to be as close as possible to drop-in replacable for it. This type
80 contains most of the *methods* used to operate on memory, but it will rarely be
81 named directly in your code. You should generally prefer to use [`BitArray`] for
82 fixed-size arrays or [`BitVec`] for dynamic vectors, and use `&BitSlice`
83 references only where you would directly use `&[bool]` or `&[u8]` references
84 before using this crate.
85
86 As it is a slice wrapper, you are intended to work with this through references
87 (`&BitSlice<O, T>` and `&mut BitSlice<O, T>`) or through the other data
88 structures provided by `bitvec` that are implemented atop it. Once created,
89 references to `BitSlice` are guaranteed to work just like references to `[bool]`
90 to the fullest extent possible in the Rust language.
91
92 Every bit-vector crate can give you an opaque type that hides shift/mask
93 operations from you. `BitSlice` does far more than this: it offers you the full
94 Rust guarantees about reference behavior, including lifetime tracking,
95 mutability and aliasing awareness, and explicit memory control, *as well as* the
96 full set of tools and APIs available to the standard `[bool]` slice type.
97 `BitSlice` can arbitrarily split and subslice, just like `[bool]`. You can write
98 a linear consuming function and keep the patterns already know.
99
100 For example, to trim all the bits off either edge that match a condition, you
101 could write
102
103 ```rust
104 use bitvec::prelude::*;
105
106 fn trim<O: BitOrder, T: BitStore>(
107 bits: &BitSlice<O, T>,
108 to_trim: bool,
109 ) -> &BitSlice<O, T> {
110 let stop = |b: &bool| *b != to_trim;
111 let front = bits.iter().position(stop).unwrap_or(0);
112 let back = bits.iter().rposition(stop).unwrap_or(0);
113 &bits[front ..= back]
114 }
115 # assert_eq!(trim(bits![0, 0, 1, 1, 0, 1, 0], false), bits![1, 1, 0, 1]);
116 ```
117
118 to get behavior something like
119 `trim(&BitSlice[0, 0, 1, 1, 0, 1, 0], false) == &BitSlice[1, 1, 0, 1]`.
120
121 # Documentation
122
123 All APIs that mirror something in the standard library will have an `Original`
124 section linking to the corresponding item. All APIs that have a different
125 signature or behavior than the original will have an `API Differences` section
126 explaining what has changed, and how to adapt your existing code to the change.
127
128 These sections look like this:
129
130 # Original
131
132 [`slice`](https://doc.rust-lang.org/std/primitive.slice.html)
133
134 # API Differences
135
136 The slice type `[bool]` has no type parameters. `BitSlice<O, T>` has two: one
137 for the memory type used as backing storage, and one for the order of bits
138 within that memory type.
139
140 `&BitSlice<O, T>` is capable of producing `&bool` references to read bits out
141 of its memory, but is not capable of producing `&mut bool` references to write
142 bits *into* its memory. Any `[bool]` API that would produce a `&mut bool` will
143 instead produce a [`BitMut<O, T>`] proxy reference.
144
145 # Behavior
146
147 `BitSlice` is a wrapper over `[T]`. It describes a region of memory, and must be
148 handled indirectly. This is most commonly through the reference types
149 `&BitSlice` and `&mut BitSlice`, which borrow memory owned by some other value
150 in the program. These buffers can be directly owned by the sibling types
151 `BitBox`, which behavios like `Box<[T]>`, and `BitVec`, which behaves like
152 `Vec<T>`. It cannot be used as the type parameter to a standard-library-provided
153 handle type.
154
155 The `BitSlice` region provides access to each individual bit in the region, as
156 if each bit had a memory address that you could use to dereference it. It packs
157 each logical bit into exactly one bit of storage memory, just like
158 [`std::bitset`] and [`std::vector<bool>`] in C++.
159
160 # Type Parameters
161
162 `BitSlice` has two type parameters which propagate through nearly every public
163 API in the crate. These are very important to its operation, and your choice
164 of type arguments informs nearly every part of this library’s behavior.
165
166 ## `T: BitStore`
167
168 This is the simpler of the two parameters. It refers to the integer type used to
169 hold bits. It must be one of the Rust unsigned integer fundamentals: `u8`,
170 `u16`, `u32`, `usize`, and on 64-bit systems only, `u64`. In addition, it can
171 also be the `Cell<N>` wrapper over any of those, or their equivalent types in
172 `core::sync::atomic`. Unless you know you need to have `Cell` or atomic
173 properties, though, you should use a plain integer.
174
175 The default type argument is `usize`.
176
177 The argument you choose is used as the basis of a `[T]` slice, over which the
178 `BitSlice` view type is placed. `BitSlice<_, T>` is subject to all of the rules
179 about alignment that `[T]` is. If you are working with in-memory representation
180 formats, chances are that you already have a `T` type with which you’ve been
181 working, and should use it here.
182
183 If you are only using this crate to discard the seven wasted bits per `bool`
184 of a collection of `bool`s, and are not too concerned about the in-memory
185 representation, then you should use the default type argument of `usize`. This
186 is because most processors work best when moving an entire `usize` between
187 memory and the processor itself, and using a smaller type may cause it to slow
188 down.
189
190 ## `O: BitOrder`
191
192 This is the more complex parameter. It has a default argument which, like
193 `usize`, is the good-enough choice when you do not explicitly need to control
194 the representation of bits in memory.
195
196 This parameter determines how to index the bits within a single memory element
197 `T`. Computers all agree that in a slice of elements `T`, the element with the
198 lower index has a lower memory address than the element with the higher index.
199 But the individual bits within an element do not have addresses, and so there is
200 no uniform standard of which bit is the zeroth, which is the first, which is the
201 penultimate, and which is the last.
202
203 To make matters even more confusing, there are two predominant ideas of
204 in-element ordering that often *correlate* with the in-element *byte* ordering
205 of integer types, but are in fact wholly unrelated! `bitvec` provides these two
206 main orders as types for you, and if you need a different one, it also provides
207 the tools you need to make your own.
208
209 ### Least Significant Bit Comes First
210
211 This ordering, named the [`Lsb0`] type, indexes bits within an element by
212 placing the `0` index at the least significant bit (numeric value `1`) and the
213 final index at the most significant bit (numeric value `T::min_value()`, for
214 signed integers on most machines).
215
216 For example, this is the ordering used by the [TCP wire format], and by most C
217 compilers to lay out bit-field struct members on little-endian **byte**-ordered
218 machines.
219
220 ### Most Significant Bit Comes First
221
222 This ordering, named the [`Msb0`] type, indexes bits within an element by
223 placing the `0` index at the most significant bit (numeric value `T::min_value()`
224 for most signed integers) and the final index at the least significant bit
225 (numeric value `1`).
226
227 This is the ordering used by most C compilers to lay out bit-field struct
228 members on big-endian **byte**-ordered machines.
229
230 ### Default Ordering
231
232 The default ordering is `Lsb0`, as it typically produces shorter object code
233 than `Msb0` does. If you are implementing a collection, then `Lsb0` is likely
234 the more performant ordering; if you are implementing a buffer protocol, then
235 your choice of ordering is dictated by the protocol definition.
236
237 # Safety
238
239 `BitSlice` is designed to never introduce new memory unsafety that you did not
240 provide yourself, either before or during the use of this crate. Bugs do, and
241 have, occured, and you are encouraged to submit any discovered flaw as a defect
242 report.
243
244 The `&BitSlice` reference type uses a private encoding scheme to hold all the
245 information needed in its stack value. This encoding is **not** part of the
246 public API of the library, and is not binary-compatible with `&[T]`.
247 Furthermore, in order to satisfy Rust’s requirements about alias conditions,
248 `BitSlice` performs type transformations on the `T` parameter to ensure that it
249 never creates the potential for undefined behavior.
250
251 You must never attempt to type-cast a reference to `BitSlice` in any way. You
252 must not use `mem::transmute` with `BitSlice` anywhere in its type arguments.
253 You must not use `as`-casting to convert between `*BitSlice` and any other type.
254 You must not attempt to modify the binary representation of a `&BitSlice`
255 reference value. These actions will all lead to runtime memory unsafety, are
256 (hopefully) likely to induce a program crash, and may possibly cause undefined
257 behavior at compile-time.
258
259 Everything in the `BitSlice` public API, even the `unsafe` parts, are guaranteed
260 to have no more unsafety than their equivalent parts in the standard library.
261 All `unsafe` APIs will have documentation explicitly detailing what the API
262 requires you to uphold in order for it to function safely and correctly. All
263 safe APIs will do so themselves.
264
265 # Performance
266
267 Like the standard library’s `[T]` slice, `BitSlice` is designed to be very easy
268 to use safely, while supporting `unsafe` when necessary. Rust has a powerful
269 optimizing engine, and `BitSlice` will frequently be compiled to have zero
270 runtime cost. Where it is slower, it will not be significantly slower than a
271 manual replacement.
272
273 As the machine instructions operate on registers rather than bits, your choice
274 of `T: BitOrder` type parameter can influence your slice’s performance. Using
275 larger register types means that slices can gallop over completely-filled
276 interior elements faster, while narrower register types permit more graceful
277 handling of subslicing and aliased splits.
278
279 # Construction
280
281 `BitSlice` views of memory can be constructed over borrowed data in a number of
282 ways. As this is a reference-only type, it can only ever be built by borrowing
283 an existing memory buffer and taking temporary control of your program’s view of
284 the region.
285
286 ## Macro Constructor
287
288 `BitSlice` buffers can be constructed at compile-time through the [`bits!`]
289 macro. This macro accepts a superset of the `vec!` arguments, and creates an
290 appropriate buffer in your program’s static memory.
291
292 ```rust
293 use bitvec::prelude::*;
294
295 let static_borrow = bits![0, 1, 0, 0, 1, 0, 0, 1];
296 let mutable_static: &mut BitSlice<_, _> = bits![mut 0; 8];
297
298 assert_ne!(static_borrow, mutable_static);
299 mutable_static.clone_from_bitslice(static_borrow);
300 assert_eq!(static_borrow, mutable_static);
301 ```
302
303 Note that, despite constructing a `static mut` binding, the `bits![mut …]` call
304 is not `unsafe`, as the constructed symbol is hidden and only accessible by the
305 sole `&mut` reference returned by the macro call.
306
307 ## Borrowing Constructors
308
309 The functions [`from_element`], [`from_element_mut`], [`from_slice`], and
310 [`from_slice_mut`] take references to existing memory, and construct `BitSlice`
311 references over them. These are the most basic ways to borrow memory and view it
312 as bits.
313
314 ```rust
315 use bitvec::prelude::*;
316
317 let data = [0u16; 3];
318 let local_borrow = BitSlice::<Lsb0, _>::from_slice(&data);
319
320 let mut data = [0u8; 5];
321 let local_mut = BitSlice::<Lsb0, _>::from_slice_mut(&mut data);
322 ```
323
324 ## Trait Method Constructors
325
326 The [`BitView`] trait implements `.view_bits::<O>()` and `.view_bits_mut::<O>()`
327 methods on elements, arrays not larger than 32 elements, and slices. This trait,
328 imported in the crate prelude, is *probably* the easiest way for you to borrow
329 memory.
330
331 ```rust
332 use bitvec::prelude::*;
333
334 let data = [0u32; 5];
335 let trait_view = data.view_bits::<Msb0>();
336
337 let mut data = 0usize;
338 let trait_mut = data.view_bits_mut::<Msb0>();
339 ```
340
341 ## Owned Bit Slices
342
343 If you wish to take ownership of a memory region and enforce that it is always
344 viewed as a `BitSlice` by default, you can use one of the [`BitArray`],
345 [`BitBox`], or [`BitVec`] types, rather than pairing ordinary buffer types with
346 the borrowing constructors.
347
348 ```rust
349 use bitvec::prelude::*;
350
351 let slice = bits![0; 27];
352 let array = bitarr![LocalBits, u8; 0; 10];
353 # #[cfg(feature = "alloc")] fn allocs() {
354 let boxed = bitbox![0; 10];
355 let vec = bitvec![0; 20];
356 # } #[cfg(feature = "alloc")] allocs();
357
358 // arrays always round up
359 assert_eq!(array.as_bitslice(), slice[.. 16]);
360 # #[cfg(feature = "alloc")] fn allocs2() {
361 # let slice = bits![0; 27];
362 # let boxed = bitbox![0; 10];
363 # let vec = bitvec![0; 20];
364 assert_eq!(boxed.as_bitslice(), slice[.. 10]);
365 assert_eq!(vec.as_bitslice(), slice[.. 20]);
366 # } #[cfg(feature = "alloc")] allocs2();
367 ```
368
369 [TCP wire format]: https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
370 [`BitArray`]: ../array/struct.BitArray.html
371 [`BitBox`]: ../boxed/struct.BitBox.html
372 [`BitMut<O, T>`]: struct.BitMut.html
373 [`BitVec`]: ../vec/struct.BitVec.html
374 [`BitView`]: ../view/trait.BitView.html
375 [`Lsb0`]: ../order/struct.Lsb0.html
376 [`Msb0`]: ../order/struct.Msb0.html
377 [`bits!`]: ../macro.bits.html
378 [`bitvec::prelude::LocalBits`]: ../order/type.LocalBits.html
379 [`std::bitset`]: https://en.cppreference.com/w/cpp/utility/bitset
380 [`std::vector<bool>`]: https://en.cppreference.com/w/cpp/container/vector_bool
381 **/
382 #[repr(transparent)]
383 pub struct BitSlice<O = Lsb0, T = usize>
384 where
385 O: BitOrder,
386 T: BitStore,
387 {
388 /// Mark the in-element ordering of bits
389 _ord: PhantomData<O>,
390 /// Mark the element type of memory
391 _typ: PhantomData<[T]>,
392 /// Indicate that this is a newtype wrapper over a wholly-untyped slice.
393 ///
394 /// This is necessary in order for the Rust compiler to remove restrictions
395 /// on the possible values of references to this slice `&BitSlice` and
396 /// `&mut BitSlice`.
397 ///
398 /// Rust has firm requirements that *any* reference that is directly usable
399 /// to dereference a real value must conform to its rules about address
400 /// liveness, type alignment, and for slices, trustworthy length. It is
401 /// undefined behavior for a slice reference *to a dereferencable type* to
402 /// violate any of these restrictions.
403 ///
404 /// However, the value of a reference to a zero-sized type has *no* such
405 /// restrictions, because that reference can never perform direct memory
406 /// access. The compiler will accept any value in a slot typed as `&[()]`,
407 /// because the values in it will never be used for a load or store
408 /// instruction. If this were `[T]`, then Rust would make the pointer
409 /// encoding used to manage values of `&BitSlice` become undefined behavior.
410 ///
411 /// See the `pointer` module for information on the encoding used.
412 _mem: [()],
413 }
414
415 /// Constructors are limited to integers only, and not their `Cell`s or atomics.
416 impl<O, T> BitSlice<O, T>
417 where
418 O: BitOrder,
419 T: BitStore + BitRegister,
420 {
421 /// Constructs a shared `&BitSlice` reference over a shared element.
422 ///
423 /// The [`BitView`] trait, implemented on all `T` elements, provides a
424 /// method [`.view_bits::<O>()`] which delegates to this function and may be
425 /// more convenient for you to write.
426 ///
427 /// # Parameters
428 ///
429 /// - `elem`: A shared reference to a memory element.
430 ///
431 /// # Returns
432 ///
433 /// A shared `&BitSlice` over the `elem` element.
434 ///
435 /// # Examples
436 ///
437 /// ```rust
438 /// use bitvec::prelude::*;
439 ///
440 /// let elem = 0u8;
441 /// let bits = BitSlice::<LocalBits, _>::from_element(&elem);
442 /// assert_eq!(bits.len(), 8);
443 /// ```
444 ///
445 /// [`BitView`]: ../view/trait.BitView.html
446 /// [`.view_bits::<O>()`]: ../view/trait.BitView.html#method.view_bits
447 #[inline]
from_element(elem: &T) -> &Self448 pub fn from_element(elem: &T) -> &Self {
449 unsafe {
450 BitPtr::new_unchecked(elem, BitIdx::ZERO, T::Mem::BITS as usize)
451 }
452 .to_bitslice_ref()
453 }
454
455 /// Constructs an exclusive `&mut BitSlice` reference over an element.
456 ///
457 /// The [`BitView`] trait, implemented on all `T` elements, provides a
458 /// method [`.view_bits_mut::<O>()`] which delegates to this function and
459 /// may be more convenient for you to write.
460 ///
461 /// # Parameters
462 ///
463 /// - `elem`: An exclusive reference to a memory element.
464 ///
465 /// # Returns
466 ///
467 /// An exclusive `&mut BitSlice` over the `elem` element.
468 ///
469 /// Note that the original `elem` reference will be inaccessible for the
470 /// duration of the returned slice handle’s lifetime.
471 ///
472 /// # Examples
473 ///
474 /// ```rust
475 /// use bitvec::prelude::*;
476 ///
477 /// let mut elem = 0u16;
478 /// let bits = BitSlice::<Msb0, _>::from_element_mut(&mut elem);
479 /// bits.set(15, true);
480 /// assert!(bits.get(15).unwrap());
481 /// assert_eq!(elem, 1);
482 /// ```
483 ///
484 /// [`BitView`]: ../view/trait.BitView.html
485 /// [`.view_bits_mut::<O>()`]:
486 /// ../view/trait.BitView.html#method.view_bits_mut
487 #[inline]
from_element_mut(elem: &mut T) -> &mut Self488 pub fn from_element_mut(elem: &mut T) -> &mut Self {
489 unsafe {
490 BitPtr::new_unchecked(elem, BitIdx::ZERO, T::Mem::BITS as usize)
491 }
492 .to_bitslice_mut()
493 }
494
495 /// Constructs a shared `&BitSlice` reference over a shared element slice.
496 ///
497 /// The [`BitView`] trait, implemented on all `[T]` slices, provides a
498 /// method [`.view_bits::<O>()`] that is equivalent to this function and may
499 /// be more convenient for you to write.
500 ///
501 /// # Parameters
502 ///
503 /// - `slice`: A shared reference over a sequence of memory elements.
504 ///
505 /// # Returns
506 ///
507 /// If `slice` does not have fewer than [`MAX_ELTS`] elements, this returns
508 /// `None`. Otherwise, it returns a shared `&BitSlice` over the `slice`
509 /// elements.
510 ///
511 /// # Conditions
512 ///
513 /// The produced `&BitSlice` handle always begins at the zeroth bit.
514 ///
515 /// # Examples
516 ///
517 /// ```rust
518 /// use bitvec::prelude::*;
519 ///
520 /// let slice = &[0u8, 1];
521 /// let bits = BitSlice::<Msb0, _>::from_slice(slice).unwrap();
522 /// assert!(bits[15]);
523 /// ```
524 ///
525 /// An example showing this function failing would require a slice exceeding
526 /// `!0usize >> 3` bytes in size, which is infeasible to produce.
527 ///
528 /// [`BitView`]: ../view/trait.BitView.html
529 /// [`MAX_ELTS`]: #associatedconstant.MAX_ELTS
530 /// [`.view_bits::<O>()`]: ../view/trait.BitView.html#method.view_bits
531 #[inline]
from_slice(slice: &[T]) -> Option<&Self>532 pub fn from_slice(slice: &[T]) -> Option<&Self> {
533 let elts = slice.len();
534 // Starting at the zeroth bit makes this counter an exclusive cap, not
535 // an inclusive cap.
536 if elts >= Self::MAX_ELTS {
537 return None;
538 }
539 Some(unsafe { Self::from_slice_unchecked(slice) })
540 }
541
542 /// Converts a slice reference into a `BitSlice` reference without checking
543 /// that its size can be safely used.
544 ///
545 /// # Safety
546 ///
547 /// If the `slice` length is too long, then it will be capped at
548 /// [`MAX_BITS`]. You are responsible for ensuring that the input slice is
549 /// not unduly truncated.
550 ///
551 /// Prefer [`from_slice`].
552 ///
553 /// [`MAX_BITS`]: #associatedconstant.MAX_BITS
554 /// [`from_slice`]: #method.from_slice
555 #[inline]
from_slice_unchecked(slice: &[T]) -> &Self556 pub unsafe fn from_slice_unchecked(slice: &[T]) -> &Self {
557 // This branch could be removed by lowering the element ceiling by one,
558 // but `from_slice` should not be in any tight loops, so it’s fine.
559 let bits = cmp::min(slice.len() * T::Mem::BITS as usize, Self::MAX_BITS);
560 BitPtr::new_unchecked(slice.as_ptr(), BitIdx::ZERO, bits)
561 .to_bitslice_ref()
562 }
563
564 /// Constructs an exclusive `&mut BitSlice` reference over a slice.
565 ///
566 /// The [`BitView`] trait, implemented on all `[T]` slices, provides a
567 /// method [`.view_bits_mut::<O>()`] that is equivalent to this function and
568 /// may be more convenient for you to write.
569 ///
570 /// # Parameters
571 ///
572 /// - `slice`: An exclusive reference over a sequence of memory elements.
573 ///
574 /// # Returns
575 ///
576 /// An exclusive `&mut BitSlice` over the `slice` elements.
577 ///
578 /// Note that the original `slice` reference will be inaccessible for the
579 /// duration of the returned slice handle’s lifetime.
580 ///
581 /// # Panics
582 ///
583 /// This panics if `slice` does not have fewer than [`MAX_ELTS`] elements.
584 ///
585 /// [`MAX_ELTS`]: #associatedconstant.MAX_ELTS
586 ///
587 /// # Conditions
588 ///
589 /// The produced `&mut BitSlice` handle always begins at the zeroth bit of
590 /// the zeroth element in `slice`.
591 ///
592 /// # Examples
593 ///
594 /// ```rust
595 /// use bitvec::prelude::*;
596 ///
597 /// let mut slice = [0u8; 2];
598 /// let bits = BitSlice::<Lsb0, _>::from_slice_mut(&mut slice).unwrap();
599 ///
600 /// assert!(!bits[0]);
601 /// bits.set(0, true);
602 /// assert!(bits[0]);
603 /// assert_eq!(slice[0], 1);
604 /// ```
605 ///
606 /// This example attempts to construct a `&mut BitSlice` handle from a slice
607 /// that is too large to index. Either the `vec!` allocation will fail, or
608 /// the bit-slice constructor will fail.
609 ///
610 /// ```rust,should_panic
611 /// # #[cfg(feature = "alloc")] {
612 /// use bitvec::prelude::*;
613 ///
614 /// let mut data = vec![0usize; BitSlice::<LocalBits, usize>::MAX_ELTS];
615 /// let bits = BitSlice::<LocalBits, _>::from_slice_mut(&mut data[..]).unwrap();
616 /// # }
617 /// # #[cfg(not(feature = "alloc"))] panic!("No allocator present");
618 /// ```
619 ///
620 /// [`BitView`]: ../view/trait.BitView.html
621 /// [`.view_bits_mut::<O>()`]:
622 /// ../view/trait.BitView.html#method.view_bits_mut
623 #[inline]
from_slice_mut(slice: &mut [T]) -> Option<&mut Self>624 pub fn from_slice_mut(slice: &mut [T]) -> Option<&mut Self> {
625 let elts = slice.len();
626 if elts >= Self::MAX_ELTS {
627 return None;
628 }
629 Some(unsafe { Self::from_slice_unchecked_mut(slice) })
630 }
631
632 /// Converts a slice reference into a `BitSlice` reference without checking
633 /// that its size can be safely used.
634 ///
635 /// # Safety
636 ///
637 /// If the `slice` length is too long, then it will be capped at
638 /// [`MAX_BITS`]. You are responsible for ensuring that the input slice is
639 /// not unduly truncated.
640 ///
641 /// Prefer [`from_slice_mut`].
642 ///
643 /// [`MAX_BITS`]: #associatedconstant.MAX_BITS
644 /// [`from_slice_mut`]: #method.from_slice_mut
645 #[inline]
from_slice_unchecked_mut(slice: &mut [T]) -> &mut Self646 pub unsafe fn from_slice_unchecked_mut(slice: &mut [T]) -> &mut Self {
647 let bits = cmp::min(slice.len() * T::Mem::BITS as usize, Self::MAX_BITS);
648 BitPtr::new_unchecked(slice.as_ptr(), BitIdx::ZERO, bits)
649 .to_bitslice_mut()
650 }
651 }
652
653 /// Methods specific to `BitSlice<_, T>`, and not present on `[T]`.
654 impl<O, T> BitSlice<O, T>
655 where
656 O: BitOrder,
657 T: BitStore,
658 {
659 /// Produces the empty slice. This is equivalent to `&[]` for ordinary
660 /// slices.
661 ///
662 /// # Examples
663 ///
664 /// ```rust
665 /// use bitvec::prelude::*;
666 ///
667 /// let bits: &BitSlice = BitSlice::empty();
668 /// assert!(bits.is_empty());
669 /// ```
670 #[inline]
empty<'a>() -> &'a Self671 pub fn empty<'a>() -> &'a Self {
672 BitPtr::EMPTY.to_bitslice_ref()
673 }
674
675 /// Produces the empty mutable slice. This is equivalent to `&mut []` for
676 /// ordinary slices.
677 ///
678 /// # Examples
679 ///
680 /// ```rust
681 /// use bitvec::prelude::*;
682 ///
683 /// let bits: &mut BitSlice = BitSlice::empty_mut();
684 /// assert!(bits.is_empty());
685 /// ```
686 #[inline]
empty_mut<'a>() -> &'a mut Self687 pub fn empty_mut<'a>() -> &'a mut Self {
688 BitPtr::EMPTY.to_bitslice_mut()
689 }
690
691 /// Sets the bit value at the given position.
692 ///
693 /// # Parameters
694 ///
695 /// - `&mut self`
696 /// - `index`: The bit index to set. It must be in the range `0 ..
697 /// self.len()`.
698 /// - `value`: The value to be set, `true` for `1` and `false` for `0`.
699 ///
700 /// # Effects
701 ///
702 /// If `index` is valid, then the bit to which it refers is set to `value`.
703 ///
704 /// # Panics
705 ///
706 /// This method panics if `index` is outside the slice domain.
707 ///
708 /// # Examples
709 ///
710 /// ```rust
711 /// use bitvec::prelude::*;
712 ///
713 /// let mut data = 0u8;
714 /// let bits = data.view_bits_mut::<Msb0>();
715 ///
716 /// assert!(!bits.get(7).unwrap());
717 /// bits.set(7, true);
718 /// assert!(bits.get(7).unwrap());
719 /// assert_eq!(data, 1);
720 /// ```
721 ///
722 /// This example panics when it attempts to set a bit that is out of bounds.
723 ///
724 /// ```rust,should_panic
725 /// use bitvec::prelude::*;
726 ///
727 /// let bits = bits![mut 0];
728 /// bits.set(1, false);
729 /// ```
730 #[inline]
set(&mut self, index: usize, value: bool)731 pub fn set(&mut self, index: usize, value: bool) {
732 let len = self.len();
733 assert!(index < len, "Index out of range: {} >= {}", index, len);
734 unsafe {
735 self.set_unchecked(index, value);
736 }
737 }
738
739 /// Sets a bit at an index, without checking boundary conditions.
740 ///
741 /// This is generally not recommended; use with caution! For a safe
742 /// alternative, see [`set`].
743 ///
744 /// # Parameters
745 ///
746 /// - `&mut self`
747 /// - `index`: The bit index to set. It must be in the range `0 ..
748 /// self.len()`. It will not be checked.
749 ///
750 /// # Effects
751 ///
752 /// The bit at `index` is set to `value`.
753 ///
754 /// # Safety
755 ///
756 /// This method is **not** safe. It performs raw pointer arithmetic to seek
757 /// from the start of the slice to the requested index, and set the bit
758 /// there. It does not inspect the length of `self`, and it is free to
759 /// perform out-of-bounds memory *write* access.
760 ///
761 /// Use this method **only** when you have already performed the bounds
762 /// check, and can guarantee that the call occurs with a safely in-bounds
763 /// index.
764 ///
765 /// # Examples
766 ///
767 /// This example uses a bit slice of length 2, and demonstrates
768 /// out-of-bounds access to the last bit in the element.
769 ///
770 /// ```rust
771 /// use bitvec::prelude::*;
772 ///
773 /// let mut data = 0u8;
774 /// let bits = &mut data.view_bits_mut::<Msb0>()[2 .. 4];
775 ///
776 /// assert_eq!(bits.len(), 2);
777 /// unsafe {
778 /// bits.set_unchecked(5, true);
779 /// }
780 /// assert_eq!(data, 1);
781 /// ```
782 ///
783 /// [`set`]: #method.set
784 #[inline]
set_unchecked(&mut self, index: usize, value: bool)785 pub unsafe fn set_unchecked(&mut self, index: usize, value: bool) {
786 self.bitptr().write::<O>(index, value);
787 }
788
789 /// Tests if *all* bits in the slice domain are set (logical `∧`).
790 ///
791 /// # Truth Table
792 ///
793 /// ```text
794 /// 0 0 => 0
795 /// 0 1 => 0
796 /// 1 0 => 0
797 /// 1 1 => 1
798 /// ```
799 ///
800 /// # Parameters
801 ///
802 /// - `&self`
803 ///
804 /// # Returns
805 ///
806 /// Whether all bits in the slice domain are set. The empty slice returns
807 /// `true`.
808 ///
809 /// # Examples
810 ///
811 /// ```rust
812 /// use bitvec::prelude::*;
813 ///
814 /// let bits = bits![1, 1, 0, 1];
815 /// assert!(bits[.. 2].all());
816 /// assert!(!bits[2 ..].all());
817 /// ```
818 #[inline]
all(&self) -> bool819 pub fn all(&self) -> bool {
820 match self.domain() {
821 Domain::Enclave { head, elem, tail } => {
822 /* Due to a bug in `rustc`, calling `.value()` on the two
823 `BitMask` types, to use `T::Mem | T::Mem == T::Mem`, causes type
824 resolution failure and only discovers the
825 `for<'a> BitOr<&'a Self>` implementation in the trait bounds
826 `T::Mem: BitMemory: IsUnsigned: BitOr<Self> + for<'a> BitOr<&'a Self>`.
827
828 Until this is fixed, routing through the `BitMask`
829 implementation suffices. The by-val and by-ref operator traits
830 are at the same position in the bounds chain, making this quite
831 a strange bug.
832 */
833 !O::mask(head, tail) | elem.load_value() == BitMask::ALL
834 },
835 Domain::Region { head, body, tail } => {
836 head.map_or(true, |(head, elem)| {
837 !O::mask(head, None) | elem.load_value() == BitMask::ALL
838 }) && body.iter().copied().all(|e| e == T::Mem::ALL)
839 && tail.map_or(true, |(elem, tail)| {
840 !O::mask(None, tail) | elem.load_value() == BitMask::ALL
841 })
842 },
843 }
844 }
845
846 /// Tests if *any* bit in the slice is set (logical `∨`).
847 ///
848 /// # Truth Table
849 ///
850 /// ```text
851 /// 0 0 => 0
852 /// 0 1 => 1
853 /// 1 0 => 1
854 /// 1 1 => 1
855 /// ```
856 ///
857 /// # Parameters
858 ///
859 /// - `&self`
860 ///
861 /// # Returns
862 ///
863 /// Whether any bit in the slice domain is set. The empty slice returns
864 /// `false`.
865 ///
866 /// # Examples
867 ///
868 /// ```rust
869 /// use bitvec::prelude::*;
870 ///
871 /// let bits = bits![0, 1, 0, 0];
872 /// assert!(bits[.. 2].any());
873 /// assert!(!bits[2 ..].any());
874 /// ```
875 #[inline]
any(&self) -> bool876 pub fn any(&self) -> bool {
877 match self.domain() {
878 Domain::Enclave { head, elem, tail } => {
879 O::mask(head, tail) & elem.load_value() != BitMask::ZERO
880 },
881 Domain::Region { head, body, tail } => {
882 head.map_or(false, |(head, elem)| {
883 O::mask(head, None) & elem.load_value() != BitMask::ZERO
884 }) || body.iter().copied().any(|e| e != T::Mem::ZERO)
885 || tail.map_or(false, |(elem, tail)| {
886 O::mask(None, tail) & elem.load_value() != BitMask::ZERO
887 })
888 },
889 }
890 }
891
892 /// Tests if *any* bit in the slice is unset (logical `¬∧`).
893 ///
894 /// # Truth Table
895 ///
896 /// ```text
897 /// 0 0 => 1
898 /// 0 1 => 1
899 /// 1 0 => 1
900 /// 1 1 => 0
901 /// ```
902 ///
903 /// # Parameters
904 ///
905 /// - `&self
906 ///
907 /// # Returns
908 ///
909 /// Whether any bit in the slice domain is unset.
910 ///
911 /// # Examples
912 ///
913 /// ```rust
914 /// use bitvec::prelude::*;
915 ///
916 /// let bits = bits![1, 1, 0, 1];
917 /// assert!(!bits[.. 2].not_all());
918 /// assert!(bits[2 ..].not_all());
919 /// ```
920 #[inline]
not_all(&self) -> bool921 pub fn not_all(&self) -> bool {
922 !self.all()
923 }
924
925 /// Tests if *all* bits in the slice are unset (logical `¬∨`).
926 ///
927 /// # Truth Table
928 ///
929 /// ```text
930 /// 0 0 => 1
931 /// 0 1 => 0
932 /// 1 0 => 0
933 /// 1 1 => 0
934 /// ```
935 ///
936 /// # Parameters
937 ///
938 /// - `&self`
939 ///
940 /// # Returns
941 ///
942 /// Whether all bits in the slice domain are unset.
943 ///
944 /// # Examples
945 ///
946 /// ```rust
947 /// use bitvec::prelude::*;
948 ///
949 /// let bits = bits![0, 1, 0, 0];
950 /// assert!(!bits[.. 2].not_any());
951 /// assert!(bits[2 ..].not_any());
952 /// ```
953 #[inline]
not_any(&self) -> bool954 pub fn not_any(&self) -> bool {
955 !self.any()
956 }
957
958 /// Tests whether the slice has some, but not all, bits set and some, but
959 /// not all, bits unset.
960 ///
961 /// This is `false` if either [`.all`] or [`.not_any`] are `true`.
962 ///
963 /// # Truth Table
964 ///
965 /// ```text
966 /// 0 0 => 0
967 /// 0 1 => 1
968 /// 1 0 => 1
969 /// 1 1 => 0
970 /// ```
971 ///
972 /// # Parameters
973 ///
974 /// - `&self`
975 ///
976 /// # Returns
977 ///
978 /// Whether the slice domain has mixed content. The empty slice returns
979 /// `false`.
980 ///
981 /// # Examples
982 ///
983 /// ```rust
984 /// use bitvec::prelude::*;
985 ///
986 /// let data = 0b111_000_10u8;
987 /// let bits = bits![1, 1, 0, 0, 1, 0];
988 ///
989 /// assert!(!bits[.. 2].some());
990 /// assert!(!bits[2 .. 4].some());
991 /// assert!(bits.some());
992 /// ```
993 ///
994 /// [`.all`]: #method.all
995 /// [`.not_any`]: #method.not_any
996 #[inline]
some(&self) -> bool997 pub fn some(&self) -> bool {
998 self.any() && self.not_all()
999 }
1000
1001 /// Returns the number of ones in the memory region backing `self`.
1002 ///
1003 /// # Parameters
1004 ///
1005 /// - `&self`
1006 ///
1007 /// # Returns
1008 ///
1009 /// The number of high bits in the slice domain.
1010 ///
1011 /// # Examples
1012 ///
1013 /// Basic usage:
1014 ///
1015 /// ```rust
1016 /// use bitvec::prelude::*;
1017 ///
1018 /// let bits = bits![1, 1, 0, 0];
1019 /// assert_eq!(bits[.. 2].count_ones(), 2);
1020 /// assert_eq!(bits[2 ..].count_ones(), 0);
1021 /// ```
1022 #[inline]
count_ones(&self) -> usize1023 pub fn count_ones(&self) -> usize {
1024 match self.domain() {
1025 Domain::Enclave { head, elem, tail } => (O::mask(head, tail)
1026 & elem.load_value())
1027 .value()
1028 .count_ones() as usize,
1029 Domain::Region { head, body, tail } => {
1030 head.map_or(0, |(head, elem)| {
1031 (O::mask(head, None) & elem.load_value())
1032 .value()
1033 .count_ones() as usize
1034 }) + body
1035 .iter()
1036 .copied()
1037 .map(|e| e.count_ones() as usize)
1038 .sum::<usize>() + tail.map_or(0, |(elem, tail)| {
1039 (O::mask(None, tail) & elem.load_value())
1040 .value()
1041 .count_ones() as usize
1042 })
1043 },
1044 }
1045 }
1046
1047 /// Returns the number of zeros in the memory region backing `self`.
1048 ///
1049 /// # Parameters
1050 ///
1051 /// - `&self`
1052 ///
1053 /// # Returns
1054 ///
1055 /// The number of low bits in the slice domain.
1056 ///
1057 /// # Examples
1058 ///
1059 /// Basic usage:
1060 ///
1061 /// ```rust
1062 /// use bitvec::prelude::*;
1063 ///
1064 /// let bits = bits![1, 1, 0, 0];
1065 /// assert_eq!(bits[.. 2].count_zeros(), 0);
1066 /// assert_eq!(bits[2 ..].count_zeros(), 2);
1067 /// ```
1068 #[inline]
count_zeros(&self) -> usize1069 pub fn count_zeros(&self) -> usize {
1070 match self.domain() {
1071 Domain::Enclave { head, elem, tail } => (!O::mask(head, tail)
1072 | elem.load_value())
1073 .value()
1074 .count_zeros() as usize,
1075 Domain::Region { head, body, tail } => {
1076 head.map_or(0, |(head, elem)| {
1077 (!O::mask(head, None) | elem.load_value())
1078 .value()
1079 .count_zeros() as usize
1080 }) + body
1081 .iter()
1082 .copied()
1083 .map(|e| e.count_zeros() as usize)
1084 .sum::<usize>() + tail.map_or(0, |(elem, tail)| {
1085 (!O::mask(None, tail) | elem.load_value())
1086 .value()
1087 .count_zeros() as usize
1088 })
1089 },
1090 }
1091 }
1092
1093 /// Sets all bits in the slice to a value.
1094 ///
1095 /// # Parameters
1096 ///
1097 /// - `&mut self`
1098 /// - `value`: The bit value to which all bits in the slice will be set.
1099 ///
1100 /// # Examples
1101 ///
1102 /// ```rust
1103 /// use bitvec::prelude::*;
1104 ///
1105 /// let mut src = 0u8;
1106 /// let bits = src.view_bits_mut::<Msb0>();
1107 /// bits[2 .. 6].set_all(true);
1108 /// assert_eq!(bits.as_slice(), &[0b0011_1100]);
1109 /// bits[3 .. 5].set_all(false);
1110 /// assert_eq!(bits.as_slice(), &[0b0010_0100]);
1111 /// bits[.. 1].set_all(true);
1112 /// assert_eq!(bits.as_slice(), &[0b1010_0100]);
1113 /// ```
1114 #[inline]
set_all(&mut self, value: bool)1115 pub fn set_all(&mut self, value: bool) {
1116 // Grab the function pointers used to commit bit-masks into memory.
1117 let setter = <<T::Alias as BitStore>::Access>::get_writers(value);
1118 match self.domain_mut() {
1119 DomainMut::Enclave { head, elem, tail } => {
1120 // Step three: write the bitmask through the accessor.
1121 setter(
1122 // Step one: attach an `::Access` marker to the reference
1123 dvl::accessor(elem),
1124 // Step two: insert an `::Alias` marker *into the bitmask*
1125 // because typechecking is “fun”
1126 O::mask(head, tail).pipe(dvl::alias_mask::<T>),
1127 );
1128 },
1129 DomainMut::Region { head, body, tail } => {
1130 if let Some((head, elem)) = head {
1131 setter(
1132 dvl::accessor(elem),
1133 O::mask(head, None).pipe(dvl::alias_mask::<T>),
1134 );
1135 }
1136 // loop assignment is `memset`’s problem, not ours
1137 unsafe {
1138 ptr::write_bytes(
1139 body.as_mut_ptr(),
1140 [0, !0][value as usize],
1141 body.len(),
1142 );
1143 }
1144 if let Some((elem, tail)) = tail {
1145 setter(
1146 dvl::accessor(elem),
1147 O::mask(None, tail).pipe(dvl::alias_mask::<T>),
1148 );
1149 }
1150 },
1151 }
1152 }
1153
1154 /// Applies a function to each bit in the slice.
1155 ///
1156 /// `BitSlice` cannot implement `IndexMut`, as it cannot manifest `&mut
1157 /// bool` references, and the [`BitMut`] proxy reference has an unavoidable
1158 /// overhead. This method bypasses both problems, by applying a function to
1159 /// each pair of index and value in the slice, without constructing a proxy
1160 /// reference.
1161 ///
1162 /// # Parameters
1163 ///
1164 /// - `&mut self`
1165 /// - `func`: A function which receives two arguments, `index: usize` and
1166 /// `value: bool`, and returns a `bool`.
1167 ///
1168 /// # Effects
1169 ///
1170 /// For each index in the slice, the result of invoking `func` with the
1171 /// index number and current bit value is written into the slice.
1172 ///
1173 /// # Examples
1174 ///
1175 /// ```rust
1176 /// use bitvec::prelude::*;
1177 ///
1178 /// let mut data = 0u8;
1179 /// let bits = data.view_bits_mut::<Msb0>();
1180 /// bits.for_each(|idx, _bit| idx % 3 == 0);
1181 /// assert_eq!(data, 0b100_100_10);
1182 /// ```
1183 #[inline]
for_each<F>(&mut self, mut func: F) where F: FnMut(usize, bool) -> bool1184 pub fn for_each<F>(&mut self, mut func: F)
1185 where F: FnMut(usize, bool) -> bool {
1186 for idx in 0 .. self.len() {
1187 unsafe {
1188 let tmp = *self.get_unchecked(idx);
1189 let new = func(idx, tmp);
1190 self.set_unchecked(idx, new);
1191 }
1192 }
1193 }
1194
1195 /// Accesses the total backing storage of the `BitSlice`, as a slice of its
1196 /// elements.
1197 ///
1198 /// This method produces a slice over all the memory elements it touches,
1199 /// using the current storage parameter. This is safe to do, as any events
1200 /// that would create an aliasing view into the elements covered by the
1201 /// returned slice will also have caused the slice to use its alias-aware
1202 /// type.
1203 ///
1204 /// # Parameters
1205 ///
1206 /// - `&self`
1207 ///
1208 /// # Returns
1209 ///
1210 /// A view of the entire memory region this slice covers, including the edge
1211 /// elements.
1212 ///
1213 /// # Examples
1214 ///
1215 /// ```rust
1216 /// use bitvec::prelude::*;
1217 ///
1218 /// let data = 0x3Cu8;
1219 /// let bits = &data.view_bits::<LocalBits>()[2 .. 6];
1220 ///
1221 /// assert!(bits.all());
1222 /// assert_eq!(bits.len(), 4);
1223 /// assert_eq!(bits.as_slice(), &[0x3Cu8]);
1224 /// ```
1225 #[inline]
1226 #[cfg(not(tarpaulin_include))]
as_slice(&self) -> &[T]1227 pub fn as_slice(&self) -> &[T] {
1228 let bitptr = self.bitptr();
1229 let (base, elts) = (bitptr.pointer().to_const(), bitptr.elements());
1230 unsafe { slice::from_raw_parts(base, elts) }
1231 }
1232
1233 /// Views the wholly-filled elements of the `BitSlice`.
1234 ///
1235 /// This will not include partially-owned edge elements, as they may be
1236 /// aliased by other handles. To gain access to all elements that the
1237 /// `BitSlice` region covers, use one of the following:
1238 ///
1239 /// - [`.as_slice`] produces a shared slice over all elements, marked
1240 /// aliased as appropriate.
1241 /// - [`.domain`] produces a view describing each component of the region,
1242 /// marking only the contended edges as aliased and the uncontended
1243 /// interior as unaliased.
1244 ///
1245 /// # Parameters
1246 ///
1247 /// - `&self`
1248 ///
1249 /// # Returns
1250 ///
1251 /// A slice of all the wholly-filled elements in the `BitSlice` backing
1252 /// storage.
1253 ///
1254 /// # Examples
1255 ///
1256 /// ```rust
1257 /// use bitvec::prelude::*;
1258 ///
1259 /// let data = [1u8, 66];
1260 /// let bits = data.view_bits::<Msb0>();
1261 ///
1262 /// let accum = bits
1263 /// .as_raw_slice()
1264 /// .iter()
1265 /// .copied()
1266 /// .map(u8::count_ones)
1267 /// .sum::<u32>();
1268 /// assert_eq!(accum, 3);
1269 /// ```
1270 ///
1271 /// [`.as_slice`]: #method.as_slice
1272 /// [`.domain`]: #method.domain
1273 #[inline]
1274 #[cfg(not(tarpaulin_include))]
as_raw_slice(&self) -> &[T::Mem]1275 pub fn as_raw_slice(&self) -> &[T::Mem] {
1276 self.domain().region().map_or(&[], |(_, b, _)| b)
1277 }
1278
1279 /// Views the wholly-filled elements of the `BitSlice`.
1280 ///
1281 /// This will not include partially-owned edge elements, as they may be
1282 /// aliased by other handles. To gain access to all elements that the
1283 /// `BitSlice` region covers, use one of the following:
1284 ///
1285 /// - [`.as_aliased_slice`] produces a shared slice over all elements,
1286 /// marked as aliased to allow for the possibliity of mutation.
1287 /// - [`.domain_mut`] produces a view describing each component of the
1288 /// region, marking only the contended edges as aliased and the
1289 /// uncontended interior as unaliased.
1290 ///
1291 /// # Parameters
1292 ///
1293 /// - `&mut self`
1294 ///
1295 /// # Returns
1296 ///
1297 /// A mutable slice of all the wholly-filled elements in the `BitSlice`
1298 /// backing storage.
1299 ///
1300 /// # Examples
1301 ///
1302 /// ```rust
1303 /// use bitvec::prelude::*;
1304 ///
1305 /// let mut data = [1u8, 64];
1306 /// let bits = data.view_bits_mut::<Msb0>();
1307 /// for elt in bits.as_raw_slice_mut() {
1308 /// *elt |= 2;
1309 /// }
1310 /// assert_eq!(&[3, 66], bits.as_slice());
1311 /// ```
1312 ///
1313 /// [`.as_aliased_slice`]: #method.as_aliased_slice
1314 /// [`.domain_mut`]: #method.domain_mut
1315 #[inline]
1316 #[cfg(not(tarpaulin_include))]
as_raw_slice_mut(&mut self) -> &mut [T::Mem]1317 pub fn as_raw_slice_mut(&mut self) -> &mut [T::Mem] {
1318 self.domain_mut().region().map_or(&mut [], |(_, b, _)| b)
1319 }
1320
1321 /// Splits the slice into the logical components of its memory domain.
1322 ///
1323 /// This produces a set of read-only subslices, marking as much as possible
1324 /// as affirmatively lacking any write-capable view (`T::NoAlias`). The
1325 /// unaliased view is able to safely perform unsynchronized reads from
1326 /// memory without causing undefined behavior, as the type system is able to
1327 /// statically prove that no other write-capable views exist.
1328 ///
1329 /// # Parameters
1330 ///
1331 /// - `&self`
1332 ///
1333 /// # Returns
1334 ///
1335 /// A `BitDomain` structure representing the logical components of the
1336 /// memory region.
1337 ///
1338 /// # Safety Exception
1339 ///
1340 /// The following snippet describes a means of constructing a `T::NoAlias`
1341 /// view into memory that is, in fact, aliased:
1342 ///
1343 /// ```rust
1344 /// # #[cfg(feature = "atomic")] {
1345 /// use bitvec::prelude::*;
1346 /// use core::sync::atomic::AtomicU8;
1347 /// type Bs<T> = BitSlice<LocalBits, T>;
1348 ///
1349 /// let data = [AtomicU8::new(0), AtomicU8::new(0), AtomicU8::new(0)];
1350 /// let bits: &Bs<AtomicU8> = data.view_bits::<LocalBits>();
1351 /// let subslice: &Bs<AtomicU8> = &bits[4 .. 20];
1352 ///
1353 /// let (_, noalias, _): (_, &Bs<u8>, _) =
1354 /// subslice.bit_domain().region().unwrap();
1355 /// # }
1356 /// ```
1357 ///
1358 /// The `noalias` reference, which has memory type `u8`, assumes that it can
1359 /// act as an `&u8` reference: unsynchronized loads are permitted, as no
1360 /// handle exists which is capable of modifying the middle bit of `data`.
1361 /// This means that LLVM is permitted to issue loads from memory *wherever*
1362 /// it wants in the block during which `noalias` is live, as all loads are
1363 /// equivalent.
1364 ///
1365 /// Use of the `bits` or `subslice` handles, which are still live for the
1366 /// lifetime of `noalias`, to issue [`.set_aliased`] calls into the middle
1367 /// element introduce **undefined behavior**. `bitvec` permits safe code to
1368 /// introduce this undefined behavior solely because it requires deliberate
1369 /// opt-in – you must start from atomic data; this cannot occur when `data`
1370 /// is non-atomic – and use of the shared-mutation facility simultaneously
1371 /// with the unaliasing view.
1372 ///
1373 /// The [`.set_aliased`] method is speculative, and will be marked as
1374 /// `unsafe` or removed at any suspicion that its presence in the library
1375 /// has any costs.
1376 ///
1377 /// # Examples
1378 ///
1379 /// This method can be used to accelerate reads from a slice that is marked
1380 /// as aliased.
1381 ///
1382 /// ```rust
1383 /// use bitvec::prelude::*;
1384 /// type Bs<T> = BitSlice<LocalBits, T>;
1385 ///
1386 /// let bits = bits![mut LocalBits, u8; 0; 24];
1387 /// let (a, b): (
1388 /// &mut Bs<<u8 as BitStore>::Alias>,
1389 /// &mut Bs<<u8 as BitStore>::Alias>,
1390 /// ) = bits.split_at_mut(4);
1391 /// let (partial, full, _): (
1392 /// &Bs<<u8 as BitStore>::Alias>,
1393 /// &Bs<<u8 as BitStore>::Mem>,
1394 /// _,
1395 /// ) = b.bit_domain().region().unwrap();
1396 /// read_from(partial); // uses alias-aware reads
1397 /// read_from(full); // uses ordinary reads
1398 /// # fn read_from<T: BitStore>(_: &BitSlice<LocalBits, T>) {}
1399 /// ```
1400 ///
1401 /// [`.set_aliased`]: #method.set_aliased
1402 #[inline(always)]
1403 #[cfg(not(tarpaulin_include))]
bit_domain(&self) -> BitDomain<O, T>1404 pub fn bit_domain(&self) -> BitDomain<O, T> {
1405 BitDomain::new(self)
1406 }
1407
1408 /// Splits the slice into the logical components of its memory domain.
1409 ///
1410 /// This produces a set of mutable subslices, marking as much as possible as
1411 /// affirmatively lacking any other view (`T::Mem`). The bare view is able
1412 /// to safely perform unsynchronized reads from and writes to memory without
1413 /// causing undefined behavior, as the type system is able to statically
1414 /// prove that no other views exist.
1415 ///
1416 /// # Why This Is More Sound Than `.bit_domain`
1417 ///
1418 /// The `&mut` exclusion rule makes it impossible to construct two
1419 /// references over the same memory where one of them is marked `&mut`. This
1420 /// makes it impossible to hold a live reference to memory *separately* from
1421 /// any references produced from this method. For the duration of all
1422 /// references produced by this method, all ancestor references used to
1423 /// reach this method call are either suspended or dead, and the compiler
1424 /// will not allow you to use them.
1425 ///
1426 /// As such, this method cannot introduce undefined behavior where a
1427 /// reference incorrectly believes that the referent memory region is
1428 /// immutable.
1429 #[inline(always)]
1430 #[cfg(not(tarpaulin_include))]
bit_domain_mut(&mut self) -> BitDomainMut<O, T>1431 pub fn bit_domain_mut(&mut self) -> BitDomainMut<O, T> {
1432 BitDomainMut::new(self)
1433 }
1434
1435 /// Splits the slice into immutable references to its underlying memory
1436 /// components.
1437 ///
1438 /// Unlike [`.bit_domain`] and [`.bit_domain_mut`], this does not return
1439 /// smaller `BitSlice` handles but rather appropriately-marked references to
1440 /// the underlying memory elements.
1441 ///
1442 /// The aliased references allow mutation of these elements. You are
1443 /// required to not use mutating methods on these references *at all*. This
1444 /// function is not marked `unsafe`, but this is a contract you must uphold.
1445 /// Use [`.domain_mut`] to modify the underlying elements.
1446 ///
1447 /// > It is not currently possible to forbid mutation through these
1448 /// > references. This may change in the future.
1449 ///
1450 /// # Safety Exception
1451 ///
1452 /// As with [`.bit_domain`], this produces unsynchronized immutable
1453 /// references over the fully-populated interior elements. If this view is
1454 /// constructed from a `BitSlice` handle over atomic memory, then it will
1455 /// remove the atomic access behavior for the interior elements. This *by
1456 /// itself* is safe, as long as no contemporaneous atomic writes to that
1457 /// memory can occur. You must not retain and use an atomic reference to the
1458 /// memory region marked as `NoAlias` for the duration of this view’s
1459 /// existence.
1460 ///
1461 /// # Parameters
1462 ///
1463 /// - `&self`
1464 ///
1465 /// # Returns
1466 ///
1467 /// A read-only descriptor of the memory elements backing `*self`.
1468 ///
1469 /// [`.bit_domain`]: #method.bit_domain
1470 /// [`.bit_domain_mut`]: #method.bit_domain_mut
1471 /// [`.domain_mut`]: #method.domain_mut
1472 #[inline(always)]
1473 #[cfg(not(tarpaulin_include))]
domain(&self) -> Domain<T>1474 pub fn domain(&self) -> Domain<T> {
1475 Domain::new(self)
1476 }
1477
1478 /// Splits the slice into mutable references to its underlying memory
1479 /// elements.
1480 ///
1481 /// Like [`.domain`], this returns appropriately-marked references to the
1482 /// underlying memory elements. These references are all writable.
1483 ///
1484 /// The aliased edge references permit modifying memory beyond their bit
1485 /// marker. You are required to only mutate the region of these edge
1486 /// elements that you currently govern. This function is not marked
1487 /// `unsafe`, but this is a contract you must uphold.
1488 ///
1489 /// > It is not currently possible to forbid out-of-bounds mutation through
1490 /// > these references. This may change in the future.
1491 ///
1492 /// # Parameters
1493 ///
1494 /// - `&mut self`
1495 ///
1496 /// # Returns
1497 ///
1498 /// A descriptor of the memory elements underneath `*self`, permitting
1499 /// mutation.
1500 ///
1501 /// [`.domain`]: #method.domain
1502 #[inline]
1503 #[cfg(not(tarpaulin_include))]
domain_mut(&mut self) -> DomainMut<T>1504 pub fn domain_mut(&mut self) -> DomainMut<T> {
1505 DomainMut::new(self)
1506 }
1507
1508 /// Splits a slice at some mid-point, without checking boundary conditions.
1509 ///
1510 /// This is generally not recommended; use with caution! For a safe
1511 /// alternative, see [`split_at`].
1512 ///
1513 /// # Parameters
1514 ///
1515 /// - `&self`
1516 /// - `mid`: The index at which to split the slice. This must be in the
1517 /// range `0 .. self.len()`.
1518 ///
1519 /// # Returns
1520 ///
1521 /// - `.0`: `&self[.. mid]`
1522 /// - `.1`: `&self[mid ..]`
1523 ///
1524 /// # Safety
1525 ///
1526 /// This function is **not** safe. It performs raw pointer arithmetic to
1527 /// construct two new references. If `mid` is out of bounds, then the first
1528 /// slice will be too large, and the second will be *catastrophically*
1529 /// incorrect. As both are references to invalid memory, they are undefined
1530 /// to *construct*, and may not ever be used.
1531 ///
1532 /// # Examples
1533 ///
1534 /// ```rust
1535 /// use bitvec::prelude::*;
1536 ///
1537 /// let data = 0x0180u16;
1538 /// let bits = data.view_bits::<Msb0>();
1539 ///
1540 /// let (one, two) = unsafe { bits.split_at_unchecked(8) };
1541 /// assert!(one[7]);
1542 /// assert!(two[0]);
1543 /// ```
1544 ///
1545 /// [`split_at`]: #method.split_at
1546 #[inline]
split_at_unchecked(&self, mid: usize) -> (&Self, &Self)1547 pub unsafe fn split_at_unchecked(&self, mid: usize) -> (&Self, &Self) {
1548 (self.get_unchecked(.. mid), self.get_unchecked(mid ..))
1549 }
1550
1551 /// Splits a mutable slice at some mid-point, without checking boundary
1552 /// conditions.
1553 ///
1554 /// This is generally not recommended; use with caution! For a safe
1555 /// alternative, see [`split_at_mut`].
1556 ///
1557 /// # Parameters
1558 ///
1559 /// - `&mut self`
1560 /// - `mid`: The index at which to split the slice. This must be in the
1561 /// range `0 .. self.len()`.
1562 ///
1563 /// # Returns
1564 ///
1565 /// - `.0`: `&mut self[.. mid]`
1566 /// - `.1`: `&mut self[mid ..]`
1567 ///
1568 /// # Safety
1569 ///
1570 /// This function is **not** safe. It performs raw pointer arithmetic to
1571 /// construct two new references. If `mid` is out of bounds, then the first
1572 /// slice will be too large, and the second will be *catastrophically*
1573 /// incorrect. As both are references to invalid memory, they are undefined
1574 /// to *construct*, and may not ever be used.
1575 ///
1576 /// # Examples
1577 ///
1578 /// ```rust
1579 /// use bitvec::prelude::*;
1580 ///
1581 /// let mut data = 0u16;
1582 /// let bits = data.view_bits_mut::<Msb0>();
1583 ///
1584 /// let (one, two) = unsafe { bits.split_at_unchecked_mut(8) };
1585 /// one.set(7, true);
1586 /// two.set(0, true);
1587 /// assert_eq!(data, 0x0180u16);
1588 /// ```
1589 ///
1590 /// [`split_at_mut`]: #method.split_at_mut
1591 #[inline]
1592 #[allow(clippy::type_complexity)]
split_at_unchecked_mut( &mut self, mid: usize, ) -> (&mut BitSlice<O, T::Alias>, &mut BitSlice<O, T::Alias>)1593 pub unsafe fn split_at_unchecked_mut(
1594 &mut self,
1595 mid: usize,
1596 ) -> (&mut BitSlice<O, T::Alias>, &mut BitSlice<O, T::Alias>)
1597 {
1598 let bp = self.alias_mut().bitptr();
1599 (
1600 bp.to_bitslice_mut().get_unchecked_mut(.. mid),
1601 bp.to_bitslice_mut().get_unchecked_mut(mid ..),
1602 )
1603 }
1604
1605 /// Splits a mutable slice at some mid-point, without checking boundary
1606 /// conditions or adding an alias marker.
1607 ///
1608 /// This method has the same behavior as [`split_at_unchecked_mut`], except
1609 /// that it does not apply an aliasing marker to the partitioned subslices.
1610 ///
1611 /// # Safety
1612 ///
1613 /// See [`split_at_unchecked_mut`] for safety requirements.
1614 ///
1615 /// Additionally, this is only safe when `T` is alias-safe.
1616 ///
1617 /// [`split_at_unchecked_mut`]: #method.split_at_unchecked_mut
1618 #[inline]
split_at_unchecked_mut_noalias( &mut self, mid: usize, ) -> (&mut Self, &mut Self)1619 pub(crate) unsafe fn split_at_unchecked_mut_noalias(
1620 &mut self,
1621 mid: usize,
1622 ) -> (&mut Self, &mut Self)
1623 {
1624 // Split the slice at the requested midpoint, adding an alias layer
1625 let (head, tail) = self.split_at_unchecked_mut(mid);
1626 // Remove the new alias layer.
1627 (Self::unalias_mut(head), Self::unalias_mut(tail))
1628 }
1629
1630 /// Swaps the bits at two indices without checking boundary conditions.
1631 ///
1632 /// This is generally not recommended; use with caution! For a safe
1633 /// alternative, see [`swap`].
1634 ///
1635 /// # Parameters
1636 ///
1637 /// - `&mut self`
1638 /// - `a`: One index to swap.
1639 /// - `b`: The other index to swap.
1640 ///
1641 /// # Effects
1642 ///
1643 /// The bit at index `a` is written into index `b`, and the bit at index `b`
1644 /// is written into `a`.
1645 ///
1646 /// # Safety
1647 ///
1648 /// Both `a` and `b` must be less than `self.len()`. Indices greater than
1649 /// the length will cause out-of-bounds memory access, which can lead to
1650 /// memory unsafety and a program crash.
1651 ///
1652 /// # Examples
1653 ///
1654 /// ```rust
1655 /// use bitvec::prelude::*;
1656 ///
1657 /// let mut data = 8u8;
1658 /// let bits = data.view_bits_mut::<Msb0>();
1659 ///
1660 /// unsafe { bits.swap_unchecked(0, 4); }
1661 ///
1662 /// assert_eq!(data, 128);
1663 /// ```
1664 ///
1665 /// [`swap`]: #method.swap
1666 #[inline]
swap_unchecked(&mut self, a: usize, b: usize)1667 pub unsafe fn swap_unchecked(&mut self, a: usize, b: usize) {
1668 let bit_a = *self.get_unchecked(a);
1669 let bit_b = *self.get_unchecked(b);
1670 self.set_unchecked(a, bit_b);
1671 self.set_unchecked(b, bit_a);
1672 }
1673
1674 /// Copies a bit from one index to another without checking boundary
1675 /// conditions.
1676 ///
1677 /// # Parameters
1678 ///
1679 /// - `&mut self`
1680 /// - `from`: The index whose bit is to be copied
1681 /// - `to`: The index into which the copied bit is written.
1682 ///
1683 /// # Effects
1684 ///
1685 /// The bit at `from` is written into `to`.
1686 ///
1687 /// # Safety
1688 ///
1689 /// Both `from` and `to` must be less than `self.len()`, in order for
1690 /// `self` to legally read from and write to them, respectively.
1691 ///
1692 /// If `self` had been split from a larger slice, reading from `from` or
1693 /// writing to `to` may not *necessarily* cause a memory-safety violation in
1694 /// the Rust model, due to the aliasing system `bitvec` employs. However,
1695 /// writing outside the bounds of a slice reference is *always* a logical
1696 /// error, as it causes changes observable by another reference handle.
1697 ///
1698 /// # Examples
1699 ///
1700 /// ```rust
1701 /// use bitvec::prelude::*;
1702 ///
1703 /// let mut data = 1u8;
1704 /// let bits = data.view_bits_mut::<Lsb0>();
1705 ///
1706 /// unsafe { bits.copy_unchecked(0, 2) };
1707 ///
1708 /// assert_eq!(data, 5);
1709 /// ```
1710 #[inline]
copy_unchecked(&mut self, from: usize, to: usize)1711 pub unsafe fn copy_unchecked(&mut self, from: usize, to: usize) {
1712 let tmp = *self.get_unchecked(from);
1713 self.set_unchecked(to, tmp);
1714 }
1715
1716 /// Copies bits from one part of the slice to another part of itself.
1717 ///
1718 /// `src` is the range within `self` to copy from. `dest` is the starting
1719 /// index of the range within `self` to copy to, which will have the same
1720 /// length as `src`. The two ranges may overlap. The ends of the two ranges
1721 /// must be less than or equal to `self.len()`.
1722 ///
1723 /// # Effects
1724 ///
1725 /// `self[src]` is copied to `self[dest .. dest + src.end() - src.start()]`.
1726 ///
1727 /// # Panics
1728 ///
1729 /// This function will panic if either range exceeds the end of the slice,
1730 /// or if the end of `src` is before the start.
1731 ///
1732 /// # Safety
1733 ///
1734 /// Both the `src` range and the target range `dest .. dest + src.len()`
1735 /// must not exceed the `self.len()` slice range.
1736 ///
1737 /// # Examples
1738 ///
1739 /// ```rust
1740 /// use bitvec::prelude::*;
1741 ///
1742 /// let mut data = 0x07u8;
1743 /// let bits = data.view_bits_mut::<Msb0>();
1744 ///
1745 /// unsafe { bits.copy_within_unchecked(5 .., 0); }
1746 ///
1747 /// assert_eq!(data, 0xE7);
1748 /// ```
1749 #[inline]
copy_within_unchecked<R>(&mut self, src: R, dest: usize) where R: RangeBounds<usize>1750 pub unsafe fn copy_within_unchecked<R>(&mut self, src: R, dest: usize)
1751 where R: RangeBounds<usize> {
1752 let len = self.len();
1753 let rev = src.contains(&dest);
1754 let source = dvl::normalize_range(src, len);
1755 let iter = source.zip(dest .. len);
1756 if rev {
1757 for (from, to) in iter.rev() {
1758 self.copy_unchecked(from, to);
1759 }
1760 }
1761 else {
1762 for (from, to) in iter {
1763 self.copy_unchecked(from, to);
1764 }
1765 }
1766 }
1767
1768 /// Produces the absolute offset in bits between two slice heads.
1769 ///
1770 /// While this method is sound for any two arbitrary bit slices, the answer
1771 /// it produces is meaningful *only* when one argument is a strict subslice
1772 /// of the other. If the two slices are created from different buffers
1773 /// entirely, a comparison is undefined; if the two slices are disjoint
1774 /// regions of the same buffer, then the semantically correct distance is
1775 /// between the tail of the lower and the head of the upper, which this
1776 /// does not measure.
1777 ///
1778 /// # Visual Description
1779 ///
1780 /// Consider the following sequence of bits:
1781 ///
1782 /// ```text
1783 /// [ 0 1 2 3 4 5 6 7 8 9 a b ]
1784 /// | ^^^^^^^ |
1785 /// ^^^^^^^^^^^^^^^^^^^^^^^
1786 /// ```
1787 ///
1788 /// It does not matter whether there are bits between the tail of the
1789 /// smaller and the larger slices. The offset is computed from the bit
1790 /// distance between the two heads.
1791 ///
1792 /// # Behavior
1793 ///
1794 /// This function computes the *semantic* distance between the heads, rather
1795 /// than the *electrical. It does not take into account the `BitOrder`
1796 /// implementation of the slice. See the [`::electrical_distance`] method
1797 /// for that comparison.
1798 ///
1799 /// # Safety and Soundness
1800 ///
1801 /// One of `self` or `other` must contain the other for this comparison to
1802 /// be meaningful.
1803 ///
1804 /// # Parameters
1805 ///
1806 /// - `&self`
1807 /// - `other`: Another bit slice. This must be either a strict subregion or
1808 /// a strict superregion of `self`.
1809 ///
1810 /// # Returns
1811 ///
1812 /// The distance in (semantic) bits betwen the heads of each region. The
1813 /// value is positive when `other` is higher in the address space than
1814 /// `self`, and negative when `other` is lower in the address space than
1815 /// `self`.
1816 ///
1817 /// [`::electrical_distance]`: #method.electrical_comparison
offset_from(&self, other: &Self) -> isize1818 pub fn offset_from(&self, other: &Self) -> isize {
1819 let (elts, bits) = unsafe { self.bitptr().ptr_diff(other.bitptr()) };
1820 elts.saturating_mul(T::Mem::BITS as isize)
1821 .saturating_add(bits as isize)
1822 }
1823
1824 /// Computes the electrical distance between the heads of two slices.
1825 ///
1826 /// This method uses the slices’ `BitOrder` implementation to compute the
1827 /// bit position of their heads, then computes the shift distance, in bits,
1828 /// between them.
1829 ///
1830 /// This computation presumes that the bits are counted in the same
1831 /// direction as are bytes in the abstract memory map.
1832 ///
1833 /// # Parameters
1834 ///
1835 /// - `&self`
1836 /// - `other`: Another bit slice. This must be either a strict subregion or
1837 /// a strict superregion of `self`.
1838 ///
1839 /// # Returns
1840 ///
1841 /// The electrical bit distance between the heads of `self` and `other`.
electrical_distance(&self, other: &Self) -> isize1842 pub fn electrical_distance(&self, other: &Self) -> isize {
1843 let this = self.bitptr();
1844 let that = other.bitptr();
1845 let (elts, bits) = unsafe {
1846 let this = BitPtr::new_unchecked(
1847 this.pointer(),
1848 BitIdx::new_unchecked(this.head().position::<O>().value()),
1849 1,
1850 );
1851 let that = BitPtr::new_unchecked(
1852 that.pointer(),
1853 BitIdx::new_unchecked(that.head().position::<O>().value()),
1854 1,
1855 );
1856 this.ptr_diff(that)
1857 };
1858 elts.saturating_mul(T::Mem::BITS as isize)
1859 .saturating_add(bits as isize)
1860 }
1861
1862 /// Marks an immutable slice as referring to aliased memory region.
1863 #[inline(always)]
1864 #[cfg(not(tarpaulin_include))]
alias(&self) -> &BitSlice<O, T::Alias>1865 pub(crate) fn alias(&self) -> &BitSlice<O, T::Alias> {
1866 unsafe { &*(self.as_ptr() as *const BitSlice<O, T::Alias>) }
1867 }
1868
1869 /// Marks a mutable slice as describing an aliased memory region.
1870 #[inline(always)]
1871 #[cfg(not(tarpaulin_include))]
alias_mut(&mut self) -> &mut BitSlice<O, T::Alias>1872 pub(crate) fn alias_mut(&mut self) -> &mut BitSlice<O, T::Alias> {
1873 unsafe { &mut *(self as *mut Self as *mut BitSlice<O, T::Alias>) }
1874 }
1875
1876 /// Removes the aliasing marker from a mutable slice handle.
1877 ///
1878 /// # Safety
1879 ///
1880 /// This must only be used when the slice is either known to be unaliased,
1881 /// or this call is combined with an operation that adds an aliasing marker
1882 /// and the total number of aliasing markers must remain unchanged.
1883 #[inline(always)]
1884 #[cfg(not(tarpaulin_include))]
unalias_mut( this: &mut BitSlice<O, T::Alias>, ) -> &mut Self1885 pub(crate) unsafe fn unalias_mut(
1886 this: &mut BitSlice<O, T::Alias>,
1887 ) -> &mut Self {
1888 &mut *(this as *mut BitSlice<O, T::Alias> as *mut Self)
1889 }
1890
1891 /// Type-cast the slice reference to its pointer structure.
1892 #[inline]
1893 #[cfg(not(tarpaulin_include))]
bitptr(&self) -> BitPtr<T>1894 pub(crate) fn bitptr(&self) -> BitPtr<T> {
1895 BitPtr::from_bitslice_ptr(self.as_ptr())
1896 }
1897
1898 /// Constructs a `BitSlice` over aliased memory.
1899 ///
1900 /// This is restricted so that it can only be used within the crate.
1901 /// Construction of a `BitSlice` over externally-aliased memory is unsound.
1902 #[cfg(not(tarpaulin_include))]
from_aliased_slice_unchecked( slice: &[T::Alias], ) -> &BitSlice<O, T::Alias>1903 pub(crate) unsafe fn from_aliased_slice_unchecked(
1904 slice: &[T::Alias],
1905 ) -> &BitSlice<O, T::Alias> {
1906 BitPtr::new_unchecked(
1907 slice.as_ptr(),
1908 BitIdx::ZERO,
1909 slice.len() * T::Mem::BITS as usize,
1910 )
1911 .to_bitslice_ref()
1912 }
1913 }
1914
1915 /// Methods available only when `T` allows shared mutability.
1916 impl<O, T> BitSlice<O, T>
1917 where
1918 O: BitOrder,
1919 T: BitStore + Radium<Item = <T as BitStore>::Mem>,
1920 {
1921 /// Splits a mutable slice at some mid-point.
1922 ///
1923 /// This method has the same behavior as [`split_at_mut`], except that it
1924 /// does not apply an aliasing marker to the partitioned subslices.
1925 ///
1926 /// # Safety
1927 ///
1928 /// Because this method is defined only on `BitSlice`s whose `T` type is
1929 /// alias-safe, the subslices do not need to be additionally marked.
1930 ///
1931 /// [`split_at_mut`]: #method.split_at_mut
1932 #[inline]
1933 // `.split_at_mut` is already tested, and `::unalias_mut` is a noöp.
1934 #[cfg(not(tarpaulin_include))]
split_at_aliased_mut( &mut self, mid: usize, ) -> (&mut Self, &mut Self)1935 pub fn split_at_aliased_mut(
1936 &mut self,
1937 mid: usize,
1938 ) -> (&mut Self, &mut Self)
1939 {
1940 let (head, tail) = self.split_at_mut(mid);
1941 unsafe { (Self::unalias_mut(head), Self::unalias_mut(tail)) }
1942 }
1943 }
1944
1945 /// Miscellaneous information.
1946 impl<O, T> BitSlice<O, T>
1947 where
1948 O: BitOrder,
1949 T: BitStore,
1950 {
1951 /// The inclusive maximum length of a `BitSlice<_, T>`.
1952 ///
1953 /// As `BitSlice` is zero-indexed, the largest possible index is one less
1954 /// than this value.
1955 ///
1956 /// |CPU word width| Value |
1957 /// |-------------:|----------------------:|
1958 /// |32 bits | `0x1fff_ffff` |
1959 /// |64 bits |`0x1fff_ffff_ffff_ffff`|
1960 pub const MAX_BITS: usize = BitPtr::<T>::REGION_MAX_BITS;
1961 /// The inclusive maximum length that a slice `[T]` can be for
1962 /// `BitSlice<_, T>` to cover it.
1963 ///
1964 /// A `BitSlice<_, T>` that begins in the interior of an element and
1965 /// contains the maximum number of bits will extend one element past the
1966 /// cutoff that would occur if the slice began at the zeroth bit. Such a
1967 /// slice must be manually constructed, but will not otherwise fail.
1968 ///
1969 /// |Type Bits|Max Elements (32-bit)| Max Elements (64-bit) |
1970 /// |--------:|--------------------:|----------------------:|
1971 /// | 8| `0x0400_0001` |`0x0400_0000_0000_0001`|
1972 /// | 16| `0x0200_0001` |`0x0200_0000_0000_0001`|
1973 /// | 32| `0x0100_0001` |`0x0100_0000_0000_0001`|
1974 /// | 64| `0x0080_0001` |`0x0080_0000_0000_0001`|
1975 pub const MAX_ELTS: usize = BitPtr::<T>::REGION_MAX_ELTS;
1976 }
1977
1978 /** Constructs a `&BitSlice` reference from its component data.
1979
1980 This is logically equivalent to [`slice::from_raw_parts`] for `[T]`.
1981
1982 # Lifetimes
1983
1984 - `'a`: The lifetime of the returned bitslice handle. This must be no longer
1985 than the duration of the referent region, as it is illegal for references to
1986 dangle.
1987
1988 # Type Parameters
1989
1990 - `O`: The ordering of bits within elements `T`.
1991 - `T`: The type of each memory element in the backing storage region.
1992
1993 # Parameters
1994
1995 - `addr`: The base address of the memory region that the `BitSlice` covers.
1996 - `head`: The index of the first live bit in `*addr`, at which the `BitSlice`
1997 begins. This is required to be in the range `0 .. T::Mem::BITS`.
1998 - `bits`: The number of live bits, beginning at `head` in `*addr`, that the
1999 `BitSlice` contains. This must be no greater than `BitSlice::MAX_BITS`.
2000
2001 # Returns
2002
2003 If the input parameters are valid, this returns `Some` shared reference to a
2004 `BitSlice`. The failure conditions causing this to return `None` are:
2005
2006 - `head` is not less than [`T::Mem::BITS`]
2007 - `bits` is greater than [`BitSlice::<O, T>::MAX_BITS`]
2008 - `addr` is not adequately aligned to `T`
2009 - `addr` is so high in the memory space that the region wraps to the base of the
2010 memory space
2011
2012 # Safety
2013
2014 The memory region described by the returned `BitSlice` must be validly allocated
2015 within the caller’s memory management system. It must also not be modified for
2016 the duration of the lifetime `'a`, unless the `T` type parameter permits safe
2017 shared mutation.
2018
2019 [`BitSlice::<O, T>::MAX_BITS`]: struct.BitSlice.html#associatedconstant.MAX_BITS
2020 [`T::Mem::BITS`]: ../mem/trait.BitMemory.html#associatedconstant.BITS
2021 [`slice::from_raw_parts`]: https://doc.rust-lang.org/core/slice/fn.from_raw_parts.html
2022 **/
2023 #[inline]
bits_from_raw_parts<'a, O, T>( addr: *const T, head: u8, bits: usize, ) -> Option<&'a BitSlice<O, T>> where O: BitOrder, T: 'a + BitStore + BitMemory,2024 pub unsafe fn bits_from_raw_parts<'a, O, T>(
2025 addr: *const T,
2026 head: u8,
2027 bits: usize,
2028 ) -> Option<&'a BitSlice<O, T>>
2029 where
2030 O: BitOrder,
2031 T: 'a + BitStore + BitMemory,
2032 {
2033 let head = crate::index::BitIdx::new(head)?;
2034 BitPtr::new(addr, head, bits).map(BitPtr::to_bitslice_ref)
2035 }
2036
2037 /** Constructs a `&mut BitSlice` reference from its component data.
2038
2039 This is logically equivalent to [`slice::from_raw_parts_mut`] for `[T]`.
2040
2041 # Lifetimes
2042
2043 - `'a`: The lifetime of the returned bitslice handle. This must be no longer
2044 than the duration of the referent region, as it is illegal for references to
2045 dangle.
2046
2047 # Type Parameters
2048
2049 - `O`: The ordering of bits within elements `T`.
2050 - `T`: The type of each memory element in the backing storage region.
2051
2052 # Parameters
2053
2054 - `addr`: The base address of the memory region that the `BitSlice` covers.
2055 - `head`: The index of the first live bit in `*addr`, at which the `BitSlice`
2056 begins. This is required to be in the range `0 .. T::Mem::BITS`.
2057 - `bits`: The number of live bits, beginning at `head` in `*addr`, that the
2058 `BitSlice` contains. This must be no greater than `BitSlice::MAX_BITS`.
2059
2060 # Returns
2061
2062 If the input parameters are valid, this returns `Some` shared reference to a
2063 `BitSlice`. The failure conditions causing this to return `None` are:
2064
2065 - `head` is not less than [`T::Mem::BITS`]
2066 - `bits` is greater than [`BitSlice::<O, T>::MAX_BITS`]
2067 - `addr` is not adequately aligned to `T`
2068 - `addr` is so high in the memory space that the region wraps to the base of the
2069 memory space
2070
2071 # Safety
2072
2073 The memory region described by the returned `BitSlice` must be validly allocated
2074 within the caller’s memory management system. It must also not be reachable for
2075 the lifetime `'a` by any path other than references derived from the return
2076 value.
2077
2078 [`BitSlice::<O, T>::MAX_BITS`]: struct.BitSlice.html#associatedconstant.MAX_BITS
2079 [`T::Mem::BITS`]: ../mem/trait.BitMemory.html#associatedconstant.BITS
2080 [`slice::from_raw_parts_mut`]: https://doc.rust-lang.org/core/slice/fn.from_raw_parts_mut.html
2081 **/
2082 #[inline]
bits_from_raw_parts_mut<'a, O, T>( addr: *mut T, head: u8, bits: usize, ) -> Option<&'a mut BitSlice<O, T>> where O: BitOrder, T: 'a + BitStore + BitMemory,2083 pub unsafe fn bits_from_raw_parts_mut<'a, O, T>(
2084 addr: *mut T,
2085 head: u8,
2086 bits: usize,
2087 ) -> Option<&'a mut BitSlice<O, T>>
2088 where
2089 O: BitOrder,
2090 T: 'a + BitStore + BitMemory,
2091 {
2092 let head = crate::index::BitIdx::new(head)?;
2093 BitPtr::new(addr, head, bits).map(BitPtr::to_bitslice_mut)
2094 }
2095
2096 mod api;
2097 mod iter;
2098 mod ops;
2099 mod proxy;
2100 mod traits;
2101
2102 // Match the `core::slice` API module topology.
2103
2104 pub use self::{
2105 api::{
2106 from_mut,
2107 from_raw_parts,
2108 from_raw_parts_mut,
2109 from_ref,
2110 BitSliceIndex,
2111 },
2112 iter::{
2113 Chunks,
2114 ChunksExact,
2115 ChunksExactMut,
2116 ChunksMut,
2117 Iter,
2118 IterMut,
2119 RChunks,
2120 RChunksExact,
2121 RChunksExactMut,
2122 RChunksMut,
2123 RSplit,
2124 RSplitMut,
2125 RSplitN,
2126 RSplitNMut,
2127 Split,
2128 SplitMut,
2129 SplitN,
2130 SplitNMut,
2131 Windows,
2132 },
2133 proxy::BitMut,
2134 };
2135
2136 #[cfg(test)]
2137 mod tests;
2138