Skip to main content

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>;