hl7_parser/builder/
segment.rs1use display::SegmentBuilderDisplay;
2
3use crate::message::Segment;
4use std::{collections::HashMap, fmt::Display};
5
6use super::FieldBuilder;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[derive(Default)]
12pub struct SegmentBuilder {
13 pub name: String,
14 pub fields: HashMap<usize, FieldBuilder>,
15}
16
17impl SegmentBuilder {
18 pub fn new<S: ToString>(name: S) -> Self {
20 SegmentBuilder {
21 name: name.to_string(),
22 fields: HashMap::new(),
23 }
24 }
25
26 pub fn push_field(&mut self, field: FieldBuilder) {
28 let index = self.fields.len();
29 self.fields.insert(index + 1, field);
30 }
31
32 pub fn name(&self) -> &str {
34 &self.name
35 }
36
37 pub fn fields(&self) -> &HashMap<usize, FieldBuilder> {
39 &self.fields
40 }
41
42 pub fn fields_mut(&mut self) -> &mut HashMap<usize, FieldBuilder> {
44 &mut self.fields
45 }
46
47 pub fn field(&self, index: usize) -> Option<&FieldBuilder> {
49 debug_assert!(index > 0, "Field numbers are 1-based");
50 self.fields.get(&index)
51 }
52
53 pub fn field_mut(&mut self, index: usize) -> Option<&mut FieldBuilder> {
55 debug_assert!(index > 0, "Field numbers are 1-based");
56 self.fields.get_mut(&index)
57 }
58
59 pub fn remove_field(&mut self, index: usize) -> Option<FieldBuilder> {
61 debug_assert!(index > 0, "Field numbers are 1-based");
62 self.fields.remove(&index)
63 }
64
65 pub fn has_field(&self, index: usize) -> bool {
67 debug_assert!(index > 0, "Field numbers are 1-based");
68 self.fields.contains_key(&index)
69 }
70
71 pub fn is_empty(&self) -> bool {
73 self.fields.is_empty()
74 }
75
76 pub fn clear(&mut self) {
78 self.fields.clear();
79 }
80
81 pub fn set_name<S: ToString>(&mut self, name: S) {
83 self.name = name.to_string();
84 }
85
86 pub fn set_field(&mut self, index: usize, field: FieldBuilder) {
88 debug_assert!(index > 0, "Field numbers are 1-based");
89 self.fields.insert(index, field);
90 }
91
92 pub fn set_field_value<S: ToString>(&mut self, index: usize, value: S) {
94 debug_assert!(index > 0, "Field numbers are 1-based");
95 let field = self.fields.entry(index).or_default();
96 field.set_value(value.to_string());
97 }
98
99 pub fn with_field<F: Into<FieldBuilder>>(mut self, index: usize, field: F) -> Self {
101 self.set_field(index, field.into());
102 self
103 }
104
105 pub fn with_field_value<S: ToString>(mut self, index: usize, value: S) -> Self {
107 self.set_field_value(index, value);
108 self
109 }
110
111 pub fn display<'a>(&'a self, separators: &'a super::Separators) -> SegmentBuilderDisplay<'a> {
113 SegmentBuilderDisplay {
114 segment: self,
115 separators,
116 }
117 }
118}
119
120mod display {
121 use super::*;
122 use crate::message::Separators;
123
124 pub struct SegmentBuilderDisplay<'a> {
126 pub(super) segment: &'a SegmentBuilder,
127 pub(super) separators: &'a Separators,
128 }
129
130 impl<'a> Display for SegmentBuilderDisplay<'a> {
131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132 write!(f, "{}", self.segment.name)?;
133
134 if self.segment.fields.is_empty() {
135 return Ok(());
136 }
137
138 let start_index = if self.segment.name == "MSH" {
139 write!(f, "{}", self.separators)?;
140 3
141 } else {
142 1
143 };
144 write!(f, "{}", self.separators.field)?;
145 let max_index = self.segment.fields.keys().max().unwrap();
146 for i in start_index..=*max_index {
147 if let Some(field) = self.segment.fields.get(&i) {
148 write!(f, "{}", field.display(self.separators))?;
149 }
150 if i < *max_index {
151 write!(f, "{}", self.separators.field)?;
152 }
153 }
154 Ok(())
155 }
156 }
157}
158
159impl<'m> From<&'m Segment<'m>> for SegmentBuilder {
160 fn from(segment: &'m Segment) -> Self {
161 let mut builder = SegmentBuilder::new(segment.name);
162 builder.fields = segment
163 .fields
164 .iter()
165 .enumerate()
166 .map(|(index, field)| (index + 1, field.into()))
167 .collect();
168 builder
169 }
170}
171
172#[cfg(test)]
173mod tests {
174 use crate::message::Separators;
175
176 use super::*;
177 use pretty_assertions_sorted::assert_eq;
178
179 #[test]
180 fn can_convert_from_segment() {
181 let segment = crate::parser::parse_segment(r#"PID|1|2|3"#).unwrap();
182 let builder: SegmentBuilder = SegmentBuilder::from(&segment);
183 assert_eq!(builder.name(), "PID");
184 assert_eq!(builder.fields().len(), 3);
185 assert_eq!(builder.field(1).unwrap().value().unwrap(), "1");
186 assert_eq!(builder.field(2).unwrap().value().unwrap(), "2");
187 assert_eq!(builder.field(3).unwrap().value().unwrap(), "3");
188 }
189
190 #[test]
191 fn can_display_segment() {
192 let segment = crate::parser::parse_segment(r#"PID|1|2|3"#).unwrap();
193 let builder: SegmentBuilder = SegmentBuilder::from(&segment);
194 let separators = Separators::default();
195 let display = builder.display(&separators).to_string();
196 assert_eq!(display, r#"PID|1|2|3"#);
197 }
198}