bitstring/utils/bigendian/
int_helpers.rs1macro_rules! impl_big_endian_for {
2 ($mod:ident => $t:ty) => {
3 #[cfg_attr(not(feature = "bigendian"), allow(dead_code))] pub mod $mod {
6 use core::cmp::min;
7
8 pub const ELEMENT_BITS: usize = <$t>::BITS as usize;
10
11 #[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 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 return (value & fixed_bits_mask, true);
50 }
51 (result, false)
52 }
53
54 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 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 pub const fn element_get(value: $t, ndx: usize) -> bool {
97 assert!(ndx < ELEMENT_BITS);
98 0 != value & mask(ndx)
99 }
100
101 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 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 pub fn element_set(value: &mut $t, ndx: usize, bit: bool) {
133 *value = make_element_set(*value, ndx, bit);
134 }
135
136 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 pub const fn make_element_flip(value: $t, ndx: usize) -> $t {
152 assert!(ndx < ELEMENT_BITS);
153 value ^ mask(ndx)
154 }
155
156 pub fn element_flip(value: &mut $t, ndx: usize) {
162 *value = make_element_flip(*value, ndx);
163 }
164
165 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 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 pub fn slice_shared_prefix_len(slice: &[$t], other: &[$t], max_len: usize) -> usize {
183 if 0 == max_len {
184 return 0;
185 }
186 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 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 pub fn element_set_false_from(value: &mut $t, ndx: usize) {
219 *value = make_element_set_false_from(*value, ndx);
220 }
221
222 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 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 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 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 pub fn element_set_true_from(value: &mut $t, ndx: usize) {
274 *value = make_element_set_true_from(*value, ndx);
275 }
276
277 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 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 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 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 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}