1use ifc_model::{EntityId, ModelError};
4use thiserror::Error;
5
6#[derive(Debug, Error)]
8#[non_exhaustive]
9pub enum StepError {
10 #[error("not a STEP physical file: {0}")]
12 NotStep(String),
13
14 #[error("syntax error at byte {offset}: {detail}")]
16 Syntax {
17 offset: usize,
19 detail: String,
21 },
22
23 #[error("entity record without an id at byte {offset}")]
25 MissingEntityId {
26 offset: usize,
28 },
29
30 #[error("syntax error at byte {offset}: REAL `{token}` has no decimal point (ISO 10303-21 requires one)")]
36 RealWithoutDecimalPoint {
37 offset: usize,
39 token: String,
41 },
42
43 #[error("entity #{entity} slot {slot} contains a non-finite REAL")]
45 NonFiniteReal {
46 entity: EntityId,
48 slot: usize,
50 },
51
52 #[error("io error: {0}")]
54 Io(String),
55}
56
57impl StepError {
58 pub(crate) fn from_step(input: &[u8], error: openbim_step::StepError) -> Self {
65 if error.is_real_without_point() {
66 let span = error.span();
67 if let Some(token) = input.get(span.start..span.end) {
68 return Self::RealWithoutDecimalPoint {
69 offset: span.start,
70 token: String::from_utf8_lossy(token).into_owned(),
71 };
72 }
73 }
74 error.into()
75 }
76}
77
78impl From<openbim_step::StepError> for StepError {
82 fn from(error: openbim_step::StepError) -> Self {
83 if error.is_not_step() {
84 Self::NotStep(error.detail().to_owned())
85 } else {
86 Self::Syntax {
87 offset: error.span().start,
88 detail: error.detail().to_owned(),
89 }
90 }
91 }
92}
93
94impl From<StepError> for ModelError {
95 fn from(error: StepError) -> Self {
96 match error {
97 StepError::NotStep(detail) => ModelError::WrongFormat {
98 expected: "STEP",
99 detail,
100 },
101 StepError::Syntax { offset, detail } => ModelError::Syntax { offset, detail },
102 StepError::MissingEntityId { offset } => ModelError::Syntax {
103 offset,
104 detail: "entity record without an id".into(),
105 },
106 StepError::RealWithoutDecimalPoint { offset, token } => ModelError::Syntax {
107 offset,
108 detail: format!(
109 "REAL `{token}` has no decimal point (ISO 10303-21 requires one; \
110 a lenient read accepts it)"
111 ),
112 },
113 StepError::NonFiniteReal { entity, slot } => ModelError::Write(format!(
114 "entity #{entity} slot {slot} contains a non-finite REAL"
115 )),
116 StepError::Io(message) => ModelError::Io(message),
117 }
118 }
119}