1use crate::component::Component;
2use crate::encoding::HL7Encoding;
3use crate::error::Hl7Error;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct Field {
10 raw: String,
11 pub components: Vec<Component>,
13 pub repetitions: Vec<Field>,
15 pub is_componentized: bool,
17 pub has_repetitions: bool,
19 pub is_delimiters_field: bool,
21}
22
23impl Field {
24 pub fn parse(raw: &str, enc: &HL7Encoding) -> Self {
26 if raw.contains(enc.repeat_delimiter) {
27 let repetitions: Vec<Field> = raw
28 .split(enc.repeat_delimiter)
29 .map(|r| Field::parse(r, enc))
30 .collect();
31
32 Self {
33 raw: raw.to_string(),
34 components: Vec::new(),
35 repetitions,
36 is_componentized: false,
37 has_repetitions: true,
38 is_delimiters_field: false,
39 }
40 } else {
41 let components: Vec<Component> = raw
42 .split(enc.component_delimiter)
43 .map(|c| Component::parse(c, enc))
44 .collect();
45 let is_componentized = components.len() > 1;
46
47 Self {
48 raw: raw.to_string(),
49 components,
50 repetitions: Vec::new(),
51 is_componentized,
52 has_repetitions: false,
53 is_delimiters_field: false,
54 }
55 }
56 }
57
58 pub(crate) fn new_delimiters(raw: &str) -> Self {
61 Self {
62 raw: raw.to_string(),
63 components: vec![Component::single(raw)],
64 repetitions: Vec::new(),
65 is_componentized: false,
66 has_repetitions: false,
67 is_delimiters_field: true,
68 }
69 }
70
71 pub fn raw(&self, enc: &HL7Encoding) -> Option<&str> {
73 if self.raw == enc.present_but_null {
74 None
75 } else {
76 Some(&self.raw)
77 }
78 }
79
80 pub fn value(&self, enc: &HL7Encoding) -> Option<String> {
82 if self.raw == enc.present_but_null {
83 None
84 } else {
85 Some(enc.decode(&self.raw))
86 }
87 }
88
89 pub fn set_value(&mut self, value: &str, enc: &HL7Encoding) {
91 if self.is_delimiters_field {
92 *self = Field::new_delimiters(value);
93 } else {
94 *self = Field::parse(value, enc);
95 }
96 }
97
98 pub fn component(&self, position: usize) -> Result<&Component, Hl7Error> {
100 position
101 .checked_sub(1)
102 .and_then(|i| self.components.get(i))
103 .ok_or_else(|| Hl7Error::new("Component not available"))
104 }
105
106 pub fn repetition(&self, repetition_number: usize) -> Option<&Field> {
108 if self.has_repetitions {
109 repetition_number.checked_sub(1).and_then(|i| self.repetitions.get(i))
110 } else {
111 None
112 }
113 }
114
115 pub fn add_component(&mut self, component: Component) {
117 self.components.push(component);
118 }
119
120 pub fn add_component_at(&mut self, component: Component, position: usize, enc: &HL7Encoding) {
123 let index = position.saturating_sub(1);
124
125 if index < self.components.len() {
126 self.components[index] = component;
127 } else {
128 while self.components.len() < index {
129 self.components.push(Component::parse("", enc));
130 }
131 self.components.push(component);
132 }
133 }
134
135 pub fn add_repeating_field(&mut self, field: Field) -> Result<(), Hl7Error> {
137 if !self.has_repetitions {
138 return Err(Hl7Error::new(
139 "Repeating field must have repetitions (has_repetitions = true)",
140 ));
141 }
142
143 self.repetitions.push(field);
144 Ok(())
145 }
146
147 pub fn remove_empty_trailing_components(&mut self, enc: &HL7Encoding) {
149 while let Some(last) = self.components.last() {
150 if last.value(enc).as_deref() == Some("") {
151 self.components.pop();
152 } else {
153 break;
154 }
155 }
156 }
157
158 pub fn serialize(&self, out: &mut String, enc: &HL7Encoding) {
160 if self.is_delimiters_field {
161 if let Some(raw) = self.raw(enc) {
162 out.push_str(raw);
163 }
164 return;
165 }
166
167 if self.has_repetitions {
168 for (j, rep) in self.repetitions.iter().enumerate() {
169 if j > 0 {
170 out.push(enc.repeat_delimiter);
171 }
172 rep.serialize_single(out, enc);
173 }
174 } else {
175 self.serialize_single(out, enc);
176 }
177 }
178
179 fn serialize_single(&self, out: &mut String, enc: &HL7Encoding) {
181 if self.components.is_empty() {
182 out.push_str(&enc.encode_opt(self.value(enc).as_deref()));
183 return;
184 }
185
186 for (idx, com) in self.components.iter().enumerate() {
187 if idx > 0 {
188 out.push(enc.component_delimiter);
189 }
190
191 if com.sub_components.is_empty() {
192 out.push_str(&enc.encode_opt(com.value(enc).as_deref()));
193 } else {
194 for (i, sub) in com.sub_components.iter().enumerate() {
195 if i > 0 {
196 out.push(enc.subcomponent_delimiter);
197 }
198 out.push_str(&enc.encode_opt(sub.value(enc).as_deref()));
199 }
200 }
201 }
202 }
203}