File: NoAlias.md

package info (click to toggle)
rust-bitvec 1.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,780 kB
  • sloc: makefile: 2
file content (103 lines) | stat: -rw-r--r-- 4,115 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# Anti-Aliasing Iterator Adapter

This structure is an adapter over a corresponding `&mut BitSlice` iterator. It
removes the `::Alias` taint marker, allowing mutations through each yielded bit
reference to skip any costs associated with aliasing.

## Safety

The default `&mut BitSlice` iterators attach an `::Alias` taint for a reason:
the iterator protocol does not mandate that yielded items have a narrower
lifespan than the iterator that produced them! As such, it is completely
possible to pull multiple yielded items out into the same scope, where they have
overlapping lifetimes.

The `BitStore` principles require that whenever two write-capable handles to the
same memory region have overlapping lifetimes, they *must* be `::Alias` tainted.
This adapter removes the `::Alias` taint, but is not able to enforce strictly
non-overlapping lifetimes of yielded items.

As such, this adapter is **unsafe to construct**, and you **must** only use it
in a `for`-loop where each yielded item does not escape the loop body.

In order to help enforce this limitation, this adapter structure is *not* `Send`
or `Sync`. It must be consumed in the scope where it was created.

## Usage

If you are using a loop that satisfies the safety requirement, you can use the
`.remove_alias()` method on your mutable iterator and configure it to yield
handles that do not impose additional alias-protection costs when accessing the
underlying memory.

Note that this adapter does not go to `T::Unalias`: it only takes an iterator
that yields `T::Alias` and unwinds it to `T`. If the source bit-slice was
*already* alias-tainted, the original protection is not removed. You are
responsible for doing so by using [`.bit_domain_mut()`].

## Examples

This example shows using `.chunks_mut()` without incurring alias protection.

This documentation is replicated on all `NoAlias` types; the examples will work
for all of them, but are not specialized in the text.

```rust
use bitvec::prelude::*;
use bitvec::slice::{ChunksMut, ChunksMutNoAlias};
type Alias8 = <u8 as BitStore>::Alias;

let mut data: BitArr!(for 40, in u8, Msb0) = bitarr![u8, Msb0; 0; 40];

let mut chunks: ChunksMut<u8, Msb0> = data.chunks_mut(5);
let _chunk: &mut BitSlice<Alias8, Msb0> = chunks.next().unwrap();

let mut chunks: ChunksMutNoAlias<u8, Msb0> = unsafe { chunks.remove_alias() };
let _chunk: &mut BitSlice<u8, Msb0> = chunks.next().unwrap();
```

This example shows how use of [`.split_at_mut()`] forces the `.remove_alias()` to
still retain a layer of alias protection.

```rust
use bitvec::prelude::*;
use bitvec::slice::{ChunksMut, ChunksMutNoAlias};
type Alias8 = <u8 as BitStore>::Alias;
type Alias8Alias = <Alias8 as BitStore>::Alias;

let mut data: BitArr!(for 40, in u8, Msb0) = bitarr!(u8, Msb0; 0; 40);
let (_head, rest): (_, &mut BitSlice<Alias8, Msb0>) = data.split_at_mut(5);

let mut chunks: ChunksMut<Alias8, Msb0> = rest.chunks_mut(5);
let _chunk: &mut BitSlice<Alias8, Msb0> = chunks.next().unwrap();

let mut chunks: ChunksMutNoAlias<Alias8, Msb0> = unsafe { chunks.remove_alias() };
let _chunk: &mut BitSlice<Alias8, Msb0> = chunks.next().unwrap();
```

And this example shows how to use `.bit_domain_mut()` in order to undo the
effects of `.split_at_mut()`, so that `.remove_alias()` can complete its work.

```rust
use bitvec::prelude::*;
use bitvec::slice::{ChunksMut, ChunksMutNoAlias};
type Alias8 = <u8 as BitStore>::Alias;

let mut data: BitArr!(for 40, in u8, Msb0) = bitarr!(u8, Msb0; 0; 40);
let (_head, rest): (_, &mut BitSlice<Alias8, Msb0>) = data.split_at_mut(5);

let (head, body, tail): (
  &mut BitSlice<Alias8, Msb0>,
  &mut BitSlice<u8, Msb0>,
  &mut BitSlice<Alias8, Msb0>,
) = rest.bit_domain_mut().region().unwrap();

let mut chunks: ChunksMut<u8, Msb0> = body.chunks_mut(5);
let _chunk: &mut BitSlice<Alias8, Msb0> = chunks.next().unwrap();

let mut chunks: ChunksMutNoAlias<u8, Msb0> = unsafe { chunks.remove_alias() };
let _chunk: &mut BitSlice<u8, Msb0> = chunks.next().unwrap();
```

[`.bit_domain_mut()`]: crate::slice::BitSlice::bit_domain_mut
[`.split_at_mut()`]: crate::slice::BitSlice::split_at_mut