use std::error::Error;
use std::fmt::Display;
use num::Complex;
use crate::Unit;
#[derive(Debug, Clone, PartialEq, Default)]
#[repr(C)]
pub struct UnitsNotEqual(pub Unit, pub Unit);
impl Display for UnitsNotEqual {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "unit {} not equal to unit {}", self.0, self.1)
}
}
impl Error for UnitsNotEqual {}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct RootError {
pub n: i32,
pub unit: Unit,
}
impl std::fmt::Display for RootError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"not possible to calculate the {}th root (exponents {} cannot be divided by {} without remainder)",
&self.n, &self.unit, &self.n
)
}
}
impl std::error::Error for RootError {}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct ParseError {
pub substring: String,
pub span: std::ops::Range<usize>,
pub reason: ParseErrorReason,
}
impl std::fmt::Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "could not parse {}: {}", &self.substring, &self.reason)
}
}
#[derive(Default, Debug, Clone, PartialEq)]
#[repr(u8)]
pub enum ParseErrorReason {
UnexpectedToken,
InputIsEmpty,
UnbalancedBrackets,
TwoInnersWithoutOperator,
TwoOperatorsWithoutInner,
MustNotStartWith,
UnitsNotEqual(UnitsNotEqual),
NotConvertibleFromComplexF64(NotConvertibleFromComplexF64),
#[default]
CouldNotParse,
}
impl std::fmt::Display for ParseErrorReason {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ParseErrorReason::UnexpectedToken => {
write!(f, "unexpected token")
}
ParseErrorReason::InputIsEmpty => {
write!(f, "input is empty")
}
ParseErrorReason::CouldNotParse => write!(f, "could not parse the input"),
ParseErrorReason::UnbalancedBrackets => {
write!(f, "unbalanced number of brackets")
}
ParseErrorReason::TwoInnersWithoutOperator => {
write!(
f,
"encountered two numbers without an operator (+ or -) between them"
)
}
ParseErrorReason::TwoOperatorsWithoutInner => {
write!(
f,
"encountered two operators (+, -, * or /) without a number between them"
)
}
ParseErrorReason::UnitsNotEqual(inner) => inner.fmt(f),
ParseErrorReason::MustNotStartWith => {
write!(f, "input must not start with this token")
}
ParseErrorReason::NotConvertibleFromComplexF64(err) => err.fmt(f),
}
}
}
impl From<UnitsNotEqual> for ParseErrorReason {
fn from(value: UnitsNotEqual) -> Self {
return Self::UnitsNotEqual(value);
}
}
impl std::error::Error for ParseErrorReason {}
#[derive(Debug, Clone, PartialEq)]
pub struct NotConvertibleFromComplexF64 {
pub source: Complex<f64>,
pub target_type: &'static str,
}
impl std::fmt::Display for NotConvertibleFromComplexF64 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"could not convert from {} into target type {}",
self.source, self.target_type
)
}
}
impl std::error::Error for NotConvertibleFromComplexF64 {}
#[derive(Debug, Clone, PartialEq)]
pub enum ConversionError {
NotConvertibleFromComplexF64(NotConvertibleFromComplexF64),
UnitMismatch {
expected: Unit,
found: Unit,
},
Custom(String),
}
impl ConversionError {
pub fn custom<T: ToString>(err: T) -> Self {
return Self::Custom(err.to_string());
}
}
impl std::fmt::Display for ConversionError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ConversionError::NotConvertibleFromComplexF64(value) => return value.fmt(f),
ConversionError::UnitMismatch { expected, found } => {
write!(f, "expected {}, found {}", expected, found)
}
ConversionError::Custom(string) => {
write!(f, "{string}")
}
}
}
}
impl std::error::Error for ConversionError {}