1use crate::header_addr::{ParseSipHeaderAddrError, SipHeaderAddr};
8use std::fmt;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
12#[non_exhaustive]
13pub enum ContactValue {
14 Wildcard,
16 Addr(Box<SipHeaderAddr>),
18}
19
20impl fmt::Display for ContactValue {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 match self {
23 Self::Wildcard => f.write_str("*"),
24 Self::Addr(addr) => write!(f, "{addr}"),
25 }
26 }
27}
28
29fn parse_contact_entry(raw: &str) -> Result<ContactValue, ParseSipHeaderAddrError> {
31 let trimmed = raw.trim();
32 if trimmed == "*" {
33 Ok(ContactValue::Wildcard)
34 } else {
35 trimmed
36 .parse::<SipHeaderAddr>()
37 .map(|a| ContactValue::Addr(Box::new(a)))
38 }
39}
40
41pub fn parse_contact_list(raw: &str) -> Result<Vec<ContactValue>, ParseSipHeaderAddrError> {
43 let trimmed = raw.trim();
44 if trimmed == "*" {
45 return Ok(vec![ContactValue::Wildcard]);
46 }
47 crate::split_comma_entries(trimmed)
48 .into_iter()
49 .map(parse_contact_entry)
50 .collect()
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn wildcard() {
59 let contacts = parse_contact_list("*").unwrap();
60 assert_eq!(contacts.len(), 1);
61 assert!(matches!(contacts[0], ContactValue::Wildcard));
62 }
63
64 #[test]
65 fn single_addr() {
66 let contacts = parse_contact_list("<sip:alice@198.51.100.1>").unwrap();
67 assert_eq!(contacts.len(), 1);
68 match &contacts[0] {
69 ContactValue::Addr(addr) => {
70 assert!(addr
71 .uri()
72 .to_string()
73 .contains("alice"));
74 }
75 _ => panic!("expected Addr"),
76 }
77 }
78
79 #[test]
80 fn multiple_addrs() {
81 let contacts =
82 parse_contact_list("<sip:alice@198.51.100.1>, \"Bob\" <sip:bob@198.51.100.2>").unwrap();
83 assert_eq!(contacts.len(), 2);
84 match &contacts[1] {
85 ContactValue::Addr(addr) => {
86 assert_eq!(addr.display_name(), Some("Bob"));
87 }
88 _ => panic!("expected Addr"),
89 }
90 }
91
92 #[test]
93 fn display_wildcard() {
94 assert_eq!(ContactValue::Wildcard.to_string(), "*");
95 }
96
97 #[test]
98 fn display_addr() {
99 let addr = "sip:alice@198.51.100.1"
100 .parse::<sip_uri::Uri>()
101 .unwrap();
102 let cv = ContactValue::Addr(Box::new(SipHeaderAddr::new(addr)));
103 assert!(cv
104 .to_string()
105 .contains("alice"));
106 }
107}