-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement 8 and optionally 16 bit integers with build.rs generated enum
- Loading branch information
Showing
4 changed files
with
209 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
#[derive(Clone, Copy)] | ||
enum BitInfo { | ||
Unsigned { | ||
prim_max: u64, | ||
}, | ||
Signed { | ||
signed_max: i64, | ||
signed_min: i64, | ||
prim_max: i64, | ||
}, | ||
} | ||
|
||
impl BitInfo { | ||
fn prim_max(&self) -> i64 { | ||
match self { | ||
Self::Unsigned { prim_max } => *prim_max as i64, | ||
Self::Signed { prim_max, .. } => *prim_max, | ||
} | ||
} | ||
} | ||
|
||
struct EnumInfo { | ||
ty_name: &'static str, | ||
name: &'static str, | ||
bit_info: BitInfo, | ||
} | ||
|
||
const FILES: &[EnumInfo] = &[ | ||
EnumInfo { | ||
ty_name: "u8", | ||
name: "u8_repr.rs", | ||
bit_info: BitInfo::Unsigned { | ||
prim_max: u8::MAX as _, | ||
}, | ||
}, | ||
EnumInfo { | ||
ty_name: "i8", | ||
name: "i8_repr.rs", | ||
bit_info: BitInfo::Signed { | ||
signed_max: i8::MAX as _, | ||
signed_min: i8::MIN as _, | ||
prim_max: u8::MAX as _, | ||
}, | ||
}, | ||
#[cfg(feature = "enum_repr_16")] | ||
EnumInfo { | ||
ty_name: "u16", | ||
name: "u16_repr.rs", | ||
bit_info: BitInfo::Unsigned { | ||
prim_max: u16::MAX as _, | ||
}, | ||
}, | ||
#[cfg(feature = "enum_repr_16")] | ||
EnumInfo { | ||
ty_name: "i16", | ||
name: "i16_repr.rs", | ||
bit_info: BitInfo::Signed { | ||
signed_max: i16::MAX as _, | ||
signed_min: i16::MIN as _, | ||
prim_max: u16::MAX as _, | ||
}, | ||
}, | ||
]; | ||
|
||
fn generate_variants( | ||
generated_file: &mut impl std::fmt::Write, | ||
repr_name: &str, | ||
bit_info: BitInfo, | ||
) { | ||
write!( | ||
generated_file, | ||
"#[derive(Clone, Copy, PartialEq, Eq, Hash)] | ||
#[allow(dead_code)] | ||
pub(crate) enum {repr_name} {{", | ||
) | ||
.unwrap(); | ||
|
||
match bit_info { | ||
BitInfo::Unsigned { prim_max } => { | ||
for i in 0..prim_max { | ||
write!(generated_file, "V{i}={i},").unwrap() | ||
} | ||
} | ||
BitInfo::Signed { | ||
signed_max, | ||
signed_min, | ||
prim_max, | ||
} => { | ||
for i in 0..signed_max { | ||
write!(generated_file, "V{i}={i},").unwrap(); | ||
} | ||
|
||
for (i, v) in (signed_max..prim_max).zip(signed_min..0) { | ||
write!(generated_file, "MV{i}={v},").unwrap(); | ||
} | ||
} | ||
} | ||
|
||
write!(generated_file, "}}").unwrap(); | ||
} | ||
|
||
fn generate_impl(generated_file: &mut impl std::fmt::Write, repr_name: &str, ty_name: &str) { | ||
write!( | ||
generated_file, | ||
"impl {repr_name} {{ | ||
pub(crate) const fn new(value: {ty_name}) -> Option<Self> {{ | ||
unsafe {{ std::mem::transmute(value) }} | ||
}} | ||
}}" | ||
) | ||
.unwrap() | ||
} | ||
|
||
fn main() { | ||
let out_dir = std::env::var("OUT_DIR").unwrap(); | ||
|
||
for file in FILES { | ||
let mut generated_file = String::with_capacity(file.bit_info.prim_max() as usize); | ||
|
||
let repr_name = format!("{}Repr", file.ty_name.to_uppercase()); | ||
|
||
generate_variants(&mut generated_file, &repr_name, file.bit_info); | ||
generate_impl(&mut generated_file, &repr_name, file.ty_name); | ||
|
||
std::fs::write(format!("{out_dir}/{}", file.name), generated_file).unwrap(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#[cfg(feature = "enum_repr_16")] | ||
pub(crate) mod i16_repr { | ||
include!(concat!(env!("OUT_DIR"), "/i16_repr.rs")); | ||
} | ||
#[cfg(feature = "enum_repr_16")] | ||
pub(crate) mod u16_repr { | ||
include!(concat!(env!("OUT_DIR"), "/u16_repr.rs")); | ||
} | ||
pub(crate) mod i8_repr { | ||
include!(concat!(env!("OUT_DIR"), "/i8_repr.rs")); | ||
} | ||
pub(crate) mod u8_repr { | ||
include!(concat!(env!("OUT_DIR"), "/u8_repr.rs")); | ||
} | ||
|
||
macro_rules! nonmax { | ||
( $nonmax: ident, $primitive: ident, $byte_repr: ident ) => { | ||
/// An integer that is known not to equal its maximum value. | ||
#[derive(Clone, Copy, PartialEq, Eq, Hash)] | ||
#[repr(transparent)] | ||
pub struct $nonmax($byte_repr); | ||
|
||
impl $nonmax { | ||
/// Creates a new non-max if the given value is not the maximum | ||
/// value. | ||
pub const fn new(value: $primitive) -> Option<Self> { | ||
match $byte_repr::new(value) { | ||
Some(byte) => Some(Self(byte)), | ||
None => None, | ||
} | ||
} | ||
|
||
/// Creates a new non-max without checking the value. | ||
/// | ||
/// # Safety | ||
/// | ||
/// The value must not equal the maximum representable value for the | ||
/// primitive type. | ||
#[inline] | ||
pub const unsafe fn new_unchecked(value: $primitive) -> Self { | ||
match Self::new(value) { | ||
Some(this) => this, | ||
None => unsafe { std::hint::unreachable_unchecked() }, | ||
} | ||
} | ||
|
||
/// Returns the value as a primitive type. | ||
#[inline] | ||
pub const fn get(&self) -> $primitive { | ||
self.0 as $primitive | ||
} | ||
} | ||
}; | ||
} | ||
|
||
pub(crate) use nonmax; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters