1use std::fmt;
4
5use fast_mesh_query::QueryError;
6use fast_mesh_store::StoreError;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum OpsError {
15 Store(StoreError),
18 Query(QueryError),
20 InvalidInput(&'static str),
22 StaleLoops,
24}
25
26impl From<StoreError> for OpsError {
27 fn from(e: StoreError) -> Self {
28 OpsError::Store(e)
29 }
30}
31
32impl From<QueryError> for OpsError {
35 fn from(e: QueryError) -> Self {
36 match e {
37 QueryError::OutOfMemory => OpsError::Store(StoreError::OutOfMemory),
38 e => OpsError::Query(e),
39 }
40 }
41}
42
43impl fmt::Display for OpsError {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 match self {
46 OpsError::Store(e) => write!(f, "store error: {e}"),
47 OpsError::Query(e) => write!(f, "query error: {e}"),
48 OpsError::InvalidInput(what) => write!(f, "invalid input: {what}"),
49 OpsError::StaleLoops => {
50 f.write_str("a requested boundary loop no longer matches the mesh")
51 }
52 }
53 }
54}
55
56impl std::error::Error for OpsError {
57 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
58 match self {
59 OpsError::Store(e) => Some(e),
60 OpsError::Query(e) => Some(e),
61 _ => None,
62 }
63 }
64}
65
66pub type Result<T> = std::result::Result<T, OpsError>;
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72 use std::error::Error;
73
74 #[test]
75 fn conversions_display_and_source() {
76 let e: OpsError = StoreError::OutOfMemory.into();
77 assert_eq!(e, OpsError::Store(StoreError::OutOfMemory));
78 assert_eq!(e.to_string(), "store error: out of memory");
79 assert!(e.source().is_some());
80 let q: OpsError = QueryError::StaleBvh.into();
81 assert_eq!(q, OpsError::Query(QueryError::StaleBvh));
82 assert!(q.source().is_some());
83 let oom: OpsError = QueryError::OutOfMemory.into();
84 assert_eq!(oom, OpsError::Store(StoreError::OutOfMemory));
85 assert_eq!(
86 OpsError::InvalidInput("no bound").to_string(),
87 "invalid input: no bound"
88 );
89 assert!(OpsError::StaleLoops.source().is_none());
90 }
91}