1use super::separators::Separators;
2use super::*;
3use std::fmt::Display;
4use std::ops::Index;
5
6#[derive(Debug, PartialEq)]
9pub struct Field<'a> {
10 pub source: &'a str,
11 pub delims: Separators,
12 pub repeats: Vec<&'a str>,
13 pub components: Vec<Vec<&'a str>>,
14 pub subcomponents: Vec<Vec<Vec<&'a str>>>,
15}
16
17impl<'a> Field<'a> {
18 pub fn parse<S: Into<&'a str>>(
20 input: S,
21 delims: &Separators,
22 ) -> Result<Field<'a>, Hl7ParseError> {
23 let input = input.into();
24 let repeats: Vec<&'a str> = input.split(delims.repeat).collect();
25 let components: Vec<Vec<&'a str>> = repeats
26 .iter()
27 .map(|r| r.split(delims.component).collect::<Vec<&'a str>>())
28 .collect();
29 let subcomponents: Vec<Vec<Vec<&'a str>>> = components
30 .iter()
31 .map(|r| {
32 r.iter()
33 .map(|c| c.split(delims.subcomponent).collect::<Vec<&'a str>>())
34 .collect::<Vec<Vec<&'a str>>>()
35 })
36 .collect();
37 let field = Field {
38 source: input,
39 delims: *delims,
40 repeats,
41 components,
42 subcomponents,
43 };
44 Ok(field)
45 }
46
47 pub fn parse_mandatory(
49 input: Option<&'a str>,
50 delims: &Separators,
51 ) -> Result<Field<'a>, Hl7ParseError> {
52 match input {
53 Some(string_value) => Field::parse(string_value, delims),
54 None => Err(Hl7ParseError::MissingRequiredValue {}),
55 }
56 }
57
58 pub fn parse_optional(
61 input: Option<&'a str>,
62 delims: &Separators,
63 ) -> Result<Option<Field<'a>>, Hl7ParseError> {
64 match input {
65 None => Ok(None),
66 Some(x) if x.is_empty() => Ok(None),
67 Some(x) => Ok(Some(Field::parse(x, delims)?)),
68 }
69 }
70
71 #[inline]
73 pub fn value(&self) -> &'a str {
74 self.source
75 }
76
77 #[inline]
79 pub fn as_str(&self) -> &'a str {
80 self.source
81 }
82
83 pub fn query<'b, S>(&self, sidx: S) -> &'a str
86 where
87 S: Into<&'b str>,
88 {
89 let sidx = sidx.into();
90 let parts = sidx.split('.').collect::<Vec<&str>>();
91
92 if parts.len() == 1 {
93 let stringnums = parts[0]
94 .chars()
95 .filter(|c| c.is_digit(10))
96 .collect::<String>();
97 let idx: usize = stringnums.parse().unwrap();
98
99 self[idx - 1]
100 } else if parts.len() == 2 {
101 let stringnums = parts[0]
102 .chars()
103 .filter(|c| c.is_digit(10))
104 .collect::<String>();
105
106 let idx0: usize = stringnums.parse().unwrap();
107
108 let stringnums = parts[1]
109 .chars()
110 .filter(|c| c.is_digit(10))
111 .collect::<String>();
112
113 let idx1: usize = stringnums.parse().unwrap();
114
115 self[(idx0 - 1, idx1 - 1)]
116 } else {
117 ""
118 }
119 }
120}
121
122impl<'a> Display for Field<'a> {
123 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125 write!(f, "{}", self.source)
126 }
127}
128
129impl<'a> Clone for Field<'a> {
130 fn clone(&self) -> Self {
132 Field::parse(self.source, &self.delims.clone()).unwrap()
133 }
134}
135
136impl<'a> Index<usize> for Field<'a> {
137 type Output = &'a str;
138 fn index(&self, idx: usize) -> &Self::Output {
140 if idx > self.repeats.len() - 1 {
141 return &""; }
143
144 &self.repeats[idx]
145 }
146}
147
148impl<'a> Index<(usize, usize)> for Field<'a> {
149 type Output = &'a str;
150 fn index(&self, idx: (usize, usize)) -> &Self::Output {
152 if idx.0 > self.repeats.len() - 1 || idx.1 > self.components[idx.0].len() - 1 {
153 return &""; }
155
156 &self.components[idx.0][idx.1]
157 }
158}
159
160impl<'a> Index<(usize, usize, usize)> for Field<'a> {
161 type Output = &'a str;
162 fn index(&self, idx: (usize, usize, usize)) -> &Self::Output {
164 if idx.0 > self.repeats.len() - 1
165 || idx.1 > self.components[idx.0].len() - 1
166 || idx.2 > self.subcomponents[idx.0][idx.1].len() - 1
167 {
168 return &""; }
170
171 &self.subcomponents[idx.0][idx.1][idx.2]
172 }
173}
174
175#[cfg(feature = "string_index")]
176impl<'a> Index<String> for Field<'a> {
177 type Output = &'a str;
178
179 #[cfg(feature = "string_index")]
181 fn index(&self, sidx: String) -> &Self::Output {
182 let parts = sidx.split('.').collect::<Vec<&str>>();
183 match parts.len() {
184 1 => {
185 let stringnums = parts[0]
186 .chars()
187 .filter(|c| c.is_digit(10))
188 .collect::<String>();
189 let idx: usize = stringnums.parse().unwrap();
190
191 &self[idx - 1]
192 }
193 2 => {
194 let stringnums = parts[0]
195 .chars()
196 .filter(|c| c.is_digit(10))
197 .collect::<String>();
198
199 let idx0: usize = stringnums.parse().unwrap();
200
201 let stringnums = parts[1]
202 .chars()
203 .filter(|c| c.is_digit(10))
204 .collect::<String>();
205
206 let idx1: usize = stringnums.parse().unwrap();
207
208 &self[(idx0 - 1, idx1 - 1)]
209 }
210 3 => {
211 let stringnums = parts[0]
212 .chars()
213 .filter(|c| c.is_digit(10))
214 .collect::<String>();
215
216 let idx0: usize = stringnums.parse().unwrap();
217
218 let stringnums = parts[1]
219 .chars()
220 .filter(|c| c.is_digit(10))
221 .collect::<String>();
222
223 let idx1: usize = stringnums.parse().unwrap();
224
225 let stringnums = parts[2]
226 .chars()
227 .filter(|c| c.is_digit(10))
228 .collect::<String>();
229
230 let idx2: usize = stringnums.parse().unwrap();
231
232 &self[(idx0 - 1, idx1 - 1, idx2 - 1)]
233 }
234 _ => &"",
235 }
236 }
237}
238
239#[cfg(feature = "string_index")]
240impl<'a> Index<&str> for Field<'a> {
241 type Output = &'a str;
242
243 #[cfg(feature = "string_index")]
245 fn index(&self, idx: &str) -> &Self::Output {
246 &self[String::from(idx)]
247 }
248}
249
250#[cfg(test)]
251mod tests {
252 use super::*;
253
254 #[test]
255 fn test_conditional_parse_handles_none() {
256 let d = Separators::default();
257
258 match Field::parse_optional(None, &d) {
260 Ok(None) => assert!(true),
261 _ => assert!(false),
262 }
263 }
264
265 #[test]
266 fn test_conditional_parse_handles_empty_string() {
267 let d = Separators::default();
268
269 match Field::parse_optional(Some(""), &d) {
271 Ok(None) => assert!(true),
272 _ => assert!(false),
273 }
274 }
275
276 #[test]
277 fn test_conditional_parse_handles_value_string() {
278 let d = Separators::default();
279
280 match Field::parse_optional(Some("xxx"), &d) {
282 Ok(Some(field)) => assert_eq!(field.value(), "xxx"),
283 _ => assert!(false),
284 }
285 }
286
287 #[test]
288 fn test_parse_mandatory_handles_some_value() {
289 let d = Separators::default();
290
291 match Field::parse_mandatory(Some("xxx"), &d) {
292 Ok(field) => assert_eq!(field.value(), "xxx"),
293 _ => assert!(false),
294 }
295 }
296
297 #[test]
298 fn test_parse_mandatory_throws_on_none() {
299 let d = Separators::default();
300
301 match Field::parse_mandatory(None, &d) {
302 Err(Hl7ParseError::MissingRequiredValue()) => assert!(true),
303 _ => assert!(false),
304 }
305 }
306 #[test]
307 fn test_parse_repeats() {
308 let d = Separators::default();
309 let f = Field::parse_mandatory(Some("x&x^y&y~a&a^b&b"), &d).unwrap();
310 assert_eq!(f.repeats.len(), 2)
311 }
312
313 #[test]
314 fn test_parse_components() {
315 let d = Separators::default();
316 let f = Field::parse_mandatory(Some("xxx^yyy"), &d).unwrap();
317 assert_eq!(f.components[0].len(), 2)
318 }
319
320 #[test]
321 fn test_parse_subcomponents() {
322 let d = Separators::default();
323 let f = Field::parse_mandatory(Some("xxx^yyy&zzz"), &d).unwrap();
324 assert_eq!(f.subcomponents[0][1].len(), 2)
325 }
326
327 #[test]
328 fn test_to_string() {
329 let d = Separators::default();
330 let f = Field::parse_mandatory(Some("xxx^yyy&zzz"), &d).unwrap();
331 assert_eq!(f.to_string(), String::from("xxx^yyy&zzz"))
332 }
333
334 #[test]
335 fn test_clone() {
336 let d = Separators::default();
337 let f = Field::parse_mandatory(Some("xxx^yyy&zzz"), &d).unwrap();
338 assert_eq!(f.to_string(), f.clone().as_str())
339 }
340
341 #[test]
342 fn test_uint_index() {
343 let d = Separators::default();
344 let f = Field::parse_mandatory(Some("xxx^yyy&zzz"), &d).unwrap();
345 assert_eq!(f[(0, 1)], "yyy&zzz");
346 assert_eq!(f[(0, 1, 1)], "zzz");
347 }
348
349 #[test]
350 fn test_string_query() {
351 let d = Separators::default();
352 let f = Field::parse_mandatory(Some("x&x^y&y~a&a^b&b"), &d).unwrap();
353 let idx0 = String::from("R2");
354 let oob = "R2.C3";
355 assert_eq!(f.query(&*idx0), "a&a^b&b");
356 assert_eq!(f.query("R2.C2"), "b&b");
357 assert_eq!(f.query(oob), "");
358 }
359
360 #[cfg(feature = "string_index")]
361 mod string_index_tests {
362 use super::*;
363 #[test]
364 fn test_string_index() {
365 let d = Separators::default();
366 let f = Field::parse_mandatory(Some("x&x^y&y~a&a^b&b"), &d).unwrap();
367 assert_eq!(f["R2"], "a&a^b&b");
368 assert_eq!(f["R2.C2"], "b&b");
369 assert_eq!(f["R2.C3"], "");
370 }
371 }
372}