use errors::{ErrorKind, dump};
use lazy::SimpleAssert;
use marker::RangeArgument;
use std::fmt::Debug;
pub trait MustBeInRange<R: Debug + RangeArgument<Self>>
: Copy + Sized + Debug + PartialOrd {
fn must_be_in_range(self, range: R) -> SimpleAssert<Self> {
if is_in_range(self, &range) {
self.into()
} else {
ErrorKind::MustBeInRange { range: dump(&range) }.but_got(self)
}
}
fn must_not_be_in_range(self, range: R) -> SimpleAssert<Self> {
if !is_in_range(self, &range) {
self.into()
} else {
ErrorKind::MustNotBeInRange { range: dump(&range) }.but_got(self)
}
}
}
impl<V, R> MustBeInRange<R> for V
where V: Copy + Sized + Debug + PartialOrd,
R: Debug + RangeArgument<V>
{
}
fn is_in_range<I, R>(item: I, range: &R) -> bool
where I: Debug + Copy + PartialOrd,
R: Debug + RangeArgument<I>
{
if let Some(start) = range.start() {
if item < *start {
return false;
}
}
if let Some(end) = range.end() {
if item >= *end {
return false;
}
}
true
}
#[test]
fn test_is_in_range() {
assert_eq!(true, is_in_range(1, &(1..)), "1 is in [1, _)");
assert_eq!(true, is_in_range(1, &(..10)), "1 is in [_, 10)");
assert_eq!(true, is_in_range(1, &(..)), "1 is in [_, _)");
assert_eq!(false, is_in_range(10, &(..10)), "10 is not in [_, 10)");
}
fn _assert() {
fn in_range<T: MustBeInRange<R>, R: Debug + RangeArgument<T>>() {}
use std::ops::{Range, RangeFrom, RangeFull, RangeTo};
in_range::<i32, Range<i32>>();
in_range::<i32, RangeTo<i32>>();
in_range::<i32, RangeFull>();
in_range::<i32, RangeFrom<i32>>();
in_range::<u64, Range<u64>>();
}