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
#[ cfg (doc) ]
use super::*;

/// Trait for encoding an item as bits for storing in a [`BitVec`]
///
pub trait BitVecEncoding <Item> {

	/// Number of bits in each encoded item
	///
	const BITS: u32;

	/// Mask for the bits in an encoded item
	///
	const MASK: usize = (1 << Self::BITS) - 1;

	/// Encode an item into its representation as bits
	///
	fn encode (item: Item) -> usize;

	/// Decode an item from its representation as bits
	///
	fn decode (bits: usize) -> Item;

	#[ inline ]
	#[ must_use ]
	fn get_bit_shift (bit_idx: u32) -> u32 {
		usize::BITS - bit_idx - Self::BITS
	}

	#[ inline ]
	#[ must_use ]
	fn item_to_word (item_enc: usize, bit_idx: u32) -> usize {
		item_enc << Self::get_bit_shift (bit_idx)
	}

	#[ inline ]
	#[ must_use ]
	fn word_to_item (word_val: usize, bit_idx: u32) -> usize {
		word_val >> Self::get_bit_shift (bit_idx)
	}

}

/// Default implementation of [`BitVecEncoding`] for items which implement [`BitVecNative`]
///
#[ derive (Clone, Debug, Eq, PartialEq) ]
pub struct BitVecEncodingDefault;

impl <Item> BitVecEncoding <Item> for BitVecEncodingDefault where Item: BitVecNative {

	const BITS: u32 = Item::BITS;

	const MASK: usize = (1 << Item::BITS) - 1;

	#[ inline ]
	fn encode (item: Item) -> usize { Item::encode (item) }

	#[ inline ]
	fn decode (bits: usize) -> Item { Item::decode (bits) }

}

/// Trait for items which know how to encode themselves for storing in a [`BitVec`]
///
pub trait BitVecNative {

	/// Number of bits in an encoded item
	///
	const BITS: u32;

	/// Encode an item into its representation as bits
	///
	fn encode (self) -> usize;

	/// Decode an item from its representation as bits
	///
	fn decode (encoded: usize) -> Self;

}

impl BitVecNative for bool {

	const BITS: u32 = 1;

	#[ inline ]
	fn encode (self) -> usize {
		usize::from (self)
	}

	#[ inline ]
	fn decode (encoded: usize) -> Self {
		encoded != 0
	}

}