Skip to main content

haste_hl7v2/
serialize.rs

1use haste_fhir_model::r4::generated::resources::{
2    HL7V2, HL7V2Segments, HL7V2SegmentsFields, HL7V2SegmentsFieldsValue,
3    HL7V2SegmentsFieldsValueValue,
4};
5
6pub struct EncodingInformation {
7    pub field_separator: String,
8    pub component_separator: String,
9    pub repetition_separator: String,
10    #[allow(dead_code)]
11    pub escape_character: String,
12    pub subcomponent_separator: String,
13}
14
15#[must_use]
16pub fn component_to_string(
17    encoding_characters: &EncodingInformation,
18    component: &HL7V2SegmentsFieldsValueValue,
19) -> Option<String> {
20    if let Some(subcomponents) = &component.subcomponents {
21        let value = subcomponents
22            .iter()
23            .map(|s| &s.value)
24            .map(|v| {
25                if let Some(s) = v {
26                    s.clone()
27                } else {
28                    String::new()
29                }
30            })
31            .collect::<Vec<_>>()
32            .join(&encoding_characters.subcomponent_separator);
33        Some(value)
34    } else {
35        component.value.as_ref().and_then(|s| s.value.clone())
36    }
37}
38
39#[must_use]
40pub fn segment_field_repetition_to_string(
41    encoding_characters: &EncodingInformation,
42    segment: &HL7V2SegmentsFieldsValue,
43) -> String {
44    let mut result = String::new();
45
46    if let Some(components) = &segment.components {
47        result.push_str(
48            &components
49                .iter()
50                .map(|c| component_to_string(encoding_characters, c).unwrap_or_default())
51                .collect::<Vec<_>>()
52                .join(&encoding_characters.component_separator),
53        );
54    } else if let Some(value) = &segment.value {
55        result.push_str(&component_to_string(encoding_characters, value).unwrap_or_default());
56    }
57
58    result
59}
60
61#[must_use]
62pub fn segment_field_to_string(
63    encoding_characters: &EncodingInformation,
64    segment: &HL7V2SegmentsFields,
65) -> String {
66    let mut result = String::new();
67
68    if let Some(repetitions) = &segment.repetitions {
69        result.push_str(
70            &repetitions
71                .iter()
72                .map(|r| segment_field_repetition_to_string(encoding_characters, r))
73                .collect::<Vec<_>>()
74                .join(&encoding_characters.repetition_separator),
75        );
76    } else if let Some(value) = &segment.value {
77        result.push_str(&segment_field_repetition_to_string(
78            encoding_characters,
79            value,
80        ));
81    }
82
83    result
84}
85
86#[must_use]
87pub fn segment_to_string(
88    encoding_characters: &EncodingInformation,
89    segment: &HL7V2Segments,
90) -> String {
91    let mut result = segment.id.value.as_deref().unwrap_or("").to_string();
92
93    result.push_str(&encoding_characters.field_separator);
94
95    let default_fields = Vec::new();
96    result.push_str(
97        &segment
98            .fields
99            .as_ref()
100            .unwrap_or(&default_fields)
101            .iter()
102            .map(|s| segment_field_to_string(encoding_characters, s))
103            .collect::<Vec<_>>()
104            .join(&encoding_characters.field_separator),
105    );
106
107    result
108}
109
110fn get_encoding_characters(hl7v2_message: &HL7V2) -> Option<String> {
111    let msh = hl7v2_message.segments.as_ref().and_then(|segments| {
112        segments
113            .iter()
114            .find(|s| s.id.value.as_deref() == Some("MSH"))
115    })?;
116
117    let encoding_characters_str = msh
118        .fields
119        .as_ref()
120        .and_then(|fields| fields.iter().next())
121        .and_then(|field| {
122            field.value.as_ref().and_then(|v| {
123                v.value
124                    .as_ref()
125                    .and_then(|s| s.value.as_ref())
126                    .and_then(|s| s.value.as_deref())
127            })
128        })?;
129
130    Some(encoding_characters_str.to_string())
131}
132
133pub struct SerializeMessage<'a>(pub &'a HL7V2);
134
135impl<'a> From<SerializeMessage<'a>> for String {
136    fn from(value: SerializeMessage<'a>) -> Self {
137        let hl7v2_message = value.0;
138        let field_separator = hl7v2_message.fieldSeparator.value.as_deref().unwrap_or("|");
139        let encoding_characters_str =
140            get_encoding_characters(hl7v2_message).unwrap_or("^~\\&".to_string());
141
142        let mut result = String::new();
143
144        let encoding_characters = EncodingInformation {
145            field_separator: field_separator.to_string(),
146            component_separator: encoding_characters_str
147                .chars()
148                .nth(0)
149                .unwrap_or('^')
150                .to_string(),
151            repetition_separator: encoding_characters_str
152                .chars()
153                .nth(1)
154                .unwrap_or('~')
155                .to_string(),
156            escape_character: encoding_characters_str
157                .chars()
158                .nth(2)
159                .unwrap_or('\\')
160                .to_string(),
161
162            subcomponent_separator: encoding_characters_str
163                .chars()
164                .nth(3)
165                .unwrap_or('&')
166                .to_string(),
167        };
168
169        if let Some(segments) = &hl7v2_message.segments {
170            let k = segments
171                .iter()
172                .map(|s| segment_to_string(&encoding_characters, s))
173                .collect::<Vec<_>>()
174                .join("\n");
175
176            result.push_str(&k);
177        }
178
179        result
180    }
181}