machine_check/types/
bitvector.rs

1use std::{
2    fmt::Debug,
3    ops::{Add, BitAnd, BitOr, BitXor, Mul, Not, Shl, Sub},
4};
5
6use mck::{
7    concr::{self, IntoMck},
8    forward::{Bitwise, HwArith, HwShift},
9};
10
11use crate::{Signed, Unsigned};
12
13/// Bitvector without signedness information.
14///
15/// The number of bits is specified in the generic parameter L.
16/// Bitvectors support bitwise operations and wrapping-arithmetic operations.
17/// Only operations where the behaviour of signed and unsigned numbers match are implemented.
18/// For others, conversion into [`Unsigned`] or [`Signed`] is necessary.
19/// Bit-extension is not possible directly, as signed and unsigned bitvectors are extended differently.
20#[derive(Clone, Copy, Hash, PartialEq, Eq)]
21pub struct Bitvector<const L: u32>(pub(super) concr::Bitvector<L>);
22
23impl<const L: u32> Bitvector<L> {
24    ///
25    /// Creates a new bitvector with the given value.
26    /// Panics if the value does not fit into the type.
27    ///
28    pub fn new(value: u64) -> Self {
29        Bitvector(concr::Bitvector::new(value))
30    }
31}
32// --- BITWISE OPERATIONS ---
33
34impl<const L: u32> Not for Bitvector<L> {
35    type Output = Self;
36
37    fn not(self) -> Self::Output {
38        Self(self.0.bit_not())
39    }
40}
41
42impl<const L: u32> BitAnd<Bitvector<L>> for Bitvector<L> {
43    type Output = Self;
44
45    fn bitand(self, rhs: Bitvector<L>) -> Self::Output {
46        Self(self.0.bit_and(rhs.0))
47    }
48}
49impl<const L: u32> BitOr<Bitvector<L>> for Bitvector<L> {
50    type Output = Self;
51
52    fn bitor(self, rhs: Bitvector<L>) -> Self::Output {
53        Self(self.0.bit_or(rhs.0))
54    }
55}
56impl<const L: u32> BitXor<Bitvector<L>> for Bitvector<L> {
57    type Output = Self;
58
59    fn bitxor(self, rhs: Bitvector<L>) -> Self::Output {
60        Self(self.0.bit_xor(rhs.0))
61    }
62}
63
64// --- ARITHMETIC OPERATIONS ---
65
66impl<const L: u32> Add<Bitvector<L>> for Bitvector<L> {
67    type Output = Self;
68
69    fn add(self, rhs: Bitvector<L>) -> Self::Output {
70        Self(self.0.add(rhs.0))
71    }
72}
73
74impl<const L: u32> Sub<Bitvector<L>> for Bitvector<L> {
75    type Output = Self;
76
77    fn sub(self, rhs: Bitvector<L>) -> Self::Output {
78        Self(self.0.sub(rhs.0))
79    }
80}
81
82impl<const L: u32> Mul<Bitvector<L>> for Bitvector<L> {
83    type Output = Self;
84
85    fn mul(self, rhs: Bitvector<L>) -> Self::Output {
86        Self(self.0.mul(rhs.0))
87    }
88}
89
90// --- SHIFT ---
91impl<const L: u32> Shl<Bitvector<L>> for Bitvector<L> {
92    type Output = Self;
93
94    fn shl(self, rhs: Bitvector<L>) -> Self::Output {
95        Self(self.0.logic_shl(rhs.0))
96    }
97}
98
99// --- CONVERSION ---
100impl<const L: u32> From<Unsigned<L>> for Bitvector<L> {
101    fn from(value: Unsigned<L>) -> Self {
102        Self(value.0)
103    }
104}
105
106impl<const L: u32> From<Signed<L>> for Bitvector<L> {
107    fn from(value: Signed<L>) -> Self {
108        Self(value.0)
109    }
110}
111
112impl<const L: u32> Debug for Bitvector<L> {
113    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
114        std::fmt::Debug::fmt(&self.0, f)
115    }
116}
117
118// --- INTERNAL IMPLEMENTATIONS ---
119
120#[doc(hidden)]
121impl<const L: u32> IntoMck for Bitvector<L> {
122    type Type = mck::concr::Bitvector<L>;
123
124    fn into_mck(self) -> Self::Type {
125        self.0
126    }
127}