I'm new to Rust. The following code is my attempt to create an extension of usize that allows for:
The struct below does all that, but it doesn't behave like a usize otherwise. Maybe I'm going about this all wrong and a struct isn't the right vehicle for this. As an example of this not working:
let mut permutable_usize = PermutableUsize::new(0b00010011, 8);
permutable_usize += 1;
The above generates an error and says I must implement AddAssign<_>.
I'm sure there's a 'right way' to do this that avoids re-implementing all the usize methods. How should I proceed?
Here's what I have now:
struct PermutableUsize {
value: usize,
num_bits: usize,
}
impl PermutableUsize {
fn new(value: usize, num_bits: usize) -> Self {
Self {
value,
num_bits,
}
}
// Method to compute the next lexicographic permutation of bits
// The logic comes from bit-twiddling hacks at https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
fn next_permutation(&mut self) {
let t = self.value | (self.value - 1);
let ctz_v = self.value.trailing_zeros();
self.value = (t + 1) | (((!t & (!t).wrapping_neg()) - 1) >> (ctz_v + 1));
}
}
use std::fmt;
impl fmt::Binary for PermutableUsize {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:0width$b}", self.value, width = self.num_bits)
}
}
fn main() {
let mut permutable_usize = PermutableUsize::new(0b00010011, 8); // example with 8 bits
println!("Initial value: {:08b}", permutable_usize);
permutable_usize.next_permutation();
println!("Next permutation: {:08b}", permutable_usize);
}
The right way is to implement all methods, but you don't have to do that manually: there are crates that can help with that, for example derive_more
. There is also a proposed RFC to help with that. The general pattern is called "delegation".
If you want all methods of usize
to be available, you can implement Deref
. The Rust community is divided on whether this is a good idea, though. Also, this doesn't help with traits (there the crates I mentioned help).