bitstring/bit_string.rs
1use core::cmp::{
2 min,
3 Ordering,
4};
5
6/// A bit string with variable (but possibly limited) length.
7///
8/// The length limit might depend on the current string; that is why
9/// writing a bit might truncate the string (but not the bit that was
10/// just modified). "Writing" a bit also includes writing without
11/// actually changing it.
12///
13/// This special case is needed to handle variants with different
14/// (maximum) lengths: a small prefix indicates the variant, then
15/// follows the actual data of the variant.
16///
17/// As an example one might want to combine IPv4 and IPv6 cidr
18/// representations into one `BitString` type; the empty bit string
19/// would represent `0.0.0.0/0` + `::/0`.
20///
21/// Apart from this special case writing a bit must not modify any other
22/// bits or change the length.
23///
24/// The required `Eq` implementation must match comparing two bitstrings
25/// by their bits (up to their length); i.e. `BitString`s must not carry
26/// additional data apart from the bits (and mustn't compare unused
27/// bits in the storage if their value isn't fixed).
28#[allow(clippy::len_without_is_empty)]
29pub trait BitString: Eq {
30 /// Get the `ndx`th bit.
31 ///
32 /// # Panics
33 ///
34 /// Should panic if `ndx >= self.len()`.
35 fn get(&self, ndx: usize) -> bool;
36
37 /// Set the `ndx`th bit to `bit`.
38 ///
39 /// Might clip the length to `ndx+1`.
40 ///
41 /// # Panics
42 ///
43 /// Should panic if `ndx >= self.len()`.
44 fn set(&mut self, ndx: usize, bit: bool);
45
46 /// Flips the `ndx`th bit.
47 ///
48 /// # Panics
49 ///
50 /// Should panic if `ndx >= self.len()`.
51 fn flip(&mut self, ndx: usize);
52
53 /// Current length of the bit string in bits.
54 #[allow(clippy::len_without_is_empty)]
55 fn len(&self) -> usize;
56
57 /// Set current length to `len`.
58 ///
59 /// Does nothing if `len <= self.len()`.
60 ///
61 /// If necessary should also zero the underlying storage if `Eq`
62 /// needs it to work properly.
63 fn clip(&mut self, len: usize);
64
65 /// Append a bit.
66 ///
67 /// # Panics
68 ///
69 /// Might panic if underlying storage can only store a limited
70 /// number of bits.
71 fn append(&mut self, bit: bool);
72
73 /// Create a new zero-length bit string.
74 ///
75 /// Underlying storage should be zeroed if `Eq` needs it to work
76 /// properly.
77 fn null() -> Self;
78
79 /// Length of the longest shared prefix of two bit strings.
80 fn shared_prefix_len(&self, other: &Self) -> usize {
81 let max_len = min(self.len(), other.len());
82 for i in 0..max_len {
83 if self.get(i) != other.get(i) {
84 return i;
85 }
86 }
87 max_len
88 }
89
90 /// Longest shared prefix of two bit strings.
91 fn shared_prefix(&self, other: &Self) -> Self
92 where
93 Self: Clone,
94 {
95 let mut a = self.clone();
96 a.clip(self.shared_prefix_len(other));
97 a
98 }
99
100 /// Partial ordering on bit strings.
101 ///
102 /// Formal definition:
103 ///
104 /// ```text
105 /// `a < b` iff `a != b` and `b` is a prefix of `a`
106 /// ```
107 ///
108 /// If you view a bit string as a set including all bit strings
109 /// starting with it, this is the subset relation.
110 fn subset_cmp(&self, other: &Self) -> Option<Ordering> {
111 let spl = self.shared_prefix_len(other);
112 if spl == self.len() {
113 // self is a prefix of other
114 if spl == other.len() {
115 Some(Ordering::Equal)
116 } else {
117 Some(Ordering::Greater)
118 }
119 } else if spl == other.len() {
120 // other is a prefix of self
121 Some(Ordering::Less)
122 } else {
123 // neither is a prefix of the other one
124 None
125 }
126 }
127
128 /// Lexicographic ordering on bit strings.
129 ///
130 /// Formal definition:
131 ///
132 /// ```text
133 /// `a < b` iff `a != b` and (
134 /// `b` is a prefix of `a`
135 /// or `a[s] < b[s]`
136 /// where s is the smallest index with `a[s] != b[s]`)
137 /// ```
138 ///
139 /// Or, if you define `_|_ < false < true`:
140 ///
141 /// ```text
142 /// `a < b` iff `a[s] < b[s]`
143 /// where s is the smallest index with `a[s] != b[s]`
144 /// ```
145 fn lexicographic_cmp(&self, other: &Self) -> Ordering {
146 let spl = self.shared_prefix_len(other);
147 if spl == self.len() {
148 // self is a prefix of other
149 if spl == other.len() {
150 Ordering::Equal
151 } else {
152 // self is shorter than other
153 Ordering::Less
154 }
155 } else if spl == other.len() {
156 // other is a prefix of self and shorter
157 Ordering::Greater
158 } else {
159 // both are at least one bit longer than the shared prefix,
160 // and they differ in that bit (otherwise shared prefix
161 // would be longer)
162 if self.get(spl) {
163 Ordering::Greater
164 } else {
165 Ordering::Less
166 }
167 }
168 }
169}