1#![no_std]
2#![deny(missing_docs)]
3#![feature(const_mut_refs)]
4#![feature(const_trait_impl)]
5
6#[macro_export]
42macro_rules! bitfield {
43 ($(#[$attributes:meta])* $visibility:vis struct $name:ident($type:ty); $($fields:tt)*) => {
45 $(#[$attributes])*
46 $visibility struct $name(pub $type);
47
48 $crate::bitfield! {@impl_range struct $name($type)}
49 impl $name {
50 $crate::bitfield! {@fields @getter $($fields)*}
51 $crate::bitfield! {@fields @setter $($fields)*}
52 }
53 };
54
55 (@impl_range struct $name:ident($type:ty)) => {
57 impl<T> const $crate::BitRange<T> for $name
58 where
59 $type: ~const $crate::BitRange<T>
60 {
61 #[inline]
62 fn bits(&self, msb: usize, lsb: usize) -> T {
63 self.0.bits(msb, lsb)
64 }
65 }
66
67 impl<T> const $crate::BitRangeMut<T> for $name
68 where
69 $type: ~const $crate::BitRange<T> + ~const $crate::BitRangeMut<T>
70 {
71 #[inline]
72 fn set_bits(&mut self, msb: usize, lsb: usize, value: T) -> &mut Self {
73 self.0.set_bits(msb, lsb, value);
74 self
75 }
76 }
77 };
78
79 (@fields @$variant:tt $(#[$attributes:meta])* $visibility:vis $type:ty, $getter:tt, $setter:tt: $($exprs:expr),*; $($rest:tt)*) => {
81 $crate::bitfield! {@fields @$variant $(#[$attributes])* $visibility $type, _, _, $getter, $setter: $($exprs),*; $($rest)*}
82 };
83
84 (@fields @$variant:tt $(#[$attributes:meta])* $visibility:vis $type:ty, from $from:ty, $getter:tt, $setter:tt: $($exprs:expr),*; $($rest:tt)*) => {
86 $crate::bitfield! {@fields @$variant $(#[$attributes])* $visibility $type, $from, $type, $getter, $setter: $($exprs),*; $($rest)*}
87 };
88
89 (@fields @$variant:tt $(#[$attributes:meta])* $visibility:vis $type:ty, into $into:ty, $getter:tt, $setter:tt: $($exprs:expr),*; $($rest:tt)*) => {
91 $crate::bitfield! {@fields @$variant $(#[$attributes])* $visibility $type, $type, $into, $getter, $setter: $($exprs),*; $($rest)*}
92 };
93
94 (@fields @$variant:tt $(#[$attributes:meta])* $visibility:vis $type:ty, from into $from_into:ty, $getter:tt, $setter:tt: $($exprs:expr),*; $($rest:tt)*) => {
96 $crate::bitfield! {@fields @$variant $(#[$attributes])* $visibility $type, $from_into, $from_into, $getter, $setter: $($exprs),*; $($rest)*}
97 };
98
99 (@fields @$variant:tt $(#[$attributes:meta])* $visibility:vis $type:ty, from $from:ty, into $into:ty, $getter:tt, $setter:tt: $($exprs:expr),*; $($rest:tt)*) => {
101 $crate::bitfield! {@fields @$variant $(#[$attributes])* $visibility $type, $from, $into, $getter, $setter: $($exprs),*; $($rest)*}
102 };
103
104 (@fields @$variant:tt $(#[$attributes:meta])* $visibility:vis $type:ty, $from:tt, $into:tt, $getter:tt, $setter:tt: $($exprs:expr),*; $($rest:tt)*) => {
106 $crate::bitfield! {@field @$variant $(#[$attributes])* $visibility $type, $from, $into, $getter, $setter: $($exprs),*}
107 $crate::bitfield! {@fields @$variant $($rest)*}
108 };
109
110 (@fields @$variant:tt) => {};
112
113 (@field @$variant:tt $(#[$attributes:meta])* $visibility:vis $type:ty, $from:tt, $into:tt, $getter:ident, $setter:ident: $($exprs:expr),*) => {
115 $crate::bitfield! {@field @$variant $(#[$attributes])* $visibility $type, $from, $into, $getter, _: $($exprs),*}
116 $crate::bitfield! {@field @$variant $(#[$attributes])* $visibility $type, $from, $into, _, $setter: $($exprs),*}
117 };
118
119 (@field @getter $(#[$attributes:meta])* $visibility:vis $type:ty, _, _, $getter:ident, _: $msb:expr, $lsb:expr) => {
121 $(#[$attributes])*
122 $visibility const fn $getter(&self) -> $type {
123 use $crate::BitRange;
124 self.bits($msb, $lsb)
125 }
126 };
127
128 (@field @getter $(#[$attributes:meta])* $visibility:vis $type:ty, $from:ty, $into:ty, $getter:ident, _: $msb:expr, $lsb:expr) => {
130 $(#[$attributes])*
131 $visibility const fn $getter(&self) -> $into
132 where $into: ~const ::core::convert::From<$type>
133 {
134 use $crate::BitRange;
135 let raw_value: $type = self.bits($msb, $lsb);
136 let value: $into = <$into>::from(raw_value);
137 value
138 }
139 };
140
141 (@field @getter $(#[$attributes:meta])* $visibility:vis $type:ty, _, _, $getter:ident, _: $bit:expr) => {
143 $(#[$attributes])*
144 $visibility const fn $getter(&self) -> bool {
145 use $crate::Bit;
146 self.bit($bit)
147 }
148 };
149
150 (@field @getter $(#[$attributes:meta])* $visibility:vis $type:ty, $from:ty, $into:ty, $getter:ident, _: $bit:expr) => {
152 $(#[$attributes])*
153 $visibility const fn $getter(&self) -> $into
154 where $into: ~const ::core::convert::From<$type>
155 {
156 use $crate::Bit;
157 let raw_value: $type = self.bit($bit);
158 let value: $into = <$into>::from(raw_value);
159 value
160 }
161 };
162
163 (@field @getter $(#[$attributes:meta])* $visibility:vis $type:ty, $from:tt, $into:tt, _, $setter:ident: $($exprs:expr),*) => {};
165
166 (@field @setter $(#[$attributes:meta])* $visibility:vis $type:ty, _, _, _, $setter:ident: $msb:expr, $lsb:expr) => {
168 $(#[$attributes])*
169 $visibility const fn $setter(&mut self, value: $type) -> &mut Self {
170 use $crate::BitRangeMut;
171 self.set_bits($msb, $lsb, value)
172 }
173 };
174
175 (@field @setter $(#[$attributes:meta])* $visibility:vis $type:ty, $from:ty, $into:ty, _, $setter:ident: $msb:expr, $lsb:expr) => {
177 $(#[$attributes])*
178 $visibility const fn $setter(&mut self, value: $from) -> &mut Self
179 where $type: ~const ::core::convert::From<$from>
180 {
181 use $crate::BitRangeMut;
182 let raw_value: $type = <$type>::from(value);
183 self.set_bits($msb, $lsb, raw_value)
184 }
185 };
186
187 (@field @setter $(#[$attributes:meta])* $visibility:vis $type:ty, _, _, _, $setter:ident: $bit:expr) => {
189 $(#[$attributes])*
190 $visibility const fn $setter(&mut self, value: $type) -> &mut Self {
191 use $crate::BitMut;
192 self.set_bit($bit, value)
193 }
194 };
195
196 (@field @setter $(#[$attributes:meta])* $visibility:vis $type:ty, $from:ty, $into:ty, _, $setter:ident: $bit:expr) => {
198 $(#[$attributes])*
199 $visibility const fn $setter(&mut self, value: $from) -> &mut Self
200 where $type: ~const ::core::convert::From<$from>
201 {
202 use $crate::BitMut;
203 let raw_value: $type = <$type>::from(value);
204 self.set_bit($bit, raw_value)
205 }
206 };
207
208 (@field @setter $(#[$attributes:meta])* $visibility:vis $type:ty, $from:tt, $into:tt, $getter:ident, _: $($exprs:expr),*) => {};
210}
211
212#[const_trait]
214pub trait BitRange<V> {
215 fn bits(&self, msb: usize, lsb: usize) -> V;
217}
218
219#[const_trait]
221pub trait BitRangeMut<V>: BitRange<V> {
222 fn set_bits(&mut self, msb: usize, lsb: usize, value: V) -> &mut Self;
224}
225
226#[const_trait]
228pub trait Bit {
229 fn bit(&self, bit: usize) -> bool;
231}
232
233#[const_trait]
235pub trait BitMut: Bit {
236 fn set_bit(&mut self, bit: usize, value: bool) -> &mut Self;
238}
239
240impl<T: ~ const BitRange<u8>> const Bit for T {
241 fn bit(&self, bit: usize) -> bool {
242 self.bits(bit, bit) != 0
243 }
244}
245
246impl<T: ~ const BitRange<u8> + ~ const BitRangeMut<u8>> const BitMut for T {
247 fn set_bit(&mut self, bit: usize, value: bool) -> &mut Self {
248 self.set_bits(bit, bit, value as u8)
249 }
250}
251
252macro_rules! impl_bitrange {
253 ($variant:tt, ($storage_type:ty, $($rest:ty),*), ($($range_type:ty),*)) => {
255 impl_bitrange! {$variant, ($storage_type), ($($range_type),*)}
256 impl_bitrange! {$variant, ($($rest),*), ($($range_type),*)}
257 };
258
259 ($variant:tt, ($storage_type:ty), ($($range_type:ty),*)) => {
261 $(impl_bitrange! {$variant, $storage_type, $range_type})*
262 };
263
264 (uint, $storage_type:ty, $range_type:ty) => {
266 impl const BitRange<$range_type> for $storage_type {
267 #[inline]
268 fn bits(&self, msb: usize, lsb: usize) -> $range_type {
269 let msb = msb + 1;
271
272 let storage_bits = ::core::mem::size_of::<$storage_type>() * 8;
274 let range_bits = ::core::mem::size_of::<$range_type>() * 8;
275
276 assert!(lsb < storage_bits, "lsb is out of bounds for bit range");
278 assert!(msb <= storage_bits, "msb is out of bounds for bit range");
279 assert!(lsb <= msb, "lsb must not be greater than msb for bit range");
280 assert!((msb - lsb) <= range_bits, "value truncated in bit range operation");
281
282 (*self << (storage_bits - msb) >> (storage_bits - msb) >> lsb) as $range_type
284 }
285 }
286
287 impl const BitRangeMut<$range_type> for $storage_type {
288 #[inline]
289 fn set_bits(&mut self, msb: usize, lsb: usize, value: $range_type) -> &mut Self {
290 let msb = msb + 1;
292
293 let storage_bits = ::core::mem::size_of::<$storage_type>() * 8;
295
296 assert!(lsb < storage_bits, "lsb is out of bounds for bit range");
298 assert!(msb <= storage_bits, "msb is out of bounds for bit range");
299 assert!(lsb < msb, "lsb must not be greater than msb for bit range");
300
301 let new_value = value as $storage_type;
303 let dropped_bits = storage_bits - (msb - lsb);
304 assert!(
305 (new_value << dropped_bits >> dropped_bits) as $range_type == value,
306 "value truncated in bit range operation"
307 );
308
309 let mask = !((!0 as $storage_type) << (storage_bits - msb) >> (storage_bits - msb) >> lsb << lsb);
311
312 *self = (*self & mask) | (new_value << lsb);
314 self
315 }
316 }
317 };
318}
319
320impl_bitrange! {uint, (u8, u16, u32, u64, u128), (u8, u16, u32, u64, u128)}
321impl_bitrange! {uint, (u8, u16, u32, u64, u128), (i8, i16, i32, i64, i128)}