Skip to main content

MappingEngine

Struct MappingEngine 

Source
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

Source

pub fn new_empty() -> MappingEngine

Create an empty engine with no definitions (for unit testing).

Source

pub fn load(dir: &Path) -> Result<MappingEngine, MappingError>

Load all TOML mapping files from a directory.

Source

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_engine maps SG2/SG3/root-level definitions (shared across PIDs)
  • transaction_engine maps SG4+ definitions (PID-specific)
Source

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.

Source

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.

  1. Loads all .toml from common_dir
  2. Filters: keeps only definitions whose source_path exists in the PID schema
  3. Loads all .toml from pid_dir
  4. For each PID definition, if a common definition has matching (source_group, discriminator), replaces the common one (file-level replacement)
  5. Merges both sets: common first, then PID additions
Source

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.

Source

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.

Source

pub fn from_definitions(definitions: Vec<MappingDefinition>) -> MappingEngine

Create an engine from an already-parsed list of definitions.

Source

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.

Source

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().

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn definitions(&self) -> &[MappingDefinition]

Get all loaded definitions.

Source

pub fn definition_for_entity(&self, entity: &str) -> Option<&MappingDefinition>

Find a definition by entity name.

Source

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”

Source

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.

Source

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.

Source

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.

Source

pub fn resolve_all_with_parent_indices<'a>( tree: &'a AssembledTree, source_path: &str, ) -> Vec<(usize, &'a AssembledGroupInstance)>

Returns Vec<(parent_rep_index, &AssembledGroupInstance)>.

Source

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]
Source

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.

Source

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).

Source

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.

Source

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”
Source

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”.

Source

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.

Source

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.

Source

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).

Source

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.

Source

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).

Source

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:

  1. Look up entity in input by meta.entity name
  2. If entity value is an array, map each element as a separate group repetition
  3. Place results by source_group: "" → root segments, "SGn" → groups

This is the inverse of map_all_forward().

Source

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 message
  • transaction_group: The group ID that represents transactions (e.g., “SG4”)

Returns a MappedMessage with message stammdaten and per-transaction results.

Source

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_engine handles message-level stammdaten → SG2/SG3 groups
  • tx_engine handles 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.

Source

pub fn build_group_from_bo4e( &self, bo4e_value: &Value, def: &MappingDefinition, ) -> AssembledGroup

Build an assembled group from BO4E values and a definition.

Source

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>

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)
Source

pub fn map_interchange_reverse_typed<M, T>( msg_engine: &MappingEngine, tx_engine: &MappingEngine, nachricht: &Nachricht<M, T>, tx_group: &str, ) -> Result<AssembledTree, Error>
where M: Serialize, T: Serialize,

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 type
  • T: transaction-level stammdaten type

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.