1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//! Typed failures while interpreting or authoring IFC external references.
use ifc_model::EntityId;
use ifc_schema::SchemaVersion;
use thiserror::Error;
/// Failure decoding, cross-checking, or authoring classification/document/library records.
#[derive(Debug, Clone, PartialEq, Error)]
#[non_exhaustive]
pub enum ClassificationError {
/// Entity did not have the expected IFC type.
#[error("expected {expected}, found {actual}")]
WrongEntityType {
/// IFC type name expected at this position.
expected: &'static str,
/// IFC type name actually found.
actual: String,
},
/// A required attribute was unset (`$` or `*`) or absent.
#[error("{entity} {id} is missing required attribute {attribute}")]
MissingAttribute {
/// IFC entity type of the offending instance.
entity: &'static str,
/// Id of the offending instance.
id: EntityId,
/// Name of the missing attribute.
attribute: &'static str,
},
/// An attribute was present but failed to decode as its expected shape.
#[error("{entity} {id} has invalid {attribute}: {value}")]
InvalidValue {
/// IFC entity type of the offending instance.
entity: &'static str,
/// Id of the offending instance.
id: EntityId,
/// Name of the invalid attribute.
attribute: &'static str,
/// Debug rendering of the offending value.
value: String,
},
/// A referenced entity id does not exist in the model.
#[error("entity {id} does not exist")]
UnknownEntity {
/// Id that could not be resolved.
id: EntityId,
},
/// An attribute reference points at an id that is not present in the model.
#[error("{entity} {id}.{attribute} reference {target} does not resolve")]
DanglingReference {
/// IFC entity type holding the dangling reference.
entity: &'static str,
/// Id of the entity holding the dangling reference.
id: EntityId,
/// Name of the attribute holding the dangling reference.
attribute: &'static str,
/// Id that could not be resolved.
target: EntityId,
},
/// An attribute reference resolves but the target entity has the wrong type for its select.
#[error("{entity} {id}.{attribute} reference {target} has type {actual}, expected {expected}")]
ReferenceType {
/// IFC entity type holding the mistyped reference.
entity: &'static str,
/// Id of the entity holding the mistyped reference.
id: EntityId,
/// Name of the attribute holding the mistyped reference.
attribute: &'static str,
/// Id of the mistyped target.
target: EntityId,
/// Select or type name the target was expected to satisfy.
expected: &'static str,
/// IFC type name the target actually has.
actual: String,
},
/// Following `ReferencedSource` links revisited an already-seen entity.
#[error("classification hierarchy contains a cycle: {path:?}")]
Cycle {
/// Entity ids on the cycle, in traversal order.
path: Vec<EntityId>,
},
/// Hierarchy traversal exceeded the caller-supplied node or depth budget.
#[error("classification hierarchy exceeded max_depth={max_depth} or max_nodes={max_nodes}")]
BudgetExceeded {
/// Maximum edge depth allowed.
max_depth: usize,
/// Maximum number of nodes allowed.
max_nodes: usize,
},
/// An occurrence object is related to more than one `IfcRelDefinesByType` type.
#[error("object {object} has {count} assigned IFC types")]
AmbiguousType {
/// The occurrence object with the ambiguous type assignment.
object: EntityId,
/// Number of types the object was found related to.
count: usize,
},
/// A draft value failed schema validation before staging.
#[error("cannot author {entity}.{attribute}: {value}")]
AuthoringInvalid {
/// IFC entity type being authored.
entity: &'static str,
/// Name of the offending attribute.
attribute: &'static str,
/// Description of why the value is invalid.
value: String,
},
/// A draft reference resolves to a staged or committed entity of the wrong type.
#[error("authoring reference {target} has type {actual}, expected {expected}")]
AuthoringReferenceType {
/// Id of the mistyped reference target.
target: EntityId,
/// Select or type name the target was expected to satisfy.
expected: &'static str,
/// IFC type name the target actually has.
actual: String,
},
/// The header declares several schemas, one of them IFC2X3, so no single
/// release can be bound to read the model against.
#[error("the header declares {schemas} schemas; classification reads bind to exactly one")]
MultipleSchemas {
/// Number of `FILE_SCHEMA` declarations.
schemas: usize,
},
/// The release the model is read against does not define this attribute
/// or record, for example `Description` on an IFC2X3 `IfcClassification`
/// or any `IfcExternalReferenceRelationship` in an IFC2X3 model. This is
/// never reported as an unset (`None`) value.
#[error("{entity} {id}.{attribute} is not defined by {schema:?}")]
NotInSchema {
/// IFC entity type of the instance.
entity: &'static str,
/// Id of the instance.
id: EntityId,
/// Attribute name, as this crate's accessor names it.
attribute: &'static str,
/// The release the model is read against.
schema: SchemaVersion,
},
/// A text accessor met an attribute the bound release types as an entity
/// record, such as an IFC2X3 `IfcCalendarDate` edition date. The value is
/// valid; read it structurally through `target`.
#[error("{entity} {id}.{attribute} is the record {target}, not text")]
StructuredValue {
/// IFC entity type of the instance.
entity: &'static str,
/// Id of the instance.
id: EntityId,
/// Attribute name.
attribute: &'static str,
/// The entity record holding the value.
target: EntityId,
},
}
/// Result of a classification/document/library query or authoring operation.
pub type ClassificationResult<T> = Result<T, ClassificationError>;