proc_bitfield/traits/
arr_impls.rs

1use super::{Bit, Bits, SetBit, SetBits, WithBit, WithBits};
2
3macro_rules! impl_bits_for_int_type {
4    ($storage: ident ($storage_u: ident), $value: ident ($value_u: ident) $(, $const:tt)?) => {
5        mod $value {
6            use super::*;
7            const S_SHIFT: u32 = <$storage>::BITS.trailing_zeros();
8            const S_MASK: usize = <$storage>::BITS as usize - 1;
9            const V_BITS: usize = <$value>::BITS as usize;
10            const V_SHIFT: u32 = <$value>::BITS.trailing_zeros();
11
12            impl<const N: usize> $($const)* Bits<$value> for [$storage; N] {
13                #[inline]
14                fn bits<const START: usize, const END: usize>(&self) -> $value {
15                    if START >= END {
16                        return 0;
17                    }
18                    let bits = if START >> S_SHIFT == (END - 1) >> S_SHIFT {
19                        (self[START >> S_SHIFT] >> (START & S_MASK)) as $value
20                    } else {
21                        let mut bits: $value = 0;
22                        let mut i = START >> S_SHIFT;
23                        while i <= (END - 1) >> S_SHIFT {
24                            let start = $crate::__private::max(START, i << S_SHIFT);
25                            bits |= ((self[i] as $storage_u >> (start & S_MASK)) as $value)
26                                << (start - START);
27                            i += 1;
28                        }
29                        bits
30                    };
31                    let read_bits = END - START;
32                    bits << (V_BITS - read_bits) >> (V_BITS - read_bits)
33                }
34            }
35
36            impl<const N: usize> $($const)* WithBits<$value> for [$storage; N] {
37                #[inline]
38                fn with_bits<const START: usize, const END: usize>(
39                    mut self,
40                    value: $value,
41                ) -> Self {
42                    self.set_bits::<START, END>(value);
43                    self
44                }
45            }
46
47            impl<const N: usize> $($const)* SetBits<$value> for [$storage; N] {
48                #[inline]
49                fn set_bits<const START: usize, const END: usize>(&mut self, value: $value) {
50                    if START >= END {
51                        return;
52                    }
53                    if START >> S_SHIFT == (END - 1) >> S_SHIFT {
54                        let i = START >> S_SHIFT;
55                        let written_bits = END - START;
56                        let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
57                            << (START & S_MASK);
58                        self[i] =
59                            (self[i] & !mask) | ((value as $storage) << (START & S_MASK) & mask);
60                    } else {
61                        let mut i = START >> S_SHIFT;
62                        while i <= (END - 1) >> S_SHIFT {
63                            let start = $crate::__private::max(START, i << S_SHIFT);
64                            let end = $crate::__private::min(END, (i + 1) << S_SHIFT);
65                            let written_bits = end - start;
66                            let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
67                                << (start & S_MASK);
68                            self[i] = (self[i] & !mask)
69                                | (((value >> (start - START)) as $storage) << (start & S_MASK)
70                                    & mask);
71                            i += 1;
72                        }
73                    }
74                }
75            }
76
77            impl $($const)* Bits<$value> for [$storage] {
78                #[inline]
79                fn bits<const START: usize, const END: usize>(&self) -> $value {
80                    if START >= END {
81                        return 0;
82                    }
83                    let bits = if START >> S_SHIFT == (END - 1) >> S_SHIFT {
84                        (self[START >> S_SHIFT] >> (START & S_MASK)) as $value
85                    } else {
86                        let mut bits: $value = 0;
87                        let mut i = START >> S_SHIFT;
88                        while i <= (END - 1) >> S_SHIFT {
89                            let start = $crate::__private::max(START, i << S_SHIFT);
90                            bits |= ((self[i] as $storage_u >> (start & S_MASK)) as $value)
91                                << (start - START);
92                            i += 1;
93                        }
94                        bits
95                    };
96                    let read_bits = END - START;
97                    bits << (V_BITS - read_bits) >> (V_BITS - read_bits)
98                }
99            }
100
101            impl $($const)* SetBits<$value> for [$storage] {
102                #[inline]
103                fn set_bits<const START: usize, const END: usize>(&mut self, value: $value) {
104                    if START >= END {
105                        return;
106                    }
107                    if START >> S_SHIFT == (END - 1) >> S_SHIFT {
108                        let i = START >> S_SHIFT;
109                        let written_bits = END - START;
110                        let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
111                            << (START & S_MASK);
112                        self[i] =
113                            (self[i] & !mask) | ((value as $storage) << (START & S_MASK) & mask);
114                    } else {
115                        let mut i = START >> S_SHIFT;
116                        while i <= (END - 1) >> S_SHIFT {
117                            let start = $crate::__private::max(START, i << S_SHIFT);
118                            let end = $crate::__private::min(END, (i + 1) << S_SHIFT);
119                            let written_bits = end - start;
120                            let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
121                                << (start & S_MASK);
122                            self[i] = (self[i] & !mask)
123                                | (((value >> (start - START)) as $storage) << (start & S_MASK)
124                                    & mask);
125                            i += 1;
126                        }
127                    }
128                }
129            }
130
131            impl<const M: usize> $($const)* Bits<[$value; M]> for $storage {
132                #[inline]
133                fn bits<const START: usize, const END: usize>(&self) -> [$value; M] {
134                    if START >= END {
135                        return [0; M];
136                    }
137                    let mut result = [0; M];
138                    let mut i = 0;
139                    while i <= (END - START - 1) >> V_SHIFT {
140                        let start = START + (i << V_SHIFT);
141                        let end = $crate::__private::min(END, start + V_BITS);
142                        let read_bits = end - start;
143                        result[i] = ((*self >> start) as $value) << (V_BITS - read_bits)
144                            >> (V_BITS - read_bits);
145                        i += 1;
146                    }
147                    result
148                }
149            }
150
151            impl<const M: usize> $($const)* WithBits<[$value; M]> for $storage {
152                #[inline]
153                fn with_bits<const START: usize, const END: usize>(
154                    mut self,
155                    value: [$value; M],
156                ) -> Self {
157                    if START >= END {
158                        return self;
159                    }
160                    let mut i = 0;
161                    while i <= (END - START - 1) >> V_SHIFT {
162                        let start = START + (i << V_SHIFT);
163                        let end = $crate::__private::min(END, start + V_BITS);
164                        let written_bits = end - start;
165                        let mask =
166                            ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1) << start;
167                        self = (self & !mask) | ((value[i] as $storage) << start & mask);
168                        i += 1;
169                    }
170                    self
171                }
172            }
173
174            impl<const M: usize> $($const)* SetBits<[$value; M]> for $storage {
175                #[inline]
176                fn set_bits<const START: usize, const END: usize>(&mut self, value: [$value; M]) {
177                    *self = self.with_bits::<START, END>(value);
178                }
179            }
180
181            impl<const M: usize, const N: usize> $($const)* Bits<[$value; M]> for [$storage; N] {
182                #[inline]
183                fn bits<const START: usize, const END: usize>(&self) -> [$value; M] {
184                    if START >= END {
185                        return [0; M];
186                    }
187                    let mut result = [0; M];
188                    let mut i = 0;
189                    while i <= (END - START - 1) >> V_SHIFT {
190                        let start = START + (i << V_SHIFT);
191                        let end = $crate::__private::min(END, start + V_BITS);
192                        let bits = if start >> S_SHIFT == (end - 1) >> S_SHIFT {
193                            (self[start >> S_SHIFT] >> (start & S_MASK)) as $value
194                        } else {
195                            let mut bits: $value = 0;
196                            let mut j = start >> S_SHIFT;
197                            while j <= (end - 1) >> S_SHIFT {
198                                let start_ = $crate::__private::max(start, j << S_SHIFT);
199                                bits |= ((self[j] as $storage_u >> (start_ & S_MASK)) as $value)
200                                    << (start_ - start);
201                                j += 1;
202                            }
203                            bits
204                        };
205                        let read_bits = end - start;
206                        result[i] = bits << (V_BITS - read_bits) >> (V_BITS - read_bits);
207                        i += 1;
208                    }
209                    result
210                }
211            }
212
213            impl<const M: usize, const N: usize> $($const)* WithBits<[$value; M]> for
214                [$storage; N]
215            {
216                #[inline]
217                fn with_bits<const START: usize, const END: usize>(
218                    mut self,
219                    value: [$value; M],
220                ) -> Self {
221                    self.set_bits::<START, END>(value);
222                    self
223                }
224            }
225
226            impl<const M: usize, const N: usize> $($const)* SetBits<[$value; M]> for [$storage; N] {
227                #[inline]
228                fn set_bits<const START: usize, const END: usize>(&mut self, value: [$value; M]) {
229                    if START >= END {
230                        return;
231                    }
232                    let mut i = 0;
233                    while i <= (END - START - 1) >> V_SHIFT {
234                        let start = START + (i << V_SHIFT);
235                        let end = $crate::__private::min(END, start + V_BITS);
236                        if start >> S_SHIFT == (end - 1) >> S_SHIFT {
237                            let j = start >> S_SHIFT;
238                            let written_bits = end - start;
239                            let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
240                                << (start & S_MASK);
241                            self[j] = (self[j] & !mask)
242                                | ((value[i] as $storage) << (start & S_MASK) & mask);
243                        } else {
244                            let mut j = start >> S_SHIFT;
245                            while j <= (end - 1) >> S_SHIFT {
246                                let start_ = $crate::__private::max(start, j << S_SHIFT);
247                                let end_ = $crate::__private::min(end, (j + 1) << S_SHIFT);
248                                let written_bits = end_ - start_;
249                                let mask = ((1 as $storage) << (written_bits - 1) << 1)
250                                    .wrapping_sub(1)
251                                    << (start_ & S_MASK);
252                                self[j] = (self[j] & !mask)
253                                    | (((value[i] >> (start_ - start)) as $storage)
254                                        << (start_ & S_MASK)
255                                        & mask);
256                                j += 1;
257                            }
258                        }
259                        i += 1;
260                    }
261                }
262            }
263
264            impl<const M: usize> $($const)* Bits<[$value; M]> for [$storage] {
265                #[inline]
266                fn bits<const START: usize, const END: usize>(&self) -> [$value; M] {
267                    if START >= END {
268                        return [0; M];
269                    }
270                    let mut result = [0; M];
271                    let mut i = 0;
272                    while i <= (END - START - 1) >> V_SHIFT {
273                        let start = START + (i << V_SHIFT);
274                        let end = $crate::__private::min(END, start + V_BITS);
275                        let bits = if start >> S_SHIFT == (end - 1) >> S_SHIFT {
276                            (self[start >> S_SHIFT] >> (start & S_MASK)) as $value
277                        } else {
278                            let mut bits: $value = 0;
279                            let mut j = start >> S_SHIFT;
280                            while j <= (end - 1) >> S_SHIFT {
281                                let start_ = $crate::__private::max(start, j << S_SHIFT);
282                                bits |= ((self[j] as $storage_u >> (start_ & S_MASK)) as $value)
283                                    << (start_ - start);
284                                j += 1;
285                            }
286                            bits
287                        };
288                        let read_bits = end - start;
289                        result[i] = bits << (V_BITS - read_bits) >> (V_BITS - read_bits);
290                        i += 1;
291                    }
292                    result
293                }
294            }
295
296            impl<const M: usize> $($const)* SetBits<[$value; M]> for [$storage] {
297                #[inline]
298                fn set_bits<const START: usize, const END: usize>(&mut self, value: [$value; M]) {
299                    if START >= END {
300                        return;
301                    }
302                    let mut i = 0;
303                    while i <= (END - START - 1) >> V_SHIFT {
304                        let start = START + (i << V_SHIFT);
305                        let end = $crate::__private::min(END, start + V_BITS);
306                        if start >> S_SHIFT == (end - 1) >> S_SHIFT {
307                            let j = start >> S_SHIFT;
308                            let written_bits = end - start;
309                            let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
310                                << (start & S_MASK);
311                            self[j] = (self[j] & !mask)
312                                | ((value[i] as $storage) << (start & S_MASK) & mask);
313                        } else {
314                            let mut j = start >> S_SHIFT;
315                            while j <= (end - 1) >> S_SHIFT {
316                                let start_ = $crate::__private::max(start, j << S_SHIFT);
317                                let end_ = $crate::__private::min(end, (j + 1) << S_SHIFT);
318                                let written_bits = end_ - start_;
319                                let mask = ((1 as $storage) << (written_bits - 1) << 1)
320                                    .wrapping_sub(1)
321                                    << (start_ & S_MASK);
322                                self[j] = (self[j] & !mask)
323                                    | (((value[i] >> (start_ - start)) as $storage)
324                                        << (start_ & S_MASK)
325                                        & mask);
326                                j += 1;
327                            }
328                        }
329                        i += 1;
330                    }
331                }
332            }
333        }
334    };
335}
336
337macro_rules! impl_bits_for_int_types {
338    (const => $($dst_ty: ident ($dst_u_ty: ident)),*) => {};
339    (=> $($dst_ty: ident ($dst_u_ty: ident)),*) => {};
340    (
341        const $src_ty: ident ($src_u_ty: ident)
342        $(, $other_src_ty: ident ($other_src_u_ty: ident))*
343        => $($dst_ty: ident ($dst_u_ty: ident)),*
344    ) => {
345        mod $src_ty {
346            use super::*;
347            $(
348                impl_bits_for_int_type!($src_ty ($src_u_ty), $dst_ty ($dst_u_ty), const);
349            )*
350        }
351        impl_bits_for_int_types!(
352            const $($other_src_ty ($other_src_u_ty)),* => $($dst_ty ($dst_u_ty)),*
353        );
354    };
355    (
356        $src_ty: ident ($src_u_ty: ident)
357        $(, $other_src_ty: ident ($other_src_u_ty: ident))*
358        => $($dst_ty: ident ($dst_u_ty: ident)),*
359    ) => {
360        mod $src_ty {
361            use super::*;
362            $(
363                impl_bits_for_int_type!($src_ty ($src_u_ty), $dst_ty ($dst_u_ty));
364            )*
365        }
366        impl_bits_for_int_types!(
367            $($other_src_ty ($other_src_u_ty)),* => $($dst_ty ($dst_u_ty)),*
368        );
369    };
370}
371
372mod bits {
373    use super::*;
374    #[cfg(not(feature = "nightly"))]
375    impl_bits_for_int_types!(
376        u8 (u8), u16 (u16), u32 (u32), u64 (u64), u128 (u128), usize (usize),
377        i8 (u8), i16 (u16), i32 (u32), i64 (u64), i128 (u128), isize (usize)
378            => u8 (u8), u16 (u16), u32 (u32), u64 (u64), u128 (u128), usize (usize),
379               i8 (u8), i16 (u16), i32 (u32), i64 (u64), i128 (u128), isize (usize)
380    );
381    #[cfg(feature = "nightly")]
382    impl_bits_for_int_types!(
383        const
384        u8 (u8), u16 (u16), u32 (u32), u64 (u64), u128 (u128), usize (usize),
385        i8 (u8), i16 (u16), i32 (u32), i64 (u64), i128 (u128), isize (usize)
386            => u8 (u8), u16 (u16), u32 (u32), u64 (u64), u128 (u128), usize (usize),
387               i8 (u8), i16 (u16), i32 (u32), i64 (u64), i128 (u128), isize (usize)
388    );
389}
390
391macro_rules! impl_bit_for_arr_int_type {
392    ($t: ident $(, $const:tt)?) => {
393        mod $t {
394            use super::*;
395            const SHIFT: u32 = <$t>::BITS.trailing_zeros();
396            const MASK: usize = <$t>::BITS as usize - 1;
397
398            impl<const N: usize> $($const)* Bit for [$t; N] {
399                #[inline]
400                fn bit<const BIT: usize>(&self) -> bool {
401                    self[BIT >> SHIFT] & 1 << (BIT & MASK) != 0
402                }
403            }
404
405            impl<const N: usize> $($const)* WithBit for [$t; N] {
406                #[inline]
407                fn with_bit<const BIT: usize>(mut self, value: bool) -> Self {
408                    self.set_bit::<BIT>(value);
409                    self
410                }
411            }
412
413            impl<const N: usize> $($const)* SetBit for [$t; N] {
414                #[inline]
415                fn set_bit<const BIT: usize>(&mut self, value: bool) {
416                    self[BIT >> SHIFT] =
417                        (self[BIT >> SHIFT] & !(1 << (BIT & MASK))) | (value as $t) << BIT;
418                }
419            }
420
421            impl $($const)* Bit for [$t] {
422                #[inline]
423                fn bit<const BIT: usize>(&self) -> bool {
424                    self[BIT >> SHIFT] & 1 << (BIT & MASK) != 0
425                }
426            }
427
428            impl $($const)* SetBit for [$t] {
429                #[inline]
430                fn set_bit<const BIT: usize>(&mut self, value: bool) {
431                    self[BIT >> SHIFT] =
432                        (self[BIT >> SHIFT] & !(1 << (BIT & MASK))) | (value as $t) << BIT;
433                }
434            }
435        }
436    };
437}
438
439macro_rules! impl_bit_for_arr_int_types {
440    (const $($t: ident),*) => {
441        $(impl_bit_for_arr_int_type!($t, const);)*
442    };
443    ($($t: ident),*) => {
444        $(impl_bit_for_arr_int_type!($t);)*
445    };
446}
447
448mod bit {
449    use super::*;
450    #[cfg(not(feature = "nightly"))]
451    impl_bit_for_arr_int_types!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
452    #[cfg(feature = "nightly")]
453    impl_bit_for_arr_int_types!(
454        const
455        u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
456    );
457}