Bit twiddling pre-RFC

Personally, I would really like if they were in libcore/libstd. They come up quite a lot in low-level programming, and they feel like fundamental things to do with integers... That may just be a matter of personal opinion, though.

Do you know why? This seems like an odd choice given that most other indexing types use usize TMK. Though really, we could probably get away with u16; not many people need 8KB-integers, so that's probably more than enough...

I really like these observations. In fact, I propose a new interface, which may even subsume the From/IntoBits proposal and Truncate!

/// Like a slice into a range of bits of a numerical type.
/// It can be used to update the original value.
/// Lol. Maybe we should call it `Biterator`?
trait Bits {
    /// Sets the selected bits of `self` with the selected bits of `other`.
    fn copy_from<B: Bits>(&mut self, other: B);
}

/// Implement this for all types where looking at bits is a valid thing
/// to do.
///
/// `unsafe` because we need to guarantee that the type is valid
/// to take as a collection of bits.
unsafe trait IntoBits: Sized {
    type BitVec: Bits;
    fn bits(&mut self, ra: RangeArgument) -> Self::BitsVec;
    
    fn all_bits(&mut self) -> Self::BitVec {
        self.bits(0..width($i))
    }
}

/// Implement this for all types that can be constructed from
/// an arbitrary bit string of the right length.
unsafe trait FromBits: Size {
    // Works for arbitrary B as long as it does not have too many bits.
    fn from_bits<B: Bits>(b: B) -> Self {
        let mut new: Self = unsafe { mem::uninitialized() };
        new.all_bits().copy_from(b);
        new
    }
}

// For all numerical types $i (probably these impls can be generated
// with a macro or something).
impl IntoBits for $i {
    type BitVec = $iBitVec;
    fn bits(...) -> Self::BitVec { ... }
}

impl FromBits for $i { }

////////////////////////////////////////////////////////////////////////////////
// Examples

let mut a = ...;
let b = ...;

// Subsumes `set_bits` proposed above
a.bits(x..y).copy_from(b.bits(w..=z))
a.bits(x..y).copy_from(b.all_bits())

// Subsumes `FromBits` and `IntoBits` from the other pre-RFC
let a: f32 = f32::from_bits(a.all_bits());
let a: f32 = f32::from_bits(0u64.bits(32..64));

// Subsumes `Truncate`
let a: u32 = u32::from_bits(0xDEADBEEF_DEADBEEF.bits(0..32));
let a: u64 = u64::from_bits(32i32.all_bits());
1 Like