etdl_parser/lib.rs
1//! Parsing for the Event Tree Definition Language (ETDL).
2//!
3//! `etdl-parser` reads `.etdl` documents — the declarative, design-time DSL for
4//! reliability-aware event-driven microservices defined by
5//! [IEC 62502:2010 (event tree analysis)](https://github.com/usamassem/etdl-specification)
6//! and [IEC 61025:2006 (fault tree analysis)](https://github.com/usamassem/etdl-specification) —
7//! and resolves their references into AsyncAPI 3.0 contracts.
8//!
9//! # Features
10//!
11//! - [`ast`] — full document AST with manual `Deserialize` (supports legacy
12//! `eventTree` and `x-*` extension fields)
13//! - [`ecel`] — the Event-tree Condition Expression Language (ECEL), a typed,
14//! side-effect-free expression language for barrier branch conditions
15//! - [`asyncapi`] — AsyncAPI 3.0 document loading and a schema-introspecting registry
16//! - [`jsonptr`] — RFC 6901 JSON Pointer resolution for `onFailureProbabilitySource`
17//! and other in-document references
18//!
19//! # Example
20//!
21//! ```no_run
22//! use etdl_parser::parse_document_from_file;
23//! use std::path::Path;
24//!
25//! let doc = parse_document_from_file(Path::new("order-fulfillment.etdl"))?;
26//! # Ok::<(), String>(())
27//! ```
28
29pub mod ast;
30pub mod asyncapi;
31pub mod ecel;
32pub mod jsonptr;
33
34use ast::EtlDocument;
35use asyncapi::AsyncApiRegistry;
36use std::path::Path;
37
38pub fn parse_document(yaml_str: &str) -> Result<EtlDocument, String> {
39 let doc: EtlDocument =
40 serde_yaml::from_str(yaml_str).map_err(|e| format!("YAML parse error: {}", e))?;
41 Ok(doc)
42}
43
44pub fn parse_document_from_file(path: &Path) -> Result<EtlDocument, String> {
45 let content =
46 std::fs::read_to_string(path).map_err(|e| format!("cannot read file: {}", e))?;
47
48 if content.starts_with('\u{feff}') {
49 return Err("E-102: document contains a byte-order mark (BOM)".to_string());
50 }
51
52 parse_document(&content)
53}
54
55pub fn load_asyncapi_imports(
56 doc: &EtlDocument,
57 base_dir: &Path,
58) -> Result<AsyncApiRegistry, String> {
59 let mut registry = AsyncApiRegistry::new();
60 for (alias, location) in &doc.asyncapi_imports {
61 registry.load(alias, location, base_dir)?;
62 }
63 Ok(registry)
64}