hl7_parser/builder/
repeat.rs1use super::ComponentBuilder;
2use crate::{
3 datetime::TimeStamp,
4 message::{Repeat, Separators},
5};
6use display::RepeatBuilderDisplay;
7use std::{collections::HashMap, fmt::Display};
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub enum RepeatBuilder {
12 Value(String),
13 Components(HashMap<usize, ComponentBuilder>),
14}
15
16impl Default for RepeatBuilder {
17 fn default() -> Self {
18 RepeatBuilder::Value(String::new())
19 }
20}
21
22impl RepeatBuilder {
23 pub fn with_value(value: String) -> Self {
24 RepeatBuilder::Value(value)
25 }
26
27 pub fn with_components(components: HashMap<usize, ComponentBuilder>) -> Self {
28 RepeatBuilder::Components(components)
29 }
30
31 pub fn value(&self) -> Option<&String> {
32 match self {
33 RepeatBuilder::Value(value) => Some(value),
34 _ => None,
35 }
36 }
37
38 pub fn components(&self) -> Option<&HashMap<usize, ComponentBuilder>> {
39 match self {
40 RepeatBuilder::Components(components) => Some(components),
41 _ => None,
42 }
43 }
44
45 pub fn value_mut(&mut self) -> Option<&mut String> {
46 match self {
47 RepeatBuilder::Value(value) => Some(value),
48 _ => None,
49 }
50 }
51
52 pub fn components_mut(&mut self) -> Option<&mut HashMap<usize, ComponentBuilder>> {
53 match self {
54 RepeatBuilder::Components(components) => Some(components),
55 _ => None,
56 }
57 }
58
59 pub fn has_components(&self) -> bool {
60 matches!(self, RepeatBuilder::Components(_))
61 }
62
63 pub fn into_value(self) -> Option<String> {
64 match self {
65 RepeatBuilder::Value(value) => Some(value),
66 _ => None,
67 }
68 }
69
70 pub fn into_components(self) -> Option<HashMap<usize, ComponentBuilder>> {
71 match self {
72 RepeatBuilder::Components(components) => Some(components),
73 _ => None,
74 }
75 }
76
77 pub fn is_empty(&self) -> bool {
78 match self {
79 RepeatBuilder::Value(value) => value.is_empty(),
80 RepeatBuilder::Components(components) => components.is_empty(),
81 }
82 }
83
84 pub fn set_value<S: ToString>(&mut self, value: S) {
85 *self = RepeatBuilder::Value(value.to_string());
86 }
87
88 pub fn set_timestamp<T: Into<TimeStamp>>(&mut self, timestamp: T) {
89 *self = RepeatBuilder::Value(timestamp.into().to_string());
90 }
91
92 pub fn set_components(&mut self, components: HashMap<usize, ComponentBuilder>) {
93 *self = RepeatBuilder::Components(components);
94 }
95
96 pub fn set_component<C: Into<ComponentBuilder>>(&mut self, index: usize, component: C) {
97 debug_assert!(index > 0, "Component numbers are 1-based");
98 match self {
99 RepeatBuilder::Components(components) => {
100 components.insert(index, component.into());
101 }
102 _ => {
103 let mut components = HashMap::new();
104 components.insert(index, component.into());
105 *self = RepeatBuilder::Components(components);
106 }
107 }
108 }
109
110 pub fn set_component_value<S: ToString>(&mut self, index: usize, value: S) {
111 debug_assert!(index > 0, "Component numbers are 1-based");
112 match self {
113 RepeatBuilder::Components(components) => {
114 let component = components
115 .entry(index)
116 .or_insert(ComponentBuilder::default());
117 component.set_value(value);
118 }
119 _ => {
120 let mut components = HashMap::new();
121 let component = ComponentBuilder::Value(value.to_string());
122 components.insert(index, component);
123 *self = RepeatBuilder::Components(components);
124 }
125 }
126 }
127
128 pub fn clear(&mut self) {
129 *self = RepeatBuilder::Value(String::new());
130 }
131
132 pub fn component(&self, index: usize) -> Option<&ComponentBuilder> {
133 debug_assert!(index > 0, "Component numbers are 1-based");
134 match self {
135 RepeatBuilder::Components(components) => components.get(&index),
136 _ => None,
137 }
138 }
139
140 pub fn component_mut(&mut self, index: usize) -> Option<&mut ComponentBuilder> {
141 debug_assert!(index > 0, "Component numbers are 1-based");
142 match self {
143 RepeatBuilder::Components(components) => components.get_mut(&index),
144 _ => None,
145 }
146 }
147
148 pub fn remove_component(&mut self, index: usize) -> Option<ComponentBuilder> {
149 debug_assert!(index > 0, "Component numbers are 1-based");
150 match self {
151 RepeatBuilder::Components(components) => components.remove(&index),
152 _ => None,
153 }
154 }
155
156 pub fn display<'a>(&'a self, separators: &'a Separators) -> RepeatBuilderDisplay<'a> {
157 RepeatBuilderDisplay {
158 repeat: self,
159 separators,
160 }
161 }
162
163 pub fn from_component_map<I: Into<usize>, C: Into<ComponentBuilder>>(
164 components: HashMap<I, C>,
165 ) -> Self {
166 let components = components
167 .into_iter()
168 .map(|(i, c)| (i.into(), c.into()))
169 .collect();
170 RepeatBuilder::Components(components)
171 }
172}
173
174mod display {
175 use super::*;
176
177 pub struct RepeatBuilderDisplay<'a> {
178 pub(super) repeat: &'a RepeatBuilder,
179 pub(super) separators: &'a Separators,
180 }
181
182 impl<'a> Display for RepeatBuilderDisplay<'a> {
183 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184 match self.repeat {
185 RepeatBuilder::Value(value) => self.separators.encode(value).fmt(f),
186 RepeatBuilder::Components(components) => {
187 if components.is_empty() {
188 return Ok(());
189 }
190 let max_index = components.keys().max().unwrap();
191 for i in 1..=*max_index {
192 if let Some(component) = components.get(&i) {
193 write!(f, "{}", component.display(self.separators))?;
194 }
195 if i < *max_index {
196 write!(f, "{}", self.separators.component)?;
197 }
198 }
199 Ok(())
200 }
201 }
202 }
203 }
204}
205
206impl<S: ToString> From<S> for RepeatBuilder {
207 fn from(value: S) -> Self {
208 RepeatBuilder::Value(value.to_string())
209 }
210}
211
212impl<'m> From<&'m Repeat<'m>> for RepeatBuilder {
213 fn from(repeat: &'m Repeat<'m>) -> Self {
214 if repeat.has_components() {
215 let components = repeat
216 .components
217 .iter()
218 .enumerate()
219 .map(|(i, c)| (i + 1, c.into()))
220 .collect();
221 RepeatBuilder::Components(components)
222 } else {
223 RepeatBuilder::Value(repeat.raw_value().to_string())
224 }
225 }
226}
227
228#[cfg(test)]
229mod tests {
230 use super::*;
231 use pretty_assertions_sorted::{assert_eq, assert_eq_sorted};
232
233 #[test]
234 fn can_display_repeat_builder() {
235 let separators = Separators::default();
236 let repeat = RepeatBuilder::with_value("value".to_string());
237 let display = repeat.display(&separators).to_string();
238 assert_eq!(display, "value");
239
240 let mut components = HashMap::new();
241 components.insert(1, ComponentBuilder::with_value("foo".to_string()));
242 components.insert(3, ComponentBuilder::with_value("bar".to_string()));
243 let repeat = RepeatBuilder::with_components(components);
244 let display = repeat.display(&separators).to_string();
245 assert_eq!(display, "foo^^bar");
246 }
247
248 #[test]
249 fn can_convert_repeat_to_repeat_builder() {
250 let repeat = crate::parser::parse_repeat("foo^^bar").expect("Can parse repeat");
251 let repeat_builder = RepeatBuilder::from(&repeat);
252 assert_eq_sorted!(
253 repeat_builder,
254 RepeatBuilder::with_components({
255 let mut components = HashMap::new();
256 components.insert(1, ComponentBuilder::with_value("foo".to_string()));
257 components.insert(2, ComponentBuilder::with_value("".to_string()));
258 components.insert(3, ComponentBuilder::with_value("bar".to_string()));
259 components
260 })
261 );
262 }
263}