freeswitch_esl_rs/
data.rs1extern crate urldecode;
2
3use std::{io, str, error, fmt, string, num};
4use std::collections::HashMap;
5use std::io::{Read, BufReader};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct Pdu {
10 inner_header: HashMap<String, String>,
11 content: Vec<u8>
12}
13
14#[derive(Debug)]
15pub enum ParseError {
16 IOError(io::Error),
17 StrError(str::Utf8Error),
18 StringError(string::FromUtf8Error),
19 NumError(num::ParseIntError),
20 FromPduError(FromPduError)
21}
22
23impl fmt::Display for ParseError {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 write!(f, "{:?}", self)
26 }
27}
28
29impl error::Error for ParseError {
30 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
31 match self {
32 ParseError::IOError(e) => Some(e),
33 ParseError::StrError(e) => Some(e),
34 ParseError::StringError(e) => Some(e),
35 ParseError::NumError(e) => Some(e),
36 ParseError::FromPduError(e) => Some(e)
37 }
38 }
39}
40
41impl From<io::Error> for ParseError {
42 fn from(e: io::Error) -> Self {
43 ParseError::IOError(e)
44 }
45}
46
47impl From<str::Utf8Error> for ParseError {
48 fn from(e: str::Utf8Error) -> Self {
49 ParseError::StrError(e)
50 }
51}
52
53impl From<string::FromUtf8Error> for ParseError {
54 fn from(e: string::FromUtf8Error) -> Self {
55 ParseError::StringError(e)
56 }
57}
58
59impl From<num::ParseIntError> for ParseError {
60 fn from(e: num::ParseIntError) -> Self {
61 ParseError::NumError(e)
62 }
63}
64
65#[derive(Debug)]
66pub struct FromPduError(&'static str);
67
68impl fmt::Display for FromPduError {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(f, "{:?}", self.0)
71 }
72}
73
74impl error::Error for FromPduError {
75 fn description(&self) -> &str {
76 &self.0
77 }
78}
79
80pub trait FromPdu: Sized {
82 type Err;
83
84 fn from_pdu(pdu: &Pdu) -> Result<Self, Self::Err>;
85}
86
87impl FromPdu for String {
89 type Err = ParseError;
90
91 fn from_pdu(pdu: &Pdu) -> Result<Self, Self::Err> {
92 let content: String = str::from_utf8(&pdu.content)?.to_string();
93 Ok(content)
94 }
95}
96
97type Header = HashMap<String, String>;
98
99fn header_parse(content: String) -> Header {
100 let mut header = Header::new();
101
102 content
103 .split('\n')
104 .filter(|line| {
105 !line.is_empty()
106 })
107 .for_each(|line| {
108
109 let mut item = line.splitn(2, ':');
110 let key = item.next().unwrap().trim().to_string();
112 let value = item.next().unwrap().trim().to_string();
113
114 header.insert(key, urldecode::decode(value));
115 });
116
117 header
118}
119
120impl Pdu {
121 pub fn header(&self, k: &str) -> String {
122 match self.inner_header.get(k) {
123 Some(v) => v.to_string(),
124 None => "".to_string()
125 }
126 }
127
128 pub fn is_empty(&self) -> bool {
129 self.content.len() == 0
130 }
131
132 pub fn parse<F: FromPdu>(&self) -> Result<F, F::Err> {
134 FromPdu::from_pdu(self)
135 }
136
137 fn get(&self, k: &str) -> String {
138 match self.inner_header.get(k) {
139 Some(v) => v.to_string(),
140 None => "".to_string()
141 }
142 }
143}
144
145pub struct PduParser {
146}
147
148impl PduParser {
149 pub fn parse<R: Read>(reader: &mut BufReader<R>) -> Result<Pdu, ParseError> {
150 let header = Self::parse_header(reader)?;
151 let content = Self::parse_content(&header, reader)?;
152
153 let pdu = Pdu {
154 inner_header: header,
155 content: content
156 };
157
158 Ok(pdu)
159 }
160
161 fn parse_header(reader: &mut impl io::BufRead) -> Result<Header, ParseError> {
162 let raw = Self::get_header_content(reader)?;
163 let raw_str = String::from_utf8(raw)?;
164 let header = header_parse(raw_str);
165
166 Ok(header)
167 }
168
169 fn parse_content(header: &Header, reader: &mut impl io::BufRead) -> Result<Vec<u8>, ParseError> {
170 if let Some(length) = header.get("Content-Length") {
171 let length: usize = length.parse()?;
172
173 let mut content = vec![0u8; length];
174 reader.read_exact(&mut content)?;
175
176 return Ok(content)
177 }
178
179 Ok(vec![0u8; 0])
180 }
181
182 fn get_header_content(reader: &mut impl io::BufRead) -> io::Result<Vec<u8>> {
183 let mut raw: Vec<u8> = Vec::with_capacity(1024);
184 let mut buf: Vec<u8> = Vec::with_capacity(1024);
185
186 loop {
187 buf.clear();
188 let readed_bytes = reader.read_until(b'\n', &mut buf)?;
189
190 if readed_bytes == 0 {
191 raw.truncate(0);
195 break;
196 } else if readed_bytes == 1 && buf[0] == b'\n' {
197 break;
198 } else {
199 raw.append(&mut buf);
200 }
201 }
202
203 Ok(raw)
204 }
205}
206
207#[derive(Debug, Clone, PartialEq, Eq)]
208pub struct Event {
209 inner: Header,
210 length: usize
211}
212
213impl Event {
214 pub fn get(&self, k: &str) -> Option<&String> {
216 self.inner.get(k)
217 }
218
219 pub fn len(&self) -> usize {
221 self.length
222 }
223
224}
225
226impl Into<Header> for Event {
227 fn into(self) -> Header {
228 self.inner.clone()
229 }
230}
231
232impl FromPdu for Event {
233 type Err = ParseError;
234
235 fn from_pdu(pdu: &Pdu) -> Result<Self, Self::Err> {
236 if pdu.get("Content-Type") == "text/event-plain" {
237 let raw = str::from_utf8(&pdu.content)?;
238 let length = raw.len();
239 let content = String::from(raw);
240 let header = header_parse(content);
241 Ok(Event{inner: header, length: length})
242 } else {
243 Err(ParseError::FromPduError(FromPduError("invalid content-type expected text/event-plain")))
244 }
245 }
246}
247
248#[cfg(test)]
249mod tests {
250 use super::*;
251
252 #[test]
253 fn it_event_into_hashmap() -> Result<(), &'static str> {
254 let mut header = Header::new();
255 header.insert("Event-Name".to_string(), "TEST".to_string());
256 let event = Event{inner: header.clone(), length: 99};
257
258 let new_header: Header = event.into();
259 assert_eq!(header, new_header);
260 Ok(())
261 }
262}