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