1use std::borrow::Cow;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{impl_default, impl_display, Error, Result};
6
7#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
9#[serde(untagged)]
10pub enum MessageTo {
11 ChannelId(u64),
13 ChannelName(String),
15 UserIds(Vec<u64>),
17 UserEmails(Vec<String>),
19}
20
21impl MessageTo {
22 pub const CHANNEL_ID_FIELD: &str = "channel_id";
24 pub const CHANNEL_NAME_FIELD: &str = "channel_name";
26 pub const USER_IDS_FIELD: &str = "user_ids";
28 pub const USER_EMAILS_FIELD: &str = "user_emails";
30
31 pub const fn new() -> Self {
33 Self::ChannelId(0)
34 }
35
36 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 pub const fn channel_id(val: u64) -> Self {
48 Self::ChannelId(val)
49 }
50
51 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 pub fn channel_name<'c, C: Into<Cow<'c, str>>>(val: C) -> Self {
65 Self::ChannelName(C::into(val).into())
66 }
67
68 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 pub fn user_ids<'c, C: Into<Cow<'c, [u64]>>>(val: C) -> Self {
82 Self::UserIds(C::into(val).into())
83 }
84
85 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 pub fn user_emails<'c, C: Into<Cow<'c, [String]>>>(val: C) -> Self {
99 Self::UserEmails(C::into(val).into())
100 }
101
102 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}