use std::ops::Range;
use crate::argument::{
ArgumentError,
ArgumentErrorKind,
ArgumentResult,
IndexRole,
};
#[inline]
pub fn require_that<T, F>(
value: T,
path: &str,
predicate: F,
code: &str,
message: &str,
) -> ArgumentResult<T>
where
F: FnOnce(&T) -> bool,
{
if predicate(&value) {
Ok(value)
} else {
Err(ArgumentError::new(
path,
ArgumentErrorKind::Custom {
code: String::from(code),
message: String::from(message),
},
))
}
}
#[inline]
pub fn check_bounds(
path: &str,
offset: usize,
length: usize,
total_length: usize,
) -> ArgumentResult<()> {
if offset > total_length {
return Err(ArgumentError::new(
path,
ArgumentErrorKind::Bounds {
offset,
length,
total_length,
},
));
}
if length > total_length - offset {
return Err(ArgumentError::new(
path,
ArgumentErrorKind::Bounds {
offset,
length,
total_length,
},
));
}
Ok(())
}
#[inline]
pub fn check_element_index(
path: &str,
index: usize,
size: usize,
) -> ArgumentResult<usize> {
if index >= size {
return Err(ArgumentError::new(
path,
ArgumentErrorKind::Index {
index,
size,
role: IndexRole::Element,
},
));
}
Ok(index)
}
#[inline]
pub fn check_position_index(
path: &str,
index: usize,
size: usize,
) -> ArgumentResult<usize> {
if index > size {
return Err(ArgumentError::new(
path,
ArgumentErrorKind::Index {
index,
size,
role: IndexRole::Position,
},
));
}
Ok(index)
}
#[inline]
pub fn check_position_range(
path: &str,
start: usize,
end: usize,
size: usize,
) -> ArgumentResult<Range<usize>> {
if start > end {
return Err(ArgumentError::new(
path,
ArgumentErrorKind::IndexRange { start, end, size },
));
}
if end > size {
return Err(ArgumentError::new(
path,
ArgumentErrorKind::IndexRange { start, end, size },
));
}
Ok(start..end)
}