#[doc = include_str!("../README.md")]
#[macro_export]
macro_rules! constraint {
(
$(#[$outer:meta])*
$vis:vis $name:ident($typ:ident) if $cond:expr
) => {
$(#[$outer])*
$vis struct $name($typ);
impl $name {
#[allow(dead_code)]
pub fn get(&self) -> &$typ {
&self.0
}
#[allow(dead_code)]
pub fn get_mut(&mut self) ->&mut $typ {
&mut self.0
}
#[allow(dead_code)]
pub fn into_inner(self) -> $typ {
self.0
}
}
impl std::convert::TryFrom<$typ> for $name {
type Error = ();
fn try_from(value: $typ) -> Result<Self, Self::Error> {
if $cond(&value) {
Ok(Self(value))
}
else {
Err(())
}
}
}
};
}
#[cfg(test)]
mod tests {
use std::convert::TryFrom;
#[test]
fn compile_bounded_i32() {
crate::constraint! { pub(crate) Bounded(i32) if |value: &i32| *value < 5 && *value > 2 }
assert!(Bounded::try_from(2).is_err());
assert!(Bounded::try_from(3).is_ok());
assert!(Bounded::try_from(4).is_ok());
assert!(Bounded::try_from(5).is_err());
}
}