use alloc::string::String;
use core::ops::Range;
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum IndexKind {
Element,
Dimension,
}
impl IndexKind {
pub fn name(&self) -> &'static str {
match self {
IndexKind::Element => "element",
IndexKind::Dimension => "dimension",
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum BoundsError {
Generic(String),
Index {
kind: IndexKind,
index: isize,
bounds: Range<isize>,
},
}
impl BoundsError {
pub fn index(kind: IndexKind, index: isize, bounds: Range<isize>) -> Self {
Self::Index {
kind,
index,
bounds,
}
}
}
impl core::fmt::Display for BoundsError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Generic(msg) => write!(f, "BoundsError: {}", msg),
Self::Index {
kind,
index,
bounds: range,
} => write!(
f,
"BoundsError: {} {} out of bounds: {:?}",
kind.name(),
index,
range
),
}
}
}
impl core::error::Error for BoundsError {}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ExpressionError {
ParseError {
message: String,
source: String,
},
InvalidExpression {
message: String,
source: String,
},
}
impl core::fmt::Display for ExpressionError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::ParseError { message, source } => {
write!(f, "ExpressionError: ParseError: {} ({})", message, source)
}
Self::InvalidExpression { message, source } => write!(
f,
"ExpressionError: InvalidExpression: {} ({})",
message, source
),
}
}
}
impl core::error::Error for ExpressionError {}
impl ExpressionError {
pub fn parse_error(message: impl Into<String>, source: impl Into<String>) -> Self {
Self::ParseError {
message: message.into(),
source: source.into(),
}
}
pub fn invalid_expression(message: impl Into<String>, source: impl Into<String>) -> Self {
Self::InvalidExpression {
message: message.into(),
source: source.into(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::format;
use alloc::string::ToString;
#[test]
fn test_bounds_error_display() {
assert_eq!(
format!("{}", BoundsError::Generic("test".to_string())),
"BoundsError: test"
);
assert_eq!(
format!(
"{}",
BoundsError::Index {
kind: IndexKind::Element,
index: 1,
bounds: 0..2
}
),
"BoundsError: element 1 out of bounds: 0..2"
);
}
#[test]
fn test_parse_error() {
let err = ExpressionError::parse_error("test", "source");
assert_eq!(
format!("{:?}", err),
"ParseError { message: \"test\", source: \"source\" }"
);
}
#[test]
fn test_invalid_expression() {
let err = ExpressionError::invalid_expression("test", "source");
assert_eq!(
format!("{:?}", err),
"InvalidExpression { message: \"test\", source: \"source\" }"
);
}
}