Skip to main content

uclicious/
error.rs

1//! Low level library that could be returned by the parser.
2//! Based on <https://github.com/draft6/libucl-rs>
3
4use std::error::Error;
5use std::fmt;
6
7use libucl_bind::{ucl_error_t, ucl_schema_error_code};
8
9/// An error returned by a generated builder's `build()` method.
10///
11/// Implements `Send + Sync` and retains the underlying error as its source,
12/// so applications can add context with `anyhow::Context`.
13#[derive(Debug, thiserror::Error)]
14pub enum BuildError {
15    /// The parser could not produce a root object.
16    #[error("{0}")]
17    Parser(#[from] UclError),
18    /// Converting or validating the parsed object failed.
19    #[error("{0}")]
20    Object(#[from] crate::ObjectError),
21}
22
23#[derive(Copy, Clone, Debug, Eq, PartialEq)]
24pub enum UclErrorType {
25    Ok,
26    Syntax,
27    Io,
28    State,
29    Nested,
30    Macro,
31    Internal,
32    SSL,
33    Other,
34}
35
36impl UclErrorType {
37    pub fn from_code(num: i32, desc: String) -> UclError {
38        match num {
39            _ if num == ucl_error_t::UCL_EOK as i32 => UclError {
40                code: UclErrorType::Ok,
41                desc,
42            },
43            _ if num == ucl_error_t::UCL_ESYNTAX as i32 => UclError {
44                code: UclErrorType::Syntax,
45                desc,
46            },
47            _ if num == ucl_error_t::UCL_EIO as i32 => UclError {
48                code: UclErrorType::Io,
49                desc,
50            },
51            _ if num == ucl_error_t::UCL_ESTATE as i32 => UclError {
52                code: UclErrorType::State,
53                desc,
54            },
55            _ if num == ucl_error_t::UCL_ENESTED as i32 => UclError {
56                code: UclErrorType::Nested,
57                desc,
58            },
59            _ if num == ucl_error_t::UCL_EMACRO as i32 => UclError {
60                code: UclErrorType::Macro,
61                desc,
62            },
63            _ if num == ucl_error_t::UCL_EINTERNAL as i32 => UclError {
64                code: UclErrorType::Internal,
65                desc,
66            },
67            _ if num == ucl_error_t::UCL_ESSL as i32 => UclError {
68                code: UclErrorType::SSL,
69                desc,
70            },
71            _ => UclError {
72                code: UclErrorType::Other,
73                desc,
74            },
75        }
76    }
77}
78
79#[derive(Clone, Debug, Eq, PartialEq)]
80pub struct UclError {
81    code: UclErrorType,
82    desc: String,
83}
84
85impl fmt::Display for UclError {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        write!(f, "{}", self.desc)
88    }
89}
90
91impl Error for UclError {
92    fn description(&self) -> &str {
93        self.desc.as_ref()
94    }
95
96    fn cause(&self) -> Option<&dyn Error> {
97        None
98    }
99}
100
101impl UclError {
102    pub fn boxed(self) -> Box<UclError> {
103        Box::new(self)
104    }
105
106    pub fn kind(&self) -> UclErrorType {
107        self.code
108    }
109}
110
111#[derive(Clone, Debug, Eq, PartialEq)]
112pub enum UclSchemaErrorType {
113    Ok,
114    TypeMismatch,
115    InvalidSchema,
116    MissingProperty,
117    Constraint,
118    MissingDependency,
119    Other,
120}
121
122impl UclSchemaErrorType {
123    pub fn from_code(num: i32, desc: String) -> UclSchemaError {
124        match num {
125            _ if num == ucl_schema_error_code::UCL_SCHEMA_OK as i32 => UclSchemaError {
126                code: UclSchemaErrorType::Ok,
127                desc,
128            },
129            _ if num == ucl_schema_error_code::UCL_SCHEMA_TYPE_MISMATCH as i32 => UclSchemaError {
130                code: UclSchemaErrorType::TypeMismatch,
131                desc,
132            },
133            _ if num == ucl_schema_error_code::UCL_SCHEMA_INVALID_SCHEMA as i32 => UclSchemaError {
134                code: UclSchemaErrorType::InvalidSchema,
135                desc,
136            },
137            _ if num == ucl_schema_error_code::UCL_SCHEMA_MISSING_PROPERTY as i32 => {
138                UclSchemaError {
139                    code: UclSchemaErrorType::MissingProperty,
140                    desc,
141                }
142            }
143            _ if num == ucl_schema_error_code::UCL_SCHEMA_CONSTRAINT as i32 => UclSchemaError {
144                code: UclSchemaErrorType::Constraint,
145                desc,
146            },
147            _ if num == ucl_schema_error_code::UCL_SCHEMA_MISSING_DEPENDENCY as i32 => {
148                UclSchemaError {
149                    code: UclSchemaErrorType::MissingDependency,
150                    desc,
151                }
152            }
153            _ => UclSchemaError {
154                code: UclSchemaErrorType::Other,
155                desc,
156            },
157        }
158    }
159}
160
161#[derive(Clone, Debug, Eq, PartialEq)]
162pub struct UclSchemaError {
163    pub code: UclSchemaErrorType,
164    pub desc: String,
165}
166
167impl fmt::Display for UclSchemaError {
168    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169        write!(f, "{}", self.desc)
170    }
171}
172
173impl Error for UclSchemaError {
174    fn description(&self) -> &str {
175        self.desc.as_ref()
176    }
177
178    fn cause(&self) -> Option<&dyn Error> {
179        None
180    }
181}