Skip to main content

ifc_step/
error.rs

1//! Why a STEP parse failed at the IFC adapter boundary.
2
3use ifc_model::{EntityId, ModelError};
4use thiserror::Error;
5
6/// Failures specific to reading or writing IFC STEP text.
7#[derive(Debug, Error)]
8#[non_exhaustive]
9pub enum StepError {
10    /// The bytes do not begin with the ISO-10303-21 magic.
11    #[error("not a STEP physical file: {0}")]
12    NotStep(String),
13
14    /// Malformed syntax at a known byte offset.
15    #[error("syntax error at byte {offset}: {detail}")]
16    Syntax {
17        /// Byte offset into the source.
18        offset: usize,
19        /// What went wrong.
20        detail: String,
21    },
22
23    /// A record in the DATA section had no `#id=` prefix.
24    #[error("entity record without an id at byte {offset}")]
25    MissingEntityId {
26        /// Byte offset into the source.
27        offset: usize,
28    },
29
30    /// The model contains a REAL value Part 21 cannot represent.
31    #[error("entity #{entity} slot {slot} contains a non-finite REAL")]
32    NonFiniteReal {
33        /// Entity containing the value.
34        entity: EntityId,
35        /// Top-level positional attribute containing the value.
36        slot: usize,
37    },
38
39    /// Underlying I/O failure.
40    #[error("io error: {0}")]
41    Io(String),
42}
43
44impl From<openbim_step::StepError> for StepError {
45    fn from(error: openbim_step::StepError) -> Self {
46        if error.is_not_step() {
47            Self::NotStep(error.detail().to_owned())
48        } else {
49            Self::Syntax {
50                offset: error.span().start,
51                detail: error.detail().to_owned(),
52            }
53        }
54    }
55}
56
57impl From<StepError> for ModelError {
58    fn from(error: StepError) -> Self {
59        match error {
60            StepError::NotStep(detail) => ModelError::WrongFormat {
61                expected: "STEP",
62                detail,
63            },
64            StepError::Syntax { offset, detail } => ModelError::Syntax { offset, detail },
65            StepError::MissingEntityId { offset } => ModelError::Syntax {
66                offset,
67                detail: "entity record without an id".into(),
68            },
69            StepError::NonFiniteReal { entity, slot } => ModelError::Write(format!(
70                "entity #{entity} slot {slot} contains a non-finite REAL"
71            )),
72            StepError::Io(message) => ModelError::Io(message),
73        }
74    }
75}