Skip to main content

fast_mesh_scene/
error.rs

1//! Errors reported by the scene.
2
3use std::fmt;
4
5use fast_mesh_bvh::BvhError;
6use fast_mesh_fields::FieldsError;
7use fast_mesh_ops::OpsError;
8use fast_mesh_query::QueryError;
9use fast_mesh_store::StoreError;
10
11use crate::MeshId;
12
13/// Why a scene operation could not run. A failed operation leaves the scene
14/// unchanged.
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub enum SceneError {
17    /// The id is stale: its mesh was removed.
18    UnknownMesh,
19    /// The field id is unknown: the field was removed, by hand or with the
20    /// mesh it was on or measured to.
21    UnknownField,
22    /// The section id is unknown: the section was removed.
23    UnknownSection,
24    /// The mesh's BVH is out of date and its update mode forbids updating it
25    /// implicitly.
26    StaleBvh(MeshId),
27    /// An argument was invalid (non-finite, not a rotation and so on).
28    InvalidInput(&'static str),
29    /// There is no open history step to end or cancel.
30    StepNotOpen,
31    /// An internal invariant was found broken.
32    Corrupted,
33    /// The mesh store reported an error (including `OutOfMemory`).
34    Store(StoreError),
35    /// The BVH reported an error (including `OutOfMemory`).
36    Bvh(BvhError),
37    /// A query reported an error (including `OutOfMemory`).
38    Query(QueryError),
39    /// A field kernel reported an error (including `OutOfMemory`).
40    Fields(FieldsError),
41    /// A repair operation run through [`Scene::edit`](crate::Scene::edit)
42    /// failed (including `OutOfMemory`).
43    Ops(OpsError),
44}
45
46impl fmt::Display for SceneError {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        match self {
49            SceneError::UnknownMesh => f.write_str("unknown or removed mesh id"),
50            SceneError::UnknownField => f.write_str("unknown or removed field id"),
51            SceneError::UnknownSection => f.write_str("unknown or removed section id"),
52            SceneError::StaleBvh(id) => write!(f, "the BVH of mesh {id:?} is out of date"),
53            SceneError::InvalidInput(what) => write!(f, "invalid input: {what}"),
54            SceneError::StepNotOpen => f.write_str("no history step is open"),
55            SceneError::Corrupted => f.write_str("scene state is corrupted"),
56            SceneError::Store(e) => write!(f, "mesh store error: {e}"),
57            SceneError::Bvh(e) => write!(f, "BVH error: {e}"),
58            SceneError::Query(e) => write!(f, "query error: {e}"),
59            SceneError::Fields(e) => write!(f, "field error: {e}"),
60            SceneError::Ops(e) => write!(f, "repair operation failed: {e}"),
61        }
62    }
63}
64
65impl std::error::Error for SceneError {
66    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
67        match self {
68            SceneError::Store(e) => Some(e),
69            SceneError::Bvh(e) => Some(e),
70            SceneError::Query(e) => Some(e),
71            SceneError::Fields(e) => Some(e),
72            SceneError::Ops(e) => Some(e),
73            _ => None,
74        }
75    }
76}
77
78impl From<StoreError> for SceneError {
79    fn from(e: StoreError) -> Self {
80        SceneError::Store(e)
81    }
82}
83
84impl From<BvhError> for SceneError {
85    fn from(e: BvhError) -> Self {
86        SceneError::Bvh(e)
87    }
88}
89
90impl From<QueryError> for SceneError {
91    fn from(e: QueryError) -> Self {
92        SceneError::Query(e)
93    }
94}
95
96impl From<FieldsError> for SceneError {
97    fn from(e: FieldsError) -> Self {
98        SceneError::Fields(e)
99    }
100}
101
102impl From<OpsError> for SceneError {
103    fn from(e: OpsError) -> Self {
104        // Out-of-memory arrives as one variant, however it was raised.
105        match e {
106            OpsError::Store(StoreError::OutOfMemory) => SceneError::Store(StoreError::OutOfMemory),
107            e => SceneError::Ops(e),
108        }
109    }
110}
111
112/// `Result` with [`SceneError`] as the error type.
113pub type Result<T> = std::result::Result<T, SceneError>;
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118
119    #[test]
120    fn ops_out_of_memory_maps_to_store() {
121        // Out-of-memory arrives as one variant, however it was raised.
122        assert_eq!(
123            SceneError::from(OpsError::Store(StoreError::OutOfMemory)),
124            SceneError::Store(StoreError::OutOfMemory)
125        );
126        assert_eq!(
127            SceneError::from(OpsError::StaleLoops),
128            SceneError::Ops(OpsError::StaleLoops)
129        );
130    }
131}