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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// feature(doc_cfg) is nightly (https://doc.rust-lang.org/unstable-book/language-features/doc-cfg.html)
// Since we don't want the entire crate to be nightly, this is enabled only when building documentation.
// Same goes for the revolutionary "link to pointers documentation" feature.
// (https://github.com/rust-lang/rust/issues/80896).
//! Structures providing guarantees on byte sequence alignment.
//!
//! For some crucial data it might be beneficial to align them to page boundaries
//! for better cache performance. This crate uses the [`page_size`](https://crates.io/crates/page_size)
//! crate to get the page size.
//!
//! # Examples
//!
//! ```
//! # use aligners::{alignment::{self, Alignment}};
//! assert_eq!(page_size::get(), alignment::Page::size());
//! ```
//! ```
//! # use aligners::{Aligned, AlignedBytes, alignment::{self, Alignment}};
//! let possibly_unaligned = [1, 2, 3];
//! let aligned = AlignedBytes::<alignment::Page>::from(possibly_unaligned);
//! let ptr = aligned.as_ptr();
//!
//! assert_eq!(ptr.align_offset(page_size::get()), 0);
//! assert_eq!(aligned, possibly_unaligned);
//! ```
//!
//! To create a new aligned block of bytes it's easiest to use [`new_zeroed`](`AlignedBytes::new_zeroed`).
//!
//! ```
//! # use aligners::{Aligned, AlignedBytes, alignment::{self, Alignment}};
//! let aligned = AlignedBytes::<alignment::Page>::new_zeroed(1024);
//! let ptr = aligned.as_ptr();
//!
//! assert_eq!(ptr.align_offset(page_size::get()), 0);
//! assert!(aligned.iter().all(|&x| x == 0));
//! ```
//!
//! You can also use [`new`](`AlignedBytes::new`) to possibly skip initialization.
//! This is `unsafe`, since the underlying memory might be uninitialized, but may be useful
//! if you immediately want to initialize the memory afterwards.
//!
//! ```
//! # use aligners::{Aligned, AlignedBytes, alignment::{self, Alignment}};
//! let mut aligned = unsafe { AlignedBytes::<alignment::Page>::new(1024) };
//! let ptr = aligned.as_ptr();
//!
//! assert_eq!(ptr.align_offset(page_size::get()), 0);
//!
//! // We cannot assert anything else, `aligned` can contain arbitrary bytes.
//! // To be able to read anything, we must first initialize.
//!
//! for i in 0..1024 {
//! aligned[i] = 1;
//! }
//!
//! let ones = std::iter::repeat(1).take(1024).collect::<Vec<u8>>();
//! assert_eq!(ones, aligned);
//!
//! ```
//!
//! If you want a safe way to initialize the bytes, there is [`new_initialize`](`AlignedBytes::new_initialize`)
//! that initializes all bytes with a function of their index.
//!
//! ```
//! # use aligners::{Aligned, AlignedBytes, alignment::{self, Alignment}};
//! let aligned = AlignedBytes::<alignment::Page>::new_initialize(8, |i| { i as u8 });
//! let ptr = aligned.as_ptr();
//!
//! assert_eq!(ptr.align_offset(page_size::get()), 0);
//! assert_eq!(aligned, [0, 1, 2, 3, 4, 5, 6, 7]);
//! ```
//!
//! ## SIMD
//!
//! Loading block-aligned bytes into SIMD is generally preferred over unaligned.
//! The SIMD alignment constructs are enabled with the `simd` default feature.
//!
//! # use aligners::{Aligned, AlignedBytes, alignment::{self, Alignment}};
//! let possibly_unaligned = [1, 2, 3];
//! let aligned = AlignedBytes::<alignment::SimdBlock>::from(possibly_unaligned);
//! let ptr = aligned.as_ptr();
//!
//! assert_eq!(ptr.align_offset(alignment::SimdBlock::size()), 0);
//! assert_eq!(aligned, possibly_unaligned);
//! ```
//!
//! ## Note on alignment checking
//!
//! Checking alignment is hard.
//! can return [`usize::MAX`]
//! without any reason and it explicitly says that it should not be relied on for correctness.
//!
//! The above examples ignore that for assertion purposes, because there is no better way.
//! In reality, the check in
//! just checks the remainder
//! of the pointer's integer representation, plus some additional bounds checking, so it is
//! fine for testing purposes on most platforms.
//!
//! This is an additional benefit of using `aligners`, as it is a strong guarantee on alignment.
//!
//! If you disagree with this assessment, feel free to [contribute to this StackOverflow question](https://stackoverflow.com/questions/71972143/assert-that-a-pointer-is-aligned-to-some-value).
//!
pub
pub use *;
pub use *;
pub use *;
/// Common trait for [`AlignedBytes`] for all different alignments.
// TODO: Implement indexing?
// TODO: Implement IntoIterator for AlignedBytes and an Iterator for AlignedSlice that iterates over aligned blocks.