1use thiserror::Error;
2
3#[derive(Debug, Error)]
4pub enum FerroxError {
5 #[error("solver returned infeasible")]
6 Infeasible,
7 #[error("solver returned unbounded")]
8 Unbounded,
9 #[error("model invalid: {0}")]
10 ModelInvalid(String),
11 #[error("solver error")]
12 SolverError,
13 #[error("serialization error: {0}")]
14 Serde(#[from] serde_json::Error),
15 #[error("no pending request")]
16 NoPendingRequest,
17}
18
19pub type Result<T> = std::result::Result<T, FerroxError>;
20
21#[cfg(test)]
22#[allow(clippy::unnecessary_wraps)]
23mod tests {
24 use super::*;
25
26 #[test]
27 fn display_formats_known_variants() {
28 assert_eq!(
29 FerroxError::Infeasible.to_string(),
30 "solver returned infeasible"
31 );
32 assert_eq!(
33 FerroxError::Unbounded.to_string(),
34 "solver returned unbounded"
35 );
36 assert!(
37 FerroxError::ModelInvalid("bad".into())
38 .to_string()
39 .contains("bad")
40 );
41 assert_eq!(FerroxError::SolverError.to_string(), "solver error");
42 assert_eq!(
43 FerroxError::NoPendingRequest.to_string(),
44 "no pending request"
45 );
46 }
47
48 #[test]
49 fn from_serde_json_error() {
50 let bad: serde_json::Error = serde_json::from_str::<i32>("not json").unwrap_err();
51 let err: FerroxError = bad.into();
52 assert!(matches!(err, FerroxError::Serde(_)));
53 assert!(err.to_string().contains("serialization"));
54 }
55
56 #[test]
57 fn result_alias_resolves() {
58 fn ok() -> Result<i32> {
59 Ok(7)
60 }
61 assert_eq!(ok().unwrap(), 7);
62 }
63}