mig_types/segment.rs
1//! Owned EDIFACT segment — a crate-independent segment representation.
2//!
3//! `OwnedSegment` stores parsed EDIFACT segment data as owned `String`s.
4//! It lives in `mig-types` so that both generated PID types and the
5//! assembly machinery can reference it without circular dependencies.
6
7use serde::{Deserialize, Serialize};
8
9/// An owned version of a parsed EDIFACT segment — stores String data.
10///
11/// Used for the two-pass assembler: pass 1 collects segments into this
12/// type, pass 2 consumes them guided by the MIG schema.
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14pub struct OwnedSegment {
15 /// Segment identifier (e.g., "NAD", "LOC", "DTM").
16 pub id: String,
17 /// Elements, where each element is a vector of component strings.
18 /// `elements[i][j]` = component `j` of element `i`.
19 pub elements: Vec<Vec<String>>,
20 /// 1-based segment number within the message.
21 pub segment_number: u32,
22}
23
24impl OwnedSegment {
25 /// Gets the first component of element at `index`, or empty string if missing.
26 pub fn get_element(&self, index: usize) -> &str {
27 self.elements
28 .get(index)
29 .and_then(|e| e.first())
30 .map(|s| s.as_str())
31 .unwrap_or("")
32 }
33
34 /// Gets a specific component within an element, or empty string if missing.
35 pub fn get_component(&self, element_index: usize, component_index: usize) -> &str {
36 self.elements
37 .get(element_index)
38 .and_then(|e| e.get(component_index))
39 .map(|s| s.as_str())
40 .unwrap_or("")
41 }
42
43 /// Checks if the segment has the given ID (case-insensitive).
44 pub fn is(&self, segment_id: &str) -> bool {
45 self.id.eq_ignore_ascii_case(segment_id)
46 }
47}