1 | #![no_std ] |
2 | #![deny ( |
3 | missing_docs, |
4 | unused_extern_crates, |
5 | unused_import_braces, |
6 | unused_qualifications |
7 | )] |
8 | |
9 | //! This crate provides macros to generate bitfield-like struct. |
10 | //! |
11 | //! See the documentation of the macros for how to use them. |
12 | //! |
13 | //! Examples and tests are also a great way to understand how to use these macros. |
14 | |
15 | /// Declares the fields of struct. |
16 | /// |
17 | /// This macro will generate the methods to access the fields of a bitfield. It must be called |
18 | /// from an `impl` block for a type that implements the `BitRange` and/or the `Bit` traits |
19 | /// (which traits are required depending on what type of fields are used). |
20 | /// |
21 | /// The syntax of this macro is composed of declarations ended by semicolons. There are two types |
22 | /// of declarations: default type, and fields. |
23 | /// |
24 | /// A default type is just a type followed by a semicolon. This will affect all the following field |
25 | /// declarations. |
26 | /// |
27 | /// A field declaration is composed of the following: |
28 | /// |
29 | /// * Optional attributes (`#[...]`), documentation comments (`///`) are attributes; |
30 | /// * An optional pub keyword to make the methods public |
31 | /// * An optional type followed by a comma |
32 | /// * Optionally, the word `into` followed by a type, followed by a comma |
33 | /// * The getter and setter idents, separated by a comma |
34 | /// * A colon |
35 | /// * One to three expressions of type `usize` |
36 | /// |
37 | /// The attributes and pub will be applied to the two methods generated. |
38 | /// |
39 | /// If the `into` part is used, the getter will convert the field after reading it. |
40 | /// |
41 | /// The getter and setter idents can be `_` to not generate one of the two. For example, if the |
42 | /// setter is `_`, the field will be read-only. |
43 | /// |
44 | /// The expressions at the end are the bit positions. Their meaning depends on the number of |
45 | /// expressions: |
46 | /// |
47 | /// * One expression: the field is a single bit. The type is ignored and `bool` is used. The trait |
48 | /// `Bit` is used. |
49 | /// * Two expressions: `msb, lsb`, the field is composed of the bits from `msb` to `lsb`, included. |
50 | /// * Three expressions: `msb, lsb, count`, the field is an array. The first element is composed of |
51 | /// the bits from `msb` to `lsb`. The following elements are consecutive bits range of the same |
52 | /// size. |
53 | /// |
54 | /// # Example |
55 | /// |
56 | /// ```rust |
57 | /// # #[macro_use ] extern crate bitfield; |
58 | /// # fn main() {} |
59 | /// # struct FooBar(u64); |
60 | /// # bitfield_bitrange!{struct FooBar(u64)} |
61 | /// # impl From<u32> for FooBar{ fn from(_: u32) -> FooBar {unimplemented!()}} |
62 | /// # impl From<FooBar> for u32{ fn from(_: FooBar) -> u32 {unimplemented!()}} |
63 | /// # impl FooBar { |
64 | /// bitfield_fields!{ |
65 | /// // The default type will be `u64 |
66 | /// u64; |
67 | /// // filed1 is read-write, public, the methods are inline |
68 | /// #[inline] |
69 | /// pub field1, set_field1: 10, 0; |
70 | /// // `field2` is read-only, private, and of type bool. |
71 | /// field2, _ : 0; |
72 | /// // `field3` will be read as an `u32` and then converted to `FooBar`. |
73 | /// // The setter is not affected, it still need an `u32` value. |
74 | /// u32, into FooBar, field3, set_field3: 10, 0; |
75 | /// // `field4` will be read as an `u32` and then converted to `FooBar`. |
76 | /// // The setter will take a `FooBar`, and converted back to an `u32`. |
77 | /// u32, from into FooBar, field4, set_field4: 10, 0; |
78 | /// } |
79 | /// # } |
80 | /// ``` |
81 | #[macro_export (local_inner_macros)] |
82 | macro_rules! bitfield_fields { |
83 | (@field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $from:ty, $into:ty, _, $setter:ident: $msb:expr, |
84 | $lsb:expr, $count:expr) => { |
85 | $(#[$attribute])* |
86 | #[allow(unknown_lints)] |
87 | #[allow(eq_op)] |
88 | $($vis)* fn $setter(&mut self, index: usize, value: $from) { |
89 | use $crate::BitRange; |
90 | __bitfield_debug_assert!(index < $count); |
91 | let width = $msb - $lsb + 1; |
92 | let lsb = $lsb + index*width; |
93 | let msb = lsb + width - 1; |
94 | self.set_bit_range(msb, lsb, $crate::Into::<$t>::into(value)); |
95 | } |
96 | }; |
97 | (@field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $from:ty, $into:ty, _, $setter:ident: $msb:expr, |
98 | $lsb:expr) => { |
99 | $(#[$attribute])* |
100 | $($vis)* fn $setter(&mut self, value: $from) { |
101 | use $crate::BitRange; |
102 | self.set_bit_range($msb, $lsb, $crate::Into::<$t>::into(value)); |
103 | } |
104 | }; |
105 | (@field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $from:ty, $into:ty, _, $setter:ident: $bit:expr) => { |
106 | $(#[$attribute])* |
107 | $($vis)* fn $setter(&mut self, value: bool) { |
108 | use $crate::Bit; |
109 | self.set_bit($bit, value); |
110 | } |
111 | }; |
112 | (@field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $from:ty, $into:ty, $getter:ident, _: $msb:expr, |
113 | $lsb:expr, $count:expr) => { |
114 | $(#[$attribute])* |
115 | #[allow(unknown_lints)] |
116 | #[allow(eq_op)] |
117 | $($vis)* fn $getter(&self, index: usize) -> $into { |
118 | use $crate::BitRange; |
119 | __bitfield_debug_assert!(index < $count); |
120 | let width = $msb - $lsb + 1; |
121 | let lsb = $lsb + index*width; |
122 | let msb = lsb + width - 1; |
123 | let raw_value: $t = self.bit_range(msb, lsb); |
124 | $crate::Into::into(raw_value) |
125 | } |
126 | }; |
127 | (@field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $from:ty, $into:ty, $getter:ident, _: $msb:expr, |
128 | $lsb:expr) => { |
129 | $(#[$attribute])* |
130 | $($vis)* fn $getter(&self) -> $into { |
131 | use $crate::BitRange; |
132 | let raw_value: $t = self.bit_range($msb, $lsb); |
133 | $crate::Into::into(raw_value) |
134 | } |
135 | }; |
136 | (@field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $from:ty, $into:ty, $getter:ident, _: $bit:expr) => { |
137 | $(#[$attribute])* |
138 | $($vis)* fn $getter(&self) -> bool { |
139 | use $crate::Bit; |
140 | self.bit($bit) |
141 | } |
142 | }; |
143 | (@field $(#[$attribute:meta])* ($($vis:tt)*) $t:ty, $from:ty, $into:ty, $getter:ident, $setter:ident: |
144 | $($exprs:expr),*) => { |
145 | bitfield_fields!(@field $(#[$attribute])* ($($vis)*) $t, $from, $into, $getter, _: $($exprs),*); |
146 | bitfield_fields!(@field $(#[$attribute])* ($($vis)*) $t, $from, $into, _, $setter: $($exprs),*); |
147 | }; |
148 | |
149 | ($t:ty;) => {}; |
150 | ($default_ty:ty; pub $($rest:tt)*) => { |
151 | bitfield_fields!{$default_ty; () pub $($rest)*} |
152 | }; |
153 | ($default_ty:ty; #[$attribute:meta] $($rest:tt)*) => { |
154 | bitfield_fields!{$default_ty; (#[$attribute]) $($rest)*} |
155 | }; |
156 | ($default_ty:ty; ($(#[$attributes:meta])*) #[$attribute:meta] $($rest:tt)*) => { |
157 | bitfield_fields!{$default_ty; ($(#[$attributes])* #[$attribute]) $($rest)*} |
158 | }; |
159 | ($default_ty:ty; ($(#[$attribute:meta])*) pub $t:ty, from into $into:ty, $getter:tt, $setter:tt: |
160 | $($exprs:expr),*; $($rest:tt)*) => { |
161 | bitfield_fields!{@field $(#[$attribute])* (pub) $t, $into, $into, $getter, $setter: $($exprs),*} |
162 | bitfield_fields!{$default_ty; $($rest)*} |
163 | }; |
164 | ($default_ty:ty; ($(#[$attribute:meta])*) pub $t:ty, into $into:ty, $getter:tt, $setter:tt: |
165 | $($exprs:expr),*; $($rest:tt)*) => { |
166 | bitfield_fields!{@field $(#[$attribute])* (pub) $t, $t, $into, $getter, $setter: $($exprs),*} |
167 | bitfield_fields!{$default_ty; $($rest)*} |
168 | }; |
169 | ($default_ty:ty; ($(#[$attribute:meta])*) pub $t:ty, $getter:tt, $setter:tt: $($exprs:expr),*; |
170 | $($rest:tt)*) => { |
171 | bitfield_fields!{@field $(#[$attribute])* (pub) $t, $t, $t, $getter, $setter: $($exprs),*} |
172 | bitfield_fields!{$default_ty; $($rest)*} |
173 | }; |
174 | ($default_ty:ty; ($(#[$attribute:meta])*) pub from into $into:ty, $getter:tt, $setter:tt: |
175 | $($exprs:expr),*; $($rest:tt)*) => { |
176 | bitfield_fields!{@field $(#[$attribute])* (pub) $default_ty, $into, $into, $getter, $setter: |
177 | $($exprs),*} |
178 | bitfield_fields!{$default_ty; $($rest)*} |
179 | }; |
180 | ($default_ty:ty; ($(#[$attribute:meta])*) pub into $into:ty, $getter:tt, $setter:tt: |
181 | $($exprs:expr),*; $($rest:tt)*) => { |
182 | bitfield_fields!{@field $(#[$attribute])* (pub) $default_ty, $default_ty, $into, $getter, $setter: |
183 | $($exprs),*} |
184 | bitfield_fields!{$default_ty; $($rest)*} |
185 | }; |
186 | ($default_ty:ty; ($(#[$attribute:meta])*) pub $getter:tt, $setter:tt: $($exprs:expr),*; |
187 | $($rest:tt)*) => { |
188 | bitfield_fields!{@field $(#[$attribute])* (pub) $default_ty, $default_ty, $default_ty, $getter, $setter: |
189 | $($exprs),*} |
190 | bitfield_fields!{$default_ty; $($rest)*} |
191 | }; |
192 | |
193 | ($default_ty:ty; ($(#[$attribute:meta])*) $t:ty, from into $into:ty, $getter:tt, $setter:tt: |
194 | $($exprs:expr),*; $($rest:tt)*) => { |
195 | bitfield_fields!{@field $(#[$attribute])* () $t, $into, $into, $getter, $setter: $($exprs),*} |
196 | bitfield_fields!{$default_ty; $($rest)*} |
197 | }; |
198 | |
199 | ($default_ty:ty; ($(#[$attribute:meta])*) $t:ty, into $into:ty, $getter:tt, $setter:tt: |
200 | $($exprs:expr),*; $($rest:tt)*) => { |
201 | bitfield_fields!{@field $(#[$attribute])* () $t, $t, $into, $getter, $setter: $($exprs),*} |
202 | bitfield_fields!{$default_ty; $($rest)*} |
203 | }; |
204 | |
205 | ($default_ty:ty; ($(#[$attribute:meta])*) $t:ty, $getter:tt, $setter:tt: $($exprs:expr),*; |
206 | $($rest:tt)*) => { |
207 | bitfield_fields!{@field $(#[$attribute])* () $t, $t, $t, $getter, $setter: $($exprs),*} |
208 | bitfield_fields!{$default_ty; $($rest)*} |
209 | }; |
210 | ($default_ty:ty; ($(#[$attribute:meta])*) from into $into:ty, $getter:tt, $setter:tt: |
211 | $($exprs:expr),*; $($rest:tt)*) => { |
212 | bitfield_fields!{@field $(#[$attribute])* () $default_ty, $into, $into, $getter, $setter: |
213 | $($exprs),*} |
214 | bitfield_fields!{$default_ty; $($rest)*} |
215 | }; |
216 | ($default_ty:ty; ($(#[$attribute:meta])*) into $into:ty, $getter:tt, $setter:tt: |
217 | $($exprs:expr),*; $($rest:tt)*) => { |
218 | bitfield_fields!{@field $(#[$attribute])* () $default_ty, $default_ty, $into, $getter, $setter: |
219 | $($exprs),*} |
220 | bitfield_fields!{$default_ty; $($rest)*} |
221 | }; |
222 | ($default_ty:ty; ($(#[$attribute:meta])*) $getter:tt, $setter:tt: $($exprs:expr),*; |
223 | $($rest:tt)*) => { |
224 | bitfield_fields!{@field $(#[$attribute])* () $default_ty, $default_ty, $default_ty, $getter, $setter: |
225 | $($exprs),*} |
226 | bitfield_fields!{$default_ty; $($rest)*} |
227 | }; |
228 | ($previous_default_ty:ty; $default_ty:ty; $($rest:tt)*) => { |
229 | bitfield_fields!{$default_ty; $($rest)*} |
230 | }; |
231 | ($default_ty:ty; $($rest:tt)*) => { |
232 | bitfield_fields!{$default_ty; () $($rest)*} |
233 | }; |
234 | ($($rest:tt)*) => { |
235 | bitfield_fields!{SET_A_DEFAULT_TYPE_OR_SPECIFY_THE_TYPE_FOR_EACH_FIELDS; $($rest)*} |
236 | } |
237 | } |
238 | |
239 | /// Generates a `fmt::Debug` implementation. |
240 | /// |
241 | /// This macros must be called from a `impl Debug for ...` block. It will generate the `fmt` method. |
242 | /// |
243 | /// In most of the case, you will not directly call this macros, but use `bitfield`. |
244 | /// |
245 | /// The syntax is `struct TheNameOfTheStruct` followed by the syntax of `bitfield_fields`. |
246 | /// |
247 | /// The write-only fields are ignored. |
248 | /// |
249 | /// # Example |
250 | /// |
251 | /// ```rust |
252 | /// # #[macro_use ] extern crate bitfield; |
253 | /// struct FooBar(u32); |
254 | /// bitfield_bitrange!{struct FooBar(u32)} |
255 | /// impl FooBar{ |
256 | /// bitfield_fields!{ |
257 | /// u32; |
258 | /// field1, _: 7, 0; |
259 | /// field2, _: 31, 24; |
260 | /// } |
261 | /// } |
262 | /// |
263 | /// impl std::fmt::Debug for FooBar { |
264 | /// bitfield_debug!{ |
265 | /// struct FooBar; |
266 | /// field1, _: 7, 0; |
267 | /// field2, _: 31, 24; |
268 | /// } |
269 | /// } |
270 | /// |
271 | /// fn main() { |
272 | /// let foobar = FooBar(0x11223344); |
273 | /// println!("{:?}" , foobar); |
274 | |
275 | /// } |
276 | /// ``` |
277 | #[macro_export (local_inner_macros)] |
278 | macro_rules! bitfield_debug { |
279 | (struct $name:ident; $($rest:tt)*) => { |
280 | fn fmt(&self, f: &mut $crate::fmt::Formatter) -> $crate::fmt::Result { |
281 | let mut debug_struct = f.debug_struct(__bitfield_stringify!($name)); |
282 | debug_struct.field(".0" , &self.0); |
283 | bitfield_debug!{debug_struct, self, $($rest)*} |
284 | debug_struct.finish() |
285 | } |
286 | }; |
287 | ($debug_struct:ident, $self:ident, #[$attribute:meta] $($rest:tt)*) => { |
288 | bitfield_debug!{$debug_struct, $self, $($rest)*} |
289 | }; |
290 | ($debug_struct:ident, $self:ident, pub $($rest:tt)*) => { |
291 | bitfield_debug!{$debug_struct, $self, $($rest)*} |
292 | }; |
293 | ($debug_struct:ident, $self:ident, _, $setter:tt: $($exprs:expr),*; $($rest:tt)*) => { |
294 | bitfield_debug!{$debug_struct, $self, $($rest)*} |
295 | }; |
296 | ($debug_struct:ident, $self:ident, $type:ty; $($rest:tt)*) => { |
297 | bitfield_debug!{$debug_struct, $self, $($rest)*} |
298 | }; |
299 | ($debug_struct:ident, $self:ident, $getter:ident, $setter:tt: $msb:expr, $lsb:expr, $count:expr; |
300 | $($rest:tt)*) => { |
301 | let mut array = [$self.$getter(0); $count]; |
302 | for (i, e) in (&mut array).into_iter().enumerate() { |
303 | *e = $self.$getter(i); |
304 | } |
305 | $debug_struct.field(__bitfield_stringify!($getter), &array); |
306 | bitfield_debug!{$debug_struct, $self, $($rest)*} |
307 | }; |
308 | ($debug_struct:ident, $self:ident, $getter:ident, $setter:tt: $($exprs:expr),*; $($rest:tt)*) |
309 | => { |
310 | $debug_struct.field(__bitfield_stringify!($getter), &$self.$getter()); |
311 | bitfield_debug!{$debug_struct, $self, $($rest)*} |
312 | }; |
313 | ($debug_struct:ident, $self:ident, from into $into:ty, $($rest:tt)*) => { |
314 | bitfield_debug!{$debug_struct, $self, $($rest)*} |
315 | }; |
316 | ($debug_struct:ident, $self:ident, into $into:ty, $($rest:tt)*) => { |
317 | bitfield_debug!{$debug_struct, $self, $($rest)*} |
318 | }; |
319 | ($debug_struct:ident, $self:ident, $type:ty, $($rest:tt)*) => { |
320 | bitfield_debug!{$debug_struct, $self, $($rest)*} |
321 | }; |
322 | ($debug_struct:ident, $self:ident, ) => {}; |
323 | } |
324 | |
325 | /// Implements `BitRange` for a tuple struct (or "newtype"). |
326 | /// |
327 | /// This macro will generate an implementation of the `BitRange` trait for an existing single |
328 | /// element tuple struct. |
329 | /// |
330 | /// The syntax is more or less the same as declaring a "newtype", **without** the attributes, |
331 | /// documentation comments and pub keyword. |
332 | /// |
333 | /// The difference with a normal "newtype" is the type in parentheses. If the type is `[t]` (where |
334 | /// `t` is any of the unsigned integer type), the "newtype" will be generic and implement |
335 | /// `BitRange` for `T: AsMut<[t]> + AsRef<[t]>` (for example a slice, an array or a `Vec`). You can |
336 | /// also use `MSB0 [t]`. The difference will be the positions of the bit. You can use the |
337 | /// `bits_positions` example to see where each bits is. If the type is neither of this two, the |
338 | /// "newtype" will wrap a value of the specified type and implements `BitRange` the same ways as |
339 | /// the wrapped type. |
340 | /// |
341 | /// # Examples |
342 | /// |
343 | /// ```rust |
344 | /// # #[macro_use ] extern crate bitfield; |
345 | /// # fn main() {} |
346 | /// struct BitField1(u32); |
347 | /// bitfield_bitrange!{struct BitField1(u32)} |
348 | /// |
349 | /// struct BitField2<T>(T); |
350 | /// bitfield_bitrange!{struct BitField2([u8])} |
351 | /// |
352 | /// struct BitField3<T>(T); |
353 | /// bitfield_bitrange!{struct BitField3(MSB0 [u8])} |
354 | /// ``` |
355 | /// |
356 | #[macro_export (local_inner_macros)] |
357 | macro_rules! bitfield_bitrange { |
358 | (@impl_bitrange_slice $name:ident, $slice_ty:ty, $bitrange_ty:ty) => { |
359 | impl<T: AsMut<[$slice_ty]> + AsRef<[$slice_ty]>> $crate::BitRange<$bitrange_ty> |
360 | for $name<T> { |
361 | fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty { |
362 | let bit_len = $crate::size_of::<$slice_ty>()*8; |
363 | let value_bit_len = $crate::size_of::<$bitrange_ty>()*8; |
364 | let mut value = 0; |
365 | for i in (lsb..=msb).rev() { |
366 | value <<= 1; |
367 | value |= ((self.0.as_ref()[i/bit_len] >> (i%bit_len)) & 1) as $bitrange_ty; |
368 | } |
369 | value << (value_bit_len - (msb - lsb + 1)) >> (value_bit_len - (msb - lsb + 1)) |
370 | } |
371 | |
372 | fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) { |
373 | let bit_len = $crate::size_of::<$slice_ty>()*8; |
374 | let mut value = value; |
375 | for i in lsb..=msb { |
376 | self.0.as_mut()[i/bit_len] &= !(1 << (i%bit_len)); |
377 | self.0.as_mut()[i/bit_len] |= (value & 1) as $slice_ty << (i%bit_len); |
378 | value >>= 1; |
379 | } |
380 | } |
381 | } |
382 | }; |
383 | (@impl_bitrange_slice_msb0 $name:ident, $slice_ty:ty, $bitrange_ty:ty) => { |
384 | impl<T: AsMut<[$slice_ty]> + AsRef<[$slice_ty]>> $crate::BitRange<$bitrange_ty> |
385 | for $name<T> { |
386 | fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty { |
387 | let bit_len = $crate::size_of::<$slice_ty>()*8; |
388 | let value_bit_len = $crate::size_of::<$bitrange_ty>()*8; |
389 | let mut value = 0; |
390 | for i in lsb..=msb { |
391 | value <<= 1; |
392 | value |= ((self.0.as_ref()[i/bit_len] >> (bit_len - i%bit_len - 1)) & 1) |
393 | as $bitrange_ty; |
394 | } |
395 | value << (value_bit_len - (msb - lsb + 1)) >> (value_bit_len - (msb - lsb + 1)) |
396 | } |
397 | |
398 | fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) { |
399 | let bit_len = $crate::size_of::<$slice_ty>()*8; |
400 | let mut value = value; |
401 | for i in (lsb..=msb).rev() { |
402 | self.0.as_mut()[i/bit_len] &= !(1 << (bit_len - i%bit_len - 1)); |
403 | self.0.as_mut()[i/bit_len] |= (value & 1) as $slice_ty |
404 | << (bit_len - i%bit_len - 1); |
405 | value >>= 1; |
406 | } |
407 | } |
408 | } |
409 | }; |
410 | (struct $name:ident([$t:ty])) => { |
411 | bitfield_bitrange!(@impl_bitrange_slice $name, $t, u8); |
412 | bitfield_bitrange!(@impl_bitrange_slice $name, $t, u16); |
413 | bitfield_bitrange!(@impl_bitrange_slice $name, $t, u32); |
414 | bitfield_bitrange!(@impl_bitrange_slice $name, $t, u64); |
415 | bitfield_bitrange!(@impl_bitrange_slice $name, $t, u128); |
416 | bitfield_bitrange!(@impl_bitrange_slice $name, $t, i8); |
417 | bitfield_bitrange!(@impl_bitrange_slice $name, $t, i16); |
418 | bitfield_bitrange!(@impl_bitrange_slice $name, $t, i32); |
419 | bitfield_bitrange!(@impl_bitrange_slice $name, $t, i64); |
420 | bitfield_bitrange!(@impl_bitrange_slice $name, $t, i128); |
421 | }; |
422 | (struct $name:ident(MSB0 [$t:ty])) => { |
423 | bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u8); |
424 | bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u16); |
425 | bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u32); |
426 | bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u64); |
427 | bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u128); |
428 | bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i8); |
429 | bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i16); |
430 | bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i32); |
431 | bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i64); |
432 | bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i128); |
433 | }; |
434 | (struct $name:ident($t:ty)) => { |
435 | impl<T> $crate::BitRange<T> for $name where $t: $crate::BitRange<T> { |
436 | fn bit_range(&self, msb: usize, lsb: usize) -> T { |
437 | self.0.bit_range(msb, lsb) |
438 | } |
439 | fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T) { |
440 | self.0.set_bit_range(msb, lsb, value); |
441 | } |
442 | } |
443 | }; |
444 | } |
445 | |
446 | /// Combines `bitfield_bitrange` and `bitfield_fields`. |
447 | /// |
448 | /// The syntax of this macro is the syntax of a tuple struct, including attributes and |
449 | /// documentation comments, followed by a semicolon, some optional elements, and finally the fields |
450 | /// as described in the `bitfield_fields` documentation. |
451 | /// |
452 | /// The first optional element is `no default BitRange;`. With that, no implementation of |
453 | /// `BitRange` will be generated. |
454 | /// |
455 | /// The second optional element is `impl Debug;`. This will generate an implementation of |
456 | /// `fmt::Debug` with the `bitfield_debug` macro. |
457 | /// |
458 | /// The difference with calling those macros separately is that `bitfield_fields` is called |
459 | /// from an appropriate `impl` block. If you use the non-slice form of `bitfield_bitrange`, the |
460 | /// default type for `bitfield_fields` will be set to the wrapped fields. |
461 | /// |
462 | /// See the documentation of these macros for more information on their respective syntax. |
463 | /// |
464 | /// # Example |
465 | /// |
466 | /// ```rust |
467 | /// # #[macro_use ] extern crate bitfield; |
468 | /// # fn main() {} |
469 | /// bitfield!{ |
470 | /// pub struct BitField1(u16); |
471 | /// impl Debug; |
472 | /// // The fields default to u16 |
473 | /// field1, set_field1: 10, 0; |
474 | /// pub field2, _ : 12, 3; |
475 | /// } |
476 | /// ``` |
477 | /// |
478 | /// or with a custom `BitRange` implementation : |
479 | /// ```rust |
480 | /// # #[macro_use ] extern crate bitfield; |
481 | /// # use bitfield::BitRange; |
482 | /// # fn main() {} |
483 | /// bitfield!{ |
484 | /// pub struct BitField1(u16); |
485 | /// no default BitRange; |
486 | /// impl Debug; |
487 | /// u8; |
488 | /// field1, set_field1: 10, 0; |
489 | /// pub field2, _ : 12, 3; |
490 | /// } |
491 | /// impl BitRange<u8> for BitField1 { |
492 | /// fn bit_range(&self, msb: usize, lsb: usize) -> u8 { |
493 | /// let width = msb - lsb + 1; |
494 | /// let mask = (1 << width) - 1; |
495 | /// ((self.0 >> lsb) & mask) as u8 |
496 | /// } |
497 | /// fn set_bit_range(&mut self, msb: usize, lsb: usize, value: u8) { |
498 | /// self.0 = (value as u16) << lsb; |
499 | /// } |
500 | /// } |
501 | /// ``` |
502 | #[macro_export (local_inner_macros)] |
503 | macro_rules! bitfield { |
504 | ($(#[$attribute:meta])* pub struct $($rest:tt)*) => { |
505 | bitfield!($(#[$attribute])* (pub) struct $($rest)*); |
506 | }; |
507 | ($(#[$attribute:meta])* struct $($rest:tt)*) => { |
508 | bitfield!($(#[$attribute])* () struct $($rest)*); |
509 | }; |
510 | // Force `impl Debug` to always be after `no default BitRange` it the two are present. |
511 | // This simplify the rest of the macro. |
512 | ($(#[$attribute:meta])* ($($vis:tt)*) struct $name:ident($($type:tt)*); impl Debug; no default BitRange; $($rest:tt)*) => { |
513 | bitfield!{$(#[$attribute])* ($($vis)*) struct $name($($type)*); no default BitRange; impl Debug; $($rest)*} |
514 | }; |
515 | |
516 | // If we have `impl Debug` without `no default BitRange`, we will still match, because when |
517 | // we call `bitfield_bitrange`, we add `no default BitRange`. |
518 | ($(#[$attribute:meta])* ($($vis:tt)*) struct $name:ident([$t:ty]); no default BitRange; impl Debug; $($rest:tt)*) => { |
519 | impl<T: AsMut<[$t]> + AsRef<[$t]> + $crate::fmt::Debug> $crate::fmt::Debug for $name<T> { |
520 | bitfield_debug!{struct $name; $($rest)*} |
521 | } |
522 | |
523 | bitfield!{$(#[$attribute])* ($($vis)*) struct $name([$t]); no default BitRange; $($rest)*} |
524 | }; |
525 | ($(#[$attribute:meta])* ($($vis:tt)*) struct $name:ident([$t:ty]); no default BitRange; $($rest:tt)*) => { |
526 | $(#[$attribute])* |
527 | $($vis)* struct $name<T>(pub T); |
528 | |
529 | impl<T: AsMut<[$t]> + AsRef<[$t]>> $name<T> { |
530 | bitfield_fields!{$($rest)*} |
531 | } |
532 | }; |
533 | ($(#[$attribute:meta])* ($($vis:tt)*) struct $name:ident([$t:ty]); $($rest:tt)*) => { |
534 | bitfield_bitrange!(struct $name([$t])); |
535 | bitfield!{$(#[$attribute])* ($($vis)*) struct $name([$t]); no default BitRange; $($rest)*} |
536 | }; |
537 | |
538 | // The only difference between the MSB0 version anf the non-MSB0 version, is the BitRange |
539 | // implementation. We delegate everything else to the non-MSB0 version of the macro. |
540 | ($(#[$attribute:meta])* ($($vis:tt)*) struct $name:ident(MSB0 [$t:ty]); no default BitRange; $($rest:tt)*) => { |
541 | bitfield!{$(#[$attribute])* ($($vis)*) struct $name([$t]); no default BitRange; $($rest)*} |
542 | }; |
543 | ($(#[$attribute:meta])* ($($vis:tt)*) struct $name:ident(MSB0 [$t:ty]); $($rest:tt)*) => { |
544 | bitfield_bitrange!(struct $name(MSB0 [$t])); |
545 | bitfield!{$(#[$attribute])* ($($vis)*) struct $name([$t]); no default BitRange; $($rest)*} |
546 | }; |
547 | |
548 | ($(#[$attribute:meta])* ($($vis:tt)*) struct $name:ident($t:ty); no default BitRange; impl Debug; $($rest:tt)*) => { |
549 | impl $crate::fmt::Debug for $name { |
550 | bitfield_debug!{struct $name; $($rest)*} |
551 | } |
552 | |
553 | bitfield!{$(#[$attribute])* ($($vis)*) struct $name($t); no default BitRange; $($rest)*} |
554 | }; |
555 | ($(#[$attribute:meta])* ($($vis:tt)*) struct $name:ident($t:ty); no default BitRange; $($rest:tt)*) => { |
556 | $(#[$attribute])* |
557 | $($vis)* struct $name(pub $t); |
558 | |
559 | impl $name { |
560 | bitfield_fields!{$t; $($rest)*} |
561 | } |
562 | }; |
563 | ($(#[$attribute:meta])* ($($vis:tt)*) struct $name:ident($t:ty); $($rest:tt)*) => { |
564 | bitfield_bitrange!(struct $name($t)); |
565 | bitfield!{$(#[$attribute])* ($($vis)*) struct $name($t); no default BitRange; $($rest)*} |
566 | }; |
567 | } |
568 | |
569 | #[doc (hidden)] |
570 | pub use core::convert::Into; |
571 | #[doc (hidden)] |
572 | pub use core::fmt; |
573 | #[doc (hidden)] |
574 | pub use core::mem::size_of; |
575 | |
576 | /// A trait to get or set ranges of bits. |
577 | pub trait BitRange<T> { |
578 | /// Get a range of bits. |
579 | fn bit_range(&self, msb: usize, lsb: usize) -> T; |
580 | /// Set a range of bits. |
581 | fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T); |
582 | } |
583 | |
584 | /// A trait to get or set a single bit. |
585 | /// |
586 | /// This trait is implemented for all type that implement `BitRange<u8>`. |
587 | pub trait Bit { |
588 | /// Get a single bit. |
589 | fn bit(&self, bit: usize) -> bool; |
590 | |
591 | /// Set a single bit. |
592 | fn set_bit(&mut self, bit: usize, value: bool); |
593 | } |
594 | |
595 | impl<T: BitRange<u8>> Bit for T { |
596 | fn bit(&self, bit: usize) -> bool { |
597 | self.bit_range(msb:bit, lsb:bit) != 0 |
598 | } |
599 | fn set_bit(&mut self, bit: usize, value: bool) { |
600 | self.set_bit_range(msb:bit, lsb:bit, value as u8); |
601 | } |
602 | } |
603 | |
604 | macro_rules! impl_bitrange_for_u { |
605 | ($t:ty, $bitrange_ty:ty) => { |
606 | impl BitRange<$bitrange_ty> for $t { |
607 | #[inline] |
608 | #[allow(unknown_lints)] |
609 | #[allow(cast_lossless)] |
610 | fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty { |
611 | let bit_len = size_of::<$t>()*8; |
612 | let result_bit_len = size_of::<$bitrange_ty>()*8; |
613 | let result = ((*self << (bit_len - msb - 1)) >> (bit_len - msb - 1 + lsb)) |
614 | as $bitrange_ty; |
615 | result << (result_bit_len - (msb - lsb + 1)) >> (result_bit_len - (msb - lsb + 1)) |
616 | } |
617 | |
618 | #[inline] |
619 | #[allow(unknown_lints)] |
620 | #[allow(cast_lossless)] |
621 | fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) { |
622 | let bit_len = size_of::<$t>()*8; |
623 | let mask: $t = !(0 as $t) |
624 | << (bit_len - msb - 1) |
625 | >> (bit_len - msb - 1 + lsb) |
626 | << (lsb); |
627 | *self &= !mask; |
628 | *self |= (value as $t << lsb) & mask; |
629 | } |
630 | } |
631 | } |
632 | } |
633 | |
634 | macro_rules! impl_bitrange_for_u_combinations { |
635 | ((),($($bitrange_ty:ty),*)) => { |
636 | |
637 | }; |
638 | (($t:ty),($($bitrange_ty:ty),*)) => { |
639 | $(impl_bitrange_for_u!{$t, $bitrange_ty})* |
640 | }; |
641 | (($t_head:ty, $($t_rest:ty),*),($($bitrange_ty:ty),*)) => { |
642 | impl_bitrange_for_u_combinations!{($t_head), ($($bitrange_ty),*)} |
643 | impl_bitrange_for_u_combinations!{($($t_rest),*), ($($bitrange_ty),*)} |
644 | }; |
645 | } |
646 | |
647 | impl_bitrange_for_u_combinations! {(u8, u16, u32, u64, u128), (u8, u16, u32, u64, u128)} |
648 | impl_bitrange_for_u_combinations! {(u8, u16, u32, u64, u128), (i8, i16, i32, i64, i128)} |
649 | |
650 | // Same as std::stringify but callable from local_inner_macros macros defined inside |
651 | // this crate. |
652 | #[macro_export ] |
653 | #[doc (hidden)] |
654 | macro_rules! __bitfield_stringify { |
655 | ($s:ident) => { |
656 | stringify!($s) |
657 | }; |
658 | } |
659 | |
660 | // Same as std::debug_assert but callable from local_inner_macros macros defined inside |
661 | // this crate. |
662 | #[macro_export ] |
663 | #[doc (hidden)] |
664 | macro_rules! __bitfield_debug_assert { |
665 | ($e:expr) => { |
666 | debug_assert!($e) |
667 | }; |
668 | } |
669 | |