Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(bitfield): add u128 support #467

Merged
merged 2 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions bitfield/src/bitfield.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
/// # Generated Implementations
///
/// The `bitfield!` macro generates a type with the following functions, where
/// `{int}` is the integer type that represents the bitfield (one of `u8`,
/// `u16`,`u32`, `u64`, or `usize`):
/// `{int}` is the integer type that represents the bitfield (one of [`u8`],
/// [`u16`], [`u32`], [`u64`], [`u128`], or [`usize`]):
///
/// - `const fn new() -> Self`: Returns a new instance of the bitfield type with
/// all bits zeroed.
Expand Down Expand Up @@ -833,11 +833,12 @@ macro_rules! bitfield {
// };

(@t usize, $V:ty, $F:ty) => { $crate::PackUsize<$V, $F> };
(@t u128, $V:ty, $F:ty) => { $crate::Pack128<$V, $F> };
(@t u64, $V:ty, $F:ty) => { $crate::Pack64<$V, $F> };
(@t u32, $V:ty, $F:ty) => { $crate::Pack32<$V, $F> };
(@t u16, $V:ty, $F:ty) => { $crate::Pack16<$V, $F> };
(@t u8, $V:ty, $F:ty) => { $crate::Pack8<$V, $F> };
(@t $T:ty, $V:ty, $F:ty) => { compile_error!(concat!("unsupported bitfield type `", stringify!($T), "`; expected one of `usize`, `u64`, `u32`, `u16`, or `u8`")) }
(@t $T:ty, $V:ty, $F:ty) => { compile_error!(concat!("unsupported bitfield type `", stringify!($T), "`; expected one of `usize`, `u128`, `u64`, `u32`, `u16`, or `u8`")) }
}

#[cfg(test)]
Expand All @@ -857,6 +858,21 @@ mod tests {
}
}

bitfield! {
/// This is only here to ensure it compiles...
#[allow(dead_code)]
struct TestBitfieldHuge<u128> {
const HELLO = 4;
const _RESERVED_1 = 3;
const WORLD: bool;
const HAVE: TestEnum;
const LOTS = 5;
const OF = 1;
const FUN = 6;
const REST = ..;
}
}

#[repr(u8)]
#[derive(Debug)]
enum TestEnum {
Expand Down Expand Up @@ -885,6 +901,19 @@ mod tests {
}
}

impl FromBits<u128> for TestEnum {
const BITS: u32 = 2;
type Error = core::convert::Infallible;

fn try_from_bits(bits: u128) -> Result<Self, Self::Error> {
FromBits::<u32>::try_from_bits(bits as u32)
}

fn into_bits(self) -> u128 {
self as u8 as u128
}
}

#[derive(Debug)]
#[allow(dead_code)]
struct TestDebug {
Expand Down
20 changes: 11 additions & 9 deletions bitfield/src/from_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,19 +337,20 @@ macro_rules! impl_frombits_for_bool {
}

impl_frombits_for_bool! {
impl FromBits<u8, u16, u32, u64, usize> for bool {}
impl FromBits<u8, u16, u32, u64, u128, usize> for bool {}
}

impl_frombits_for_ty! {
impl FromBits<u8, u16, u32, u64> for u8 {}
impl FromBits<u16, u32, u64> for u16 {}
impl FromBits<u32, u64> for u32 {}
impl FromBits<u64> for u64 {}
impl FromBits<u8, u16, u32, u64, u128> for u8 {}
impl FromBits<u16, u32, u64, u128> for u16 {}
impl FromBits<u32, u64, u128> for u32 {}
impl FromBits<u64, u128> for u64 {}
impl FromBits<u128> for u128 {}

impl FromBits<u8, u16, u32, u64> for i8 {}
impl FromBits<u16, u32, u64> for i16 {}
impl FromBits<u32, u64> for i32 {}
impl FromBits<u64> for i64 {}
impl FromBits<u8, u16, u32, u64, u128> for i8 {}
impl FromBits<u16, u32, u64, u128> for i16 {}
impl FromBits<u32, u64, u128> for i32 {}
impl FromBits<u64, u128> for i64 {}

// Rust doesn't support 8 bit targets, so {u,i}size are always at least 16 bit wide,
// source: https://doc.rust-lang.org/1.45.2/src/core/convert/num.rs.html#134-139
Expand All @@ -363,6 +364,7 @@ impl_frombits_for_ty! {

impl FromBits<usize> for usize {}
impl FromBits<usize> for isize {}
impl FromBits<u128> for usize {}
}

#[cfg(target_pointer_width = "16")]
Expand Down
13 changes: 11 additions & 2 deletions bitfield/src/pack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
//! The bit packing utilities consist of a type that defines a specification for
//! a bit range to pack into, and a wrapper type for an unsigned integer
//! defining methods to pack bit ranges into it. Packing specs are defined for
//! [`u64`], [`u32`], [`u16`], and [`u8`], as [`Pack64`], [`Pack32`],
//! [`Pack16`], and [`Pack8`], respectively.
//! [`usize`], [`u128`], [`u64`], [`u32`], [`u16`], and [`u8`], as
//! [`PackUsize`], [`Pack128`], [`Pack64`], [`Pack32`], [`Pack16`], and
//! [`Pack8`], respectively.
//!
//! Note that the bit packing utilities are generic using macros, rather than
//! using generics and traits, because they are intended to be usable in
Expand Down Expand Up @@ -1079,6 +1080,7 @@ macro_rules! make_packers {

make_packers! {
pub struct PackUsize { bits: usize, packing: PackingUsize, pair: PairUsize }
pub struct Pack128 { bits: u128, packing: Packing128, pair: Pair128 }
pub struct Pack64 { bits: u64, packing: Packing64, pair: Pair64, }
pub struct Pack32 { bits: u32, packing: Packing32, pair: Pair32, }
pub struct Pack16 { bits: u16, packing: Packing16, pair: Pair16, }
Expand Down Expand Up @@ -1281,34 +1283,41 @@ mod tests {
}

test_pack_unpack! {
fn pack_unpack_128<Pack128, u128>(128);
fn pack_unpack_64<Pack64, u64>(64);
fn pack_unpack_32<Pack32, u32>(32);
fn pack_unpack_16<Pack16, u16>(16);
fn pack_unpack_8<Pack8, u8>(8);
}

test_pack_methods! {

fn pack_methods_128<Pack128, u128>(128);
fn pack_methods_64<Pack64, u64>(64);
fn pack_methods_32<Pack32, u32>(32);
fn pack_methods_16<Pack16, u16>(16);
fn pack_methods_8<Pack8, u8>(8);
}

test_from_range! {
fn pack_from_src_range_128<Pack128, u128>(128);
fn pack_from_src_range_64<Pack64, u64>(64);
fn pack_from_src_range_32<Pack32, u32>(32);
fn pack_from_src_range_16<Pack16, u16>(16);
fn pack_from_src_range_8<Pack8, u8>(8);
}

test_pair_least_sig_zeroed! {

fn pair_least_sig_zeroed_128<Pack128, u128>(128);
fn pair_least_sig_zeroed_64<Pack64, u64>(64);
fn pair_least_sig_zeroed_32<Pack32, u32>(32);
fn pair_least_sig_zeroed_16<Pack16, u16>(16);
fn pair_least_sig_zeroed_8<Pack8, u8>(8);
}

test_pair_least_sig_arbitrary! {
fn pair_least_sig_arbitrary_128<Pack128, u128>(128);
fn pair_least_sig_arbitrary_64<Pack64, u64>(64);
fn pair_least_sig_arbitrary_32<Pack32, u32>(32);
fn pair_least_sig_arbitrary_16<Pack16, u16>(16);
Expand Down
Loading