1 /*! Ordering of bits within register elements.
2
3 `bitvec` structures are parametric over any ordering of bits within a register.
4 The `BitOrder` trait maps a cursor position (indicated by the `BitIdx` type) to an
5 electrical position (indicated by the `BitPos` type) within that element, and
6 also defines the order of traversal over a register.
7
8 The only requirement on implementors of `BitOrder` is that the transform function
9 from cursor (`BitIdx`) to position (`BitPos`) is *total* (every integer in the
10 domain `0 .. T::BITS` is used) and *unique* (each cursor maps to one and only
11 one position, and each position is mapped by one and only one cursor).
12 Contiguity is not required.
13
14 `BitOrder` is a stateless trait, and implementors should be zero-sized types.
15 !*/
16
17 use crate::index::{
18 BitIdx,
19 BitMask,
20 BitPos,
21 BitRegister,
22 BitSel,
23 BitTail,
24 };
25
26 /** An ordering over a register.
27
28 # Usage
29
30 `bitvec` structures store and operate on semantic counts, not bit positions. The
31 `BitOrder::at` function takes a semantic ordering, `BitIdx`, and produces an
32 electrical position, `BitPos`.
33
34 # Safety
35
36 If your implementation violates any of the requirements on these functions, then
37 the program will become incorrect and have unspecified behavior. The best-case
38 scenario is that operations relying on your implementation will crash the
39 program; the worst-case is that memory access will silently become corrupt.
40
41 You are responsible for adhering to the requirements of these functions. In the
42 future, a verification function may be provided for your test suite; however, it
43 is not yet possible to verify your implementation at compile-time.
44
45 This is an `unsafe trait` to implement, because you are responsible for
46 upholding the state requirements. The types you manipulate have `unsafe fn`
47 constructors, because they require you to maintain correct and consistent
48 processes in order for the rest of the library to use them.
49
50 The implementations of `BitOrder` are trusted to drive safe code, and once data
51 leaves a `BitOrder` implementation, it is considered safe to use as the basis
52 for interaction with memory.
53
54 # Verification
55
56 Rust currently lacks Zig’s compile-time computation capability. This means that
57 `bitvec` cannot fail a compile if it detects that a `BitOrder` implementation is
58 invalid and breaks the stated requirements. `bitvec` does offer a function,
59 [`verify`], which ensures the correctness of an implementation. When Rust gains
60 the capability to run this function in generic `const` contexts, `bitvec` will
61 use it to prevent at compile-time the construction of data structures that use
62 incorrect ordering implementations.
63
64 The verifier function panics when it detects invalid behavior, with an error
65 message intended to clearly indicate the broken requirement.
66
67 ```rust
68 use bitvec::{
69 index::{BitIdx, BitPos, BitRegister},
70 order::{self, BitOrder},
71 };
72 # use bitvec::{index::*, order::Lsb0};
73
74 pub struct Custom;
75 unsafe impl BitOrder for Custom {
76 fn at<R: BitRegister>(idx: BitIdx<R>) -> BitPos<R> {
77 // impl
78 # return Lsb0::at::<R>(idx);
79 }
80 }
81
82 #[test]
83 #[cfg(test)]
84 fn prove_custom() {
85 order::verify::<Custom>();
86 }
87 ```
88
89 [`verify`]: fn.verify.html
90 **/
91 pub unsafe trait BitOrder {
92 /// Converts a semantic bit index into an electrical bit position.
93 ///
94 /// This function is the basis of the trait, and must adhere to a number of
95 /// requirements in order for an implementation to be considered correct.
96 ///
97 /// # Parameters
98 ///
99 /// - `index`: The semantic index of a bit within a register `R`.
100 ///
101 /// # Returns
102 ///
103 /// The electrical position of the indexed bit within a register `R`. See
104 /// the `BitPos` documentation for what electrical positions are considered
105 /// to mean.
106 ///
107 /// # Type Parameters
108 ///
109 /// - `R`: The register type which the index and position describe.
110 ///
111 /// # Requirements
112 ///
113 /// This function must satisfy the following requirements for all possible
114 /// input and output values for all possible type parameters:
115 ///
116 /// ## Totality
117 ///
118 /// This function must be able to accept every input in the `BitIdx<R>`
119 /// value range, and produce a corresponding `BitPos<R>`. It must not abort
120 /// the program or return an invalid `BitPos<R>` for any input value in the
121 /// `BitIdx<R>` range.
122 ///
123 /// ## Bijection
124 ///
125 /// There must be an exactly one-to-one correspondence between input value
126 /// and output value. No input index may select from a set of more than one
127 /// output position, and no output position may be produced by more than one
128 /// input index.
129 ///
130 /// ## Purity
131 ///
132 /// The translation from index to position must be consistent for the
133 /// lifetime of the program. This function *may* refer to global state, but
134 /// that state **must** be immutable for the program lifetime, and must not
135 /// be used to violate the totality or bijection requirements.
136 ///
137 /// ## Output Validity
138 ///
139 /// The produced `BitPos<R>` must be within the valid range of that type.
140 /// Call sites of this function will not take any steps to constrain the
141 /// output value. If you use `unsafe` code to produce an invalid
142 /// `BitPos<R>`, the program is permanently incorrect, and will likely
143 /// crash.
144 ///
145 /// # Usage
146 ///
147 /// This function will only ever be called with input values in the valid
148 /// `BitIdx<R>` range. Implementors are not required to consider any values
149 /// outside this range in their function body.
at<R>(index: BitIdx<R>) -> BitPos<R> where R: BitRegister150 fn at<R>(index: BitIdx<R>) -> BitPos<R>
151 where R: BitRegister;
152
153 /// Converts a semantic bit index into a one-hot selector mask.
154 ///
155 /// This is an optional function; a default implementation is provided for
156 /// you.
157 ///
158 /// The default implementation of this function calls `Self::at` to produce
159 /// an electrical position, then turns that into a selector mask by setting
160 /// the `n`th bit more significant than the least significant bit of the
161 /// element. `BitOrder` implementations may choose to provide a faster mask
162 /// production here, but they must satisfy the requirements listed below.
163 ///
164 /// # Parameters
165 ///
166 /// - `index`: The semantic index of a bit within a register `R`.
167 ///
168 /// # Returns
169 ///
170 /// A one-hot selector mask for the bit indicated by the index value.
171 ///
172 /// # Type Parameters
173 ///
174 /// - `R`: The storage type for which the mask will be calculated. The mask
175 /// must also be this type, as it will be applied to a register of `R` in
176 /// order to set, clear, or test a single bit.
177 ///
178 /// # Requirements
179 ///
180 /// A one-hot encoding means that there is exactly one bit set in the
181 /// produced value. It must be equivalent to `1 << Self::at::<R>(place)`.
182 ///
183 /// As with `at`, this function must produce a unique mapping from each
184 /// legal index in the `R` domain to a one-hot value of `R`.
185 #[inline]
select<R>(index: BitIdx<R>) -> BitSel<R> where R: BitRegister186 fn select<R>(index: BitIdx<R>) -> BitSel<R>
187 where R: BitRegister {
188 Self::at::<R>(index).select()
189 }
190
191 /// Constructs a multi-bit selector mask for batch operations on a single
192 /// register `R`.
193 ///
194 /// The default implementation of this function traverses the index range,
195 /// converting each index into a single-bit selector with `Self::select` and
196 /// accumulating into a combined register value.
197 ///
198 /// # Parameters
199 ///
200 /// - `from`: The inclusive starting index for the mask.
201 /// - `upto`: The exclusive ending index for the mask.
202 ///
203 /// # Returns
204 ///
205 /// A bit-mask with all bits corresponding to the input index range set high
206 /// and all others set low.
207 ///
208 /// # Type Parameters
209 ///
210 /// - `R`: The storage type for which the mask will be calculated. The mask
211 /// must also be this type, as it will be applied to a register of `R` in
212 /// order to set, clear, or test all the selected bits.
213 ///
214 /// # Requirements
215 ///
216 /// This function must always be equivalent to
217 ///
218 /// ```rust,ignore
219 /// (from .. upto)
220 /// .map(1 << Self::at::<R>)
221 /// .fold(0, |mask, sel| mask | sel)
222 /// ```
223 #[inline]
mask<R>( from: impl Into<Option<BitIdx<R>>>, upto: impl Into<Option<BitTail<R>>>, ) -> BitMask<R> where R: BitRegister,224 fn mask<R>(
225 from: impl Into<Option<BitIdx<R>>>,
226 upto: impl Into<Option<BitTail<R>>>,
227 ) -> BitMask<R>
228 where
229 R: BitRegister,
230 {
231 let (from, upto) = match (from.into(), upto.into()) {
232 (None, None) => return BitMask::ALL,
233 (Some(from), None) => (from, BitTail::<R>::END),
234 (None, Some(upto)) => (BitIdx::<R>::ZERO, upto),
235 (Some(from), Some(upto)) => (from, upto),
236 };
237 BitIdx::<R>::range(from, upto).map(Self::select::<R>).sum()
238 }
239 }
240
241 /// Traverses a register from `MSbit` to `LSbit`.
242 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
243 pub struct Msb0;
244
245 unsafe impl BitOrder for Msb0 {
246 #[cfg_attr(not(tarpaulin_include), inline(always))]
at<R>(index: BitIdx<R>) -> BitPos<R> where R: BitRegister247 fn at<R>(index: BitIdx<R>) -> BitPos<R>
248 where R: BitRegister {
249 unsafe { BitPos::new_unchecked(R::MASK - index.value()) }
250 }
251
252 #[cfg_attr(not(tarpaulin_include), inline(always))]
select<R>(index: BitIdx<R>) -> BitSel<R> where R: BitRegister253 fn select<R>(index: BitIdx<R>) -> BitSel<R>
254 where R: BitRegister {
255 /* Set the MSbit, then shift it down. The left expr is const-folded.
256 Note: this is not equivalent to `1 << (mask - index)`, because that
257 requires a runtime subtraction, but the expression below is only a
258 single right-shift.
259 */
260 unsafe { BitSel::new_unchecked((R::ONE << R::MASK) >> index.value()) }
261 }
262
263 #[inline]
mask<R>( from: impl Into<Option<BitIdx<R>>>, upto: impl Into<Option<BitTail<R>>>, ) -> BitMask<R> where R: BitRegister,264 fn mask<R>(
265 from: impl Into<Option<BitIdx<R>>>,
266 upto: impl Into<Option<BitTail<R>>>,
267 ) -> BitMask<R>
268 where
269 R: BitRegister,
270 {
271 let from = from.into().unwrap_or(BitIdx::ZERO).value();
272 let upto = upto.into().unwrap_or(BitTail::END).value();
273 debug_assert!(upto >= from, "Ranges must run from low index to high");
274 let ct = upto - from;
275 if ct == R::BITS {
276 return BitMask::ALL;
277 }
278 // 1. Set all bits high.
279 // 2. Shift right by the number of bits in the mask. These are now low.
280 // 3. Invert. The mask bits (at MSedge) are high; the rest are low.
281 // 4. Shift right by the distance from MSedge.
282 unsafe { BitMask::new(!(R::ALL >> ct) >> from) }
283 }
284 }
285
286 /// Traverses a register from `LSbit` to `MSbit`.
287 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
288 pub struct Lsb0;
289
290 unsafe impl BitOrder for Lsb0 {
291 #[cfg_attr(not(tarpaulin), inline(always))]
at<R>(index: BitIdx<R>) -> BitPos<R> where R: BitRegister292 fn at<R>(index: BitIdx<R>) -> BitPos<R>
293 where R: BitRegister {
294 unsafe { BitPos::new_unchecked(index.value()) }
295 }
296
297 #[cfg_attr(not(tarpaulin), inline(always))]
select<R>(index: BitIdx<R>) -> BitSel<R> where R: BitRegister298 fn select<R>(index: BitIdx<R>) -> BitSel<R>
299 where R: BitRegister {
300 unsafe { BitSel::new_unchecked(R::ONE << index.value()) }
301 }
302
303 #[inline]
mask<R>( from: impl Into<Option<BitIdx<R>>>, upto: impl Into<Option<BitTail<R>>>, ) -> BitMask<R> where R: BitRegister,304 fn mask<R>(
305 from: impl Into<Option<BitIdx<R>>>,
306 upto: impl Into<Option<BitTail<R>>>,
307 ) -> BitMask<R>
308 where
309 R: BitRegister,
310 {
311 let from = from.into().unwrap_or(BitIdx::ZERO).value();
312 let upto = upto.into().unwrap_or(BitTail::END).value();
313 debug_assert!(upto >= from, "Ranges must run from low index to high");
314 let ct = upto - from;
315 if ct == R::BITS {
316 return BitMask::ALL;
317 }
318 // 1. Set all bits high.
319 // 2. Shift left by the number of bits in the mask. These are now low.
320 // 3. Invert. The mask bits at LSedge are high; the rest are low.
321 // 4. Shift left by the distance from LSedge.
322 unsafe { BitMask::new(!(R::ALL << ct) << from) }
323 }
324 }
325
326 /** A default bit ordering.
327
328 Typically, your platform’s C compiler uses most-significant-bit-first ordering
329 for bitfields. The Msb0 bit ordering and big-endian byte ordering are otherwise
330 completely unrelated.
331 **/
332 #[cfg(target_endian = "big")]
333 pub type LocalBits = Msb0;
334
335 /** A default bit ordering.
336
337 Typically, your platform’s C compiler uses least-significant-bit-first ordering
338 for bitfields. The Lsb0 bit ordering and little-endian byte ordering are
339 otherwise completely unrelated.
340 **/
341 #[cfg(target_endian = "little")]
342 pub type LocalBits = Lsb0;
343
344 #[cfg(not(any(target_endian = "big", target_endian = "little")))]
345 compile_fail!(concat!(
346 "This architecture is currently not supported. File an issue at ",
347 env!(CARGO_PKG_REPOSITORY)
348 ));
349
350 /** Verifies a `BitOrder` implementation’s adherence to the stated rules.
351
352 This function checks some `BitOrder` implementation’s behavior on each of the
353 `BitRegister` types it must handle, and reports any violation of the rules that
354 it detects.
355
356 # Type Parameters
357
358 - `O`: The `BitOrder` implementation to test.
359
360 # Parameters
361
362 - `verbose`: Sets whether the test should print diagnostic information to
363 `stdout`.
364
365 # Panics
366
367 This panics if it detects any violation of the `BitOrder` implementation rules
368 for `O`.
369 **/
370 #[cfg(test)]
verify<O>(verbose: bool) where O: BitOrder371 pub fn verify<O>(verbose: bool)
372 where O: BitOrder {
373 verify_for_type::<O, u8>(verbose);
374 verify_for_type::<O, u16>(verbose);
375 verify_for_type::<O, u32>(verbose);
376 verify_for_type::<O, usize>(verbose);
377
378 #[cfg(target_pointer_width = "64")]
379 verify_for_type::<O, u64>(verbose);
380 }
381
382 /** Verifies a `BitOrder` implementation’s adherence to the stated rules, for
383 one register type.
384
385 This function checks some `BitOrder` implementation against only one of the
386 `BitRegister` types that it will encounter. This is useful if you are
387 implementing an ordering that only needs to be concerned with a subset of the
388 types, and you know that you will never use it with the types it does not
389 support.
390
391 # Type Parameters
392
393 - `O`: The `BitOrder` implementation to test.
394 - `R`: The `BitRegister` type for which to test `O`.
395
396 # Parameters
397
398 - `verbose`: Sets whether the test should print diagnostic information to
399 `stdout`.
400
401 # Panics
402
403 This panics if it detects any violation of the `BitOrder` implementation rules
404 for the combination of input types and index values.
405 **/
406 #[cfg(test)]
verify_for_type<O, R>(verbose: bool) where O: BitOrder, R: BitRegister,407 pub fn verify_for_type<O, R>(verbose: bool)
408 where
409 O: BitOrder,
410 R: BitRegister,
411 {
412 use core::any::type_name;
413 let mut accum = BitMask::<R>::ZERO;
414
415 let oname = type_name::<O>();
416 let mname = type_name::<R>();
417
418 for n in 0 .. R::BITS {
419 // Wrap the counter as an index.
420 let idx = unsafe { BitIdx::<R>::new_unchecked(n) };
421
422 // Compute the bit position for the index.
423 let pos = O::at::<R>(idx);
424 if verbose {
425 #[cfg(feature = "std")]
426 println!(
427 "`<{} as BitOrder>::at::<{}>({})` produces {}",
428 oname,
429 mname,
430 n,
431 pos.value(),
432 );
433 }
434
435 // If the computed position exceeds the valid range, fail.
436 assert!(
437 pos.value() < R::BITS,
438 "Error when verifying the implementation of `BitOrder` for `{}`: \
439 Index {} produces a bit position ({}) that exceeds the type width \
440 {}",
441 oname,
442 n,
443 pos.value(),
444 R::BITS,
445 );
446
447 // Check `O`’s implementation of `select`
448 let sel = O::select::<R>(idx);
449 if verbose {
450 #[cfg(feature = "std")]
451 println!(
452 "`<{} as BitOrder>::select::<{}>({})` produces {:b}",
453 oname, mname, n, sel,
454 );
455 }
456
457 // If the selector bit is not one-hot, fail.
458 assert_eq!(
459 sel.value().count_ones(),
460 1,
461 "Error when verifying the implementation of `BitOrder` for `{}`: \
462 Index {} produces a bit selector ({:b}) that is not a one-hot mask",
463 oname,
464 n,
465 sel,
466 );
467
468 // Check that the selection computed from the index matches the
469 // selection computed from the position.
470 let shl = pos.select();
471 // If `O::select(idx)` does not produce `1 << pos`, fail.
472 assert_eq!(
473 sel,
474 shl,
475 "Error when verifying the implementation of `BitOrder` for `{}`: \
476 Index {} produces a bit selector ({:b}) that is not equal to `1 \
477 << {}` ({:b})",
478 oname,
479 n,
480 sel,
481 pos.value(),
482 shl,
483 );
484
485 // Check that the produced selector bit has not already been added to
486 // the accumulator.
487 assert!(
488 !accum.test(sel),
489 "Error when verifying the implementation of `BitOrder` for `{}`: \
490 Index {} produces a bit position ({}) that has already been \
491 produced by a prior index",
492 oname,
493 n,
494 pos.value(),
495 );
496 accum.insert(sel);
497 if verbose {
498 #[cfg(feature = "std")]
499 println!(
500 "`<{} as BitOrder>::at::<{}>({})` accumulates {:b}",
501 oname, mname, n, accum,
502 );
503 }
504 }
505
506 // Check that all indices produced all positions.
507 assert_eq!(
508 accum,
509 BitMask::ALL,
510 "Error when verifying the implementation of `BitOrder` for `{}`: The \
511 bit positions marked with a `0` here were never produced from an \
512 index, despite all possible indices being passed in for translation: \
513 {:b}",
514 oname,
515 accum,
516 );
517
518 // Check that `O::mask` is correct for all range combinations.
519 for from in BitIdx::<R>::range_all() {
520 for upto in BitTail::<R>::range_from(from) {
521 let mask = O::mask(from, upto);
522 let check = BitIdx::<R>::range(from, upto)
523 .map(O::at::<R>)
524 .map(BitPos::<R>::select)
525 .sum::<BitMask<R>>();
526 assert_eq!(
527 mask,
528 check,
529 "Error when verifying the implementation of `BitOrder` for \
530 `{o}`: `{o}::mask::<{m}>({f}, {u})` produced {bad:b}, but \
531 expected {good:b}",
532 o = oname,
533 m = mname,
534 f = from,
535 u = upto,
536 bad = mask,
537 good = check,
538 );
539 }
540 }
541 }
542
543 #[cfg(all(test, not(miri)))]
544 mod tests {
545 use super::*;
546
547 #[test]
verify_impls()548 fn verify_impls() {
549 verify::<Lsb0>(cfg!(feature = "testing"));
550 verify::<Msb0>(cfg!(feature = "testing"));
551
552 struct DefaultImpl;
553 unsafe impl BitOrder for DefaultImpl {
554 fn at<R>(index: BitIdx<R>) -> BitPos<R>
555 where R: BitRegister {
556 unsafe { BitPos::new_unchecked(index.value()) }
557 }
558 }
559
560 verify::<DefaultImpl>(cfg!(feature = "testing"));
561 }
562 }
563