• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2022 Collabora, Ltd.
3  * SPDX-License-Identifier: MIT
4  */
5 
6 use std::ops::Range;
7 
8 pub trait BitViewable {
bits(&self) -> usize9     fn bits(&self) -> usize;
10 
get_bit_range_u64(&self, range: Range<usize>) -> u6411     fn get_bit_range_u64(&self, range: Range<usize>) -> u64;
12 }
13 
14 pub trait BitMutViewable: BitViewable {
set_bit_range_u64(&mut self, range: Range<usize>, val: u64)15     fn set_bit_range_u64(&mut self, range: Range<usize>, val: u64);
16 }
17 
u64_mask_for_bits(bits: usize) -> u6418 fn u64_mask_for_bits(bits: usize) -> u64 {
19     assert!(bits > 0 && bits <= 64);
20     !0u64 >> (64 - bits)
21 }
22 
23 macro_rules! decl_bit_set_viewable_for_uint {
24     ($ty: ty) => {
25         impl BitViewable for $ty {
26             fn bits(&self) -> usize {
27                 <$ty>::BITS as usize
28             }
29 
30             fn get_bit_range_u64(&self, range: Range<usize>) -> u64 {
31                 assert!(!range.is_empty());
32                 assert!(range.end <= self.bits());
33 
34                 let mask = <$ty>::MAX >> (self.bits() - range.len());
35                 ((self >> range.start) & mask).into()
36             }
37         }
38 
39         impl BitMutViewable for $ty {
40             fn set_bit_range_u64(&mut self, range: Range<usize>, val: u64) {
41                 assert!(!range.is_empty());
42                 assert!(range.end <= self.bits());
43 
44                 let mask = <$ty>::MAX >> (self.bits() - range.len());
45 
46                 assert!((val & u64::from(mask)) == val);
47                 let val = val as $ty;
48 
49                 *self = (*self & !(mask << range.start)) | (val << range.start);
50             }
51         }
52 
53         impl BitViewable for [$ty] {
54             fn bits(&self) -> usize {
55                 self.len() * (<$ty>::BITS as usize)
56             }
57 
58             fn get_bit_range_u64(&self, range: Range<usize>) -> u64 {
59                 assert!(!range.is_empty());
60                 assert!(range.end <= self.bits());
61 
62                 let mask = u64_mask_for_bits(range.len());
63 
64                 let bits = <$ty>::BITS as usize;
65                 let c0_idx = range.start / bits;
66                 let c0_start = range.start % bits;
67                 let chunks = (c0_start + range.len()).div_ceil(bits);
68 
69                 let mut val = 0_u64;
70                 for i in 0..chunks {
71                     let chunk = u64::from(self[c0_idx + i]);
72                     if i == 0 {
73                         val |= chunk >> c0_start;
74                     } else {
75                         val |= chunk << (i * bits) - c0_start;
76                     };
77                 }
78                 val & mask
79             }
80         }
81 
82         impl BitMutViewable for [$ty] {
83             fn set_bit_range_u64(&mut self, range: Range<usize>, val: u64) {
84                 assert!(!range.is_empty());
85                 assert!(range.end <= self.bits());
86 
87                 let mask = u64_mask_for_bits(range.len());
88                 assert!((val & u64::from(mask)) == val);
89 
90                 let bits = <$ty>::BITS as usize;
91                 let c0_idx = range.start / bits;
92                 let c0_start = range.start % bits;
93                 let chunks = (c0_start + range.len()).div_ceil(bits);
94 
95                 for i in 0..chunks {
96                     let chunk = &mut self[c0_idx + i];
97                     if i == 0 {
98                         *chunk &= !((mask << c0_start) as $ty);
99                         *chunk |= (val << c0_start) as $ty;
100                     } else {
101                         let shift = (i * bits) - c0_start;
102                         *chunk &= !((mask >> shift) as $ty);
103                         *chunk |= (val >> shift) as $ty;
104                     }
105                 }
106             }
107         }
108 
109         impl<const N: usize> BitViewable for [$ty; N] {
110             fn bits(&self) -> usize {
111                 N * (<$ty>::BITS as usize)
112             }
113 
114             fn get_bit_range_u64(&self, range: Range<usize>) -> u64 {
115                 self[..].get_bit_range_u64(range)
116             }
117         }
118 
119         impl<const N: usize> BitMutViewable for [$ty; N] {
120             fn set_bit_range_u64(&mut self, range: Range<usize>, val: u64) {
121                 self[..].set_bit_range_u64(range, val);
122             }
123         }
124     };
125 }
126 
127 decl_bit_set_viewable_for_uint!(u8);
128 decl_bit_set_viewable_for_uint!(u16);
129 decl_bit_set_viewable_for_uint!(u32);
130 decl_bit_set_viewable_for_uint!(u64);
131 
132 pub struct BitView<'a, BS: BitViewable + ?Sized> {
133     parent: &'a BS,
134     range: Range<usize>,
135 }
136 
137 #[allow(dead_code)]
138 impl<'a, BS: BitViewable + ?Sized> BitView<'a, BS> {
new(parent: &'a BS) -> Self139     pub fn new(parent: &'a BS) -> Self {
140         let len = parent.bits();
141         Self {
142             parent: parent,
143             range: 0..len,
144         }
145     }
146 
new_subset(parent: &'a BS, range: Range<usize>) -> Self147     pub fn new_subset(parent: &'a BS, range: Range<usize>) -> Self {
148         assert!(range.end <= parent.bits());
149         Self {
150             parent: parent,
151             range: range,
152         }
153     }
154 
subset( &'a self, range: Range<usize>, ) -> BitView<'a, BitView<'a, BS>>155     pub fn subset(
156         &'a self,
157         range: Range<usize>,
158     ) -> BitView<'a, BitView<'a, BS>> {
159         BitView::new_subset(self, range)
160     }
161 
range_in_parent(&self, range: Range<usize>) -> Range<usize>162     fn range_in_parent(&self, range: Range<usize>) -> Range<usize> {
163         let new_start = self.range.start + range.start;
164         let new_end = self.range.start + range.end;
165         assert!(new_end <= self.range.end);
166         new_start..new_end
167     }
168 
get_bit(&self, bit: usize) -> bool169     pub fn get_bit(&self, bit: usize) -> bool {
170         self.get_bit_range_u64(bit..(bit + 1)) != 0
171     }
172 }
173 
174 impl<'a, BS: BitViewable + ?Sized> BitViewable for BitView<'a, BS> {
bits(&self) -> usize175     fn bits(&self) -> usize {
176         self.range.end - self.range.start
177     }
178 
get_bit_range_u64(&self, range: Range<usize>) -> u64179     fn get_bit_range_u64(&self, range: Range<usize>) -> u64 {
180         self.parent.get_bit_range_u64(self.range_in_parent(range))
181     }
182 }
183 
184 pub struct BitMutView<'a, BS: BitMutViewable + ?Sized> {
185     parent: &'a mut BS,
186     range: Range<usize>,
187 }
188 
189 #[allow(dead_code)]
190 impl<'a, BS: BitMutViewable + ?Sized> BitMutView<'a, BS> {
new(parent: &'a mut BS) -> Self191     pub fn new(parent: &'a mut BS) -> Self {
192         let len = parent.bits();
193         Self {
194             parent: parent,
195             range: 0..len,
196         }
197     }
198 
new_subset(parent: &'a mut BS, range: Range<usize>) -> Self199     pub fn new_subset(parent: &'a mut BS, range: Range<usize>) -> Self {
200         assert!(range.end <= parent.bits());
201         Self {
202             parent: parent,
203             range: range,
204         }
205     }
206 
subset_mut<'b>( &'b mut self, range: Range<usize>, ) -> BitMutView<'b, BitMutView<'a, BS>>207     pub fn subset_mut<'b>(
208         &'b mut self,
209         range: Range<usize>,
210     ) -> BitMutView<'b, BitMutView<'a, BS>> {
211         BitMutView::new_subset(self, range)
212     }
213 
range_in_parent(&self, range: Range<usize>) -> Range<usize>214     fn range_in_parent(&self, range: Range<usize>) -> Range<usize> {
215         let new_start = self.range.start + range.start;
216         let new_end = self.range.start + range.end;
217         assert!(new_end <= self.range.end);
218         new_start..new_end
219     }
220 
221     #[allow(dead_code)]
get_bit(&self, bit: usize) -> bool222     pub fn get_bit(&self, bit: usize) -> bool {
223         self.get_bit_range_u64(bit..(bit + 1)) != 0
224     }
225 
set_bit(&mut self, bit: usize, val: bool)226     pub fn set_bit(&mut self, bit: usize, val: bool) {
227         self.set_bit_range_u64(bit..(bit + 1), u64::from(val));
228     }
229 }
230 
231 impl<'a, BS: BitMutViewable + ?Sized> BitViewable for BitMutView<'a, BS> {
bits(&self) -> usize232     fn bits(&self) -> usize {
233         self.range.end - self.range.start
234     }
235 
get_bit_range_u64(&self, range: Range<usize>) -> u64236     fn get_bit_range_u64(&self, range: Range<usize>) -> u64 {
237         self.parent.get_bit_range_u64(self.range_in_parent(range))
238     }
239 }
240 
241 impl<'a, BS: BitMutViewable + ?Sized> BitMutViewable for BitMutView<'a, BS> {
set_bit_range_u64(&mut self, range: Range<usize>, val: u64)242     fn set_bit_range_u64(&mut self, range: Range<usize>, val: u64) {
243         self.parent
244             .set_bit_range_u64(self.range_in_parent(range), val);
245     }
246 }
247 
248 pub trait SetFieldU64 {
set_field_u64(&mut self, range: Range<usize>, val: u64)249     fn set_field_u64(&mut self, range: Range<usize>, val: u64);
250 }
251 
252 impl<'a, BS: BitMutViewable + ?Sized> SetFieldU64 for BitMutView<'a, BS> {
set_field_u64(&mut self, range: Range<usize>, val: u64)253     fn set_field_u64(&mut self, range: Range<usize>, val: u64) {
254         let bits = range.end - range.start;
255 
256         /* Check that it fits in the bitfield */
257         assert!((val & u64_mask_for_bits(bits)) == val);
258 
259         self.set_bit_range_u64(range, val);
260     }
261 }
262 
263 pub trait SetField<T> {
set_field(&mut self, range: Range<usize>, val: T)264     fn set_field(&mut self, range: Range<usize>, val: T);
265 }
266 
267 impl<T: SetFieldU64> SetField<u64> for T {
set_field(&mut self, range: Range<usize>, val: u64)268     fn set_field(&mut self, range: Range<usize>, val: u64) {
269         self.set_field_u64(range, val);
270     }
271 }
272 
273 impl<T: SetFieldU64> SetField<u32> for T {
set_field(&mut self, range: Range<usize>, val: u32)274     fn set_field(&mut self, range: Range<usize>, val: u32) {
275         self.set_field(range, u64::from(val));
276     }
277 }
278 
279 impl<T: SetFieldU64> SetField<u16> for T {
set_field(&mut self, range: Range<usize>, val: u16)280     fn set_field(&mut self, range: Range<usize>, val: u16) {
281         self.set_field(range, u64::from(val));
282     }
283 }
284 
285 impl<T: SetFieldU64> SetField<u8> for T {
set_field(&mut self, range: Range<usize>, val: u8)286     fn set_field(&mut self, range: Range<usize>, val: u8) {
287         self.set_field(range, u64::from(val));
288     }
289 }
290 
291 impl<T: SetFieldU64> SetField<bool> for T {
set_field(&mut self, range: Range<usize>, val: bool)292     fn set_field(&mut self, range: Range<usize>, val: bool) {
293         assert!(range.end == range.start + 1);
294         self.set_field(range, u64::from(val));
295     }
296 }
297 
298 pub trait SetBit {
set_bit(&mut self, bit: usize, val: bool)299     fn set_bit(&mut self, bit: usize, val: bool);
300 }
301 
302 impl<T: SetFieldU64> SetBit for T {
set_bit(&mut self, bit: usize, val: bool)303     fn set_bit(&mut self, bit: usize, val: bool) {
304         self.set_field(bit..(bit + 1), val);
305     }
306 }
307 
308 impl<T: SetFieldU64> SetField<i64> for T {
set_field(&mut self, range: Range<usize>, val: i64)309     fn set_field(&mut self, range: Range<usize>, val: i64) {
310         let bits = range.end - range.start;
311         let mask = u64_mask_for_bits(bits);
312 
313         /* It's easier to work with a u64 */
314         let val = val as u64;
315 
316         /* Check that it fits in the bitfield, taking sign into account */
317         let sign_mask = !(mask >> 1);
318         assert!((val & sign_mask) == 0 || (val & sign_mask) == sign_mask);
319 
320         self.set_field_u64(range, val & mask);
321     }
322 }
323 
324 impl<T: SetFieldU64> SetField<i32> for T {
set_field(&mut self, range: Range<usize>, val: i32)325     fn set_field(&mut self, range: Range<usize>, val: i32) {
326         self.set_field(range, i64::from(val));
327     }
328 }
329 
330 impl<T: SetFieldU64> SetField<i16> for T {
set_field(&mut self, range: Range<usize>, val: i16)331     fn set_field(&mut self, range: Range<usize>, val: i16) {
332         self.set_field(range, i64::from(val));
333     }
334 }
335 
336 impl<T: SetFieldU64> SetField<i8> for T {
set_field(&mut self, range: Range<usize>, val: i8)337     fn set_field(&mut self, range: Range<usize>, val: i8) {
338         self.set_field(range, i64::from(val));
339     }
340 }
341