Skip to main content

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}