Macro bounded_integer

Source
macro_rules! bounded_integer {
    (
        $(#![$($outer_attr:tt)*])*
        $(#[$($attr:tt)*])*
        $(pub $(($($vis:tt)*))?)? struct $name:ident($min:expr, $max:expr);
    ) => { ... };
    (
        $(#![$($outer_attr:tt)*])*
        $(#[$($attr:tt)*])*
        $(pub $(($($vis:tt)*))?)? enum $name:ident($min:expr, $max:expr);
    ) => { ... };
    (
        $(#![$($outer_attr:tt)*])*
        $(#[$($attr:tt)*])*
        $(pub $(($($vis:tt)*))?)? enum $name:ident {
            $($(#[$($var_attr:tt)*])* $variant:ident $(= $val:literal)?),* $(,)?
        }
    ) => { ... };
    ($(#[$($attr:tt)*])* $vis:vis struct $name:ident { $($_:tt)* }) => { ... };
    ($(#[$($attr:tt)*])* $vis:vis enum $name:ident { $($_:tt)* }) => { ... };
}
Available on crate feature macro only.
Expand description

Generate a bounded integer type.

It takes in single struct or enum, with the content being a bounded range expression, whose upper bound can be inclusive (x, y) or exclusive (x, y). The attributes and visibility (e.g. pub) of the type are forwarded directly to the output type.

If the type is a struct and the bounded integer’s range does not include zero, the struct will have a niche at zero, allowing for Option<BoundedInteger> to be the same size as BoundedInteger itself.

See the examples module for examples of what this macro generates.

§Examples

With a struct:

bounded_integer! {
    pub struct S(2, 5);
}

The generated item should look like this (u8 is chosen as it is the smallest repr):

#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct S(u8);

And the methods will ensure that 2 ≤ S.0 ≤ 5.

With an enum:

bounded_integer! {
    pub enum S(-1, 1);
}

The generated item should look like this (i8 is chosen as it is the smallest repr):

#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(i8)]
pub enum S {
    N1 = -1, Z, P1
}

You can also ascribe dedicated names to the enum variants:

bounded_integer! {
    pub enum Sign {
        Negative = -1,
        Zero,
        Positive,
    }
}
assert_eq!(Sign::Negative.get(), -1);
assert_eq!(Sign::new(1).unwrap(), Sign::Positive);

§Custom repr

The item can have a repr attribute to specify how it will be represented in memory, which can be a u* or i* type. In this example we override the repr to be a u16, when it would have normally been a u8.

bounded_integer! {
    #[repr(u16)]
    pub struct S(2, 4);
}

The generated item should look like this:

#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct S(u16);