1use std::convert::TryFrom;
2use std::convert::TryInto;
3use std::time;
4
5use crate::id::Id;
6use crate::line::Line;
7use crate::word::Word;
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub struct Message {
12 pub id: Id,
14 pub reply_on: Option<Id>,
16 pub roomname: Box<Word>,
18 pub username: Box<Word>,
20 pub timestamp: time::SystemTime,
22 pub message: Box<Line>,
24}
25
26impl Message {
27 pub(super) fn try_parse(words: &[&str]) -> Result<Self, String> {
28 let err = |field| format!("got invalid value for message field: {}", field);
29
30 macro_rules! parse {
31 ($val:expr, $type:ty, $field:expr) => {
32 $val.parse::<$type>().map_err(|_| err($field))?
33 };
34 }
35 let parse_id = |val, field| Id::try_from(val).map_err(|_| err(field));
36
37 let id = parse!(words[3], i64, "id");
38 let id = parse_id(id, "id")?;
39
40 let reply_on = match parse!(words[4], i64, "reply_on") {
41 -1 => None,
42 id => Some(parse_id(id, "reply_on")?),
43 };
44 let roomname = words[0].to_string().try_into()?;
45 let username = words[1].to_string().try_into()?;
46
47 let timestamp = parse!(words[2], u64, "timestamp");
48 let timestamp = time::UNIX_EPOCH + time::Duration::from_micros(timestamp);
49
50 let message = words[5..].join(" ");
51 let message = message.try_into()?;
52
53 Ok(Self {
54 id,
55 reply_on,
56 roomname,
57 username,
58 timestamp,
59 message,
60 })
61 }
62}