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
//! Strict-decoding support for BO4E payloads.
//!
//! Every BO4E enum carries an `Unknown` forward-compatibility catch-all, so the
//! lenient `serde` deserialization path never fails on an unrecognized wire value
//! — it maps to `Unknown`. That is the right default for forward-compatibility,
//! but the wrong default at an **ingest boundary** that must reject typos, legacy
//! codes, or values from a newer schema.
//!
//! The [`Bo4eStrict`](crate::Bo4eStrict) trait — implemented by every generated BO,
//! COM, enum, and by `AnyBo` — walks a value **recursively** and reports the
//! JSON-path of every enum field that decoded to `Unknown`. This turns the MaKo
//! "round-trip as validation" pattern into an actually-strict one:
//!
//! ```
//! # #[cfg(feature = "json")] {
//! use rubo4e::{Bo4eStrict, current::Messlokation};
//!
//! // `sparte` carries a value this schema version does not define.
//! let body = r#"{"messlokationsId":"DE0123456789012345678901234567890","sparte":"PLASMA"}"#;
//! let melo: Messlokation = serde_json::from_str(body).unwrap(); // lenient decode
//!
//! // One call finds it, wherever it sits in the tree:
//! let err = melo.ensure_known_enums().unwrap_err();
//! assert_eq!(err.paths, ["sparte"]);
//! # }
//! ```
//!
//! One call replaces the hand-written `field == T::Unknown` checks scattered across
//! every handler.
/// The set of JSON-paths at which a payload holds an out-of-schema (`Unknown`)
/// enum value, produced by [`Bo4eStrict::ensure_known_enums`](crate::Bo4eStrict::ensure_known_enums).
///
/// Paths are dotted, with array indices in brackets, relative to the value that
/// was checked — e.g. `zaehler[0].zaehlertyp` or `bilanzierung.aggregationsverantwortung`.
/// Joins a child field name onto a parent JSON-path.
///
/// Used by generated [`Bo4eStrict`](crate::Bo4eStrict) impls; rarely called
/// directly. The root path is the empty string, so the first segment carries no
/// leading dot.
/// Joins an array index onto a parent JSON-path (`parent[i]`).
///
/// Used by generated [`Bo4eStrict`](crate::Bo4eStrict) impls; rarely called directly.