ifc_tabular/error.rs
1//! Refusals raised while staging tabular records, and read failures.
2
3use ifc_model::EntityId;
4use thiserror::Error;
5
6/// Why a tabular record was refused.
7#[derive(Debug, Clone, PartialEq, Eq, Error)]
8#[non_exhaustive]
9pub enum TabularError {
10 /// A row carries a different cell count than the first row (WR1).
11 ///
12 /// Ragged tables parse and render; the damage appears only when a
13 /// reader indexes a column the short row does not have.
14 #[error("{entity}: row {row} has {found} cells, the first row has {expected}")]
15 RaggedRow {
16 /// The entity being staged.
17 entity: &'static str,
18 /// Zero-based index of the offending row.
19 row: usize,
20 /// Cells in the first row.
21 expected: usize,
22 /// Cells in this row.
23 found: usize,
24 },
25 /// More than one row is marked as a heading (WR2).
26 #[error("{entity}: {found} heading rows, at most one is allowed")]
27 TooManyHeadings {
28 /// The entity being staged.
29 entity: &'static str,
30 /// How many rows claimed to be headings.
31 found: usize,
32 },
33 /// A required list was empty.
34 ///
35 /// The schema spells these `LIST [1:?]`, so an empty list is not a
36 /// sparse record but a malformed one.
37 #[error("{entity}.{attribute} requires at least one entry")]
38 EmptyList {
39 /// The entity being staged.
40 entity: &'static str,
41 /// The attribute that came up empty.
42 attribute: &'static str,
43 },
44 /// A required label was absent or whitespace-only.
45 ///
46 /// A blank string satisfies EXISTS while naming nothing, so it is
47 /// refused rather than written.
48 #[error("{entity}.{attribute} requires a non-blank value")]
49 BlankRequired {
50 /// The entity being staged.
51 entity: &'static str,
52 /// The attribute that was blank.
53 attribute: &'static str,
54 },
55 /// A numeric attribute was not finite.
56 #[error("{entity}.{attribute} requires a finite value")]
57 NotFinite {
58 /// The entity being staged.
59 entity: &'static str,
60 /// The offending attribute.
61 attribute: &'static str,
62 },
63}
64
65/// Result alias for tabular staging.
66pub type TabularResult<T> = Result<T, TabularError>;
67
68/// Why a read could not produce a view at all.
69///
70/// Defects INSIDE a table or series are not errors: they are reported as
71/// [`crate::TabularIssue`]s on the view, beside what did decode.
72#[derive(Debug, Clone, PartialEq, Eq, Error)]
73#[non_exhaustive]
74pub enum TabularReadError {
75 /// No record has this id.
76 #[error("entity {id} does not exist")]
77 UnknownEntity {
78 /// The requested id.
79 id: EntityId,
80 },
81 /// The record is not the kind the read asked for.
82 #[error("{id} is {actual}, expected {expected}")]
83 WrongEntityType {
84 /// The requested id.
85 id: EntityId,
86 /// The type or types the read accepts.
87 expected: &'static str,
88 /// The record's type.
89 actual: String,
90 },
91 /// The declared schema is not one this view decodes.
92 #[error("{schema} is not supported; tabular reads decode IFC4 and IFC4X3")]
93 UnsupportedSchema {
94 /// The schema's name.
95 schema: String,
96 },
97}
98
99/// Result alias for tabular reads.
100pub type TabularReadResult<T> = Result<T, TabularReadError>;