use std::{
fmt::{self, Display},
ops::{Bound, RangeBounds},
};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct RangeOutOfBoundsError {
use_check_to_instantiate: (),
}
impl RangeOutOfBoundsError {
pub fn check<R>(range: &R, len: usize) -> Result<(), Self>
where
R: RangeBounds<usize>,
{
let start = match range.start_bound() {
Bound::Included(&start) => start,
Bound::Excluded(&start) => start.checked_add(1).ok_or(RangeOutOfBoundsError {
use_check_to_instantiate: (),
})?,
Bound::Unbounded => 0,
};
let end = match range.end_bound() {
Bound::Included(&end) => end.checked_add(1).ok_or(RangeOutOfBoundsError {
use_check_to_instantiate: (),
})?,
Bound::Excluded(&end) => end,
Bound::Unbounded => len,
};
if start > end || end > len {
Err(RangeOutOfBoundsError {
use_check_to_instantiate: (),
})
} else {
Ok(())
}
}
}
impl Display for RangeOutOfBoundsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self:#?}\n The range was out of bounds: Either the starting point was greater than the end point or the end point was greater than the length.")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_range_out_of_bounds_error() {
assert!(RangeOutOfBoundsError::check(&(0..7), 7).is_ok());
assert!(RangeOutOfBoundsError::check(&(0..8), 7).is_err());
}
}