sse_client/
data.rs

1pub struct EventBuilder {
2    pending_event: EventBuilderState
3}
4
5/// Event data sent by server
6#[derive(Debug, PartialEq, Clone)]
7pub struct Event {
8    /// Represents message `id` field. Default "".
9    pub id: String,
10    /// Represents message `event` field. Default "message".
11    pub type_: String,
12    /// Represents message `data` field. Default "".
13    pub data: String
14}
15
16#[derive(Debug, PartialEq, Clone)]
17pub enum EventBuilderState {
18    Empty,
19    Pending(Event),
20    Complete(Event)
21}
22
23impl Event {
24    pub fn new(type_: &str, data: &str) -> Event {
25        Event { id: String::from(""), type_: String::from(type_), data: String::from(data) }
26    }
27}
28
29impl EventBuilder {
30    pub fn new() -> EventBuilder {
31        EventBuilder { pending_event: EventBuilderState::Empty }
32    }
33
34    pub fn update(&mut self, message: &str) -> EventBuilderState {
35        if message == "" {
36            self.finalize_event();
37        } else if !message.starts_with(":") && message.contains(":") {
38            self.pending_event = self.update_event(message);
39        }
40
41        self.get_event()
42    }
43
44    fn finalize_event(&mut self) {
45        self.pending_event = match self.pending_event {
46            EventBuilderState::Complete(_) => EventBuilderState::Empty,
47            EventBuilderState::Pending(ref event) => EventBuilderState::Complete(event.clone()),
48            ref e => e.clone()
49        };
50    }
51
52    fn update_event(&mut self, message: &str) -> EventBuilderState {
53        let mut pending_event = match &self.pending_event {
54            EventBuilderState::Pending(ref e) => e.clone(),
55            _ => Event::new("message", "")
56        };
57
58        match parse_field(message) {
59            ("data", value) => pending_event.data = String::from(value),
60            ("event", value) => pending_event.type_ = String::from(value),
61            ("id", value) => pending_event.id = String::from(value),
62            _ => {}
63        }
64
65        EventBuilderState::Pending(pending_event)
66    }
67
68    pub fn clear(&mut self) {
69        self.pending_event =  EventBuilderState::Empty;
70    }
71
72    pub fn get_event(&self) -> EventBuilderState {
73       self.pending_event.clone()
74    }
75}
76
77fn parse_field<'a>(message: &'a str) -> (&'a str, &'a str) {
78    let parts: Vec<&str> = message.splitn(2, ":").collect();
79    (parts[0], parts[1].trim())
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn should_start_with_empty_state() {
88        let e = EventBuilder::new();
89
90        assert_eq!(e.get_event(), EventBuilderState::Empty);
91    }
92
93    #[test]
94    fn should_set_message_as_default_event_type() {
95        let mut e = EventBuilder::new();
96        e.update("data: test");
97
98        if let EventBuilderState::Pending(event) = e.get_event() {
99            assert_eq!(event.type_, String::from("message"));
100        } else {
101            panic!("event should be pending");
102        }
103    }
104
105    #[test]
106    fn should_change_status_to_complete_when_empty_message_received() {
107        let mut e = EventBuilder::new();
108        e.update("data: test");
109        e.update("");
110
111        if let EventBuilderState::Complete(event) = e.get_event() {
112            assert_eq!(event.data, String::from("test"));
113        } else {
114            panic!("event should be complete");
115        }
116    }
117
118    #[test]
119    fn should_remain_as_empty_if_empty_message_is_received_while_buffer_is_empty() {
120        let mut e = EventBuilder::new();
121        e.update("");
122
123        assert_eq!(e.get_event(), EventBuilderState::Empty);
124    }
125
126    #[test]
127    fn should_fill_data_field() {
128        let mut e = EventBuilder::new();
129        e.update("data: test");
130
131        if let EventBuilderState::Pending(event) = e.get_event() {
132            assert_eq!(event.data, String::from("test"));
133        } else {
134            panic!("event should be pending");
135        }
136    }
137
138    #[test]
139    fn should_fill_event_type_field() {
140        let mut e = EventBuilder::new();
141        e.update("event: some_event");
142
143        if let EventBuilderState::Pending(event) = e.get_event() {
144            assert_eq!(event.type_, String::from("some_event"));
145        } else {
146            panic!("event should be pending");
147        }
148    }
149
150    #[test]
151    fn should_fill_event_id_field() {
152        let mut e = EventBuilder::new();
153        e.update("id: 123abc");
154
155        if let EventBuilderState::Pending(event) = e.get_event() {
156            assert_eq!(event.id, String::from("123abc"));
157        } else {
158            panic!("event should be pending");
159        }
160    }
161
162    #[test]
163    fn should_incrementally_fill_event_fields() {
164        let expected_event = Event::new("some_event", "test");
165        let mut e = EventBuilder::new();
166        e.update("event: some_event");
167        e.update("data: test");
168
169        if let EventBuilderState::Pending(event) = e.get_event() {
170            assert_eq!(event, expected_event);
171        } else {
172            panic!("event should be pending");
173        }
174    }
175
176    #[test]
177    fn should_change_status_to_empty_when_event_is_complete_and_empty_message_is_received() {
178        let mut e = EventBuilder::new();
179
180        e.update("data: test");
181        e.update("");
182        e.update("");
183
184        assert_eq!(e.get_event(), EventBuilderState::Empty);
185    }
186
187    #[test]
188    fn should_start_clean_event_after_previous_is_completed() {
189        let expected_event = Event::new("message", "test2");
190        let mut e = EventBuilder::new();
191
192        e.update("event: some_event");
193        e.update("data: test");
194        e.update("");
195        e.update("data: test2");
196
197        if let EventBuilderState::Pending(event) = e.get_event() {
198            assert_eq!(event, expected_event);
199        } else {
200            panic!("event should be pending");
201        }
202    }
203
204    #[test]
205    fn should_ignore_updates_started_with_colon() {
206        let expected_event = Event::new("some_event", "test");
207        let mut e = EventBuilder::new();
208
209        e.update("event: some_event");
210        e.update(":some commentary");
211        e.update("data: test");
212
213        if let EventBuilderState::Pending(event) = e.get_event() {
214            assert_eq!(event, expected_event);
215        } else {
216            panic!("event should be pending");
217        }
218    }
219
220    #[test]
221    fn should_return_event_on_update() {
222        let mut e = EventBuilder::new();
223        assert_eq!(e.update("event: some_event"), e.get_event());
224        assert_eq!(e.update("data: test"), e.get_event());
225    }
226
227    #[test]
228    fn should_parse_messages_even_with_colons() {
229        let expected_event = Event::new("some:id:with:colons", "some:data:with:colons");
230        let mut e = EventBuilder::new();
231
232        e.update("event: some:id:with:colons");
233        e.update("data: some:data:with:colons");
234
235        if let EventBuilderState::Pending(event) = e.get_event() {
236            assert_eq!(event, expected_event);
237        } else {
238            panic!("event should be pending");
239        }
240
241    }
242
243    #[test]
244    fn should_be_empty_when_only_comments_received() {
245        let mut e = EventBuilder::new();
246
247        e.update(":hi");
248        e.update("");
249
250        assert_eq!(e.get_event(), EventBuilderState::Empty);
251    }
252
253    #[test]
254    fn should_ignore_messages_without_colon() {
255        let expected_event = Event::new("some_event", "test");
256        let mut e = EventBuilder::new();
257
258        e.update("event: some_event");
259        e.update("this is a random message that should be ignored");
260        e.update("data: test");
261
262        if let EventBuilderState::Pending(event) = e.get_event() {
263            assert_eq!(event, expected_event);
264        } else {
265            panic!("event should be pending");
266        }
267    }
268}