freeswitch_types/commands/endpoint/
audio.rs1use std::fmt;
2
3use super::{extract_variables, write_variables};
4use crate::commands::originate::{OriginateError, Variables};
5
6#[derive(Debug, Clone, Default, PartialEq, Eq)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12#[non_exhaustive]
13pub struct AudioEndpoint {
14 #[cfg_attr(
16 feature = "serde",
17 serde(default, skip_serializing_if = "Option::is_none")
18 )]
19 pub destination: 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 AudioEndpoint {
29 pub fn new() -> Self {
31 Self::default()
32 }
33
34 pub fn with_destination(mut self, destination: impl Into<String>) -> Self {
36 self.destination = Some(destination.into());
37 self
38 }
39
40 pub fn with_variables(mut self, variables: Variables) -> Self {
42 self.variables = Some(variables);
43 self
44 }
45
46 pub fn fmt_with_prefix(&self, f: &mut fmt::Formatter<'_>, prefix: &str) -> fmt::Result {
48 write_variables(f, &self.variables)?;
49 match &self.destination {
50 Some(dest) => write!(f, "{}/{}", prefix, dest),
51 None => f.write_str(prefix),
52 }
53 }
54
55 pub fn parse_with_prefix(s: &str, prefix: &str) -> Result<Self, OriginateError> {
57 let (variables, uri) = extract_variables(s)?;
58 let rest = uri
59 .strip_prefix(prefix)
60 .ok_or_else(|| OriginateError::ParseError(format!("not a {} endpoint", prefix)))?;
61 let destination = rest
62 .strip_prefix('/')
63 .and_then(|d| {
64 if d.is_empty() {
65 None
66 } else {
67 Some(d.to_string())
68 }
69 });
70 Ok(Self {
71 destination,
72 variables,
73 })
74 }
75}
76
77impl fmt::Display for AudioEndpoint {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 self.fmt_with_prefix(f, "audio")
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn parse_with_prefix_portaudio() {
95 let ep = AudioEndpoint::parse_with_prefix("portaudio/auto_answer", "portaudio").unwrap();
96 assert_eq!(
97 ep.destination
98 .as_deref(),
99 Some("auto_answer")
100 );
101 assert!(ep
102 .variables
103 .is_none());
104 }
105
106 #[test]
107 fn parse_with_prefix_bare() {
108 let ep = AudioEndpoint::parse_with_prefix("alsa", "alsa").unwrap();
109 assert!(ep
110 .destination
111 .is_none());
112 }
113
114 #[test]
115 fn parse_with_prefix_trailing_slash() {
116 let ep = AudioEndpoint::parse_with_prefix("pulseaudio/", "pulseaudio").unwrap();
117 assert!(ep
118 .destination
119 .is_none());
120 }
121
122 #[test]
123 fn parse_with_prefix_wrong_module() {
124 let result = AudioEndpoint::parse_with_prefix("portaudio/x", "alsa");
125 assert!(result.is_err());
126 }
127}