1use std::convert::Infallible;
10use std::marker::PhantomData;
11
12use crate::fields::ControlKind;
13
14pub trait Packed: Sized {
19 const MAX_BITS: u32;
22
23 const DECODE_BITS: u32 = Self::MAX_BITS;
28
29 const CONTROL: ControlKind = ControlKind::Number;
36
37 type Error;
39
40 fn from_bits(bits: u64) -> Result<Self, Self::Error>;
42
43 fn to_bits(&self) -> u64;
45}
46
47pub const fn bits_for(max: u64) -> u32 {
49 64 - max.leading_zeros()
50}
51
52impl Packed for bool {
53 const MAX_BITS: u32 = 1;
54 const DECODE_BITS: u32 = 1;
55 const CONTROL: ControlKind = ControlKind::Toggle;
56 type Error = Infallible;
57
58 fn from_bits(bits: u64) -> Result<Self, Infallible> {
59 Ok(bits != 0)
60 }
61
62 fn to_bits(&self) -> u64 {
63 *self as u64
64 }
65}
66
67macro_rules! impl_packed_uint {
68 ($($t:ty),* $(,)?) => { $(
69 impl Packed for $t {
70 const MAX_BITS: u32 = <$t>::BITS;
71 const DECODE_BITS: u32 = <$t>::BITS;
72 type Error = Infallible;
73
74 fn from_bits(bits: u64) -> Result<Self, Infallible> {
75 Ok(bits as $t)
76 }
77
78 fn to_bits(&self) -> u64 {
79 *self as u64
80 }
81 }
82 )* };
83}
84
85impl_packed_uint!(u8, u16, u32, u64);
86
87const fn extract(raw: &[u8], lo: u32, hi: u32) -> u64 {
89 let mut bits = 0;
90 let mut i = lo;
91 while i <= hi {
92 bits = (bits << 1) | ((raw[(i / 8) as usize] >> (7 - i % 8)) & 1) as u64;
93 i += 1;
94 }
95 bits
96}
97
98fn splice(raw: &mut [u8], lo: u32, hi: u32, bits: u64) {
101 for (n, i) in (lo..=hi).enumerate() {
102 let mask = 1u8 << (7 - i % 8);
103 let set = (bits >> (hi - lo - n as u32)) & 1 != 0;
104 let byte = &mut raw[(i / 8) as usize];
105 *byte = if set { *byte | mask } else { *byte & !mask };
106 }
107}
108
109pub struct Field<T, const LO: u32, const HI: u32>(PhantomData<fn() -> T>);
142
143struct SpanFits<const N: usize, const HI: u32>;
145
146impl<const N: usize, const HI: u32> SpanFits<N, HI> {
147 const OK: () = assert!(((HI / 8) as usize) < N, "bit field extends past the panel");
148}
149
150impl<T: Packed, const LO: u32, const HI: u32> Field<T, LO, HI> {
151 pub const WIDTH: u32 = {
153 assert!(HI >= LO, "a bit range must not end before it starts");
154 assert!(HI - LO < 64, "a bit field cannot be wider than u64");
155 HI - LO + 1
156 };
157
158 const FITS: () = assert!(
160 T::MAX_BITS <= Self::WIDTH,
161 "this type can hold values wider than the field; give this field a type that \
162 carries its range",
163 );
164
165 const COHERENT: () = assert!(
167 T::MAX_BITS <= T::DECODE_BITS,
168 "this type claims more value bits than it can decode",
169 );
170
171 const READS: () = assert!(
173 Self::WIDTH <= T::DECODE_BITS,
174 "this field is wider than its type; decoding it would discard high bits",
175 );
176
177 pub fn get<const N: usize>(raw: &[u8; N]) -> Result<T, T::Error> {
179 let () = Self::COHERENT;
180 let () = Self::READS;
181 let () = SpanFits::<N, HI>::OK;
182 T::from_bits(extract(raw, LO, HI))
183 }
184
185 pub fn set<const N: usize>(raw: &mut [u8; N], value: T) {
190 let () = Self::COHERENT;
191 let () = Self::READS;
192 let () = Self::FITS;
193 let () = SpanFits::<N, HI>::OK;
194 splice(raw, LO, HI, value.to_bits());
195 }
196}
197
198impl<T: Packed<Error = Infallible>, const LO: u32, const HI: u32> Field<T, LO, HI> {
199 pub fn read<const N: usize>(raw: &[u8; N]) -> T {
201 match Self::get(raw) {
202 Ok(value) => value,
203 Err(never) => match never {},
204 }
205 }
206}
207
208#[cfg(test)]
209mod tests {
210 use super::*;
211
212 #[derive(Debug, PartialEq, Eq)]
214 struct Small<const BITS: u32>(u8);
215
216 impl<const BITS: u32> Packed for Small<BITS> {
217 const MAX_BITS: u32 = BITS;
218 const DECODE_BITS: u32 = u8::BITS;
219 type Error = Infallible;
220
221 fn from_bits(bits: u64) -> Result<Self, Infallible> {
222 Ok(Small(bits as u8))
223 }
224
225 fn to_bits(&self) -> u64 {
226 self.0 as u64
227 }
228 }
229
230 type Nibble = Field<Small<4>, 4, 7>;
232 type Byte = Field<u8, 8, 15>;
233 type Flag = Field<bool, 11, 11>;
234
235 #[test]
236 fn a_field_reads_only_its_own_bits() {
237 assert_eq!(Nibble::read(&[0xab, 0xcd]), Small(0xb));
238 assert_eq!(Byte::read(&[0xab, 0xcd]), 0xcd);
239 assert!(Flag::read(&[0x00, 0x10]));
240 assert!(!Flag::read(&[0xff, 0xef]));
241 }
242
243 #[test]
244 fn a_write_disturbs_no_other_bit() {
245 let mut raw = [0xab, 0xcd];
246 Nibble::set(&mut raw, Small(0x3));
247 assert_eq!(raw, [0xa3, 0xcd]);
248
249 let mut raw = [0b1010_1010];
250 Field::<bool, 3, 3>::set(&mut raw, true);
251 assert_eq!(raw, [0b1011_1010]);
252 Field::<bool, 3, 3>::set(&mut raw, false);
253 assert_eq!(raw, [0b1010_1010]);
254 }
255
256 #[test]
259 fn a_field_may_span_bytes() {
260 type Spanning = Field<Small<7>, 5, 11>;
263 assert_eq!(Spanning::WIDTH, 7);
264 assert_eq!(
265 Spanning::read(&[0b0000_0101, 0b1101_0000]),
266 Small(0b101_1101)
267 );
268 assert_eq!(Spanning::read(&[0, 0]), Small(0));
269
270 let mut raw = [0b1111_1000, 0b0000_1111];
271 Spanning::set(&mut raw, Small(0b101_1101));
272 assert_eq!(raw, [0b1111_1101, 0b1101_1111]);
273 assert_eq!(Spanning::read(&raw), Small(0b101_1101));
274 }
275
276 #[test]
277 fn widths_come_from_the_range_alone() {
278 assert_eq!(Flag::WIDTH, 1);
279 assert_eq!(Nibble::WIDTH, 4);
280 assert_eq!(Field::<u64, 0, 63>::WIDTH, 64);
281 }
282
283 #[test]
284 fn bits_for_counts_what_a_value_needs() {
285 assert_eq!(bits_for(0), 0);
286 assert_eq!(bits_for(1), 1);
287 assert_eq!(bits_for(12), 4);
288 assert_eq!(bits_for(13), 4);
289 assert_eq!(bits_for(127), 7);
290 assert_eq!(bits_for(128), 8);
291 }
292}