1use bitvec::prelude::*;
2use serde::ser::SerializeSeq;
3use serde::{Serialize, Serializer};
4use std::fmt::{Debug, Display, Formatter, Write};
5
6pub mod units;
7
8#[derive(Clone, Copy, PartialEq, Eq)]
10pub struct StatusBitMap(BitArray<[u16; 8], Lsb0>);
11
12impl Serialize for StatusBitMap {
13 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
14 where
15 S: Serializer,
16 {
17 if serializer.is_human_readable() {
19 return serializer.serialize_str(&self.to_string());
20 }
21
22 let r = self.as_raw_slice();
24 let short = r.iter().skip(4).all(|x| *x == 0);
25
26 let mut seq = serializer.serialize_seq(Some(if short { 4 } else { 8 }))?;
27 seq.serialize_element(&r[0])?;
28 seq.serialize_element(&r[1])?;
29 seq.serialize_element(&r[2])?;
30 seq.serialize_element(&r[3])?;
31
32 if !short {
33 seq.serialize_element(&r[4])?;
34 seq.serialize_element(&r[5])?;
35 seq.serialize_element(&r[6])?;
36 seq.serialize_element(&r[7])?;
37 }
38 seq.end()
39 }
40}
41
42impl Debug for StatusBitMap {
43 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
44 let mut str = String::with_capacity(128 + 4);
45 let arr = self.0.as_raw_slice();
46
47 for byte in 0..arr.len() {
48 str += &format!("{:032b} ", arr[byte]);
49 if arr[byte..].iter().all(|x| *x == 0) {
50 break;
51 }
52 }
53
54 f.debug_tuple("StatusBitMap")
55 .field(&str.trim_end())
56 .finish()
57 }
58}
59
60impl Default for StatusBitMap {
61 fn default() -> Self {
62 Self(BitArray::new([0; 8]))
63 }
64}
65
66impl StatusBitMap {
67 pub fn new() -> Self {
68 Self::default()
69 }
70
71 pub fn as_raw_slice(&self) -> &[u16] {
72 self.0.as_raw_slice()
73 }
74 pub fn as_mut_raw_slice(&mut self) -> &mut [u16] {
75 self.0.as_raw_mut_slice()
76 }
77
78 pub fn has_extra(&self) -> bool {
79 self.0.as_raw_slice()[4..].iter().any(|x| *x != 0)
80 }
81
82 pub fn set(&mut self, idx: usize, value: bool) {
83 self.0.set(idx, value);
84 }
85
86 pub fn get(&self, idx: usize) -> bool {
87 self.0[idx]
88 }
89
90 pub fn len(&self) -> usize {
91 self.0.len()
92 }
93
94 pub fn is_empty(&self) -> bool {
95 self.0.is_empty()
96 }
97
98 pub fn get_range(&self, range: impl IntoIterator<Item = u8>) -> u32 {
99 let mut result = 0;
100 let mut iter = range.into_iter().peekable();
101 let start = *iter.peek().unwrap_or(&0);
102 for i in iter {
103 result |= (self.get(i as usize) as u32) << (i - start) as usize;
104 }
105 result
106 }
107
108 pub fn set_range(&mut self, range: impl IntoIterator<Item = u8>, mut value: u32) {
111 for i in range.into_iter() {
112 self.set(i as usize, value & 1 != 0);
113 value >>= 1;
114 }
115 }
116
117 pub fn debug_header() -> String {
118 " Upper Lower\n\
119 0 1 2 3 4 5 6\n\
120 01234567890123456789012345678901 23456789012345678901234567890123\n\
121 0123456789ABCDEFGHIJKLMNOPQRSTUV 0123456789ABCDEFGHIJKLMNOPQRSTUV\n\
122 "
123 .to_string()
124 }
125
126 pub fn debug_string(&self, header: bool) -> String {
127 let mut result = String::new();
128 if header {
129 result += &Self::debug_header();
130 }
131
132 fn output_u64(mut word64: u64) -> String {
133 let mut word_str = String::new();
134 while word64 != 0 {
135 word_str.push(if word64 & 1 != 0 { 'X' } else { ' ' });
136 word64 >>= 1;
137 }
138 if word_str.len() > 32 {
139 word_str.insert(32, ' ');
140 }
141 word_str
142 }
143
144 let raw = self.0.as_raw_slice();
145 result.push_str(&output_u64(
146 (raw[0] as u64)
147 | ((raw[1] as u64) << 16)
148 | ((raw[2] as u64) << 32)
149 | ((raw[3] as u64) << 48),
150 ));
151
152 if raw[4] != 0 || raw[5] != 0 || raw[6] != 0 || raw[7] != 0 {
153 if header {
154 result += "\n\
155 0 0 0 0 1 1 1 \n\
156 6 7 8 9 0 1 2 \n\
157 45678901234567890123456789012345 67890123456789012345678901234567\n\
158 ";
159 }
160 result.push_str(&output_u64(
161 ((raw[0] as u64) << 48)
162 | ((raw[1] as u64) << 32)
163 | ((raw[2] as u64) << 16)
164 | (raw[3] as u64),
165 ));
166 }
167
168 result.push('\n');
169 result
170 }
171
172 pub fn iter(&self) -> impl Iterator<Item = bool> + '_ {
173 self.0.iter().by_vals()
174 }
175}
176
177impl Display for StatusBitMap {
178 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
179 for i in 0..(if self.has_extra() { 128 } else { 64 }) {
180 f.write_char(if self.get(i) { '1' } else { '0' })?;
181 }
182 Ok(())
183 }
184}
185
186#[test]
187fn status_bits() {
188 let mut status_bits = StatusBitMap::new();
189 status_bits.set(0, true);
190 status_bits.set(2, true);
191 status_bits.set_range(4..8, 0b0101);
192
193 status_bits.set_range(32..34, 3);
194 status_bits.set_range(64..67, 3);
195 status_bits.set_range(96..120, 8);
196
197 assert_eq!(
198 status_bits.to_string(),
199 concat!(
200 "10101010000000000000000000000000",
201 "11000000000000000000000000000000",
202 "11000000000000000000000000000000",
203 "00010000000000000000000000000000"
204 )
205 );
206
207 assert_eq!(status_bits.get_range(32..34), 3);
208 assert_eq!(status_bits.get_range(64..67), 3);
209}