1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//! `ifc-validate` -- Schema and model validation: is this file actually legal IFC?
//!
//! Split from parsing on purpose. A reader that rejects everything imperfect is
//! useless on real data -- roughly half of production files violate something --
//! so parsing is permissive and validation is an explicit, separate pass.
//!
//! # What a report means
//!
//! ```no_run
//! # use ifc_model::Model;
//! # fn demo(model: &Model) {
//! let report = ifc_validate::validate(model, ifc_schema::ifc4());
//! if report.is_conformant() {
//! // No *errors*. There may still be warnings, and there are certainly
//! // rules this validator does not evaluate -- `report.summary()`
//! // says how many.
//! }
//! # }
//! ```
//!
//! The four severities are not a mood scale. [`Severity::Error`] means the
//! file breaks a schema requirement; [`Severity::EvaluationError`] means an
//! implemented rule applied to an instance but could not be decided for it;
//! [`Severity::Warning`] means it is legal but will behave badly;
//! [`Severity::Unsupported`] is a statement about *this validator*, not about
//! the file. Errors and evaluation errors affect [`Report::is_conformant`]:
//! a rule nobody could decide is not a rule that passed.
//!
//! # What this crate deliberately does not do
//!
//! It does not evaluate arbitrary EXPRESS `WHERE` expressions -- there is no
//! expression evaluator here. Rules that need one are registered as
//! unsupported and reported, so a clean report never silently means
//! "unchecked". See [`where_rule::RULES`].
//!
//! It does not check aggregate bounds (`LIST [3:?]`), because the schema
//! parser retains whether an attribute is an aggregate but not its bounds.
//! Claiming otherwise would be worse than the gap.
//!
//! It also does not derive `INVERSE` relationship semantics. A selected rule
//! whose IFC2X3 form depends on an inverse is therefore reported unsupported,
//! even when a later schema revision exposes equivalent direct attributes.
//!
//! # Module map
//!
//! | Module | Role |
//! |---|---|
//! | [`header`] | Declared schema and implementation level |
//! | [`structure`] | References, required slots, cardinality, unique ids |
//! | [`type_check`] | Values against their declared EXPRESS types |
//! | [`where_rule`] | Native rules, and honest reporting of the rest |
//! | [`report`] | Findings, paths, severities, summaries |
//! | [`error`] | Why validation could not run |
pub use ValidateError;
pub use ;
pub use Budget;
use Model;
use Schema;
/// Validate a model against a schema with the default budget.
///
/// Runs every check this crate implements: header, structure, types, and the
/// natively implemented rules. Unsupported rules are recorded rather than
/// skipped.
/// Validate under an explicit budget.
///
/// A budget bounds how many findings are recorded. Hitting it marks the
/// report truncated: `12 errors` from a truncated report means "at least 12".
/// Validate against the schema the file itself declares.
///
/// # Errors
///
/// Returns [`ValidateError`] when the file declares no schema, or declares
/// one this build has no tables for. Validating an IFC2X3 file against IFC4
/// tables would produce confident nonsense, so it is refused rather than
/// approximated.