1use std::fmt::{Display, Formatter, LowerHex};
2use std::ops::{Index, IndexMut, Range, RangeInclusive};
3
4
5fn bit(b: bool) -> usize { if b { 1 } else { 0 } }
6
7
8#[derive(Default, Debug, Clone, Copy)]
9struct SignedHex(i32);
10
11impl LowerHex for SignedHex {
12 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
13 let prefix = if f.alternate() { "0x" } else { "" };
14 let bare_hex = format!("{:x}", self.0.abs());
15 f.pad_integral(self.0 >= 0, prefix, &bare_hex)
16 }
17}
18
19
20#[derive(Debug, Copy, Clone)]
21pub enum BitsError {
22 InvalidInputString,
24 BitWidthMismatch { expected: usize, found: usize },
26 BitIndexOutOfRange,
28}
29
30
31#[derive(Debug, Copy, Clone)]
35pub struct Bits<const SIZE: usize>(pub [bool; SIZE]);
36
37impl<const SIZE: usize> Bits<SIZE> {
38 pub fn new() -> Self {
40 Bits([false; SIZE])
41 }
42
43 pub fn from_signed(x: i32) -> Self {
49 let mut bits = Vec::new();
50 if SIZE <= 32 {
51 for i in 0..SIZE {
52 bits.push(((x >> (SIZE-1 - i)) & 1) != 0);
53 }
54 }
55 else {
56 let extend_bits = SIZE - 32;
57 for _ in 0..extend_bits {
58 bits.push(if x < 0 { true } else { false });
59 }
60 for i in 0..32 {
61 bits.push(((x >> (31 - i)) & 1) != 0);
62 }
63 }
64 Bits(bits.try_into().unwrap())
65 }
66
67
68 pub fn from_unsigned(x: u32) -> Self {
74 let mut bits = Vec::new();
75 if SIZE <= 32 {
76 for i in 0..SIZE {
77 bits.push(((x >> (SIZE-1 - i)) & 1) != 0);
78 }
79 }
80 else {
81 let extend_bits = SIZE - 32;
82 for _ in 0..extend_bits {
83 bits.push(false);
84 }
85 for i in 0..32 {
86 bits.push(((x >> (31 - i)) & 1) != 0);
87 }
88 }
89 Bits(bits.try_into().unwrap())
90 }
91
92 pub fn from_slice(slice: &[bool]) -> Result<Self, BitsError> {
96 if slice.len() != SIZE {
97 return Err(BitsError::BitWidthMismatch { expected: SIZE, found: slice.len() });
98 }
99 let mut copied = [false; SIZE];
100 for i in 0..SIZE {
101 copied[i] = slice[i];
102 }
103 Ok(Bits(copied))
104 }
105
106 #[doc(hidden)]
107 pub fn from_reverse_index(slice: &[bool], hi: usize, lo: usize) -> Result<Self, BitsError> {
109 let high = lo.max(hi);
110 let low = lo.min(hi);
111 let width = high - low + 1;
112 if slice.len() - high < 1 { return Err(BitsError::BitIndexOutOfRange);
114 }
115 if width != SIZE {
116 return Err(BitsError::BitWidthMismatch{ expected: SIZE, found: width});
117 }
118 let mut copied = [false; SIZE];
119 for i in 0..SIZE {
120 copied[i] = slice[slice.len() - high - 1 + i];
121 }
122 Ok(Bits(copied))
123 }
124
125 pub const fn size(&self) -> usize { SIZE }
127
128 pub fn get_bit(&self, n: usize) -> Option<&bool> { self.0.get(n) }
133
134
135 pub fn get_bit_mut(&mut self, n: usize) -> Option<&mut bool> { self.0.get_mut(n) }
140
141 pub fn unsigned_value(&self) -> u32 {
143 let mut result = 0u32;
144 let start_idx = (SIZE as i32 - 32).max(0) as usize;
145 for i in 0..self.size().min(32) {
146 result <<= 1;
147 result |= bit(self.0[start_idx+i]) as u32;
148 }
149 result
150 }
151
152 pub fn signed_value(&self) -> i32 {
154 let mut result = 0u32;
155 let start_idx = (SIZE as i32 - 32).max(0) as usize;
156 let extend_bits = (32 - SIZE as i32).max(0) as usize;
157 let is_negative = self.0[0] == true;
158 for _ in 0..extend_bits {
159 result <<= 1;
160 result |= if is_negative { 1 } else { 0 };
161 }
162 for i in 0..SIZE.min(32) {
163 result <<= 1;
164 result |= *self.get_bit(start_idx+i).unwrap() as u32;
165 }
166 unsafe { std::mem::transmute(result) }
167 }
168
169 pub fn unsigned_add(&self, other: Self) -> (Self, bool) {
172 let a = self.unsigned_value() as u64;
173 let b = other.unsigned_value() as u64;
174 let sum = a + b;
175 let mut mask = 1u64;
176 for _ in 0..SIZE-1 {
177 mask <<= 1;
178 mask |= 1;
179 }
180 let result = (sum & mask) as u32;
181 (Bits::from_unsigned(result), (sum >> SIZE) > 0)
182 }
183
184 pub fn signed_add(&self, other: Self) -> (Self, bool) {
187 let a = self.signed_value() as i64;
188 let b = other.signed_value() as i64;
189 let sum = a + b;
190 let mut mask = 1i64;
191 for _ in 0..SIZE-1 {
192 mask <<= 1;
193 mask |= 1;
194 }
195 let result = (sum & mask) as i32;
196 let overflow = sum < -(2u64.pow(SIZE as u32 - 1) as i64) || sum > (2u64.pow(SIZE as u32 - 1) - 1) as i64;
197 (Bits::from_signed(result), overflow)
198 }
199
200 pub fn rotate_right(&self, n: usize) -> Self {
203 let n = n % SIZE;
204 let mut result = Bits::new();
205 for i in 0..SIZE {
206 result.0[(i+n)%SIZE] = self.0[i];
207 }
208 result
209 }
210
211 pub fn rotate_left(&self, n: usize) -> Self {
214 let n = n % SIZE;
215 let mut result = Bits::new();
216 for i in 0..SIZE {
217 result.0[(i+SIZE-n) % SIZE] = self.0[i];
219 }
220 result
221 }
222
223 pub fn bits_string(&self, pretty: bool) -> String {
228 let mut bitstr: String = self.0.map(|b| if b { "1".into() } else { "0".into() })
229 .into_iter()
230 .collect::<Vec<String>>()
231 .join("");
232 if pretty {
233 for i in 1..SIZE {
234 let idx = SIZE - i;
235 if idx % 4 == 0 {
236 bitstr.insert(idx, ' ');
237 }
238 }
239 }
240 bitstr
241 }
242
243 pub fn pretty_uhex_string(&self) -> String {
246 let digits = (SIZE as f32 / 4.0).ceil() as usize;
247 let hex_padding = digits % 2;
248 let mut uhex_chars = vec![' '; hex_padding];
249 uhex_chars.extend(format!("{:01$x}", self.unsigned_value(), digits)
250 .chars()
251 .into_iter());
252 uhex_chars
253 .chunks(2)
254 .map(|chunk| chunk.iter().map(|c| String::from(*c)).collect::<Vec<_>>().join("").replace(" ",""))
256 .collect::<Vec<_>>()
257 .join(" ")
258 }
259}
260
261
262impl<const N: usize> Default for Bits<N> {
263 fn default() -> Self {
264 Bits([false; N])
265 }
266}
267
268
269impl<const N: usize> Display for Bits<N> {
270 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
271 write!(f, "Bits<{0}>{{ {1} | dec {2}/{3} | hex {4:#x}/{5:#x} }}",
272 N,
273 self.bits_string(true),
274 self.unsigned_value(),
275 self.signed_value(),
276 self.unsigned_value(),
277 SignedHex(self.signed_value()))
278 }
279}
280
281
282impl<const N: usize> TryFrom<&str> for Bits<N> {
283 type Error = BitsError;
284
285 fn try_from(input: &str) -> Result<Self, Self::Error> {
286 let input = input.replace(" ","");
287 if input.len() > N || input.chars().any(|c| c != '0' && c != '1') {
288 return Err(BitsError::InvalidInputString);
289 }
290 let mut result = Bits([false; N]);
291 for i in 0..N {
292 let c = input.chars().nth(i).unwrap();
293 result.0[i] = if c == '0' { false } else { true };
294 }
295 Ok(result)
296 }
297}
298
299
300impl<const N: usize> Index<usize> for Bits<N> {
301 type Output = bool;
302
303 fn index(&self, index: usize) -> &Self::Output {
304 self.get_bit(index).unwrap()
305 }
306}
307
308
309impl<const N: usize> IndexMut<usize> for Bits<N> {
310 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
311 self.get_bit_mut(index).unwrap()
312 }
313}
314
315
316impl <const N: usize> Index<Range<usize>>for Bits<N> {
317 type Output = [bool];
318
319 fn index(&self, index: Range<usize>) -> &Self::Output {
320 &self.0[index]
321 }
322}
323
324
325impl <const N: usize> Index<RangeInclusive<usize>>for Bits<N> {
326 type Output = [bool];
327
328 fn index(&self, index: RangeInclusive<usize>) -> &Self::Output {
329 &self.0[index]
330 }
331}
332
333
334impl <const N: usize> IndexMut<Range<usize>>for Bits<N> {
335 fn index_mut(&mut self, index: Range<usize>) -> &mut Self::Output {
336 &mut self.0[index]
337 }
338}
339
340
341impl <const N: usize> IndexMut<RangeInclusive<usize>>for Bits<N> {
342 fn index_mut(&mut self, index: RangeInclusive<usize>) -> &mut Self::Output {
343 &mut self.0[index]
344 }
345}
346
347#[macro_export]
349macro_rules! bitslice {
350 ($name:ident[$high:literal:$low:literal]) => {
351 bitmath::Bits::<{$high-$low+1}>::from_reverse_index(&$name.0,$high,$low).unwrap()
352 }
353}