Skip to main content

zulip_api/message/
to.rs

1use std::borrow::Cow;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{impl_default, impl_display, Error, Result};
6
7/// Represents the recipient for the Zulip message.
8#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
9#[serde(untagged)]
10pub enum MessageTo {
11    /// Represents the recipient channel ID.
12    ChannelId(u64),
13    /// Represents the recipient channel name.
14    ChannelName(String),
15    /// Represents the list of recipient user IDs.
16    UserIds(Vec<u64>),
17    /// Represents the list of recipient user Zulip API email adddresses.
18    UserEmails(Vec<String>),
19}
20
21impl MessageTo {
22    /// Represents the field name for channel ID.
23    pub const CHANNEL_ID_FIELD: &str = "channel_id";
24    /// Represents the field name for channel name.
25    pub const CHANNEL_NAME_FIELD: &str = "channel_name";
26    /// Represents the field name for user IDs.
27    pub const USER_IDS_FIELD: &str = "user_ids";
28    /// Represents the field name for user emails.
29    pub const USER_EMAILS_FIELD: &str = "user_emails";
30
31    /// Creates a new [MessageTo].
32    pub const fn new() -> Self {
33        Self::ChannelId(0)
34    }
35
36    /// Gets the field name of the [Self] variant.
37    pub const fn field_name(&self) -> &'static str {
38        match self {
39            Self::ChannelId(_) => Self::CHANNEL_ID_FIELD,
40            Self::ChannelName(_) => Self::CHANNEL_NAME_FIELD,
41            Self::UserIds(_) => Self::USER_IDS_FIELD,
42            Self::UserEmails(_) => Self::USER_EMAILS_FIELD,
43        }
44    }
45
46    /// Creates a new channel ID [Self].
47    pub const fn channel_id(val: u64) -> Self {
48        Self::ChannelId(val)
49    }
50
51    /// Attempts to get the channel ID [MessageTo] variant.
52    pub fn as_channel_id(&self) -> Result<u64> {
53        match self {
54            Self::ChannelId(n) => Ok(*n),
55            _ => Err(Error::invalid_field(
56                "message to",
57                self.field_name(),
58                Self::CHANNEL_ID_FIELD,
59            )),
60        }
61    }
62
63    /// Creates a new channel name [Self].
64    pub fn channel_name<'c, C: Into<Cow<'c, str>>>(val: C) -> Self {
65        Self::ChannelName(C::into(val).into())
66    }
67
68    /// Attempts to get the channel name [MessageTo] variant.
69    pub fn as_channel_name(&self) -> Result<&str> {
70        match self {
71            Self::ChannelName(n) => Ok(n.as_str()),
72            _ => Err(Error::invalid_field(
73                "message to",
74                self.field_name(),
75                Self::CHANNEL_NAME_FIELD,
76            )),
77        }
78    }
79
80    /// Creates a new user IDs [Self].
81    pub fn user_ids<'c, C: Into<Cow<'c, [u64]>>>(val: C) -> Self {
82        Self::UserIds(C::into(val).into())
83    }
84
85    /// Attempts to get the user IDs [MessageTo] variant.
86    pub fn as_user_ids(&self) -> Result<&[u64]> {
87        match self {
88            Self::UserIds(n) => Ok(n.as_ref()),
89            _ => Err(Error::invalid_field(
90                "message to",
91                self.field_name(),
92                Self::USER_IDS_FIELD,
93            )),
94        }
95    }
96
97    /// Creates a new user emails [Self].
98    pub fn user_emails<'c, C: Into<Cow<'c, [String]>>>(val: C) -> Self {
99        Self::UserEmails(C::into(val).into())
100    }
101
102    /// Attempts to get the user emails [MessageTo] variant.
103    pub fn as_user_emails(&self) -> Result<&[String]> {
104        match self {
105            Self::UserEmails(n) => Ok(n.as_ref()),
106            _ => Err(Error::invalid_field(
107                "message to",
108                self.field_name(),
109                Self::USER_EMAILS_FIELD,
110            )),
111        }
112    }
113
114    pub fn as_string(&self) -> String {
115        serde_json::to_string(&self)
116            .ok()
117            .and_then(|s| {
118                s.strip_prefix("\"")
119                    .and_then(|v| v.strip_suffix("\"").map(String::from))
120            })
121            .unwrap_or_default()
122    }
123}
124
125impl_default!(MessageTo);
126impl_display!(MessageTo);
127
128#[cfg(test)]
129mod tests {
130    use super::*;
131
132    #[test]
133    fn test_message_to_channel_name() {
134        let chan_name = String::from("#test");
135        let chan_name_json = format!(r#""{chan_name}""#);
136        let to_chan_name = MessageTo::ChannelName(chan_name.clone());
137
138        assert_eq!(
139            serde_json::to_string(&to_chan_name).unwrap().as_str(),
140            chan_name_json
141        );
142        assert_eq!(
143            serde_json::from_str::<MessageTo>(chan_name_json.as_str()).unwrap(),
144            to_chan_name
145        );
146        assert_eq!(to_chan_name.as_channel_name(), Ok(chan_name.as_str()));
147    }
148
149    #[test]
150    fn test_message_to_user_emails() {
151        let user_emails = vec![String::from("test@example.com")];
152        let user_emails_json = format!(r#"["{}"]"#, user_emails[0]);
153        let to_user_emails = MessageTo::UserEmails(user_emails.clone());
154
155        assert_eq!(
156            serde_json::to_string(&to_user_emails).unwrap().as_str(),
157            user_emails_json
158        );
159        assert_eq!(
160            serde_json::from_str::<MessageTo>(user_emails_json.as_str()).unwrap(),
161            to_user_emails
162        );
163        assert_eq!(to_user_emails.as_user_emails(), Ok(user_emails.as_slice()));
164    }
165
166    #[test]
167    fn test_message_to_channel_id() {
168        (0..=u64::BITS)
169            .map(|r| ((1u128 << r) - 1) as u64)
170            .for_each(|id| {
171                let chan_id_json = format!("{id}");
172                let to_chan_id = MessageTo::ChannelId(id);
173
174                assert_eq!(
175                    serde_json::to_string(&to_chan_id).unwrap().as_str(),
176                    chan_id_json
177                );
178                assert_eq!(
179                    serde_json::from_str::<MessageTo>(chan_id_json.as_str()).unwrap(),
180                    to_chan_id
181                );
182                assert_eq!(to_chan_id.as_channel_id(), Ok(id));
183            });
184    }
185
186    #[test]
187    fn test_message_to_user_ids() {
188        (0..=u64::BITS)
189            .map(|r| ((1u128 << r) - 1) as u64)
190            .for_each(|id| {
191                let user_ids = vec![id];
192                let user_ids_json = format!("[{id}]");
193                let to_user_ids = MessageTo::UserIds(user_ids.clone());
194
195                assert_eq!(
196                    serde_json::to_string(&to_user_ids).unwrap().as_str(),
197                    user_ids_json
198                );
199                assert_eq!(
200                    serde_json::from_str::<MessageTo>(user_ids_json.as_str()).unwrap(),
201                    to_user_ids
202                );
203                assert_eq!(to_user_ids.as_user_ids(), Ok(user_ids.as_slice()));
204            });
205    }
206}