#[ambit]Expand description
Creates a ranged number newtype, along with various helpers.
#[ambit(range = "0..=10")]
pub struct ZeroToTen;Generates:
#[repr(transparent)]
pub struct ZeroToTen(u8);
impl ZeroToTen {
pub const MIN_VALUE: u8 = 0;
pub const MAX_VALUE: u8 = 10;
pub const MIN: Self = unsafe { Self::new_unchecked(0) };
pub const MAX: Self = unsafe { Self::new_unchecked(10) };
pub fn iter() -> ZeroToTenIter {
ZeroToTenIter(Some(Self::MIN))
}
pub const fn new(n: u8) -> Result<Self, ZeroToTenError> {
if n < 0 || n > 10 {
return Err(ZeroToTenError(n));
}
Ok(unsafe { Self::new_unchecked(n) })
}
pub const unsafe fn new_unchecked(n: u8) -> Self {
Self(n)
}
pub const fn value(&self) -> u8 {
self.0
}
pub const fn is_min(&self) -> bool {
self.value() == Self::MIN.value()
}
pub const fn is_max(&self) -> bool {
self.value() == Self::MAX.value()
}
pub fn pred(&self) -> Option<Self> {
(!self.is_min()).then(|| unsafe { Self::new_unchecked(self.value() - 1) })
}
pub fn succ(&self) -> Option<Self> {
(!self.is_max()).then(|| unsafe { Self::new_unchecked(self.value() + 1) })
}
}
impl PartialEq<u8> for ZeroToTen {
fn eq(&self, &other: &u8) -> bool {
self.value() == other
}
}
impl TryFrom<u8> for ZeroToTen {
type Error = ZeroToTenError;
fn try_from(n: u8) -> Result<Self, ZeroToTenError> {
Self::new(n)
}
}
pub struct ZeroToTenIter(Option<ZeroToTen>);
impl Iterator for ZeroToTenIter {
type Item = ZeroToTen;
fn next(&mut self) -> Option<ZeroToTen> {
if let Some(next) = self.0.as_ref()?.succ() {
self.0.replace(next)
} else {
self.0.take()
}
}
}
#[derive(Debug)]
#[non_exhaustive]
pub struct ZeroToTenError(pub u8);
impl std::error::Error for ZeroToTenError {}
impl std::fmt::Display for ZeroToTenError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.write_fmt(format_args!("invalid ZeroToTen: {0}", self.0))
}
}
#[macro_export]
macro_rules! zerototen {
(0) => { unsafe { Self::new_unchecked(0) } };
(1) => { unsafe { Self::new_unchecked(1) } };
(2) => { unsafe { Self::new_unchecked(2) } };
(3) => { unsafe { Self::new_unchecked(3) } };
(4) => { unsafe { Self::new_unchecked(4) } };
(5) => { unsafe { Self::new_unchecked(5) } };
(6) => { unsafe { Self::new_unchecked(6) } };
(7) => { unsafe { Self::new_unchecked(7) } };
(8) => { unsafe { Self::new_unchecked(8) } };
(9) => { unsafe { Self::new_unchecked(9) } };
(10) => { unsafe { Self::new_unchecked(10) } };
}The provided range must be an ascending range of unsigned integers. Inclusive (..)
and exclusive (..=) ranges are both supported. The internal type (u8, etc) of the newtype
will be inferred from the range. If the range does not include zero, the internal type will be
a NonZero.
The generated code is not otherwise configurable. I may expand this in the future, in particular adding a way to turn off various parts (the macro_rules, iterators).