#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum SchemaVersion {
Ifc2x3,
Ifc4,
Ifc4x1,
Ifc4x2,
Ifc4x3,
}
impl SchemaVersion {
pub const ALL: [Self; 5] = [
Self::Ifc2x3,
Self::Ifc4,
Self::Ifc4x1,
Self::Ifc4x2,
Self::Ifc4x3,
];
#[must_use]
pub const fn release_id(self) -> &'static str {
match self {
Self::Ifc2x3 => "IFC2X3_TC1",
Self::Ifc4 => "IFC4_ADD2_TC1",
Self::Ifc4x1 => "IFC4X1_FINAL",
Self::Ifc4x2 => "IFC4X2_FINAL",
Self::Ifc4x3 => "IFC4X3_ADD2",
}
}
#[must_use]
pub const fn expected_entity_count(self) -> usize {
match self {
Self::Ifc2x3 => 653,
Self::Ifc4 => 776,
Self::Ifc4x1 => 801,
Self::Ifc4x2 => 816,
Self::Ifc4x3 => 876,
}
}
#[must_use]
pub const fn expected_type_count(self) -> usize {
match self {
Self::Ifc2x3 => 327,
Self::Ifc4 => 397,
Self::Ifc4x1 => 400,
Self::Ifc4x2 => 407,
Self::Ifc4x3 => 436,
}
}
#[must_use]
pub const fn header_tokens(self) -> &'static [&'static str] {
match self {
Self::Ifc2x3 => &["IFC2X3"],
Self::Ifc4 => &["IFC4"],
Self::Ifc4x1 => &["IFC4X1"],
Self::Ifc4x2 => &["IFC4X2"],
Self::Ifc4x3 => &["IFC4X3", "IFC4X3_ADD2"],
}
}
#[must_use]
pub const fn feature_name(self) -> &'static str {
match self {
Self::Ifc2x3 => "ifc2x3",
Self::Ifc4 => "ifc4",
Self::Ifc4x1 => "ifc4x1",
Self::Ifc4x2 => "ifc4x2",
Self::Ifc4x3 => "ifc4x3",
}
}
#[must_use]
pub const fn is_bundled(self) -> bool {
match self {
Self::Ifc2x3 => cfg!(feature = "ifc2x3"),
Self::Ifc4 => cfg!(feature = "ifc4"),
Self::Ifc4x1 => cfg!(feature = "ifc4x1"),
Self::Ifc4x2 => cfg!(feature = "ifc4x2"),
Self::Ifc4x3 => cfg!(feature = "ifc4x3"),
}
}
pub fn from_header_token(token: &str) -> Option<Self> {
match token.trim().to_ascii_uppercase().as_str() {
"IFC2X3" => Some(Self::Ifc2x3),
"IFC4" => Some(Self::Ifc4),
"IFC4X1" => Some(Self::Ifc4x1),
"IFC4X2" => Some(Self::Ifc4x2),
"IFC4X3" | "IFC4X3_ADD2" => Some(Self::Ifc4x3),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn recognizes_the_schema_tokens_our_fixtures_carry() {
assert_eq!(
SchemaVersion::from_header_token("IFC4"),
Some(SchemaVersion::Ifc4)
);
assert_eq!(
SchemaVersion::from_header_token("ifc2x3"),
Some(SchemaVersion::Ifc2x3)
);
assert_eq!(SchemaVersion::from_header_token("STEP"), None);
}
#[test]
fn header_tokens_and_release_ids_round_trip_for_every_version() {
for version in SchemaVersion::ALL {
for token in version.header_tokens() {
assert_eq!(SchemaVersion::from_header_token(token), Some(version));
assert_eq!(
SchemaVersion::from_header_token(&token.to_ascii_lowercase()),
Some(version)
);
}
}
assert_eq!(
SchemaVersion::from_header_token("IFC4X1"),
Some(SchemaVersion::Ifc4x1)
);
assert_eq!(
SchemaVersion::from_header_token(" ifc4x2 "),
Some(SchemaVersion::Ifc4x2)
);
assert_eq!(SchemaVersion::Ifc4x1.release_id(), "IFC4X1_FINAL");
assert_eq!(SchemaVersion::Ifc4x2.release_id(), "IFC4X2_FINAL");
let ids: std::collections::BTreeSet<_> =
SchemaVersion::ALL.iter().map(|v| v.release_id()).collect();
assert_eq!(ids.len(), SchemaVersion::ALL.len());
}
}