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