1use std::fmt;
6
7pub type SpotResult<T> = Result<T, SpotError>;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum SpotError {
13 MemoryAllocationFailed = 1000,
15 LevelOutOfBounds = 1001,
17 QOutOfBounds = 1002,
19 ExcessThresholdIsNaN = 1003,
21 AnomalyThresholdIsNaN = 1004,
23 DataIsNaN = 1005,
25}
26
27impl SpotError {
28 pub fn from_code(code: i32) -> Self {
30 match code.abs() {
31 1000 => SpotError::MemoryAllocationFailed,
32 1001 => SpotError::LevelOutOfBounds,
33 1002 => SpotError::QOutOfBounds,
34 1003 => SpotError::ExcessThresholdIsNaN,
35 1004 => SpotError::AnomalyThresholdIsNaN,
36 1005 => SpotError::DataIsNaN,
37 _ => SpotError::MemoryAllocationFailed, }
39 }
40
41 pub fn message(&self) -> &'static str {
43 match self {
44 SpotError::MemoryAllocationFailed => "Memory allocation failed",
45 SpotError::LevelOutOfBounds => {
46 "The level parameter is out of bounds (it must be between 0 and 1, but close to 1)"
47 }
48 SpotError::QOutOfBounds => "The q parameter must between 0 and 1-level",
49 SpotError::ExcessThresholdIsNaN => "The excess threshold has not been initialized",
50 SpotError::AnomalyThresholdIsNaN => "The anomaly threshold has not been initialized",
51 SpotError::DataIsNaN => "The input data is NaN",
52 }
53 }
54
55 pub fn code(&self) -> i32 {
57 *self as i32
58 }
59}
60
61impl fmt::Display for SpotError {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 write!(f, "{}", self.message())
64 }
65}
66
67impl std::error::Error for SpotError {}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn test_error_codes_match_c() {
75 assert_eq!(SpotError::MemoryAllocationFailed.code(), 1000);
76 assert_eq!(SpotError::LevelOutOfBounds.code(), 1001);
77 assert_eq!(SpotError::QOutOfBounds.code(), 1002);
78 assert_eq!(SpotError::ExcessThresholdIsNaN.code(), 1003);
79 assert_eq!(SpotError::AnomalyThresholdIsNaN.code(), 1004);
80 assert_eq!(SpotError::DataIsNaN.code(), 1005);
81 }
82
83 #[test]
84 fn test_from_code() {
85 assert_eq!(
86 SpotError::from_code(-1000),
87 SpotError::MemoryAllocationFailed
88 );
89 assert_eq!(SpotError::from_code(-1001), SpotError::LevelOutOfBounds);
90 assert_eq!(SpotError::from_code(-1002), SpotError::QOutOfBounds);
91 assert_eq!(SpotError::from_code(-1003), SpotError::ExcessThresholdIsNaN);
92 assert_eq!(
93 SpotError::from_code(-1004),
94 SpotError::AnomalyThresholdIsNaN
95 );
96 assert_eq!(SpotError::from_code(-1005), SpotError::DataIsNaN);
97 }
98
99 #[test]
100 fn test_error_messages() {
101 assert_eq!(
102 SpotError::MemoryAllocationFailed.message(),
103 "Memory allocation failed"
104 );
105 assert_eq!(
106 SpotError::LevelOutOfBounds.message(),
107 "The level parameter is out of bounds (it must be between 0 and 1, but close to 1)"
108 );
109 }
110
111 #[test]
112 fn test_error_display() {
113 let error = SpotError::DataIsNaN;
114 assert_eq!(format!("{}", error), "The input data is NaN");
115 }
116}