1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use crate::Field;
use std::ops::Range;

/// The separators for the message
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Separators {
    /// The character that separates fields (default: `'|'`)
    pub field: char,
    /// The character that separates components (default: `'^'`)
    pub component: char,
    /// The character that indicates repeats (default: `'~'`)
    pub repeat: char,
    /// The escape character (default: `'\'`)
    pub escape: char,
    /// The character that separates sub-components (default: `'&'`)
    pub subcomponent: char,
}

impl Default for Separators {
    fn default() -> Self {
        Separators {
            field: '|',
            component: '^',
            repeat: '~',
            escape: '\\',
            subcomponent: '&',
        }
    }
}

impl Separators {
    /// Given an un-decoded source, will decode the string into its canonical form
    ///
    /// # Examples
    ///
    /// ```
    /// # use hl7_parser::Separators;
    /// let separators = Separators::default();
    /// assert_eq!(
    ///     separators.decode(r#"Pierre DuRho\S\ne \T\ Cie"#).as_str(),
    ///     r#"Pierre DuRho^ne & Cie"#
    /// );
    /// ```
    pub fn decode<S: AsRef<str>>(&self, source: S) -> String {
        let mut tmp = [0; 4];
        source
            .as_ref()
            .replace(r#"\F\"#, self.field.encode_utf8(&mut tmp))
            .replace(r#"\R\"#, self.repeat.encode_utf8(&mut tmp))
            .replace(r#"\S\"#, self.component.encode_utf8(&mut tmp))
            .replace(r#"\T\"#, self.subcomponent.encode_utf8(&mut tmp))
            .replace(r#"\.br\"#, "\r")
            .replace(r#"\X0A\"#, "\n")
            .replace(r#"\X0D\"#, "\r")
            .replace(r#"\E\"#, self.escape.encode_utf8(&mut tmp))
    }

    /// Utility to check if a character is a special character
    pub fn is_special_char(&self, c: char) -> bool {
        c == self.field
            || c == self.component
            || c == self.repeat
            || c == self.escape
            || c == self.subcomponent
    }
}

#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub(crate) struct Msh {
    pub range: Range<usize>,
    pub separators: Separators,
    pub fields: Vec<Field>,
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn can_decode_encoding_characters() {
        let separators = Separators::default();
        assert_eq!(separators.decode(r#"\.br\\X0A\\X0D\"#).as_str(), "\r\n\r");
        assert_eq!(separators.decode(r#"\F\\R\\S\\T\\E\"#).as_str(), r#"|~^&\"#);
        assert_eq!(separators.decode(r#"\E\\F\\E\"#).as_str(), r#"\|\"#);
    }
}