openbim_ifcx_geometry/
error.rs

1//! The error shared by every attribute decoder in this crate.
2
3use std::fmt;
4
5/// Why an attribute value could not be decoded into geometry.
6///
7/// `at` fields locate the offending value inside the attribute value, for
8/// example `points[3][1]` or `faceVertexIndices[7]`.
9#[derive(Debug, Clone, PartialEq)]
10#[non_exhaustive]
11pub enum DecodeError {
12    /// A value does not have the JSON shape the attribute requires.
13    WrongShape {
14        at: String,
15        /// What was expected, for example `"array of 3 numbers"`.
16        expected: &'static str,
17    },
18    /// A required field of an object-valued attribute is absent.
19    MissingField { field: &'static str },
20    /// A vertex index points past the end of the vertex list.
21    IndexOutOfRange {
22        at: String,
23        index: u32,
24        vertex_count: usize,
25    },
26    /// A triangle index list whose length is not a multiple of three.
27    NotTriangles { index_count: usize },
28    /// A face that is not a triangle, from `faceVertexCounts`.
29    NonTriangleFace { face: usize, vertex_count: u64 },
30    /// Per-face or per-curve vertex counts that do not add up to the
31    /// number of indices or points they describe.
32    CountMismatch {
33        field: &'static str,
34        counted: u64,
35        available: usize,
36    },
37    /// A curve with fewer than two vertices, which cannot form a line.
38    CurveTooShort { curve: usize, vertex_count: u64 },
39    /// A 4×4 transform whose last column is not `(0, 0, 0, 1)`.
40    NonAffineTransform { last_column: [f64; 4] },
41    /// A string that is not one of the tokens the attribute allows.
42    UnknownToken {
43        at: String,
44        token: String,
45        /// The allowed tokens, for example `"inherited or invisible"`.
46        expected: &'static str,
47    },
48    /// Two lists that must have one entry each, such as point colours and
49    /// positions, differ in length.
50    LengthMismatch {
51        field: &'static str,
52        len: usize,
53        expected: usize,
54    },
55    /// A base64 string is malformed.
56    InvalidBase64 { at: String, reason: String },
57    /// Decoded binary data is not a whole number of elements.
58    ByteLength {
59        at: String,
60        bytes: usize,
61        element_size: usize,
62    },
63    /// A PCD header or data section is malformed or truncated.
64    InvalidPcd { reason: String },
65    /// A well-formed PCD file in a layout the upstream viewer cannot read
66    /// either, such as `f64` coordinates or `DATA binary_lz4`.
67    UnsupportedPcd { reason: String },
68}
69
70impl fmt::Display for DecodeError {
71    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72        match self {
73            Self::WrongShape { at, expected } => write!(f, "{at}: expected {expected}"),
74            Self::MissingField { field } => write!(f, "missing field `{field}`"),
75            Self::IndexOutOfRange {
76                at,
77                index,
78                vertex_count,
79            } => write!(
80                f,
81                "{at}: index {index} out of range for {vertex_count} vertices"
82            ),
83            Self::NotTriangles { index_count } => write!(
84                f,
85                "{index_count} face vertex indices is not a multiple of 3"
86            ),
87            Self::NonTriangleFace { face, vertex_count } => write!(
88                f,
89                "face {face} has {vertex_count} vertices; only triangles are supported"
90            ),
91            Self::CountMismatch {
92                field,
93                counted,
94                available,
95            } => write!(f, "`{field}` adds up to {counted}, but {available} exist"),
96            Self::CurveTooShort {
97                curve,
98                vertex_count,
99            } => write!(
100                f,
101                "curve {curve} has {vertex_count} vertices; a line needs at least 2"
102            ),
103            Self::NonAffineTransform { last_column } => write!(
104                f,
105                "transform last column is {last_column:?}, expected [0, 0, 0, 1]"
106            ),
107            Self::UnknownToken {
108                at,
109                token,
110                expected,
111            } => write!(f, "{at}: unknown token {token:?}, expected {expected}"),
112            Self::LengthMismatch {
113                field,
114                len,
115                expected,
116            } => write!(f, "`{field}` has {len} entries, expected {expected}"),
117            Self::InvalidBase64 { at, reason } => write!(f, "{at}: invalid base64: {reason}"),
118            Self::ByteLength {
119                at,
120                bytes,
121                element_size,
122            } => write!(
123                f,
124                "{at}: {bytes} bytes is not a whole number of {element_size}-byte elements"
125            ),
126            Self::InvalidPcd { reason } => write!(f, "invalid PCD: {reason}"),
127            Self::UnsupportedPcd { reason } => write!(f, "unsupported PCD: {reason}"),
128        }
129    }
130}
131
132impl std::error::Error for DecodeError {}