ifc_control/error.rs
1//! Typed failures for bounded IFC control semantics.
2
3use ifc_model::EntityId;
4use thiserror::Error;
5
6/// Control projection or authoring failure.
7///
8/// Only the variants this crate can actually raise are declared. A
9/// variant that no code path constructs is a promise the crate does
10/// not keep, and callers write dead match arms for it.
11#[derive(Debug, Clone, PartialEq, Error)]
12#[non_exhaustive]
13pub enum ControlError {
14 /// Entity kind differs from the requested projection.
15 #[error("expected {expected}, found {actual}")]
16 WrongEntityType {
17 /// Expected IFC entity.
18 expected: &'static str,
19 /// Actual IFC entity.
20 actual: String,
21 },
22 /// Required positional attribute is absent or null.
23 #[error("{entity} {id} is missing {attribute}")]
24 MissingAttribute {
25 /// Entity kind.
26 entity: &'static str,
27 /// Entity identifier.
28 id: EntityId,
29 /// Attribute name.
30 attribute: &'static str,
31 },
32 /// Requested entity is absent.
33 #[error("entity {id} does not exist")]
34 UnknownEntity {
35 /// Missing identifier.
36 id: EntityId,
37 },
38 /// Draft value is invalid before staging, including an `OwnerHistory`
39 /// that is not an `IfcOwnerHistory`.
40 #[error("cannot author {entity}.{attribute}: {value}")]
41 AuthoringInvalid {
42 /// Entity kind.
43 entity: &'static str,
44 /// Attribute or rule.
45 attribute: &'static str,
46 /// Rejected value.
47 value: String,
48 },
49 /// The relating control of an assignment, or the record a reader was
50 /// asked for, is not one this crate owns.
51 ///
52 /// Cost schedules, cost items and work controls are `IfcControl`s
53 /// too; their own crates write and read them.
54 #[error("{id} is {actual}, not a control ifc-control owns")]
55 ForeignControl {
56 /// The offered relating control.
57 id: EntityId,
58 /// Its type name.
59 actual: String,
60 },
61 /// The schema in use does not declare this entity.
62 ///
63 /// Authoring an entity the schema omits is a caller error, not a
64 /// silently-skipped attribute.
65 #[error("{schema} does not declare {entity}")]
66 UnsupportedEntity {
67 /// Schema name.
68 schema: String,
69 /// Entity that is not declared.
70 entity: &'static str,
71 },
72 /// The model's header declares several schemas; release-bound
73 /// authoring binds to exactly one.
74 #[error("the header declares {schemas} schemas; authoring binds to exactly one")]
75 MultipleSchemas {
76 /// Number of `FILE_SCHEMA` declarations.
77 schemas: usize,
78 },
79 /// The model's header declares one schema with no bundled table, so no
80 /// layout can be trusted.
81 #[error("the header declares {schema}, which has no bundled table")]
82 UnsupportedSchema {
83 /// The `FILE_SCHEMA` token as written.
84 schema: String,
85 },
86 /// A draft supplied a value for an attribute the release does not
87 /// declare, such as a `PredefinedType` for an IFC2X3 `IfcPermit`. It is
88 /// refused rather than dropped.
89 #[error("cannot author {entity}.{attribute}: not declared by {schema}")]
90 AuthoringNotInSchema {
91 /// Entity kind.
92 entity: &'static str,
93 /// The attribute, by its IFC4 name.
94 attribute: &'static str,
95 /// Schema name.
96 schema: String,
97 },
98 /// A draft supplied a value the release's declaration of the attribute
99 /// cannot hold.
100 #[error("cannot author {entity}.{attribute}: {schema} declares it {declared}")]
101 AuthoringValueType {
102 /// Entity kind.
103 entity: &'static str,
104 /// The attribute, by its IFC4 name.
105 attribute: &'static str,
106 /// The type the release declares.
107 declared: String,
108 /// Schema name.
109 schema: String,
110 },
111 /// The release requires an attribute the call leaves unset, such as the
112 /// IFC2X3 `IfcRoot.OwnerHistory` (#198, #202) or `IfcPermit.PermitID`.
113 /// It is refused rather than written as `$`; the `*_with_owner_history`
114 /// writers take the `IfcOwnerHistory` IFC2X3 needs.
115 #[error("cannot author {entity}: {schema} requires {attribute}")]
116 AuthoringRequired {
117 /// Entity kind.
118 entity: &'static str,
119 /// The attribute, by the release's own name.
120 attribute: String,
121 /// Schema name.
122 schema: String,
123 },
124 /// A stored record holds, in a slot its release declares, a value that
125 /// declaration cannot hold (text where an enumeration belongs, a token
126 /// outside the release's enumeration). It is refused rather than read
127 /// as absent.
128 #[error("{entity} {id}: {schema} declares {attribute} as {declared}; the record holds another value")]
129 InvalidAttribute {
130 /// Entity kind.
131 entity: &'static str,
132 /// Entity identifier.
133 id: EntityId,
134 /// The attribute, by the release's own name.
135 attribute: &'static str,
136 /// The type the release declares.
137 declared: String,
138 /// Schema name.
139 schema: String,
140 },
141 /// A stored record has more attributes than its release declares, so
142 /// its layout is not the release's and no slot can be trusted.
143 #[error("{entity} {id} has {found} attributes; {schema} declares {declared}")]
144 ExtraAttributes {
145 /// Entity kind.
146 entity: &'static str,
147 /// Entity identifier.
148 id: EntityId,
149 /// Attributes the release declares.
150 declared: usize,
151 /// Attributes the record holds.
152 found: usize,
153 /// Schema name.
154 schema: String,
155 },
156}
157
158/// Result alias for control operations.
159pub type ControlResult<T> = Result<T, ControlError>;