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