ifc_author/lib.rs
1//! `ifc-author` — schema-checked construction and editing of IFC entities.
2//!
3//! # Why this is not part of `ifc-model`
4//!
5//! [`ifc_model::Model::push`] takes a type name and a positional
6//! `Vec<Value>`. That is the right primitive for a codec, which is reproducing
7//! a record it just parsed, and the wrong one for an application, which is
8//! inventing a record and has no way to know it got the arity right.
9//!
10//! The fix is not typed setters on `Model`: the model is the L0 record core and
11//! must not depend on the schema tables. Authoring is therefore an L2 concern
12//! that borrows both. See
13//! [ADR 0007](https://openbimrs.github.io/ifc/adr/0007-authoring-is-a-schema-layer-not-a-model-layer).
14//!
15//! # What is checked
16//!
17//! | Failure | Example |
18//! | --- | --- |
19//! | Unknown entity | `IfcAnnotaton` (typo) |
20//! | Unknown attribute | `IfcAnnotation.Nmae` |
21//! | Attribute set twice | two `Name` calls |
22//! | Required attribute unset | `IfcAnnotation` with no `GlobalId` |
23//! | Declared-type mismatch | a string where `IfcLengthMeasure` is declared |
24//! | Value form (ISO 10303-21) | `IFCAREAMEASURE(12.5)` where `IfcAreaMeasure`, not a SELECT, is declared; a bare `1.` where `IfcValue` is |
25//! | Scalar/aggregate confusion | a scalar where `LIST OF` is declared |
26//! | Malformed GlobalId | not 22 characters in IFC's base-64 alphabet |
27//!
28//! Slot positions come from [`ifc_schema::Schema::attributes`], which returns
29//! inherited attributes first — the ordering STEP records depend on.
30//!
31//! # What is not checked
32//!
33//! WHERE rules, inverse attributes, uniqueness, and cross-entity consistency.
34//! Those need a whole model rather than one entity, and `ifc-validate` owns
35//! them. This crate refuses obviously-wrong construction; it does not certify
36//! a valid file.
37//!
38//! # Example
39//!
40//! ```
41//! use ifc_author::EntityBuilder;
42//! use ifc_model::Model;
43//! use ifc_schema::Schema;
44//!
45//! let schema = Schema::from_express(
46//! "SCHEMA IFC4;\n\
47//! TYPE IfcGloballyUniqueId = STRING; END_TYPE;\n\
48//! TYPE IfcLabel = STRING; END_TYPE;\n\
49//! ENTITY IfcAnnotation;\n\
50//! GlobalId : IfcGloballyUniqueId;\n\
51//! Name : OPTIONAL IfcLabel;\n\
52//! END_ENTITY;\n\
53//! END_SCHEMA;",
54//! );
55//!
56//! let mut model = Model::new();
57//! let id = EntityBuilder::new(&schema, "IfcAnnotation")
58//! .text("GlobalId", "3vB2YO$MX4xv5uCqZZG05x")
59//! .text("Name", "Brandwand")
60//! .insert(&mut model)?;
61//!
62//! assert_eq!(model.get(id).unwrap().text(1), Some("Brandwand"));
63//! # Ok::<(), ifc_author::AuthorError>(())
64//! ```
65
66mod builder;
67mod check;
68mod editor;
69mod error;
70mod owner;
71
72pub use builder::EntityBuilder;
73pub use editor::EntityEditor;
74pub use error::{AuthorError, AuthorResult};
75pub use owner::{
76 add_application, add_organization, add_owner_history, add_person, add_person_and_organization,
77 ApplicationDraft, OrganizationDraft, OwnerHistoryDraft, PersonDraft,
78};