wagon_value/
result.rs

1use std::error::Error;
2use std::fmt::Display;
3use crate::{Value, Valueable};
4
5/// A result type for operations on a [`Valueable`].
6///
7/// Either returns something of type `T`. Or a [`ValueError`] over `U`.
8pub type ValueResult<T, U> = Result<T, ValueError<U>>;
9
10#[derive(Debug, Eq, PartialEq, Clone)]
11/// Errors that can occur while dealing with semi-dynamic [`Value`]s.
12///
13/// A [`ValueError<Value<T>>`] can be automatically converted into a [`ValueError<T>`] when you are 
14/// implementing your own [`Valueable`] type, but the compiler may require some manual convincing to get it to work
15/// (as in, you will have to call `from` manually).
16pub enum ValueError<T: Valueable> {
17    /// Something horrible happened for which we have no specific error.
18    Fatal(String),
19    /// Tried to perform some operation on two incompatible values.
20    OperationError(T, T, String),
21    /// Tried to perform an operation on a float which is NaN.
22    FloatIsNan(ordered_float::FloatIsNan),
23    /// Tried to convert something from an int and failed.
24    IntConversionError(std::num::TryFromIntError),
25    /// This type can not be negated.
26    NegationError(T),
27    /// Tried to compare a value to another value and failed.
28    ComparisonError(T, T),
29    /// Tried to convert `T` to [`Value`] but failed
30    ConversionError(T),
31}
32
33impl<T: Valueable> Error for ValueError<T> {
34    fn source(&self) -> Option<&(dyn Error + 'static)> {
35        match self {
36            Self::FloatIsNan(e) => Some(e),
37            Self::IntConversionError(e) => Some(e),
38            _ => None
39        }
40    }
41}
42
43impl<T: Valueable> Display for ValueError<T> {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        match self {
46            Self::Fatal(s) => write!(f, "{s}"),
47            Self::OperationError(v1, v2, o) => write!(f, "Can not perform {o} on values of type {v1:?} and {v2:?}"),
48            Self::FloatIsNan(e) => e.fmt(f),
49            Self::IntConversionError(e) => e.fmt(f),
50            Self::NegationError(v) => write!(f, "Can not negate value of type {v:?}"),
51            Self::ComparisonError(v1, v2) => write!(f, "Can not compare value of type {v1:?} with value of type {v2:?}"),
52            Self::ConversionError(v) => write!(f, "Unable to convert {v:?} to inner value type")
53        }
54    }
55}
56
57impl<T: Valueable> From<ordered_float::FloatIsNan> for ValueError<T> {
58    fn from(value: ordered_float::FloatIsNan) -> Self {
59        Self::FloatIsNan(value)
60    }
61}
62
63impl<T: Valueable> From<std::num::TryFromIntError> for ValueError<T> {
64    fn from(value: std::num::TryFromIntError) -> Self {
65        Self::IntConversionError(value)
66    }
67}
68
69impl<T: Valueable + From<Value<T>>> From<ValueError<Value<T>>> for ValueError<T> {
70    fn from(value: ValueError<Value<T>>) -> Self {
71        match value {
72            ValueError::Fatal(f) => Self::Fatal(f),
73            ValueError::OperationError(v1, v2, o) => Self::OperationError(T::from(v1), T::from(v2), o),
74            ValueError::FloatIsNan(e) => Self::FloatIsNan(e),
75            ValueError::IntConversionError(e) => Self::IntConversionError(e),
76            ValueError::NegationError(v) => Self::NegationError(T::from(v)),
77            ValueError::ComparisonError(v1, v2) => Self::ComparisonError(T::from(v1), T::from(v2)),
78            ValueError::ConversionError(v) => Self::ConversionError(T::from(v))
79        }
80    }
81}
82
83impl<T: Valueable> From<std::convert::Infallible> for ValueError<T> {
84    fn from(e: std::convert::Infallible) -> Self {
85        Self::Fatal(format!("Got an error from infallible, which should be impossible: {e:?}"))
86    }
87}