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