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