bitstring/utils/bigendian/
int_helpers.rs

1macro_rules! impl_big_endian_for {
2	($mod:ident => $t:ty) => {
3		/// `BigEndianBitString` functions for specific integer type
4		#[cfg_attr(not(feature = "bigendian"), allow(dead_code))] // lots of unused parts unless we export it
5		pub mod $mod {
6			use core::cmp::min;
7
8			/// bits in a single element
9			pub const ELEMENT_BITS: usize = <$t>::BITS as usize;
10
11			/// integer with single bit set. bit 0 is the highest bit (big
12			/// endian).  Wraps at `ELEMENT_BITS`.
13			#[inline]
14			pub const fn mask(ndx: usize) -> $t {
15				let bit_ndx = ELEMENT_BITS - 1 - (ndx % ELEMENT_BITS);
16				1 << bit_ndx
17			}
18
19			const fn mask_suffix(ndx: usize) -> $t {
20				assert!(ndx <= ELEMENT_BITS);
21				if ndx >= ELEMENT_BITS {
22					0
23				} else {
24					!0 >> ndx
25				}
26			}
27
28			/// increment from right; don't touch first `prefix` bits; returns
29			/// true on overflow
30			///
31			/// # Panics
32			///
33			/// Panics if `prefix > ELEMENT_BITS`.
34			pub const fn make_element_inc(value: $t, prefix: usize) -> ($t, bool) {
35				assert!(prefix <= ELEMENT_BITS);
36				if prefix == ELEMENT_BITS {
37					return (value, true);
38				}
39				if prefix == 0 {
40					return value.overflowing_add(1);
41				}
42
43				let result = value.wrapping_add(1);
44
45				let fixed_bits_mask = !mask_suffix(prefix);
46
47				if (result ^ value) & fixed_bits_mask != 0 {
48					// overflow: set all non-fixed bits to false (from "prefix"th bit)
49					return (value & fixed_bits_mask, true);
50				}
51				(result, false)
52			}
53
54			/// increment from right; don't touch first `prefix` bits; returns
55			/// true on overflow
56			///
57			/// # Panics
58			///
59			/// Panics if `prefix > ELEMENT_BITS`.
60			pub fn element_inc(value: &mut $t, prefix: usize) -> bool {
61				let overflow;
62				(*value, overflow) = make_element_inc(*value, prefix);
63				overflow
64			}
65
66			/// increment from right; don't touch first `prefix` bits; returns
67			/// true on overflow
68			///
69			/// # Panics
70			///
71			/// Panics if `prefix > ELEMENT_BITS * slice.len()`.
72			pub fn slice_inc(slice: &mut [$t], prefix: usize) -> bool {
73				let slice_ndx = prefix / ELEMENT_BITS;
74				let element_ndx = prefix % ELEMENT_BITS;
75				if slice_ndx >= slice.len() {
76					assert!(element_ndx == 0);
77					return true;
78				}
79
80				for i in (slice_ndx + 1..slice.len()).rev() {
81					let overflow;
82					(slice[i], overflow) = slice[i].overflowing_add(1);
83					if !overflow {
84						return false;
85					}
86				}
87
88				element_inc(&mut slice[slice_ndx], element_ndx)
89			}
90
91			/// Get the `ndx`th bit.
92			///
93			/// # Panics
94			///
95			/// Panics if `ndx >= ELEMENT_BITS`.
96			pub const fn element_get(value: $t, ndx: usize) -> bool {
97				assert!(ndx < ELEMENT_BITS);
98				0 != value & mask(ndx)
99			}
100
101			/// Get the `ndx`th bit.
102			///
103			/// # Panics
104			///
105			/// Panics if `ndx >= ELEMENT_BITS * slice.len()`.
106			pub const fn slice_get(slice: &[$t], ndx: usize) -> bool {
107				let slice_ndx = ndx / ELEMENT_BITS;
108				let element_ndx = ndx % ELEMENT_BITS;
109				element_get(slice[slice_ndx], element_ndx)
110			}
111
112			/// Set the `ndx`th bit to `bit`.
113			///
114			/// # Panics
115			///
116			/// Panics if `ndx >= ELEMENT_BITS`.
117			pub const fn make_element_set(value: $t, ndx: usize, bit: bool) -> $t {
118				assert!(ndx < ELEMENT_BITS);
119				let mask = mask(ndx);
120				if bit {
121					value | mask
122				} else {
123					value & !mask
124				}
125			}
126
127			/// Set the `ndx`th bit to `bit`.
128			///
129			/// # Panics
130			///
131			/// Panics if `ndx >= ELEMENT_BITS`.
132			pub fn element_set(value: &mut $t, ndx: usize, bit: bool) {
133				*value = make_element_set(*value, ndx, bit);
134			}
135
136			/// Set the `ndx`th bit to `bit`.
137			///
138			/// # Panics
139			///
140			/// Panics if `ndx >= ELEMENT_BITS * slice.len()`.
141			pub fn slice_set(slice: &mut [$t], ndx: usize, bit: bool) {
142				let slice_ndx = ndx / ELEMENT_BITS;
143				element_set(&mut slice[slice_ndx], ndx % ELEMENT_BITS, bit);
144			}
145
146			/// Flips the `ndx`th bit.
147			///
148			/// # Panics
149			///
150			/// Panics if `ndx >= ELEMENT_BITS`.
151			pub const fn make_element_flip(value: $t, ndx: usize) -> $t {
152				assert!(ndx < ELEMENT_BITS);
153				value ^ mask(ndx)
154			}
155
156			/// Flips the `ndx`th bit.
157			///
158			/// # Panics
159			///
160			/// Panics if `ndx >= ELEMENT_BITS`.
161			pub fn element_flip(value: &mut $t, ndx: usize) {
162				*value = make_element_flip(*value, ndx);
163			}
164
165			/// Flips the `ndx`th bit.
166			///
167			/// # Panics
168			///
169			/// Panics if `ndx >= ELEMENT_BITS * slice.len()`.
170			pub fn slice_flip(slice: &mut [$t], ndx: usize) {
171				let slice_ndx = ndx / ELEMENT_BITS;
172				element_flip(&mut slice[slice_ndx], ndx % ELEMENT_BITS);
173			}
174
175			/// Length of the longest shared prefix of two bit strings.
176			pub fn element_shared_prefix_len(value: $t, other: $t, max_len: usize) -> usize {
177				assert!(max_len <= ELEMENT_BITS);
178				min((value ^ other).leading_zeros() as usize, max_len)
179			}
180
181			/// Length of the longest shared prefix of two bit strings.
182			pub fn slice_shared_prefix_len(slice: &[$t], other: &[$t], max_len: usize) -> usize {
183				if 0 == max_len {
184					return 0;
185				}
186				// slice index of last bit to compare
187				let slice_ndx = (max_len - 1) / ELEMENT_BITS;
188				for i in 0..slice_ndx {
189					let diff = slice[i] ^ other[i];
190					if 0 != diff {
191						return i * ELEMENT_BITS + diff.leading_zeros() as usize;
192					}
193				}
194				let diff = slice[slice_ndx] ^ other[slice_ndx];
195				if 0 != diff {
196					min(
197						max_len,
198						slice_ndx * ELEMENT_BITS + diff.leading_zeros() as usize,
199					)
200				} else {
201					max_len
202				}
203			}
204
205			/// Set all bits from [ndx..] to `false` (`0`).
206			///
207			/// Doesn't do anything if `ndx >= ELEMENT_BITS`.
208			pub const fn make_element_set_false_from(value: $t, ndx: usize) -> $t {
209				if ndx >= ELEMENT_BITS {
210					return value;
211				}
212				value & !mask_suffix(ndx)
213			}
214
215			/// Set all bits from [ndx..] to `false` (`0`).
216			///
217			/// Doesn't do anything if `ndx >= ELEMENT_BITS`.
218			pub fn element_set_false_from(value: &mut $t, ndx: usize) {
219				*value = make_element_set_false_from(*value, ndx);
220			}
221
222			/// Set all bits from [ndx..] to `false` (`0`).
223			///
224			/// Doesn't do anything if `ndx >= ELEMENT_BITS * slice.len()`.
225			pub fn slice_set_false_from(slice: &mut [$t], ndx: usize) {
226				let slice_ndx = ndx / ELEMENT_BITS;
227				if slice_ndx >= slice.len() {
228					return;
229				}
230				element_set_false_from(&mut slice[slice_ndx], ndx % ELEMENT_BITS);
231				for i in slice_ndx + 1..slice.len() {
232					slice[i] = 0;
233				}
234			}
235
236			/// Whether all bits from [ndx..] are `false` (`0`).
237			///
238			/// Returns `true` if `ndx >= ELEMENT_BITS`.
239			pub const fn element_is_false_from(value: $t, ndx: usize) -> bool {
240				if ndx >= ELEMENT_BITS {
241					return true;
242				}
243				0 == value & mask_suffix(ndx)
244			}
245
246			/// Whether all bits from [ndx..] are `false` (`0`).
247			///
248			/// Returns `true` if `ndx >= ELEMENT_BITS * slice.len()`.
249			pub fn slice_is_false_from(slice: &[$t], ndx: usize) -> bool {
250				let slice_ndx = ndx / ELEMENT_BITS;
251				if slice_ndx >= slice.len() {
252					return true;
253				}
254				if !element_is_false_from(slice[slice_ndx], ndx % ELEMENT_BITS) {
255					return false;
256				}
257				slice[slice_ndx + 1..].iter().all(|&value| value == 0)
258			}
259
260			/// Set all bits from [ndx..] to `true` (`1`).
261			///
262			/// Doesn't do anything if `ndx >= ELEMENT_BITS`.
263			pub const fn make_element_set_true_from(value: $t, ndx: usize) -> $t {
264				if ndx >= ELEMENT_BITS {
265					return value;
266				}
267				value | mask_suffix(ndx)
268			}
269
270			/// Set all bits from [ndx..] to `true` (`1`).
271			///
272			/// Doesn't do anything if `ndx >= ELEMENT_BITS`.
273			pub fn element_set_true_from(value: &mut $t, ndx: usize) {
274				*value = make_element_set_true_from(*value, ndx);
275			}
276
277			/// Set all bits from [ndx..] to `true` (`1`).
278			///
279			/// Doesn't do anything if `ndx >= ELEMENT_BITS * slice.len()`.
280			pub fn slice_set_true_from(slice: &mut [$t], ndx: usize) {
281				let slice_ndx = ndx / ELEMENT_BITS;
282				if slice_ndx >= slice.len() {
283					return;
284				}
285				element_set_true_from(&mut slice[slice_ndx], ndx % ELEMENT_BITS);
286				for i in slice_ndx + 1..slice.len() {
287					slice[i] = !0;
288				}
289			}
290
291			/// Whether all bits from [ndx..] are `true` (`1`).
292			///
293			/// Returns `true` if `ndx >= ELEMENT_BITS`.
294			pub const fn element_is_true_from(value: $t, ndx: usize) -> bool {
295				if ndx >= ELEMENT_BITS {
296					return true;
297				}
298				!0 == value | !mask_suffix(ndx)
299			}
300
301			/// Whether all bits from [ndx..] are `true` (`1`).
302			///
303			/// Returns `true` if `ndx >= ELEMENT_BITS * slice.len()`.
304			pub fn slice_is_true_from(slice: &[$t], ndx: usize) -> bool {
305				let slice_ndx = ndx / ELEMENT_BITS;
306				if slice_ndx >= slice.len() {
307					return true;
308				}
309				if !element_is_true_from(slice[slice_ndx], ndx % ELEMENT_BITS) {
310					return false;
311				}
312				slice[slice_ndx + 1..].iter().all(|&value| value == !0)
313			}
314
315			/// check whether another bit string `other` shares the first
316			/// `prefix` bits with `value`
317			///
318			/// # Panics
319			///
320			/// Panics if `prefix >= ELEMENT_BITS`.
321			pub const fn element_contains(value: $t, prefix: usize, other: $t) -> bool {
322				let mask = !mask_suffix(prefix);
323				0 == mask & (value ^ other)
324			}
325
326			/// check whether another bit string `other` shares the first
327			/// `prefix` bits with `slice`
328			///
329			/// # Panics
330			///
331			/// Panics if `prefix >= ELEMENT_BITS * slice.len()`.
332			pub fn slice_contains(slice: &[$t], prefix: usize, other: &[$t]) -> bool {
333				let slice_ndx = prefix / ELEMENT_BITS;
334				for i in 0..slice_ndx {
335					if slice[i] != other[i] {
336						return false;
337					}
338				}
339				let element_ndx = prefix % ELEMENT_BITS;
340				if 0 == element_ndx {
341					return true;
342				}
343				element_contains(slice[slice_ndx], element_ndx, other[slice_ndx])
344			}
345		}
346	};
347}
348
349impl_big_endian_for! {u8 => u8}
350impl_big_endian_for! {u16 => u16}
351impl_big_endian_for! {u32 => u32}
352impl_big_endian_for! {u64 => u64}
353impl_big_endian_for! {u128 => u128}