hl7_parser/builder/
repeat.rs

1use 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}