Skip to main content

ifc_spatial/authoring/
error.rs

1//! Why a spatial record was refused.
2
3use ifc_model::EntityId;
4use ifc_schema::SchemaVersion;
5
6/// Why a spatial record was refused.
7#[derive(Debug, Clone, PartialEq, Eq)]
8#[non_exhaustive]
9pub enum SpatialAuthoringError {
10    /// A value the schema constrains was not acceptable.
11    Invalid {
12        /// The entity being authored.
13        entity: &'static str,
14        /// The attribute at fault.
15        attribute: &'static str,
16        /// What was supplied.
17        value: String,
18    },
19    /// The model's header declares several schemas; release-bound
20    /// authoring binds to exactly one.
21    MultipleSchemas {
22        /// Number of `FILE_SCHEMA` declarations.
23        schemas: usize,
24    },
25    /// The model's header declares one schema with no bundled table, so no
26    /// layout can be trusted.
27    UnsupportedSchema {
28        /// The `FILE_SCHEMA` token as written.
29        schema: String,
30    },
31    /// The model's release does not declare this entity, such as
32    /// `IfcRelDeclares` in IFC2X3 or `IfcRelPositions` outside IFC4X3.
33    EntityNotInSchema {
34        /// The entity being authored.
35        entity: &'static str,
36        /// The release the model declares.
37        schema: SchemaVersion,
38    },
39    /// A value for an attribute the release does not declare. It is
40    /// refused rather than dropped.
41    AuthoringNotInSchema {
42        /// The entity being authored.
43        entity: &'static str,
44        /// The attribute, by its IFC4 name.
45        attribute: &'static str,
46        /// The release the model declares.
47        schema: SchemaVersion,
48    },
49    /// A value the release's declaration of the attribute cannot hold,
50    /// such as an IFC4 enumeration token IFC2X3 does not declare.
51    AuthoringValueType {
52        /// The entity being authored.
53        entity: &'static str,
54        /// The attribute, by its IFC4 name.
55        attribute: &'static str,
56        /// The type the release declares.
57        declared: &'static str,
58        /// The release the model declares.
59        schema: SchemaVersion,
60    },
61    /// The release requires an attribute the call leaves unset, such as
62    /// the IFC2X3 `IfcRoot.OwnerHistory` (#202). It is refused rather than
63    /// written as `$`; the `*_with_owner_history` writers take the
64    /// `IfcOwnerHistory` IFC2X3 needs.
65    AuthoringRequired {
66        /// The entity being authored.
67        entity: &'static str,
68        /// The attribute, by the release's own name.
69        attribute: &'static str,
70        /// The release the model declares.
71        schema: SchemaVersion,
72    },
73    /// A reference names an entity neither in the model nor staged.
74    MissingReference {
75        /// The entity being authored.
76        entity: &'static str,
77        /// The reference attribute.
78        attribute: &'static str,
79        /// The missing entity.
80        target: EntityId,
81    },
82    /// A reference names an entity of a type the release does not accept
83    /// there, such as an `OwnerHistory` that is not an `IfcOwnerHistory`.
84    WrongReferenceType {
85        /// The entity being authored.
86        entity: &'static str,
87        /// The reference attribute.
88        attribute: &'static str,
89        /// The referenced entity.
90        target: EntityId,
91        /// Its type.
92        actual: String,
93        /// The type expected.
94        expected: &'static str,
95    },
96}
97
98impl std::fmt::Display for SpatialAuthoringError {
99    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
100        match self {
101            Self::Invalid {
102                entity,
103                attribute,
104                value,
105            } => write!(f, "{entity}.{attribute}: {value}"),
106            Self::MultipleSchemas { schemas } => write!(
107                f,
108                "the header declares {schemas} schemas; authoring binds to exactly one"
109            ),
110            Self::UnsupportedSchema { schema } => {
111                write!(
112                    f,
113                    "the header declares {schema}, which has no bundled table"
114                )
115            }
116            Self::EntityNotInSchema { entity, schema } => {
117                write!(f, "{entity} is not an entity of {schema:?}")
118            }
119            Self::AuthoringNotInSchema {
120                entity,
121                attribute,
122                schema,
123            } => write!(
124                f,
125                "cannot author {entity}.{attribute}: not declared by {schema:?}"
126            ),
127            Self::AuthoringValueType {
128                entity,
129                attribute,
130                declared,
131                schema,
132            } => write!(
133                f,
134                "cannot author {entity}.{attribute}: {schema:?} declares it {declared}"
135            ),
136            Self::AuthoringRequired {
137                entity,
138                attribute,
139                schema,
140            } => write!(f, "cannot author {entity}: {schema:?} requires {attribute}"),
141            Self::MissingReference {
142                entity,
143                attribute,
144                target,
145            } => write!(f, "{entity}.{attribute} references missing {target}"),
146            Self::WrongReferenceType {
147                entity,
148                attribute,
149                target,
150                actual,
151                expected,
152            } => write!(
153                f,
154                "{entity}.{attribute} references {target} of type {actual}; expected {expected}"
155            ),
156        }
157    }
158}
159
160impl std::error::Error for SpatialAuthoringError {}
161
162/// Result of staging a spatial record.
163pub type SpatialAuthoringResult<T> = Result<T, SpatialAuthoringError>;
164
165pub(crate) fn invalid(
166    entity: &'static str,
167    attribute: &'static str,
168    value: impl Into<String>,
169) -> SpatialAuthoringError {
170    SpatialAuthoringError::Invalid {
171        entity,
172        attribute,
173        value: value.into(),
174    }
175}