Skip to content

Commit

Permalink
add assignment operations, reduce code duplication for array implemen…
Browse files Browse the repository at this point in the history
…tations
  • Loading branch information
PokeJofeJr4th authored and dzamlo committed Jul 22, 2024
1 parent 5a3e57e commit edb295b
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 17 deletions.
62 changes: 46 additions & 16 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ macro_rules! bitfield_impl {
impl<const N: usize> $crate::ops::BitAnd for $name<[$t; N]> {
type Output = Self;
fn bitand(self, rhs: Self) -> Self {
let mut output = Self([Default::default(); N]);
for i in 0..N {
output.0[i] = self.0[i] & rhs.0[i];
}
output
bitfield_impl!(@consume self rhs &)
}
}
impl<const N: usize> $crate::ops::BitAndAssign for $name<[$t; N]> {
fn bitand_assign(&mut self, rhs: Self) {
bitfield_impl!(@mutate self rhs &=);
}
}
};
Expand All @@ -53,16 +54,22 @@ macro_rules! bitfield_impl {
Self(self.0 & rhs.0)
}
}
impl $crate::ops::BitAndAssign for $name {
fn bitand_assign(&mut self, rhs: Self) {
self.0 &= rhs.0;
}
}
};
(BitOr for struct $name:ident([$t:ty]); $($rest:tt)*) => {
impl<const N: usize> $crate::ops::BitOr for $name<[$t; N]> {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
let mut output = Self([Default::default(); N]);
for i in 0..N {
output.0[i] = self.0[i] | rhs.0[i];
}
output
bitfield_impl!(@consume self rhs |)
}
}
impl<const N: usize> $crate::ops::BitOrAssign for $name<[$t; N]> {
fn bitor_assign(&mut self, rhs: Self) {
bitfield_impl!(@mutate self rhs |=);
}
}
};
Expand All @@ -73,16 +80,22 @@ macro_rules! bitfield_impl {
Self(self.0 | rhs.0)
}
}
impl $crate::ops::BitOrAssign for $name {
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0;
}
}
};
(BitXor for struct $name:ident([$t:ty]); $($rest:tt)*) => {
impl<const N: usize> $crate::ops::BitXor for $name<[$t; N]> {
type Output = Self;
fn bitxor(self, rhs: Self) -> Self {
let mut output = Self([Default::default(); N]);
for i in 0..N {
output.0[i] = self.0[i] ^ rhs.0[i];
}
output
bitfield_impl!(@consume self rhs ^)
}
}
impl<const N: usize> $crate::ops::BitXorAssign for $name<[$t; N]> {
fn bitxor_assign(&mut self, rhs: Self) {
bitfield_impl!(@mutate self rhs ^=);
}
}
};
Expand All @@ -93,7 +106,24 @@ macro_rules! bitfield_impl {
Self(self.0 ^ rhs.0)
}
}
impl $crate::ops::BitXorAssign for $name {
fn bitxor_assign(&mut self, rhs: Self) {
self.0 ^= rhs.0;
}
}
};
(@consume $self:ident $rhs:ident $op:tt) => {{
let mut output = Self([Default::default(); N]);
for i in 0..N {
output.0[i] = $self.0[i] $op $rhs.0[i];
}
output
}};
(@mutate $self:ident $rhs:ident $op:tt) => {{
for i in 0..N {
$self.0[i] $op $rhs.0[i];
}
}};
// display a more friendly error message when someone tries to use `impl <Trait>;` syntax when not supported
($macro:ident for struct $name:ident $($rest:tt)*) => {
::std::compile_error!(::std::stringify!(Unsupported impl $macro for struct $name));
Expand Down Expand Up @@ -672,7 +702,7 @@ macro_rules! bitfield_bitrange {
///
/// The second optional element is a set of lines of the form `impl <Trait>;`. The following traits are supported:
/// * `Debug`; This will generate an implementation of `fmt::Debug` with the `bitfield_debug` macro.
/// * `BitAnd`, `BitOr`, `BitXor`; These will generate implementations of the relevant `ops::_` traits.
/// * `BitAnd`, `BitOr`, `BitXor`; These will generate implementations of the relevant `ops::Bit___` and `ops::Bit___Assign` traits.
///
/// The difference with calling those macros separately is that `bitfield_fields` is called
/// from an appropriate `impl` block. If you use the non-slice form of `bitfield_bitrange`, the
Expand Down
11 changes: 10 additions & 1 deletion tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,12 @@ fn test_bitwise_ops() {
assert!(ffxor.b());
assert!(ffxor.c());
assert!(!ffxor.d());

ff1 ^= ff2;
assert!(!ff1.a());
assert!(ff1.b());
assert!(ff1.c());
assert!(!ff1.d());
}

#[test]
Expand Down Expand Up @@ -797,7 +803,7 @@ fn test_arraybitfield_msb0() {

#[test]
fn test_arraybitfield_bitops() {
let a = ArrayBitfield([1u8; 3]);
let mut a = ArrayBitfield([1u8; 3]);
let b = ArrayBitfield([1u8, 2u8, 4u8]);

let c = a | b;
Expand All @@ -808,6 +814,9 @@ fn test_arraybitfield_bitops() {

let e = a ^ b;
assert_eq!(e.0, [0, 3, 5]);

a ^= b;
assert_eq!(a.0, [0, 3, 5]);
}

mod some_module {
Expand Down

0 comments on commit edb295b

Please sign in to comment.