#[macro_use] pub mod type_math;
pub mod slice;
pub mod slice_mut;
#[macro_use] mod constraint_macro;
pub use self::type_math::{ TypeNum, Operator };
use std::{
convert::TryFrom, error::Error,
fmt::{ self, Display, Formatter }
};
#[derive(Debug)]
pub struct ConstraintViolation {
#[doc(hidden)]
pub constraint: String,
#[doc(hidden)]
pub by: i128
}
impl ConstraintViolation {
pub fn fixed<Val: TypeNum>(len: usize) -> Self {
let by = i128::try_from(len).unwrap() - i128::try_from(Val::VALUE).unwrap();
assert_ne!(by, 0, "Cannot construct `ConstraintViolation` for valid constraint");
Self{ constraint: format!("{:?}", Val::default()), by }
}
pub fn ranged<Start: TypeNum, End: TypeNum>(len: usize) -> Self {
let len = i128::try_from(len).unwrap();
let (start, end) =
(i128::try_from(Start::VALUE).unwrap(), i128::try_from(End::VALUE).unwrap());
let by = match (start, end) {
(start, _) if len < start => len - start,
(_, end) if len >= end => len - (end - 1),
_ => panic!("Cannot construct `ConstraintViolation` for valid constraint")
};
Self{ constraint: format!("Range<{:?} .. {:?}>", Start::default(), End::default()), by }
}
pub fn relative<Op: Operator, By: TypeNum>(len: usize, other: usize) -> Self {
let abs_len = Op::r#do(other, By::VALUE)
.expect("Cannot construct `ConstraintViolation` for illegal constraint");
let by = i128::try_from(len).unwrap() - i128::try_from(abs_len).unwrap();
assert_ne!(by, 0, "Cannot construct `ConstraintViolation` for valid constraint");
Self{ constraint: format!("{:?}({:?})", Op::default(), By::default()), by }
}
}
impl Display for ConstraintViolation {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let sign = match self.by.is_positive() {
true => "+",
false => ""
};
write!(f, "The length constraint `{}` was violated by {}{}", self.constraint, sign, self.by)
}
}
impl Error for ConstraintViolation {}