Skip to main content

edifact_primitives/
position.rs

1/// Position metadata for a parsed EDIFACT segment.
2///
3/// Tracks where a segment was found in the input stream, enabling
4/// error reporting with byte-level precision.
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub struct SegmentPosition {
7    /// 1-based segment number within the interchange.
8    pub segment_number: u32,
9    /// Byte offset from the start of the input.
10    pub byte_offset: usize,
11    /// 1-based message number within the interchange (0 for service segments UNB/UNZ).
12    pub message_number: u32,
13}
14
15impl SegmentPosition {
16    /// Creates a new segment position.
17    pub fn new(segment_number: u32, byte_offset: usize, message_number: u32) -> Self {
18        Self {
19            segment_number,
20            byte_offset,
21            message_number,
22        }
23    }
24}
25
26impl std::fmt::Display for SegmentPosition {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        write!(
29            f,
30            "segment {} at byte {} (message {})",
31            self.segment_number, self.byte_offset, self.message_number
32        )
33    }
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39
40    #[test]
41    fn test_segment_position_new() {
42        let pos = SegmentPosition::new(5, 128, 1);
43        assert_eq!(pos.segment_number, 5);
44        assert_eq!(pos.byte_offset, 128);
45        assert_eq!(pos.message_number, 1);
46    }
47
48    #[test]
49    fn test_segment_position_display() {
50        let pos = SegmentPosition::new(3, 42, 1);
51        assert_eq!(pos.to_string(), "segment 3 at byte 42 (message 1)");
52    }
53
54    #[test]
55    fn test_segment_position_service_segment() {
56        let pos = SegmentPosition::new(1, 0, 0);
57        assert_eq!(pos.message_number, 0);
58    }
59
60    #[test]
61    fn test_segment_position_equality() {
62        let a = SegmentPosition::new(1, 0, 1);
63        let b = SegmentPosition::new(1, 0, 1);
64        let c = SegmentPosition::new(2, 0, 1);
65        assert_eq!(a, b);
66        assert_ne!(a, c);
67    }
68
69    #[test]
70    fn test_segment_position_clone() {
71        let pos = SegmentPosition::new(1, 100, 2);
72        let cloned = pos;
73        assert_eq!(pos, cloned);
74    }
75}