ifc-schema
IFC schema as data: entity table, supertype chain, attribute names.
| Status | Implemented |
| Latest release | 0.3.0 (2026-09-29) |
| Registries | crates.io ifc-schema |
| Via the facade | openbim-ifc feature properties, schema-api |
| API documentation | rustdoc · docs.rs |
| Source | crates/ifc-schema/ |
Overview
ifc-schema — the IFC schema as data, not as 2,500 generated structs.
Features
| Feature | Default | Enables |
|---|---|---|
artifact | dep:bincode, dep:thiserror | |
express | dep:openbim-step | |
generation | express, ifc2x3, ifc4, ifc4x1, ifc4x2, ifc4x3 | |
ifc2x3 | yes | artifact |
ifc4 | yes | artifact |
ifc4x1 | yes | artifact |
ifc4x2 | yes | artifact |
ifc4x3 | yes | artifact |
Changes
Latest release, 0.3.0 (2026-09-29):
Changed (breaking)
- Artifact format 3 records the facts above; format 1 and 2 artifacts still decode, with those facts empty.
- A nested aggregate attribute's
type_nameis its innermost element type (IfcLengthMeasureforLIST OF LIST OF IfcLengthMeasure), where the old extractor recorded the inner keywordLIST. - The
expressandgenerationfeatures useopenbim-step=0.10.0(the runtime links none). - One cargo feature per bundled release (#112):
ifc2x3,ifc4,ifc4x1,ifc4x2andifc4x3, all indefault, so a default build bundles every release as before. Each accessor (ifc2x3(),ifc4(), ...) exists only with its feature.ifc4used to ship all bundled tables; it now ships IFC4 only, so a build withdefault-features = false, features = ["ifc4"]loses the other releases -- name them, or keep defaults. for_versionreturnsResult<&Schema, NotBundled>instead ofOption<&Schema>, and exists in every build.Err(NotBundled)means a recognised release whose feature is off; an unknownFILE_SCHEMAtoken is stillNonefromSchemaVersion::from_header_token, so the two cases stay distinguishable.write_structural_catalogandwrite_direct_structural_catalogexist in every build and return anio::ErrorKind::Unsupportederror wrappingNotBundledfor a release that is not compiled in, instead of panicking.artifact_decode_schemaandBundledSchemaErrorneed the newartifactfeature (enabled by every release feature) instead ofifc4.SchemaVersionis#[non_exhaustive], derivesHash, and gainsIfc4x1andIfc4x2(#33). Amatchon it needs a wildcard arm; a consumer should refuse a release it has not verified, never alias it to a neighbour.write_structural_catalogandwrite_direct_structural_catalogaccept the new versions.ifc-schemaowns its schema types.Attribute,EntityDef,TypeDef,TypeKindand the newly exportedWhereRuleare defined here instead of re-exported fromopenbim_step::express, and all five are#[non_exhaustive]: construct them withAttribute::new,EntityDef::new,TypeDef::new,WhereRule::newand the builder methods (with_supertype,with_attribute,with_derived,with_where_rule,abstract_entity,optional,aggregate), and give everymatchonTypeKinda wildcard arm. Field names,supertype(),is_derived()andis_defined()are unchanged. Rationale: anopenbim-steprelease no longer ripples into this crate's public API, and later facts about a declaration (aggregate bounds, INVERSE, UNIQUE) can be added as fields without another break.openbim-stepis an optional dependency, linked only by the newexpressfeature and bygeneration. The bundled tables decode straight into the owned types; the default build no longer links a parser.Schema::from_expressandSchema::from_express_bytesrequire the newexpressfeature.- Removed:
Schema::from_parsed(ParsedSchema)(useSchema::new(name, entities, types)),Schema::graph()(theopenbim_step::SchemaGraphit returned is no longer held;Schemaanswers the same queries itself), and theexpressmodule with itsparse/ParsedSchemare-exports (useopenbim_step::expressdirectly). EntityDefno longer carriesredeclared/is_redeclared(). No bundled table ever recorded explicit redeclarations (the artifact format drops them), so they were always empty forifc2x3(),ifc4()andifc4x3().artifact_decode_schemareturns aSchemaandartifact_encode_schema(generation) takes one, instead ofopenbim_step::express::ParsedSchema.
Added
- Aggregate bounds, nested aggregation, INVERSE and UNIQUE (#111):
Attribute::aggregation(levels outermost first, each anAggregationwithAggregateKind, lower and upperBound,unique,optional_elements),EntityDef::inverses(InverseAttribute) andEntityDef::unique_rules(UniqueRule), with builders. Additive: the types were already#[non_exhaustive]. All five bundled tables are regenerated with them: 115/153/158/160/165 INVERSE and 17/4/4/4/4 UNIQUE declarations for IFC2X3/IFC4/IFC4X1/IFC4X2/IFC4X3, pinned by tests. NotBundled,SchemaVersion::is_bundled()andSchemaVersion::feature_name().- IFC4X1 FINAL and IFC4X2 FINAL (#33): bundled tables
data/ifc4x1-final.bin(801 entities, 400 types) anddata/ifc4x2-final.bin(816 entities, 407 types), generated from the official EXPRESS files like the other three; accessorsifc4x1()andifc4x2();for_versionreturns them; header tokensIFC4X1andIFC4X2(the files' ownSCHEMAnames); release idsIFC4X1_FINALandIFC4X2_FINAL. Tests pin that both counts differ from IFC4 and IFC4X3 and that each carries its own release's entities. SchemaVersion::ALL, every known version oldest first.Schema::new,Schema::entities()andSchema::types()(declarations in source order),PartialEq/EqforSchema, and theBundledSchemaErrorexport.
Unchanged
- The bundled artifacts are byte-identical: regenerating all three with the ported generator reproduces the committed files, and
FORMAT_VERSIONstays 2.
Changed
- Requires
openbim-step0.7.0, matchingifc-step. Both pin the parser exactly, so the pair must move together.openbim-step0.6 replacedEntityDef::supertype(a field) withsupertypesplus asupertype()accessor for multiple inheritance; IFC schemas are single-inheritance, so the serialized artifact is unchanged.
Full history: crates/ifc-schema/CHANGELOG.md