pub struct MappingEngine { /* private fields */ }Expand description
The mapping engine holds all loaded mapping definitions and provides methods for bidirectional conversion.
Implementations§
Source§impl MappingEngine
impl MappingEngine
Sourcepub fn new_empty() -> MappingEngine
pub fn new_empty() -> MappingEngine
Create an empty engine with no definitions (for unit testing).
Sourcepub fn load(dir: &Path) -> Result<MappingEngine, MappingError>
pub fn load(dir: &Path) -> Result<MappingEngine, MappingError>
Load all TOML mapping files from a directory.
Sourcepub fn load_split(
message_dir: &Path,
transaction_dir: &Path,
) -> Result<(MappingEngine, MappingEngine), MappingError>
pub fn load_split( message_dir: &Path, transaction_dir: &Path, ) -> Result<(MappingEngine, MappingEngine), MappingError>
Load message-level and transaction-level TOML mappings from separate directories.
Returns (message_engine, transaction_engine) where:
message_enginemaps SG2/SG3/root-level definitions (shared across PIDs)transaction_enginemaps SG4+ definitions (PID-specific)
Sourcepub fn load_merged(dirs: &[&Path]) -> Result<MappingEngine, MappingError>
pub fn load_merged(dirs: &[&Path]) -> Result<MappingEngine, MappingError>
Load TOML mapping files from multiple directories into a single engine.
Useful for combining message-level and transaction-level mappings when a single engine with all definitions is needed.
Sourcepub fn load_with_common(
common_dir: &Path,
pid_dir: &Path,
schema_index: &PidSchemaIndex,
) -> Result<MappingEngine, MappingError>
pub fn load_with_common( common_dir: &Path, pid_dir: &Path, schema_index: &PidSchemaIndex, ) -> Result<MappingEngine, MappingError>
Load transaction-level mappings with common template inheritance.
- Loads all
.tomlfromcommon_dir - Filters: keeps only definitions whose
source_pathexists in the PID schema - Loads all
.tomlfrompid_dir - For each PID definition, if a common definition has matching
(source_group, discriminator), replaces the common one (file-level replacement) - Merges both sets: common first, then PID additions
Sourcepub fn load_common_only(
common_dir: &Path,
schema_index: &PidSchemaIndex,
) -> Result<MappingEngine, MappingError>
pub fn load_common_only( common_dir: &Path, schema_index: &PidSchemaIndex, ) -> Result<MappingEngine, MappingError>
Load common definitions only (no per-PID dir), filtered by schema index.
Used for PIDs that have no per-PID directory but can use shared common/ definitions.
Sourcepub fn load_split_with_common(
message_dir: &Path,
common_dir: &Path,
transaction_dir: &Path,
schema_index: &PidSchemaIndex,
) -> Result<(MappingEngine, MappingEngine), MappingError>
pub fn load_split_with_common( message_dir: &Path, common_dir: &Path, transaction_dir: &Path, schema_index: &PidSchemaIndex, ) -> Result<(MappingEngine, MappingEngine), MappingError>
Load message + transaction engines with common template inheritance.
Returns (message_engine, transaction_engine) where the transaction engine
inherits shared templates from common_dir, filtered by the PID schema.
Sourcepub fn from_definitions(definitions: Vec<MappingDefinition>) -> MappingEngine
pub fn from_definitions(definitions: Vec<MappingDefinition>) -> MappingEngine
Create an engine from an already-parsed list of definitions.
Sourcepub fn save_cached(&self, path: &Path) -> Result<(), MappingError>
pub fn save_cached(&self, path: &Path) -> Result<(), MappingError>
Save definitions to a cache file.
Only the definitions are serialized — segment_structure and code_lookup
must be re-attached after loading from cache. Paths in the definitions are
already resolved to numeric indices, so no PathResolver is needed at load time.
Sourcepub fn load_cached_or_toml(
cache_path: &Path,
toml_dir: &Path,
) -> Result<MappingEngine, MappingError>
pub fn load_cached_or_toml( cache_path: &Path, toml_dir: &Path, ) -> Result<MappingEngine, MappingError>
Load from cache if available, otherwise fall back to TOML directory.
When loading from cache, PathResolver is NOT needed (paths pre-resolved).
When falling back to TOML, the caller should chain .with_path_resolver().
Sourcepub fn load_cached(path: &Path) -> Result<MappingEngine, MappingError>
pub fn load_cached(path: &Path) -> Result<MappingEngine, MappingError>
Load definitions from a cache file.
Returns an engine with only definitions populated. Attach segment_structure
and code_lookup via the builder methods if needed.
Sourcepub fn with_segment_structure(self, ss: SegmentStructure) -> MappingEngine
pub fn with_segment_structure(self, ss: SegmentStructure) -> MappingEngine
Attach a MIG-derived segment structure for trailing element padding.
When set, map_reverse pads each segment’s elements up to the
MIG-defined count, ensuring trailing empty elements are preserved.
Sourcepub fn with_code_lookup(self, cl: CodeLookup) -> MappingEngine
pub fn with_code_lookup(self, cl: CodeLookup) -> MappingEngine
Attach a code lookup for enriching companion field values.
When set, companion fields that map to code-type elements in the PID schema
are emitted as {"code": "Z15", "meaning": "Ja"} objects instead of plain strings.
Sourcepub fn with_path_resolver(self, resolver: PathResolver) -> MappingEngine
pub fn with_path_resolver(self, resolver: PathResolver) -> MappingEngine
Attach a path resolver to normalize EDIFACT ID paths to numeric indices.
This allows TOML mapping files to use named paths like loc.c517.d3225
instead of numeric indices like loc.1.0. Resolution happens once at
load time — the engine hot path is completely unchanged.
Sourcepub fn definitions(&self) -> &[MappingDefinition]
pub fn definitions(&self) -> &[MappingDefinition]
Get all loaded definitions.
Sourcepub fn definition_for_entity(&self, entity: &str) -> Option<&MappingDefinition>
pub fn definition_for_entity(&self, entity: &str) -> Option<&MappingDefinition>
Find a definition by entity name.
Sourcepub fn extract_field(
&self,
tree: &AssembledTree,
group_path: &str,
path: &str,
repetition: usize,
) -> Option<String>
pub fn extract_field( &self, tree: &AssembledTree, group_path: &str, path: &str, repetition: usize, ) -> Option<String>
Extract a field value from an assembled tree using a mapping path.
group_path supports dotted notation for nested groups (e.g., “SG4.SG5”).
Parent groups default to repetition 0; repetition applies to the leaf group.
Path format: “segment.composite.data_element” e.g., “loc.c517.d3225”
Sourcepub fn resolve_group_instance<'a>(
tree: &'a AssembledTree,
group_path: &str,
repetition: usize,
) -> Option<&'a AssembledGroupInstance>
pub fn resolve_group_instance<'a>( tree: &'a AssembledTree, group_path: &str, repetition: usize, ) -> Option<&'a AssembledGroupInstance>
Navigate a potentially nested group path to find a group instance.
For “SG4.SG5”, finds SG4[0] then SG5 at the given repetition within it. For “SG8”, finds SG8 at the given repetition in the top-level groups.
Supports intermediate repetition with colon syntax: “SG4.SG8:1.SG10” means SG4[0] → SG8[1] → SG10[repetition]. Without a colon suffix, intermediate groups default to repetition 0.
Sourcepub fn resolve_by_source_path<'a>(
tree: &'a AssembledTree,
source_path: &str,
) -> Option<&'a AssembledGroupInstance>
pub fn resolve_by_source_path<'a>( tree: &'a AssembledTree, source_path: &str, ) -> Option<&'a AssembledGroupInstance>
Navigate the assembled tree using a source_path with qualifier suffixes.
Source paths like "sg4.sg8_z98.sg10" encode qualifiers inline:
sg8_z98 means “find the SG8 repetition whose entry segment has qualifier Z98”.
Parts without underscores (e.g., sg4, sg10) use the first repetition.
Returns None if any part of the path can’t be resolved.
Sourcepub fn resolve_all_by_source_path<'a>(
tree: &'a AssembledTree,
source_path: &str,
) -> Vec<&'a AssembledGroupInstance>
pub fn resolve_all_by_source_path<'a>( tree: &'a AssembledTree, source_path: &str, ) -> Vec<&'a AssembledGroupInstance>
Resolve ALL matching instances for a source_path, returning a Vec.
Like resolve_by_source_path but returns all repetitions matching
at any level, not just the first. For example, if there are two SG5
reps with LOC+Z17, resolve_all_by_source_path(tree, "sg4.sg5_z17")
returns both. For deeper paths like “sg4.sg8_zf3.sg10”, if there are
two SG8 reps with ZF3, it returns SG10 children from both.
Sourcepub fn resolve_all_with_parent_indices<'a>(
tree: &'a AssembledTree,
source_path: &str,
) -> Vec<(usize, &'a AssembledGroupInstance)>
pub fn resolve_all_with_parent_indices<'a>( tree: &'a AssembledTree, source_path: &str, ) -> Vec<(usize, &'a AssembledGroupInstance)>
Returns Vec<(parent_rep_index, &AssembledGroupInstance)>.
Sourcepub fn extract_from_instance(
instance: &AssembledGroupInstance,
path: &str,
) -> Option<String>
pub fn extract_from_instance( instance: &AssembledGroupInstance, path: &str, ) -> Option<String>
Extract a field from a group instance by path.
Supports qualifier-based segment selection with tag[qualifier] syntax:
"dtm.0.1"→ first DTM segment, elements[0][1]"dtm[92].0.1"→ DTM where elements[0][0] == “92”, then elements[0][1]
Sourcepub fn extract_all_from_instance(
instance: &AssembledGroupInstance,
path: &str,
) -> Vec<String>
pub fn extract_all_from_instance( instance: &AssembledGroupInstance, path: &str, ) -> Vec<String>
Extract ALL matching values from a group instance for a collect-all path.
Used with wildcard occurrence syntax tag[qualifier,*] to collect values
from every segment matching the qualifier, not just the Nth one.
Returns a Vec<String> of all extracted values in segment order.
Sourcepub fn map_forward(
&self,
tree: &AssembledTree,
def: &MappingDefinition,
repetition: usize,
) -> Value
pub fn map_forward( &self, tree: &AssembledTree, def: &MappingDefinition, repetition: usize, ) -> Value
Map all fields in a definition from the assembled tree to a BO4E JSON object.
group_path is the definition’s source_group (may be dotted, e.g., “SG4.SG5”).
An empty source_group maps root-level segments (BGM, DTM, etc.).
Returns a flat JSON object with target field names as keys.
If the definition has companion_fields, those are extracted into a nested
object keyed by companion_type (or "_companion" if not specified).
Sourcepub fn map_forward_from_segments(
&self,
segments: &[OwnedSegment],
def: &MappingDefinition,
) -> Value
pub fn map_forward_from_segments( &self, segments: &[OwnedSegment], def: &MappingDefinition, ) -> Value
Map a PID struct field’s segments to BO4E JSON.
segments are the OwnedSegments from a PID wrapper field.
Converts to AssembledSegment format for compatibility with existing
field extraction logic, then applies the definition’s field mappings.
Sourcepub fn map_reverse(
&self,
bo4e_value: &Value,
def: &MappingDefinition,
) -> AssembledGroupInstance
pub fn map_reverse( &self, bo4e_value: &Value, def: &MappingDefinition, ) -> AssembledGroupInstance
Map a BO4E JSON object back to an assembled group instance.
Uses the definition’s field mappings to populate segment elements.
Fields with default values are used when no BO4E value is present
(useful for fixed qualifiers like LOC qualifier “Z16”).
Supports:
- Named paths:
"d3227"→ element[0][0],"c517.d3225"→ element[1][0] - Numeric index:
"0"→ element[0][0],"1.2"→ element[1][2] - Qualifier selection:
"dtm[92].0.1"→ DTM segment with qualifier “92”
Sourcepub fn populate_field(
&self,
bo4e_value: &Value,
target_field: &str,
) -> Option<String>
pub fn populate_field( &self, bo4e_value: &Value, target_field: &str, ) -> Option<String>
Extract a value from a BO4E JSON object by target field name. Supports dotted paths like “nested.field_name”.
Sourcepub fn build_segment_from_bo4e(
&self,
bo4e_value: &Value,
segment_tag: &str,
target_field: &str,
) -> AssembledSegment
pub fn build_segment_from_bo4e( &self, bo4e_value: &Value, segment_tag: &str, target_field: &str, ) -> AssembledSegment
Build a segment from BO4E values using the reverse mapping.
Sourcepub fn resolve_repetition(
tree: &AssembledTree,
group_path: &str,
discriminator: &str,
) -> Option<usize>
pub fn resolve_repetition( tree: &AssembledTree, group_path: &str, discriminator: &str, ) -> Option<usize>
Parse a discriminator string (e.g., “SEQ.0.0=Z79”) and find the matching repetition index within the given group path.
Discriminator format: "TAG.element_idx.component_idx=expected_value"
Scans all repetitions of the leaf group and returns the first rep index
where the entry segment matches.
Sourcepub fn resolve_all_repetitions(
tree: &AssembledTree,
group_path: &str,
discriminator: &str,
) -> Vec<usize>
pub fn resolve_all_repetitions( tree: &AssembledTree, group_path: &str, discriminator: &str, ) -> Vec<usize>
Like resolve_repetition, but returns ALL matching rep indices instead of just the first.
This is used for multi-Zeitscheibe support where multiple SG6 reps may match the same discriminator (e.g., multiple RFF+Z49 time slices).
Sourcepub fn map_all_forward(&self, tree: &AssembledTree) -> Value
pub fn map_all_forward(&self, tree: &AssembledTree) -> Value
Resolve a discriminated instance using source_path for parent navigation.
Like resolve_repetition + resolve_group_instance, but navigates to the
parent group via source_path qualifier suffixes. Returns the matching instance
directly (not just a rep index) to avoid re-navigation in map_forward_inner.
For example, source_path = "sg4.sg8_z98.sg10" with discriminator = "CCI.2.0=ZB3"
navigates to the SG8 instance with SEQ qualifier Z98, then finds the SG10 rep
where CCI element 2 component 0 equals “ZB3”.
Map all definitions against a tree, returning a JSON object with entity names as keys.
For each definition:
- Has discriminator → find matching rep via
resolve_repetition, map single instance - Root-level (empty source_group) → map rep 0 as single object
- No discriminator, 1 rep in tree → map as single object
- No discriminator, multiple reps in tree → map ALL reps into a JSON array
When multiple definitions share the same entity name, their fields are
deep-merged into a single JSON object. This allows related TOML files
(e.g., LOC location + SEQ info + SG10 characteristics) to contribute
fields to the same BO4E entity.
Sourcepub fn map_all_forward_enriched(
&self,
tree: &AssembledTree,
enrich_codes: bool,
) -> Value
pub fn map_all_forward_enriched( &self, tree: &AssembledTree, enrich_codes: bool, ) -> Value
Like map_all_forward but with explicit
enrich_codes control (when false, code fields are plain strings
instead of {"code": …, "meaning": …} objects).
Sourcepub fn map_all_reverse(
&self,
entities: &Value,
nesting_info: Option<&HashMap<String, Vec<usize>>>,
) -> AssembledTree
pub fn map_all_reverse( &self, entities: &Value, nesting_info: Option<&HashMap<String, Vec<usize>>>, ) -> AssembledTree
Reverse-map a BO4E entity map back to an AssembledTree.
For each definition:
- Look up entity in input by
meta.entityname - If entity value is an array, map each element as a separate group repetition
- Place results by
source_group:""→ root segments,"SGn"→ groups
This is the inverse of map_all_forward().
Sourcepub fn map_interchange(
msg_engine: &MappingEngine,
tx_engine: &MappingEngine,
tree: &AssembledTree,
transaction_group: &str,
enrich_codes: bool,
) -> MappedMessage
pub fn map_interchange( msg_engine: &MappingEngine, tx_engine: &MappingEngine, tree: &AssembledTree, transaction_group: &str, enrich_codes: bool, ) -> MappedMessage
Map an assembled tree into message-level and transaction-level results.
msg_engine: MappingEngine loaded with message-level definitions (SG2, SG3, root segments)tx_engine: MappingEngine loaded with transaction-level definitions (relative to SG4)tree: The assembled tree for one messagetransaction_group: The group ID that represents transactions (e.g., “SG4”)
Returns a MappedMessage with message stammdaten and per-transaction results.
Sourcepub fn map_interchange_reverse(
msg_engine: &MappingEngine,
tx_engine: &MappingEngine,
mapped: &MappedMessage,
transaction_group: &str,
filtered_mig: Option<&MigSchema>,
) -> AssembledTree
pub fn map_interchange_reverse( msg_engine: &MappingEngine, tx_engine: &MappingEngine, mapped: &MappedMessage, transaction_group: &str, filtered_mig: Option<&MigSchema>, ) -> AssembledTree
Reverse-map a MappedMessage back to an AssembledTree.
Two-engine approach mirroring map_interchange():
msg_enginehandles message-level stammdaten → SG2/SG3 groupstx_enginehandles per-transaction stammdaten → SG4 instances
All entities (including prozessdaten/nachricht) are in tx.stammdaten.
Results are merged into one AssembledGroupInstance per transaction,
collected into an SG4 AssembledGroup, then combined with message-level groups.
Sourcepub fn build_group_from_bo4e(
&self,
bo4e_value: &Value,
def: &MappingDefinition,
) -> AssembledGroup
pub fn build_group_from_bo4e( &self, bo4e_value: &Value, def: &MappingDefinition, ) -> AssembledGroup
Build an assembled group from BO4E values and a definition.
Sourcepub fn map_interchange_typed<M, T>(
msg_engine: &MappingEngine,
tx_engine: &MappingEngine,
tree: &AssembledTree,
tx_group: &str,
enrich_codes: bool,
nachrichtendaten: Nachrichtendaten,
interchangedaten: Interchangedaten,
) -> Result<Interchange<M, T>, Error>where
M: DeserializeOwned,
T: DeserializeOwned,
pub fn map_interchange_typed<M, T>(
msg_engine: &MappingEngine,
tx_engine: &MappingEngine,
tree: &AssembledTree,
tx_group: &str,
enrich_codes: bool,
nachrichtendaten: Nachrichtendaten,
interchangedaten: Interchangedaten,
) -> Result<Interchange<M, T>, Error>where
M: DeserializeOwned,
T: DeserializeOwned,
Forward-map an assembled tree to a typed interchange.
Runs the dynamic mapping pipeline, wraps the result with metadata, then converts via JSON serialization into the caller’s typed structs.
M: message-level stammdaten type (e.g.,Pid55001MsgStammdaten)T: transaction-level stammdaten type (e.g.,Pid55001TxStammdaten)
Sourcepub fn map_interchange_reverse_typed<M, T>(
msg_engine: &MappingEngine,
tx_engine: &MappingEngine,
nachricht: &Nachricht<M, T>,
tx_group: &str,
) -> Result<AssembledTree, Error>
pub fn map_interchange_reverse_typed<M, T>( msg_engine: &MappingEngine, tx_engine: &MappingEngine, nachricht: &Nachricht<M, T>, tx_group: &str, ) -> Result<AssembledTree, Error>
Reverse-map a typed interchange nachricht back to an assembled tree.
Serializes the typed struct to JSON, then runs the dynamic reverse pipeline.
M: message-level stammdaten typeT: transaction-level stammdaten type