use std::fmt;
use ifc_model::EntityId;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum AuthorError {
MissingEntity {
id: EntityId,
},
UnknownEntity {
entity: String,
},
UnknownAttribute {
entity: String,
attribute: String,
known: Vec<String>,
},
MissingRequired {
entity: String,
attribute: String,
},
DuplicateAttribute {
entity: String,
attribute: String,
},
TypeMismatch {
entity: String,
attribute: String,
expected: String,
found: String,
},
AggregateMismatch {
entity: String,
attribute: String,
expected_aggregate: bool,
},
InvalidGlobalId {
entity: String,
found: String,
},
DerivedAttribute {
entity: String,
attribute: String,
found: String,
},
NotDerived {
entity: String,
attribute: String,
},
ArityMismatch {
entity: String,
expected: usize,
found: usize,
},
ValueForm {
entity: String,
attribute: String,
declared: String,
typed_required: bool,
found: String,
},
}
impl fmt::Display for AuthorError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::MissingEntity { id } => write!(f, "model has no entity `{id}`"),
Self::UnknownEntity { entity } => {
write!(f, "schema does not declare entity `{entity}`")
}
Self::UnknownAttribute {
entity,
attribute,
known,
} => write!(
f,
"`{entity}` has no attribute `{attribute}`; declared: {}",
known.join(", ")
),
Self::MissingRequired { entity, attribute } => write!(
f,
"`{entity}` requires attribute `{attribute}`, which was not set"
),
Self::DuplicateAttribute { entity, attribute } => {
write!(f, "`{entity}` attribute `{attribute}` was set twice")
}
Self::TypeMismatch {
entity,
attribute,
expected,
found,
} => write!(
f,
"`{entity}.{attribute}` expects {expected}, found {found}"
),
Self::ValueForm {
entity,
attribute,
declared,
typed_required: true,
found,
} => write!(
f,
"`{entity}.{attribute}` is declared {declared}, a SELECT, so a value \
must be written as a typed parameter naming its type; found {found}"
),
Self::ValueForm {
entity,
attribute,
declared,
typed_required: false,
found,
} => write!(
f,
"`{entity}.{attribute}` is declared {declared}, which is not a SELECT, \
so its value is written bare; found {found}"
),
Self::AggregateMismatch {
entity,
attribute,
expected_aggregate,
} => {
let (want, got) = if *expected_aggregate {
("an aggregate", "a scalar")
} else {
("a scalar", "an aggregate")
};
write!(f, "`{entity}.{attribute}` expects {want}, found {got}")
}
Self::InvalidGlobalId { entity, found } => write!(
f,
"`{entity}.GlobalId` must be a 22-character IFC GUID, found `{found}`"
),
Self::DerivedAttribute {
entity,
attribute,
found,
} => write!(
f,
"`{entity}.{attribute}` is derived by the schema and must be written `*`, found {found}"
),
Self::NotDerived { entity, attribute } => write!(
f,
"`{entity}.{attribute}` is not derived by the schema, so it cannot be written `*`"
),
Self::ArityMismatch {
entity,
expected,
found,
} => write!(
f,
"`{entity}` declares {expected} attributes, but the model contains {found}"
),
}
}
}
impl std::error::Error for AuthorError {}
pub type AuthorResult<T> = Result<T, AuthorError>;