1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
use crate::display::ComponentDisplay;
use super::{Separators, Subcomponent};
use std::ops::Range;
/// A component is a part of a field, and is separated from other components by the component
/// separator character. A component is composed of 0 or more subcomponents.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct Component<'m> {
pub(crate) source: &'m str,
/// The subcomponents of the component
pub subcomponents: Vec<Subcomponent<'m>>,
/// The range of the component in the original message
pub range: Range<usize>,
}
impl<'m> Component<'m> {
pub(crate) fn new_single(source: &'m str, range: Range<usize>) -> Self {
Component {
source,
subcomponents: vec![Subcomponent::new_single(source, range.clone())],
range,
}
}
#[inline]
/// An iterator over the subcomponents of the component
pub fn subcomponents(&self) -> impl Iterator<Item = &Subcomponent<'m>> {
self.subcomponents.iter()
}
#[inline]
/// Display the component value, using the separators to decode escape sequences
/// by default. Note: if you want to display the raw value without decoding escape
/// sequences, use the `#` flag, e.g. `format!("{:#}", component.display(separators))`.
/// Components will be separated by the component separator character.
pub fn display(&'m self, separators: &'m Separators) -> ComponentDisplay<'m> {
ComponentDisplay {
subcomponents: &self.subcomponents,
separators,
}
}
#[inline]
/// Get the raw value of the component. This is the value as it appears in the message,
/// without any decoding of escape sequences, and including all subcomponents and
/// their separators.
///
/// # Examples
///
/// ```
/// let component = hl7_parser::parser::parse_component("foo&bar").unwrap();
/// assert_eq!(component.subcomponents.len(), 2);
/// assert_eq!(component.raw_value(), "foo&bar");
/// ```
pub fn raw_value(&self) -> &'m str {
self.source
}
#[inline]
/// Returns true if the component has more than one subcomponent. Note that
/// if the component has only one subcomponent, the value of that subcomponent
/// is essentially the value of the component, so the value of the component
/// can be obtained using `raw_value()`.
///
/// # Examples
///
/// ```
/// let component = hl7_parser::parser::parse_component("foo&bar").unwrap();
/// assert_eq!(component.has_subcomponents(), true);
/// let component = hl7_parser::parser::parse_component("foo").unwrap();
/// assert_eq!(component.has_subcomponents(), false);
/// ```
pub fn has_subcomponents(&self) -> bool {
self.subcomponents.len() > 1
}
/// Returns true if the component has no subcomponents, or if all subcomponents
/// have empty values.
///
/// # Examples
///
/// ```
/// let component = hl7_parser::parser::parse_component("foo&bar").unwrap();
/// assert_eq!(component.is_empty(), false);
/// let component = hl7_parser::parser::parse_component("foo").unwrap();
/// assert_eq!(component.is_empty(), false);
/// let component = hl7_parser::parser::parse_component("foo&").unwrap();
/// assert_eq!(component.is_empty(), false);
/// let component = hl7_parser::parser::parse_component("").unwrap();
/// assert_eq!(component.is_empty(), true);
/// let component = hl7_parser::parser::parse_component("&").unwrap();
/// assert_eq!(component.is_empty(), true);
/// ```
pub fn is_empty(&self) -> bool {
self.subcomponents.is_empty() || self.subcomponents.iter().all(|s| s.value.is_empty())
}
/// Get a subcomponent by its number. Subcomponent numbers are 1-based.
/// Returns `None` if the subcomponent number is out of range.
///
/// # Examples
///
/// ```
/// let component = hl7_parser::parser::parse_component("foo&bar").unwrap();
/// assert_eq!(component.subcomponent(1).unwrap().value, "foo");
/// assert_eq!(component.subcomponent(2).unwrap().value, "bar");
/// assert_eq!(component.subcomponent(3), None);
/// ```
pub fn subcomponent(&self, number: usize) -> Option<&Subcomponent<'m>> {
debug_assert!(number > 0, "Subcomponent numbers are 1-based");
self.subcomponents.get(number - 1)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_get_component_raw_value() {
let component = Component {
source: "foo&bar",
subcomponents: vec![
Subcomponent {
value: "foo",
range: 0..1, // ignore
},
Subcomponent {
value: "bar",
range: 0..1, // ignore
},
],
range: 0..1, // ignore
};
assert_eq!(component.raw_value(), "foo&bar");
}
#[test]
fn components_can_display_raw() {
let component = Component {
source: r"foo\F\bar&baz",
subcomponents: vec![
Subcomponent {
value: r"foo\F\bar",
range: 0..1, // ignore
},
Subcomponent {
value: r"baz",
range: 0..1, // ignore
},
],
range: 0..1, // ignore
};
let formatted = format!("{:#}", component.display(&Separators::default()));
assert_eq!(formatted, r"foo\F\bar&baz");
}
#[test]
fn components_can_display_decoded() {
let component = Component {
source: r"foo\F\bar&baz",
subcomponents: vec![
Subcomponent {
value: r"foo\F\bar",
range: 0..1, // ignore
},
Subcomponent {
value: r"baz",
range: 0..1, // ignore
},
],
range: 0..1, // ignore
};
let formatted = format!("{}", component.display(&Separators::default()));
assert_eq!(formatted, "foo|bar&baz");
}
}