kanade_shared/wire/
group_contacts.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq)]
13pub struct GroupContacts {
14 pub emails: Vec<String>,
19}
20
21impl GroupContacts {
22 pub fn new<I, S>(emails: I) -> Self
25 where
26 I: IntoIterator<Item = S>,
27 S: Into<String>,
28 {
29 let mut v: Vec<String> = emails
30 .into_iter()
31 .map(|e| e.into().trim().to_lowercase())
32 .filter(|e| !e.is_empty())
33 .collect();
34 v.sort();
35 v.dedup();
36 Self { emails: v }
37 }
38
39 pub fn is_empty(&self) -> bool {
40 self.emails.is_empty()
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn new_trims_lowercases_sorts_dedups_and_drops_blanks() {
50 let c = GroupContacts::new([
51 " Ops@Example.com ",
52 "it@example.com",
53 "OPS@example.com",
54 " ",
55 "",
56 ]);
57 assert_eq!(c.emails, vec!["it@example.com", "ops@example.com"]);
58 }
59
60 #[test]
61 fn round_trips_through_json() {
62 let c = GroupContacts::new(["sec@example.com"]);
63 let json = serde_json::to_string(&c).unwrap();
64 assert_eq!(json, r#"{"emails":["sec@example.com"]}"#);
65 let back: GroupContacts = serde_json::from_str(&json).unwrap();
66 assert_eq!(back, c);
67 }
68
69 #[test]
70 fn empty_round_trips() {
71 let c = GroupContacts::default();
72 assert_eq!(serde_json::to_string(&c).unwrap(), r#"{"emails":[]}"#);
73 assert!(c.is_empty());
74 }
75
76 #[test]
77 fn accepts_unknown_fields_for_forward_compat() {
78 let json = r#"{"emails":["a@b.com"],"display_name":"IT","set_by":"alice"}"#;
79 let c: GroupContacts = serde_json::from_str(json).unwrap();
80 assert_eq!(c.emails, vec!["a@b.com"]);
81 }
82}