eventsource_threaded/
event.rs1use std::fmt;
2use std::time::Duration;
3
4#[derive(Debug)]
6pub struct Event {
7 pub id: Option<String>,
9 pub event_type: Option<String>,
11 pub data: String,
13}
14
15#[derive(Debug, PartialEq)]
17pub enum ParseResult {
18 Next,
20 Dispatch,
22 SetRetry(Duration),
24}
25
26pub fn parse_event_line(line: &str, event: &mut Event) -> ParseResult {
51 let line = line.trim_end_matches(|c| c == '\r' || c == '\n');
52 if line == "" {
53 ParseResult::Dispatch
54 } else {
55 let (field, value) = if let Some(pos) = line.find(':') {
56 let (f, v) = line.split_at(pos);
57 let v = &v[1..];
59 let v = if v.starts_with(' ') { &v[1..] } else { v };
60 (f, v)
61 } else {
62 (line, "")
63 };
64
65 match field {
66 "event" => {
67 event.event_type = Some(value.to_string());
68 }
69 "data" => {
70 event.data.push_str(value);
71 event.data.push('\n');
72 }
73 "id" => {
74 event.id = Some(value.to_string());
75 }
76 "retry" => {
77 if let Ok(retry) = value.parse::<u64>() {
78 return ParseResult::SetRetry(Duration::from_millis(retry));
79 }
80 }
81 _ => (), }
83
84 ParseResult::Next
85 }
86}
87
88impl Event {
89 pub fn new() -> Event {
91 Event {
92 id: None,
93 event_type: None,
94 data: "".to_string(),
95 }
96 }
97
98 pub fn is_empty(&self) -> bool {
102 self.id.is_none() && self.event_type.is_none() && self.data.is_empty()
103 }
104
105 pub fn clear(&mut self) {
107 self.id = None;
108 self.event_type = None;
109 self.data.clear();
110 }
111}
112
113impl fmt::Display for Event {
114 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115 if let Some(ref id) = self.id {
116 write!(f, "id: {}\n", id)?;
117 }
118 if let Some(ref event_type) = self.event_type {
119 write!(f, "event: {}\n", event_type)?;
120 }
121 for line in self.data.lines() {
122 write!(f, "data: {}\n", line)?;
123 }
124 Ok(())
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[test]
133 fn basic_event_display() {
134 assert_eq!(
135 "data: hello world\n",
136 Event {
137 id: None,
138 event_type: None,
139 data: "hello world".to_string()
140 }
141 .to_string()
142 );
143 assert_eq!(
144 "id: foo\ndata: hello world\n",
145 Event {
146 id: Some("foo".to_string()),
147 event_type: None,
148 data: "hello world".to_string()
149 }
150 .to_string()
151 );
152 assert_eq!(
153 "event: bar\ndata: hello world\n",
154 Event {
155 id: None,
156 event_type: Some("bar".to_string()),
157 data: "hello world".to_string()
158 }
159 .to_string()
160 );
161 }
162
163 #[test]
164 fn multiline_event_display() {
165 assert_eq!(
166 "data: hello\ndata: world\n",
167 Event {
168 id: None,
169 event_type: None,
170 data: "hello\nworld".to_string()
171 }
172 .to_string()
173 );
174 assert_eq!(
175 "data: hello\ndata: \ndata: world\n",
176 Event {
177 id: None,
178 event_type: None,
179 data: "hello\n\nworld".to_string()
180 }
181 .to_string()
182 );
183 }
184}