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 #[error("Cast to type failed {0:?}")]
49 CastFailed(Vec<(Key, String)>),
50}
51
52impl PartialEq for Error {
53 fn eq(&self, other: &Self) -> bool {
54 match (self, other) {
55 (Self::EmptyData, Self::EmptyData) => true,
56 (Self::NotFound(a), Self::NotFound(b)) => a == b,
57 (Self::DataSetSizeDoesntMatch(a, b), Self::DataSetSizeDoesntMatch(c, d)) => {
58 a == c && b == d
59 }
60 (Self::IndexOutOfRange(a, b), Self::IndexOutOfRange(c, d)) => a == c && b == d,
61 (Self::IndexOutOfOrder(a, b), Self::IndexOutOfOrder(c, d)) => a == c && b == d,
62 (Self::Candidate(a), Self::Candidate(b)) => a == b,
63 (Self::FeatureSearch(a), Self::FeatureSearch(b)) => a == b,
64 (Self::MissingField(a), Self::MissingField(b)) => a == b,
65 (Self::UnknownError(a), Self::UnknownError(b)) => a == b,
66 (
67 Self::InvalidOperation {
68 operation: a,
69 features: b,
70 },
71 Self::InvalidOperation {
72 operation: c,
73 features: d,
74 },
75 ) => a == c && b == d,
76 (Self::IOError(a), Self::IOError(b)) => a.kind() == b.kind(),
77 (Self::ColumnAlreadyExists(a), Self::ColumnAlreadyExists(b)) => a == b,
78 (Self::CannotBroadcast, Self::CannotBroadcast) => true,
79 #[cfg(feature = "python")]
80 (Self::PyO3(a), Self::PyO3(b)) => a.to_string() == b.to_string(),
81 #[cfg(feature = "polars-df")]
82 (Self::Polars(a), Self::Polars(b)) => a.to_string() == b.to_string(),
83 _ => false,
84 }
85 }
86}
87
88#[cfg(test)]
89mod test {
90 #[cfg(feature = "python")]
91 use pyo3::{exceptions::PyValueError, PyErr};
92
93 use super::*;
94 #[test]
95 fn test_error() {
96 let err1 = Error::EmptyData;
97 assert_eq!(err1, Error::EmptyData);
98 let err = Error::DataSetSizeDoesntMatch(1, 2);
99 assert_eq!(err, Error::DataSetSizeDoesntMatch(1, 2));
100 assert_ne!(err1, err);
101 let err = Error::IndexOutOfRange(1, 2);
102 assert_eq!(err, Error::IndexOutOfRange(1, 2));
103 let err = Error::Candidate("test".into());
104 assert_eq!(err, Error::Candidate("test".into()));
105 let err = Error::FeatureSearch("test".into());
106 assert_eq!(err, Error::FeatureSearch("test".into()));
107 let err = Error::UnknownError("test".into());
108 assert_eq!(err, Error::UnknownError("test".into()));
109 let err = Error::MissingField("test".into());
110 assert_eq!(err, Error::MissingField("test".into()));
111 assert_eq!(
112 Error::NotFound("test".into()),
113 Error::NotFound("test".into())
114 );
115 assert_eq!(Error::CannotBroadcast, Error::CannotBroadcast);
116 assert_eq!(
117 Error::ColumnAlreadyExists("test".into()),
118 Error::ColumnAlreadyExists("test".into())
119 );
120 assert_eq!(
121 Error::IndexOutOfOrder(vec!["test".into()], vec!["test".into()]),
122 Error::IndexOutOfOrder(vec!["test".into()], vec!["test".into()])
123 );
124 let err = Error::IOError(std::io::Error::new(std::io::ErrorKind::Other, "test"));
125 assert_eq!(
126 err,
127 Error::IOError(std::io::Error::new(std::io::ErrorKind::Other, "test"))
128 );
129 let err = Error::InvalidOperation {
130 operation: "test".into(),
131 features: vec!["test".into()],
132 };
133 assert_eq!(
134 err,
135 Error::InvalidOperation {
136 operation: "test".into(),
137 features: vec!["test".into()],
138 }
139 );
140 #[cfg(feature = "python")]
141 {
142 let err = Error::PyO3(PyErr::new::<PyValueError, _>("foo"));
143 assert_eq!(err, Error::PyO3(PyErr::new::<PyValueError, _>("foo")));
144 }
145 #[cfg(feature = "polars-df")]
146 {
147 let err = Error::Polars(polars::error::PolarsError::ColumnNotFound("e".into()));
148 assert_eq!(
149 err,
150 Error::Polars(polars::error::PolarsError::ColumnNotFound("e".into()))
151 );
152 }
153 }
154}