trs_dataframe/
error.rs

1use smartstring::alias::String as SString;
2use thiserror::Error as ThisError;
3
4use crate::Key;
5
6#[derive(Debug, ThisError)]
7pub enum Error {
8    #[error("Empty dataset")]
9    EmptyData,
10    #[error("Dataset size doesn't match expected: {0}, get: {1}")]
11    DataSetSizeDoesntMatch(usize, usize),
12    #[error("Dataset size doesn't match idx: {0}, size of data: {1}")]
13    IndexOutOfRange(usize, usize),
14    #[error("Indexes are out of order expected: {0:?}, get: {1:?}")]
15    IndexOutOfOrder(Vec<Key>, Vec<Key>),
16    #[error("Cannot find candidate: {0}")]
17    Candidate(SString),
18    #[error("Cannot find key: {0}")]
19    NotFound(Key),
20    #[error("Column already exists: {0}")]
21    ColumnAlreadyExists(Key),
22    #[error("Cannot broadcast data")]
23    CannotBroadcast,
24    #[error("Cannot find feature: {0}")]
25    FeatureSearch(SString),
26    #[error("Invalid operation for feature: {operation} with features: {features:?}")]
27    InvalidOperation {
28        operation: SString,
29        features: Vec<SString>,
30    },
31    #[error("Unknown error: {0}")]
32    UnknownError(String),
33    #[error("IOError {0}")]
34    IOError(#[from] std::io::Error),
35    #[cfg(feature = "python")]
36    #[error("PyO3 error: {0}")]
37    PyO3(#[from] pyo3::prelude::PyErr),
38    #[error("{0}")]
39    Shape(#[from] ndarray::ShapeError),
40    #[error("Cannot find feature: {0}")]
41    MissingField(SString),
42    #[cfg(feature = "polars-df")]
43    #[error("Polars error {0}")]
44    Polars(#[from] polars::error::PolarsError),
45
46    #[error("Filter expression: {0}")]
47    Filter(#[from] crate::filter::error::Error),
48}
49
50impl PartialEq for Error {
51    fn eq(&self, other: &Self) -> bool {
52        match (self, other) {
53            (Self::EmptyData, Self::EmptyData) => true,
54            (Self::NotFound(a), Self::NotFound(b)) => a == b,
55            (Self::DataSetSizeDoesntMatch(a, b), Self::DataSetSizeDoesntMatch(c, d)) => {
56                a == c && b == d
57            }
58            (Self::IndexOutOfRange(a, b), Self::IndexOutOfRange(c, d)) => a == c && b == d,
59            (Self::IndexOutOfOrder(a, b), Self::IndexOutOfOrder(c, d)) => a == c && b == d,
60            (Self::Candidate(a), Self::Candidate(b)) => a == b,
61            (Self::FeatureSearch(a), Self::FeatureSearch(b)) => a == b,
62            (Self::MissingField(a), Self::MissingField(b)) => a == b,
63            (Self::UnknownError(a), Self::UnknownError(b)) => a == b,
64            (
65                Self::InvalidOperation {
66                    operation: a,
67                    features: b,
68                },
69                Self::InvalidOperation {
70                    operation: c,
71                    features: d,
72                },
73            ) => a == c && b == d,
74            (Self::IOError(a), Self::IOError(b)) => a.kind() == b.kind(),
75            (Self::ColumnAlreadyExists(a), Self::ColumnAlreadyExists(b)) => a == b,
76            (Self::CannotBroadcast, Self::CannotBroadcast) => true,
77            #[cfg(feature = "python")]
78            (Self::PyO3(a), Self::PyO3(b)) => a.to_string() == b.to_string(),
79            #[cfg(feature = "polars-df")]
80            (Self::Polars(a), Self::Polars(b)) => a.to_string() == b.to_string(),
81            _ => false,
82        }
83    }
84}
85
86#[cfg(test)]
87mod test {
88    #[cfg(feature = "python")]
89    use pyo3::{exceptions::PyValueError, PyErr};
90
91    use super::*;
92    #[test]
93    fn test_error() {
94        let err1 = Error::EmptyData;
95        assert_eq!(err1, Error::EmptyData);
96        let err = Error::DataSetSizeDoesntMatch(1, 2);
97        assert_eq!(err, Error::DataSetSizeDoesntMatch(1, 2));
98        assert_ne!(err1, err);
99        let err = Error::IndexOutOfRange(1, 2);
100        assert_eq!(err, Error::IndexOutOfRange(1, 2));
101        let err = Error::Candidate("test".into());
102        assert_eq!(err, Error::Candidate("test".into()));
103        let err = Error::FeatureSearch("test".into());
104        assert_eq!(err, Error::FeatureSearch("test".into()));
105        let err = Error::UnknownError("test".into());
106        assert_eq!(err, Error::UnknownError("test".into()));
107        let err = Error::MissingField("test".into());
108        assert_eq!(err, Error::MissingField("test".into()));
109        assert_eq!(
110            Error::NotFound("test".into()),
111            Error::NotFound("test".into())
112        );
113        assert_eq!(Error::CannotBroadcast, Error::CannotBroadcast);
114        assert_eq!(
115            Error::ColumnAlreadyExists("test".into()),
116            Error::ColumnAlreadyExists("test".into())
117        );
118        assert_eq!(
119            Error::IndexOutOfOrder(vec!["test".into()], vec!["test".into()]),
120            Error::IndexOutOfOrder(vec!["test".into()], vec!["test".into()])
121        );
122        let err = Error::IOError(std::io::Error::new(std::io::ErrorKind::Other, "test"));
123        assert_eq!(
124            err,
125            Error::IOError(std::io::Error::new(std::io::ErrorKind::Other, "test"))
126        );
127        let err = Error::InvalidOperation {
128            operation: "test".into(),
129            features: vec!["test".into()],
130        };
131        assert_eq!(
132            err,
133            Error::InvalidOperation {
134                operation: "test".into(),
135                features: vec!["test".into()],
136            }
137        );
138        #[cfg(feature = "python")]
139        {
140            let err = Error::PyO3(PyErr::new::<PyValueError, _>("foo"));
141            assert_eq!(err, Error::PyO3(PyErr::new::<PyValueError, _>("foo")));
142        }
143        #[cfg(feature = "polars-df")]
144        {
145            let err = Error::Polars(polars::error::PolarsError::ColumnNotFound("e".into()));
146            assert_eq!(
147                err,
148                Error::Polars(polars::error::PolarsError::ColumnNotFound("e".into()))
149            );
150        }
151    }
152}