Skip to main content

ifc_approval/
error.rs

1//! Typed failures for bounded approval semantics.
2
3use ifc_model::EntityId;
4use ifc_schema::SchemaVersion;
5use thiserror::Error;
6
7/// Approval projection or authoring failure.
8#[derive(Debug, Clone, PartialEq, Error)]
9#[non_exhaustive]
10pub enum ApprovalError {
11    /// Entity kind differs from the requested projection.
12    #[error("expected {expected}, found {actual}")]
13    WrongEntityType {
14        /// Expected IFC entity.
15        expected: &'static str,
16        /// Actual IFC entity.
17        actual: String,
18    },
19    /// Required positional attribute is absent or null.
20    #[error("{entity} {id} is missing {attribute}")]
21    MissingAttribute {
22        /// Entity kind.
23        entity: &'static str,
24        /// Entity identifier.
25        id: EntityId,
26        /// Attribute name.
27        attribute: &'static str,
28    },
29    /// Attribute has the wrong value shape or cardinality.
30    #[error("{entity} {id}.{attribute} is invalid: {value}")]
31    InvalidValue {
32        /// Entity kind.
33        entity: &'static str,
34        /// Entity identifier.
35        id: EntityId,
36        /// Attribute name.
37        attribute: &'static str,
38        /// Diagnostic value.
39        value: String,
40    },
41    /// Requested entity is absent.
42    #[error("entity {id} does not exist")]
43    UnknownEntity {
44        /// Missing identifier.
45        id: EntityId,
46    },
47    /// Authored or projected reference does not resolve.
48    #[error("{entity} {id}.{attribute} reference {target} does not resolve")]
49    DanglingReference {
50        /// Relationship or record kind.
51        entity: &'static str,
52        /// Owning entity identifier.
53        id: EntityId,
54        /// Attribute name.
55        attribute: &'static str,
56        /// Missing target.
57        target: EntityId,
58    },
59    /// Resolved reference is outside the declared IFC SELECT/type.
60    #[error("{entity} {id}.{attribute} target {target} has {actual}, expected {expected}")]
61    ReferenceType {
62        /// Relationship or record kind.
63        entity: &'static str,
64        /// Owning entity identifier.
65        id: EntityId,
66        /// Attribute name.
67        attribute: &'static str,
68        /// Referenced target.
69        target: EntityId,
70        /// Expected entity or SELECT.
71        expected: &'static str,
72        /// Actual entity kind.
73        actual: String,
74    },
75    /// Declared WHERE-style rule failed.
76    #[error("{entity} {id} violates {rule}: {detail}")]
77    Semantic {
78        /// Entity kind.
79        entity: &'static str,
80        /// Entity identifier.
81        id: EntityId,
82        /// Bounded rule name.
83        rule: &'static str,
84        /// Human-readable detail.
85        detail: String,
86    },
87    /// Draft value is invalid before staging.
88    #[error("cannot author {entity}.{attribute}: {value}")]
89    AuthoringInvalid {
90        /// Entity kind.
91        entity: &'static str,
92        /// Attribute or rule.
93        attribute: &'static str,
94        /// Rejected value.
95        value: String,
96    },
97    /// Draft reference is outside the required entity/SELECT.
98    #[error("authoring target {target} has {actual}, expected {expected}")]
99    AuthoringReferenceType {
100        /// Referenced target.
101        target: EntityId,
102        /// Expected entity or SELECT.
103        expected: &'static str,
104        /// Actual entity kind.
105        actual: String,
106    },
107    /// The model's header declares several schemas; authoring binds to
108    /// exactly one release.
109    #[error("the header declares {schemas} schemas; authoring binds to exactly one")]
110    MultipleSchemas {
111        /// Number of `FILE_SCHEMA` declarations.
112        schemas: usize,
113    },
114    /// The model's header declares one schema this crate is not verified
115    /// against (anything but IFC2X3, IFC4 and IFC4X3), so no layout can be
116    /// trusted. Never read or written as another release.
117    #[error("the header declares {schema}, which this crate is not verified against")]
118    UnsupportedSchema {
119        /// The `FILE_SCHEMA` token as written.
120        schema: String,
121    },
122    /// An accessor asked for an attribute the model's release does not
123    /// declare, such as `RequestingApproval` on an IFC2X3 `IfcApproval`.
124    /// Never read from the slot another release gives it (#212).
125    #[error("{entity} {id}.{attribute} is not defined by {schema:?}")]
126    NotInSchema {
127        /// Entity kind.
128        entity: &'static str,
129        /// Entity identifier.
130        id: EntityId,
131        /// The attribute, by this crate's (IFC4) name.
132        attribute: &'static str,
133        /// The release the model is read against.
134        schema: SchemaVersion,
135    },
136    /// A text accessor met an attribute the release types as an entity
137    /// record, such as the IFC2X3 `IfcApproval.ApprovalDateTime`, an
138    /// `IfcDateTimeSelect`. The value is valid; read it through `target`.
139    #[error("{entity} {id}.{attribute} is the record {target}, not text")]
140    StructuredValue {
141        /// Entity kind.
142        entity: &'static str,
143        /// Entity identifier.
144        id: EntityId,
145        /// The attribute, by this crate's (IFC4) name.
146        attribute: &'static str,
147        /// The entity record holding the value.
148        target: EntityId,
149    },
150    /// The model's release does not declare this entity, such as
151    /// `IfcResourceApprovalRelationship` in IFC2X3.
152    #[error("{entity} is not an instantiable entity of {schema:?}")]
153    EntityNotInSchema {
154        /// The entity type.
155        entity: &'static str,
156        /// The release the model declares.
157        schema: SchemaVersion,
158    },
159    /// A draft supplied a value for an attribute the model's release does
160    /// not declare, such as a `Status` for an IFC2X3 `IfcApproval`. It is
161    /// refused rather than dropped.
162    #[error("cannot author {entity}.{attribute}: not defined by {schema:?}")]
163    AuthoringNotInSchema {
164        /// The entity type being authored.
165        entity: &'static str,
166        /// The attribute, by this crate's (IFC4) name.
167        attribute: &'static str,
168        /// The release the model declares.
169        schema: SchemaVersion,
170    },
171    /// A draft supplied a value in a form the release's declaration cannot
172    /// hold, such as text where IFC2X3 declares an `IfcDateTimeSelect`
173    /// record, or several related approvals where IFC2X3 declares one.
174    #[error("cannot author {entity}.{attribute}: {schema:?} declares {declared}")]
175    AuthoringValueType {
176        /// The entity type being authored.
177        entity: &'static str,
178        /// The attribute, by this crate's (IFC4) name.
179        attribute: &'static str,
180        /// The type the release declares.
181        declared: &'static str,
182        /// The release the model declares.
183        schema: SchemaVersion,
184    },
185    /// The model's release requires an attribute the authoring call leaves
186    /// unset, such as the IFC2X3 `IfcRoot.OwnerHistory`.
187    #[error("cannot author {entity}: {schema:?} requires {attribute}")]
188    AuthoringRequired {
189        /// The entity type being authored.
190        entity: &'static str,
191        /// The required attribute, as the release names it.
192        attribute: &'static str,
193        /// The release the model declares.
194        schema: SchemaVersion,
195    },
196}
197
198/// Result alias for approval operations.
199pub type ApprovalResult<T> = Result<T, ApprovalError>;