1extern crate core;
48
49use std::fmt;
50
51const SB: u8 = 11u8;
53const EB: u8 = 28u8;
55const CR: u8 = 13u8;
57const ACK: u8 = 6u8;
58const NAK: u8 = 15u8;
60
61pub struct MllpCodec { }
62
63impl MllpCodec {
64 pub fn encode(with: &[u8]) -> Vec<u8> {
65 let mut buf: Vec<u8> = vec![];
66
67 buf.push(SB);
68 buf.extend(with.iter());
69 buf.push(EB);
70 buf.push(CR);
71
72 buf
73 }
74
75 pub fn decode(with: &[u8]) -> Result<&[u8], MllpSyntaxError> {
76 assert!(with.len() >= 4);
77
78 let sb = with[0];
79 let hl7 = &with[1..with.len() - 2];
80 let eb = with[with.len() - 2];
81 let cr = with[with.len() - 1];
82
83 if sb == SB && eb == EB && cr == CR {
84 Ok(hl7)
85 } else {
86 Err(MllpSyntaxError)
87 }
88 }
89
90 pub fn ack() -> [u8;4] {
97 [SB, ACK, EB, CR]
98 }
99
100 pub fn nak() -> [u8;4] {
107 [SB, NAK, EB, CR]
108 }
109
110 pub fn is_ack(with: &[u8]) -> bool {
111 with == Self::ack()
112 }
113
114 pub fn is_nak(with: &[u8]) -> bool {
115 with == Self::nak()
116 }
117}
118
119#[derive(Debug)]
120pub struct MllpSyntaxError;
121
122impl fmt::Display for MllpSyntaxError {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 write!(f, "Expected bytes <SB>...<EB><CR>")
125 }
126}
127
128impl std::error::Error for MllpSyntaxError { }
129
130#[cfg(test)]
131mod tests {
132 use std::io::{Read, Write};
133 use std::net::{SocketAddr, TcpListener, TcpStream};
134 use std::sync::mpsc;
135 use std::thread;
136 use std::time::Duration;
137 use crate::MllpCodec;
138
139 #[test]
140 fn encode_and_decode_same_message() {
141 let data = "MSH|^~\\&|ZIS|1^AHospital|||200405141144||¶ADT^A01|20041104082400|P|2.3|||AL|NE|||8859/15|¶EVN|A01|20041104082400.0000+0100|20041104082400¶PID||\"\"|10||Vries^Danny^D.^^de||19951202|M|||Rembrandlaan^7^Leiden^^7301TH^\"\"^^P||\"\"|\"\"||\"\"|||||||\"\"|\"\"¶PV1||I|3w^301^\"\"^01|S|||100^van den Berg^^A.S.^^\"\"^dr|\"\"||9||||H||||20041104082400.0000+0100";
142 let encoded_data = MllpCodec::encode(data.as_bytes());
143 let decoded_data = MllpCodec::decode(encoded_data.as_slice());
144
145 assert!(decoded_data.is_ok());
146 assert_eq!(decoded_data.unwrap(), data.as_bytes());
147 }
148
149 #[test]
150 fn listen_and_receive_mllp_packet() {
151 let data = "MSH|^~\\&|ZIS|1^AHospital|||200405141144||¶ADT^A01|20041104082400|P|2.3|||AL|NE|||8859/15|¶EVN|A01|20041104082400.0000+0100|20041104082400¶PID||\"\"|10||Vries^Danny^D.^^de||19951202|M|||Rembrandlaan^7^Leiden^^7301TH^\"\"^^P||\"\"|\"\"||\"\"|||||||\"\"|\"\"¶PV1||I|3w^301^\"\"^01|S|||100^van den Berg^^A.S.^^\"\"^dr|\"\"||9||||H||||20041104082400.0000+0100";
152 let original_data = data.clone();
153 let addr = "127.0.0.1:5000";
154 let (tx, rx) = mpsc::channel();
155
156 let handler = thread::spawn(move || {
157 let listener = TcpListener::bind(addr).unwrap();
158 tx.send(true).unwrap();
159
160 for stream in listener.incoming() {
161 assert!(stream.is_ok());
162 let mut buf: Vec<u8> = vec![];
163 let _ = stream.unwrap().read_to_end(&mut buf);
164 let decoded_data = String::from_utf8_lossy(MllpCodec::decode(buf.as_slice()).unwrap());
165 assert_eq!(decoded_data, data);
166 break;
167 }
168 drop(listener);
170 });
171
172 let handler2 = thread::spawn(move || {
173 for received in rx {
174 if received {
175 let socket_addr = SocketAddr::from(([127, 0, 0, 1], 5000));
176 let mut stream = TcpStream::connect_timeout(&socket_addr, Duration::from_secs(3)).unwrap();
177 let _ = stream.write(MllpCodec::encode(original_data.as_bytes()).as_slice());
178 }
179 }
180
181 });
182
183 handler2.join().expect("TODO: panic message server");
184 handler.join().expect("TODO: panic message listener");
185 }
186
187 #[test]
188 fn it_creates_ack() {
189 let ack = MllpCodec::ack();
190 assert!(MllpCodec::is_ack(&ack));
191 }
192
193 #[test]
194 fn it_creates_nak() {
195 let nak = MllpCodec::nak();
196 assert!(MllpCodec::is_nak(&nak));
197 }
198}