freeswitch_types/commands/endpoint/
user.rs1use std::str::FromStr;
2
3use super::strip_endpoint_prefix;
4use crate::commands::originate::OriginateError;
5use crate::commands::variables::DialStringCarrier;
6use crate::commands::variables::Variables;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[non_exhaustive]
12pub struct UserEndpoint {
13 pub name: String,
15 #[cfg_attr(
17 feature = "serde",
18 serde(default, skip_serializing_if = "Option::is_none")
19 )]
20 pub domain: Option<String>,
21 #[cfg_attr(
23 feature = "serde",
24 serde(default, skip_serializing_if = "Option::is_none")
25 )]
26 pub variables: Option<Variables>,
27}
28
29impl UserEndpoint {
30 pub fn new(name: impl Into<String>) -> Self {
32 Self {
33 name: name.into(),
34 domain: None,
35 variables: None,
36 }
37 }
38
39 pub fn with_domain(mut self, domain: impl Into<String>) -> Self {
41 self.domain = Some(domain.into());
42 self
43 }
44}
45
46impl_dial_string_with_variables!(UserEndpoint, |this, f| match &this.domain {
47 Some(d) => write!(f, "user/{}@{}", this.name, d),
48 None => write!(f, "user/{}", this.name),
49});
50
51impl FromStr for UserEndpoint {
52 type Err = OriginateError;
53
54 fn from_str(s: &str) -> Result<Self, Self::Err> {
55 let (variables, rest) =
56 strip_endpoint_prefix(s, "user/", "user", DialStringCarrier::EslApi)?;
57 let (name, domain) = if let Some((n, d)) = rest.split_once('@') {
58 (n.to_string(), Some(d.to_string()))
59 } else {
60 (rest.to_string(), None)
61 };
62 Ok(Self {
63 name,
64 domain,
65 variables,
66 })
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn user_endpoint_display() {
76 let ep = UserEndpoint {
77 name: "1000".into(),
78 domain: Some("example.com".into()),
79 variables: None,
80 };
81 assert_eq!(ep.to_string(), "user/1000@example.com");
82 }
83
84 #[test]
85 fn user_endpoint_display_no_domain() {
86 let ep = UserEndpoint {
87 name: "1000".into(),
88 domain: None,
89 variables: None,
90 };
91 assert_eq!(ep.to_string(), "user/1000");
92 }
93
94 #[test]
95 fn user_endpoint_from_str() {
96 let ep: UserEndpoint = "user/1000@example.com"
97 .parse()
98 .unwrap();
99 assert_eq!(ep.name, "1000");
100 assert_eq!(
101 ep.domain
102 .as_deref(),
103 Some("example.com")
104 );
105 }
106
107 #[test]
108 fn user_endpoint_from_str_no_domain() {
109 let ep: UserEndpoint = "user/1000"
110 .parse()
111 .unwrap();
112 assert_eq!(ep.name, "1000");
113 assert!(ep
114 .domain
115 .is_none());
116 }
117
118 #[test]
119 fn user_endpoint_round_trip() {
120 let ep = UserEndpoint {
121 name: "bob".into(),
122 domain: Some("example.com".into()),
123 variables: None,
124 };
125 let s = ep.to_string();
126 let parsed: UserEndpoint = s
127 .parse()
128 .unwrap();
129 assert_eq!(parsed, ep);
130 }
131
132 #[test]
133 fn serde_user_endpoint() {
134 let ep = UserEndpoint {
135 name: "1000".into(),
136 domain: Some("example.com".into()),
137 variables: None,
138 };
139 let json = serde_json::to_string(&ep).unwrap();
140 let parsed: UserEndpoint = serde_json::from_str(&json).unwrap();
141 assert_eq!(parsed, ep);
142 }
143
144 #[test]
145 fn serde_user_endpoint_no_domain() {
146 let ep = UserEndpoint {
147 name: "1000".into(),
148 domain: None,
149 variables: None,
150 };
151 let json = serde_json::to_string(&ep).unwrap();
152 let parsed: UserEndpoint = serde_json::from_str(&json).unwrap();
153 assert_eq!(parsed, ep);
154 }
155}