hl7_parser/parser/
component.rs

1use super::{subcomponent::subcomponent, Span};
2use crate::message::{Component, Separators};
3use nom::{character::complete::char, combinator::consumed, multi::separated_list0, IResult};
4
5pub fn component<'i>(seps: Separators) -> impl FnMut(Span<'i>) -> IResult<Span<'i>, Component<'i>> {
6    move |i| parse_component(i, seps)
7}
8
9fn parse_component(i: Span<'_>, seps: Separators) -> IResult<Span<'_>, Component<'_>> {
10    let pos_start = i.offset;
11    let (i, (component_src, v)) =
12        consumed(separated_list0(char(seps.subcomponent), subcomponent(seps)))(i)?;
13    let pos_end = i.offset;
14
15    let v = Component {
16        source: component_src.input,
17        subcomponents: v,
18        range: pos_start..pos_end,
19    };
20    Ok((i, v))
21}
22
23#[cfg(test)]
24mod tests {
25    use super::*;
26    use pretty_assertions_sorted::assert_eq;
27
28    #[test]
29    fn can_parse_component_basic() {
30        let separators = Separators::default();
31
32        let input = Span::new("foo");
33        let actual = parse_component(input, separators).unwrap().1;
34        dbg!(&actual);
35        assert_eq!(actual.subcomponents.len(), 1);
36        assert_eq!(actual.display(&separators).to_string(), "foo");
37        assert_eq!(actual.range, 0..3);
38    }
39
40    #[test]
41    fn can_parse_component_with_subcomponents() {
42        let separators = Separators::default();
43
44        let input = Span::new("foo&bar");
45        let actual = parse_component(input, separators).unwrap().1;
46        dbg!(&actual);
47        assert_eq!(actual.subcomponents.len(), 2);
48        assert_eq!(actual.display(&separators).to_string(), "foo&bar");
49        assert_eq!(actual.range, 0..7);
50        assert_eq!(actual.subcomponents[0].value, "foo");
51        assert_eq!(actual.subcomponents[1].value, "bar");
52        assert_eq!(actual.subcomponents[0].range, 0..3);
53        assert_eq!(actual.subcomponents[1].range, 4..7);
54    }
55
56    #[test]
57    fn can_parse_component_with_no_subcomponents_and_escaped_subcomponent_separator() {
58        let separators = Separators::default();
59
60        let input = Span::new(r"foo\T\bar");
61        let actual = parse_component(input, separators).unwrap().1;
62        dbg!(&actual);
63        assert_eq!(actual.subcomponents.len(), 1);
64        assert_eq!(actual.subcomponents[0].value, r"foo\T\bar");
65    }
66
67    #[test]
68    fn can_parse_component_at_end_of_line() {
69        let separators = Separators::default();
70
71        let input = Span::new("foo\rbar");
72        let actual = parse_component(input, separators).unwrap().1;
73        assert_eq!(actual.subcomponents.len(), 1);
74        assert_eq!(actual.display(&separators).to_string(), "foo");
75    }
76
77    #[test]
78    fn can_parse_component_in_field() {
79        let separators = Separators::default();
80
81        let input = Span::new("foo|bar");
82        let actual = parse_component(input, separators).unwrap().1;
83        assert_eq!(actual.subcomponents.len(), 1);
84        assert_eq!(actual.display(&separators).to_string(), "foo");
85
86        let input = Span::new("foo&bar|baz");
87        let actual = parse_component(input, separators).unwrap().1;
88        assert_eq!(actual.subcomponents.len(), 2);
89        assert_eq!(actual.display(&separators).to_string(), "foo&bar");
90        assert_eq!(actual.subcomponents[0].value, "foo");
91        assert_eq!(actual.subcomponents[1].value, "bar");
92    }
93}