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)) => {
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> Bits<$value> for [$storage; N] {
13                #[inline]
14                fn bits<const START: usize, const END: usize>(&self) -> $value {
15                    let bits = if START >> S_SHIFT == (END - 1) >> S_SHIFT {
16                        (self[START >> S_SHIFT] >> (START & S_MASK)) as $value
17                    } else {
18                        let mut bits: $value = 0;
19                        for i in START >> S_SHIFT..=(END - 1) >> S_SHIFT {
20                            let start = START.max(i << S_SHIFT);
21                            bits |= ((self[i] as $storage_u >> (start & S_MASK)) as $value)
22                                << (start - START);
23                        }
24                        bits
25                    };
26                    let read_bits = END - START;
27                    bits << (V_BITS - read_bits) >> (V_BITS - read_bits)
28                }
29            }
30
31            impl<const N: usize> WithBits<$value> for [$storage; N] {
32                #[inline]
33                fn with_bits<const START: usize, const END: usize>(
34                    mut self,
35                    value: $value,
36                ) -> Self {
37                    self.set_bits::<START, END>(value);
38                    self
39                }
40            }
41
42            impl<const N: usize> SetBits<$value> for [$storage; N] {
43                #[inline]
44                fn set_bits<const START: usize, const END: usize>(&mut self, value: $value) {
45                    if START >> S_SHIFT == (END - 1) >> S_SHIFT {
46                        let i = START >> S_SHIFT;
47                        let written_bits = END - START;
48                        let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
49                            << (START & S_MASK);
50                        self[i] =
51                            (self[i] & !mask) | ((value as $storage) << (START & S_MASK) & mask);
52                    } else {
53                        for i in START >> S_SHIFT..=(END - 1) >> S_SHIFT {
54                            let start = START.max(i << S_SHIFT);
55                            let end = END.min((i + 1) << S_SHIFT);
56                            let written_bits = end - start;
57                            let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
58                                << (start & S_MASK);
59                            self[i] = (self[i] & !mask)
60                                | (((value >> (start - START)) as $storage) << (start & S_MASK)
61                                    & mask);
62                        }
63                    }
64                }
65            }
66
67            impl Bits<$value> for [$storage] {
68                #[inline]
69                fn bits<const START: usize, const END: usize>(&self) -> $value {
70                    let bits = if START >> S_SHIFT == (END - 1) >> S_SHIFT {
71                        (self[START >> S_SHIFT] >> (START & S_MASK)) as $value
72                    } else {
73                        let mut bits: $value = 0;
74                        for i in START >> S_SHIFT..=(END - 1) >> S_SHIFT {
75                            let start = START.max(i << S_SHIFT);
76                            bits |= ((self[i] as $storage_u >> (start & S_MASK)) as $value)
77                                << (start - START);
78                        }
79                        bits
80                    };
81                    let read_bits = END - START;
82                    bits << (V_BITS - read_bits) >> (V_BITS - read_bits)
83                }
84            }
85
86            impl SetBits<$value> for [$storage] {
87                #[inline]
88                fn set_bits<const START: usize, const END: usize>(&mut self, value: $value) {
89                    if START >> S_SHIFT == (END - 1) >> S_SHIFT {
90                        let i = START >> S_SHIFT;
91                        let written_bits = END - START;
92                        let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
93                            << (START & S_MASK);
94                        self[i] =
95                            (self[i] & !mask) | ((value as $storage) << (START & S_MASK) & mask);
96                    } else {
97                        for i in START >> S_SHIFT..=(END - 1) >> S_SHIFT {
98                            let start = START.max(i << S_SHIFT);
99                            let end = END.min((i + 1) << S_SHIFT);
100                            let written_bits = end - start;
101                            let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
102                                << (start & S_MASK);
103                            self[i] = (self[i] & !mask)
104                                | (((value >> (start - START)) as $storage) << (start & S_MASK)
105                                    & mask);
106                        }
107                    }
108                }
109            }
110
111            impl<const M: usize> Bits<[$value; M]> for $storage {
112                #[inline]
113                fn bits<const START: usize, const END: usize>(&self) -> [$value; M] {
114                    let mut result = [0; M];
115                    for i in 0..=(END - START - 1) >> V_SHIFT {
116                        let start = START + (i << V_SHIFT);
117                        let end = (start + V_BITS).min(END);
118                        let read_bits = end - start;
119                        result[i] = ((*self >> start) as $value) << (V_BITS - read_bits)
120                            >> (V_BITS - read_bits);
121                    }
122                    result
123                }
124            }
125
126            impl<const M: usize> WithBits<[$value; M]> for $storage {
127                #[inline]
128                fn with_bits<const START: usize, const END: usize>(
129                    mut self,
130                    value: [$value; M],
131                ) -> Self {
132                    for i in 0..=(END - START - 1) >> V_SHIFT {
133                        let start = START + (i << V_SHIFT);
134                        let end = (start + V_BITS).min(END);
135                        let written_bits = end - start;
136                        let mask =
137                            ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1) << start;
138                        self = (self & !mask) | ((value[i] as $storage) << start & mask);
139                    }
140                    self
141                }
142            }
143
144            impl<const M: usize> SetBits<[$value; M]> for $storage {
145                #[inline]
146                fn set_bits<const START: usize, const END: usize>(&mut self, value: [$value; M]) {
147                    *self = self.with_bits::<START, END>(value);
148                }
149            }
150
151            impl<const M: usize, const N: usize> Bits<[$value; M]> for [$storage; N] {
152                #[inline]
153                fn bits<const START: usize, const END: usize>(&self) -> [$value; M] {
154                    let mut result = [0; M];
155                    for i in 0..=(END - START - 1) >> V_SHIFT {
156                        let start = START + (i << V_SHIFT);
157                        let end = (start + V_BITS).min(END);
158                        let bits = if start >> S_SHIFT == (end - 1) >> S_SHIFT {
159                            (self[start >> S_SHIFT] >> (start & S_MASK)) as $value
160                        } else {
161                            let mut bits: $value = 0;
162                            for j in start >> S_SHIFT..=(end - 1) >> S_SHIFT {
163                                let start_ = start.max(j << S_SHIFT);
164                                bits |= ((self[j] as $storage_u >> (start_ & S_MASK)) as $value)
165                                    << (start_ - start);
166                            }
167                            bits
168                        };
169                        let read_bits = end - start;
170                        result[i] = bits << (V_BITS - read_bits) >> (V_BITS - read_bits);
171                    }
172                    result
173                }
174            }
175
176            impl<const M: usize, const N: usize> WithBits<[$value; M]> for [$storage; N] {
177                #[inline]
178                fn with_bits<const START: usize, const END: usize>(
179                    mut self,
180                    value: [$value; M],
181                ) -> Self {
182                    self.set_bits::<START, END>(value);
183                    self
184                }
185            }
186
187            impl<const M: usize, const N: usize> SetBits<[$value; M]> for [$storage; N] {
188                #[inline]
189                fn set_bits<const START: usize, const END: usize>(&mut self, value: [$value; M]) {
190                    for i in 0..=(END - START - 1) >> V_SHIFT {
191                        let start = START + (i << V_SHIFT);
192                        let end = (start + V_BITS).min(END);
193                        if start >> S_SHIFT == (end - 1) >> S_SHIFT {
194                            let j = start >> S_SHIFT;
195                            let written_bits = end - start;
196                            let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
197                                << (start & S_MASK);
198                            self[j] = (self[j] & !mask)
199                                | ((value[i] as $storage) << (start & S_MASK) & mask);
200                        } else {
201                            for j in start >> S_SHIFT..=(end - 1) >> S_SHIFT {
202                                let start_ = start.max(j << S_SHIFT);
203                                let end_ = end.min((j + 1) << S_SHIFT);
204                                let written_bits = end_ - start_;
205                                let mask = ((1 as $storage) << (written_bits - 1) << 1)
206                                    .wrapping_sub(1)
207                                    << (start_ & S_MASK);
208                                self[j] = (self[j] & !mask)
209                                    | (((value[i] >> (start_ - start)) as $storage)
210                                        << (start_ & S_MASK)
211                                        & mask);
212                            }
213                        }
214                    }
215                }
216            }
217
218            impl<const M: usize> Bits<[$value; M]> for [$storage] {
219                #[inline]
220                fn bits<const START: usize, const END: usize>(&self) -> [$value; M] {
221                    let mut result = [0; M];
222                    for i in 0..=(END - START - 1) >> V_SHIFT {
223                        let start = START + (i << V_SHIFT);
224                        let end = (start + V_BITS).min(END);
225                        let bits = if start >> S_SHIFT == (end - 1) >> S_SHIFT {
226                            (self[start >> S_SHIFT] >> (start & S_MASK)) as $value
227                        } else {
228                            let mut bits: $value = 0;
229                            for j in start >> S_SHIFT..=(end - 1) >> S_SHIFT {
230                                let start_ = start.max(j << S_SHIFT);
231                                bits |= ((self[j] as $storage_u >> (start_ & S_MASK)) as $value)
232                                    << (start_ - start);
233                            }
234                            bits
235                        };
236                        let read_bits = end - start;
237                        result[i] = bits << (V_BITS - read_bits) >> (V_BITS - read_bits);
238                    }
239                    result
240                }
241            }
242
243            impl<const M: usize> SetBits<[$value; M]> for [$storage] {
244                #[inline]
245                fn set_bits<const START: usize, const END: usize>(&mut self, value: [$value; M]) {
246                    for i in 0..=(END - START - 1) >> V_SHIFT {
247                        let start = START + (i << V_SHIFT);
248                        let end = (start + V_BITS).min(END);
249                        if start >> S_SHIFT == (end - 1) >> S_SHIFT {
250                            let j = start >> S_SHIFT;
251                            let written_bits = end - start;
252                            let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
253                                << (start & S_MASK);
254                            self[j] = (self[j] & !mask)
255                                | ((value[i] as $storage) << (start & S_MASK) & mask);
256                        } else {
257                            for j in start >> S_SHIFT..=(end - 1) >> S_SHIFT {
258                                let start_ = start.max(j << S_SHIFT);
259                                let end_ = end.min((j + 1) << S_SHIFT);
260                                let written_bits = end_ - start_;
261                                let mask = ((1 as $storage) << (written_bits - 1) << 1)
262                                    .wrapping_sub(1)
263                                    << (start_ & S_MASK);
264                                self[j] = (self[j] & !mask)
265                                    | (((value[i] >> (start_ - start)) as $storage)
266                                        << (start_ & S_MASK)
267                                        & mask);
268                            }
269                        }
270                    }
271                }
272            }
273        }
274    };
275}
276
277macro_rules! impl_bits_for_int_types {
278    (=> $($dst_ty: ident ($dst_u_ty: ident)),*) => {};
279    (
280        $src_ty: ident ($src_u_ty: ident)
281        $(, $other_src_ty: ident ($other_src_u_ty: ident))*
282        => $($dst_ty: ident ($dst_u_ty: ident)),*
283    ) => {
284        mod $src_ty {
285            use super::*;
286            $(
287                impl_bits_for_int_type!($src_ty ($src_u_ty), $dst_ty ($dst_u_ty));
288            )*
289        }
290        impl_bits_for_int_types!(
291            $($other_src_ty ($other_src_u_ty)),* => $($dst_ty ($dst_u_ty)),*
292        );
293    };
294}
295
296mod bits {
297    use super::*;
298    impl_bits_for_int_types!(
299        u8 (u8), u16 (u16), u32 (u32), u64 (u64), u128 (u128), usize (usize),
300        i8 (u8), i16 (u16), i32 (u32), i64 (u64), i128 (u128), isize (usize)
301            => u8 (u8), u16 (u16), u32 (u32), u64 (u64), u128 (u128), usize (usize),
302               i8 (u8), i16 (u16), i32 (u32), i64 (u64), i128 (u128), isize (usize)
303    );
304}
305
306macro_rules! impl_bit_for_arr_int_type {
307    ($t: ident) => {
308        mod $t {
309            use super::*;
310            const SHIFT: u32 = <$t>::BITS.trailing_zeros();
311            const MASK: usize = <$t>::BITS as usize - 1;
312
313            impl<const N: usize> Bit for [$t; N] {
314                #[inline]
315                fn bit<const BIT: usize>(&self) -> bool {
316                    self[BIT >> SHIFT] & 1 << (BIT & MASK) != 0
317                }
318            }
319
320            impl<const N: usize> WithBit for [$t; N] {
321                #[inline]
322                fn with_bit<const BIT: usize>(mut self, value: bool) -> Self {
323                    self.set_bit::<BIT>(value);
324                    self
325                }
326            }
327
328            impl<const N: usize> SetBit for [$t; N] {
329                #[inline]
330                fn set_bit<const BIT: usize>(&mut self, value: bool) {
331                    self[BIT >> SHIFT] =
332                        (self[BIT >> SHIFT] & !(1 << (BIT & MASK))) | (value as $t) << BIT;
333                }
334            }
335
336            impl Bit for [$t] {
337                #[inline]
338                fn bit<const BIT: usize>(&self) -> bool {
339                    self[BIT >> SHIFT] & 1 << (BIT & MASK) != 0
340                }
341            }
342
343            impl SetBit for [$t] {
344                #[inline]
345                fn set_bit<const BIT: usize>(&mut self, value: bool) {
346                    self[BIT >> SHIFT] =
347                        (self[BIT >> SHIFT] & !(1 << (BIT & MASK))) | (value as $t) << BIT;
348                }
349            }
350        }
351    };
352}
353
354macro_rules! impl_bit_for_arr_int_types {
355    ($($t: ident),*) => {
356        $(impl_bit_for_arr_int_type!($t);)*
357    };
358}
359
360mod bit {
361    use super::*;
362    impl_bit_for_arr_int_types!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
363}