ifc/lib.rs
1//! `ifc` — the facade. Pick your codecs and domains as cargo features.
2//!
3//! # The shape of the library
4//!
5//! ```text
6//! codecs model domain views
7//! --------------- --------------- ------------------
8//! ifc-step \ / ifc-cost
9//! ifc-xml >-----> ifc-model <--< ifc-schedule
10//! (ifc-json) / (entities) \ ifc-properties, ...
11//! ```
12//!
13//! Two separations hold this together, and both are enforced by tests rather
14//! than convention:
15//!
16//! **1. The model knows no domain semantics.** [`Model`] stores
17//! `(id, type_name, attributes)` and nothing else. It has never heard of a
18//! cost item. Domain crates are *views* that borrow a `&Model` and interpret
19//! it, so a build without them still reads and writes their data untouched.
20//!
21//! **2. The model knows no serialization.** [`Codec`] is a trait *in the model
22//! crate*; `ifc-step` and `ifc-xml` implement it. IFC-JSON would be a third
23//! implementation, requiring no change to the model.
24//!
25//! # Choosing features
26//!
27//! | Feature | Pulls in | For |
28//! | --- | --- | --- |
29//! | `step` *(default)* | `ifc-step` | Reading `.ifc` files |
30//! | `ifcxml` | `ifc-xml` | Reading/writing `.ifcxml` |
31//! | `schema` | `ifc-schema` | Subtype queries, conformant XML names |
32//! | `material-templates` | `ifc-material` + template catalog | Material PSD applicability |
33//! | `cost`, `schedule`, ... | one domain crate each | Interpreting that domain |
34//! | `codecs` | both codecs | |
35//! | `domains` | every domain view | |
36//! | `full` | everything | |
37//!
38//! A thin viewer takes `default-features = false, features = ["step"]` and
39//! compiles no domain code and no geometry stack, while still round-tripping
40//! every entity in the file.
41//!
42//! ```
43//! # #[cfg(feature = "step")] {
44//! use ifc::{Codec, StepCodec};
45//!
46//! let source = b"ISO-10303-21;\nHEADER;\nFILE_DESCRIPTION((''),'2;1');\n\
47//! FILE_NAME('t.ifc','',( ''),(''),'','','');\n\
48//! FILE_SCHEMA(('IFC4'));\nENDSEC;\nDATA;\n\
49//! #1= IFCCOSTITEM('guid',$,'Excavation',$,$,$,$);\n\
50//! ENDSEC;\nEND-ISO-10303-21;\n";
51//!
52//! let model = StepCodec.read_bytes(source).unwrap();
53//! assert_eq!(model.len(), 1);
54//!
55//! // The cost entity is present and re-exportable with no `cost` feature on.
56//! let out = StepCodec.write_bytes(&model).unwrap();
57//! assert!(String::from_utf8_lossy(&out).contains("IFCCOSTITEM"));
58//! # }
59//! ```
60
61// The model is always available: it is the common vocabulary.
62pub use ifc_model::{codec, Codec, Entity, EntityId, Header, Model, ModelError, Value};
63// `EntityEditor::stage` and the domain writers take a transaction; without
64// these a facade user could build an editor but never apply it.
65pub use ifc_model::{Applied, Conflict, Transaction};
66
67/// The STEP physical file codec (`.ifc`).
68#[cfg(feature = "step")]
69pub use ifc_step::StepCodec;
70
71/// A STEP reader with an explicit policy: recovery, eager decoding, or a
72/// memory-mapped read ([`StepReader::read_path_mapped`]).
73#[cfg(feature = "step")]
74pub use ifc_step::{OnMalformed, ParseOptions, StepReader};
75
76/// The ifcXML codec (`.ifcxml`).
77#[cfg(feature = "ifcxml")]
78pub use ifc_xml::{XmlCodec, XmlProfile};
79
80/// The IFC schema as queryable data.
81#[cfg(feature = "schema")]
82pub use ifc_schema::{Schema, SchemaVersion};
83
84/// The whole schema crate, including the bundled schemas
85/// (`schema::ifc4()`, `schema::for_version(..)`) that
86/// [`ids_of_type_including_subtypes`] needs as input.
87#[cfg(feature = "schema")]
88pub use ifc_schema as schema;
89
90// Needs the model's type index and the schema's subtype tree, which ADR 0003
91// keeps in separate crates, so the join lives in this orchestration layer.
92#[cfg(feature = "schema")]
93mod subtype_query;
94#[cfg(feature = "schema")]
95pub use subtype_query::ids_of_type_including_subtypes;
96
97/// Cost semantics as a borrowed view.
98#[cfg(feature = "cost")]
99pub use ifc_cost as cost;
100
101/// Property sets and quantities.
102#[cfg(feature = "properties")]
103pub use ifc_properties as properties;
104
105/// Versioned external PSD/QTO template catalogs and correction profiles.
106#[cfg(feature = "property-catalog")]
107pub use ifc_template_catalog as property_catalog;
108
109/// Tasks, sequencing, calendars.
110#[cfg(feature = "schedule")]
111pub use ifc_schedule as schedule;
112
113/// Material layer sets, profile sets, constituents.
114#[cfg(feature = "material")]
115pub use ifc_material as material;
116#[cfg(feature = "material-templates")]
117pub mod material_templates;
118
119/// Classification, documents, libraries, and external-reference relationships.
120#[cfg(feature = "classification")]
121pub use ifc_classification as classification;
122
123/// Approval resource semantics and approval associations.
124#[cfg(feature = "approval")]
125pub use ifc_approval as approval;
126
127/// Permits, project orders, action requests, and performance history.
128#[cfg(feature = "control")]
129pub use ifc_control as control;
130
131/// Tables and time series: value containers indexed by position or time.
132#[cfg(feature = "tabular")]
133pub use ifc_tabular as tabular;
134
135/// Metrics, objectives, and constraint relationships.
136#[cfg(feature = "constraint")]
137pub use ifc_constraint as constraint;
138
139/// Element, resource, and process type definitions.
140#[cfg(feature = "element-type")]
141pub use ifc_element_type as element_type;
142
143/// Built element and distribution occurrence classes.
144#[cfg(feature = "occurrence")]
145pub use ifc_occurrence as occurrence;
146
147/// Structural analysis model.
148#[cfg(feature = "structural")]
149pub use ifc_structural as structural;
150
151/// Construction resources: actors, labour, equipment, crew, material,
152/// product, subcontract, resource types, inventory, and usage quantities.
153#[cfg(feature = "resource")]
154pub use ifc_resource as resource;
155
156/// Distribution systems and ports.
157#[cfg(feature = "systems")]
158pub use ifc_systems as systems;
159
160/// Presentation styles.
161#[cfg(feature = "style")]
162pub use ifc_style as style;
163
164/// Schema and integrity validation.
165#[cfg(feature = "validate")]
166pub use ifc_validate as validate;
167
168/// Schema-checked construction and editing of entities.
169#[cfg(feature = "author")]
170pub use ifc_author as author;
171
172/// Build or edit an entity by naming attributes rather than positioning them.
173#[cfg(feature = "author")]
174pub use ifc_author::{EntityBuilder, EntityEditor};
175
176/// Containment and objectified relationship traversal.
177#[cfg(feature = "spatial")]
178pub use ifc_spatial as spatial;
179
180/// The project/site/building/storey/element tree of a model.
181#[cfg(feature = "spatial")]
182pub use ifc_spatial::{SpatialKind, SpatialTree};
183
184/// Representation selection and, with `geometry`, lowering to the DAG.
185///
186/// Available under `geometry-select` too: the module is the same, but a
187/// select-only build compiles no geometry kernel and therefore exposes no
188/// `lower` submodule.
189#[cfg(feature = "geometry-select")]
190pub use ifc_geometry as geometry;
191
192/// Representation contexts and the selectors that choose 3D or 2D geometry.
193///
194/// Re-exported at the root because choosing what a drawing draws is a
195/// first-class question, not an implementation detail of lowering.
196#[cfg(feature = "geometry-select")]
197pub use ifc_geometry::{
198 all_contexts, context_of, plan_contexts, select_plan_representation,
199 select_shape_representation, RepresentationContext, TargetView, PLAN_IDENTIFIERS,
200 SOLID_IDENTIFIERS,
201};
202
203/// Where a product sits in the world.
204///
205/// Re-exported at the root, and available without the geometry kernel,
206/// because every consumer needs world coordinates and a hand-rolled
207/// `IfcLocalPlacement` walk is the most commonly botched code in an IFC
208/// viewer: the composition order and the unit scaling are both easy to
209/// invert.
210#[cfg(feature = "geometry-select")]
211pub use ifc_geometry::{product_world_transform, products_world_transforms};
212
213/// How a product's body is modelled: its representation kind and, for swept
214/// solids, the profile parameters, direction and depth in SI and world
215/// coordinates.
216///
217/// Available without the geometry kernel, because a rule check asking "is
218/// this beam an extrusion of an HEA300" reads parameters, not a mesh.
219#[cfg(feature = "geometry-select")]
220pub use ifc_geometry::{
221 body_description, describe_profile, profile_outline, BodyDescription, BodyItem, BodyKind,
222 ProfileDescription, ProfileOutline, ProfileParameters, SweepPath, SweptSolid,
223};
224
225/// Map conversion and coordinate reference systems.
226#[cfg(feature = "georef")]
227pub use ifc_georef as georef;
228
229/// IFC4x3 alignment and linear placement.
230#[cfg(feature = "alignment")]
231pub use ifc_alignment as alignment;
232
233// Answering "will a viewer draw this" needs containment AND representation
234// contexts -- two sibling domain crates that ADR 0003 forbids from depending on
235// each other, so the check lives in this orchestration layer.
236#[cfg(all(feature = "spatial", feature = "geometry-select"))]
237mod unreachable;
238#[cfg(all(feature = "spatial", feature = "geometry-select"))]
239pub use unreachable::{unreachable_products, Unreachable};
240
241// A door's leaves and a window's panels need the product's placement AND its
242// operation type and panel properties -- `ifc-geometry` and `ifc-properties`,
243// siblings under ADR 0003 -- so the joins live in this orchestration layer
244// (#148, #170). `operation` holds what the two share. Each of the three
245// modules gates itself on `all(geometry-select, properties)` with an inner
246// `#![cfg]`, so the declarations below compile to nothing without both.
247mod door_operation;
248mod operation;
249mod window_operation;
250#[cfg(all(feature = "geometry-select", feature = "properties"))]
251pub use {
252 door_operation::{
253 door_operation, DoorOperation, DoorOperationError, DoorOperationType, Leaf, LeafMotion,
254 PanelPosition, RefusedOperation,
255 },
256 operation::{Sector, Side},
257 window_operation::{
258 window_operation, RefusedWindowOperation, WindowOperation, WindowOperationError,
259 WindowPanel, WindowPanelMotion, WindowPanelOperation, WindowPanelPosition,
260 WindowPartitioning,
261 },
262};
263
264// Each spatial container's elements with their exact properties (#121) joins
265// `ifc-spatial` and `ifc-properties`, siblings under ADR 0003. The module
266// gates itself on `all(spatial, properties)` with an inner `#![cfg]`.
267mod spatial_properties;
268#[cfg(all(feature = "spatial", feature = "properties"))]
269pub use spatial_properties::{
270 spatial_properties, ContainerElements, ContainerName, ElementMember, ElementProperties,
271 SpatialContainer, SpatialMembership, SpatialProperties,
272};
273
274mod feature_report;
275mod io;
276
277pub use feature_report::compiled_features;
278pub use io::{codecs, read_path};
279
280#[cfg(feature = "step")]
281pub use io::from_step_bytes;