1use crate::encoding::HL7Encoding;
2use crate::error::Hl7Error;
3use crate::field::Field;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct Segment {
8 raw: String,
9 pub name: String,
11 pub fields: Vec<Field>,
14 pub(crate) sequence_no: usize,
16}
17
18impl Segment {
19 pub fn new(name: impl Into<String>) -> Self {
21 Self {
22 raw: String::new(),
23 name: name.into(),
24 fields: Vec::new(),
25 sequence_no: 0,
26 }
27 }
28
29 pub fn parse(raw: &str, enc: &HL7Encoding) -> Result<Self, Hl7Error> {
32 if raw.chars().count() < 3 {
33 return Err(Hl7Error::with_code(
34 format!("Invalid segment (too short): {raw}"),
35 Hl7Error::BAD_MESSAGE,
36 ));
37 }
38
39 let name: String = raw.chars().take(3).collect();
40 let is_msh = name == "MSH";
41
42 let parts: Vec<&str> = raw.split(enc.field_delimiter).collect();
43 let mut fields = Vec::with_capacity(parts.len());
44
45 for (i, part) in parts.iter().enumerate().skip(1) {
46 let field = if is_msh && i == 1 {
47 Field::new_delimiters(part)
48 } else {
49 Field::parse(part, enc)
50 };
51 fields.push(field);
52 }
53
54 if is_msh {
55 fields.insert(0, Field::new_delimiters(&enc.field_delimiter.to_string()));
57 }
58
59 Ok(Self { raw: raw.to_string(), name, fields, sequence_no: 0 })
60 }
61
62 pub fn deep_copy(&self) -> Segment {
64 self.clone()
65 }
66
67 pub fn raw(&self, enc: &HL7Encoding) -> Option<&str> {
69 if self.raw == enc.present_but_null {
70 None
71 } else {
72 Some(&self.raw)
73 }
74 }
75
76 pub fn value(&self, enc: &HL7Encoding) -> Option<String> {
78 if self.raw == enc.present_but_null {
79 None
80 } else {
81 Some(enc.decode(&self.raw))
82 }
83 }
84
85 pub fn sequence_no(&self) -> usize {
87 self.sequence_no
88 }
89
90 pub fn add_empty_field(&mut self, enc: &HL7Encoding) {
92 self.add_new_field(Field::parse("", enc));
93 }
94
95 pub fn add_new_field_value(&mut self, content: &str, enc: &HL7Encoding) {
97 self.add_new_field(Field::parse(content, enc));
98 }
99
100 pub fn add_new_field(&mut self, field: Field) {
102 self.fields.push(field);
103 }
104
105 pub fn add_new_field_at(&mut self, field: Field, position: usize, enc: &HL7Encoding) {
108 let index = position.saturating_sub(1);
109
110 if index < self.fields.len() {
111 self.fields[index] = field;
112 } else {
113 while self.fields.len() < index {
114 self.fields.push(Field::parse("", enc));
115 }
116 self.fields.push(field);
117 }
118 }
119
120 pub fn field(&self, position: usize) -> Result<&Field, Hl7Error> {
122 position
123 .checked_sub(1)
124 .and_then(|i| self.fields.get(i))
125 .ok_or_else(|| Hl7Error::new("Field not available"))
126 }
127
128 pub fn serialize(&self, out: &mut String, enc: &HL7Encoding) {
130 out.push_str(&self.name);
131
132 if !self.fields.is_empty() {
133 out.push(enc.field_delimiter);
134 }
135
136 let start = if self.name == "MSH" { 1 } else { 0 };
138
139 for i in start..self.fields.len() {
140 if i > start {
141 out.push(enc.field_delimiter);
142 }
143 self.fields[i].serialize(out, enc);
144 }
145
146 out.push_str(&enc.segment_delimiter);
147 }
148}