webrtc/peer_connection/policy/
sdp_semantics.rs1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Default, Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)]
10pub enum RTCSdpSemantics {
11 Unspecified = 0,
12
13 #[serde(rename = "unified-plan")]
17 #[default]
18 UnifiedPlan = 1,
19
20 #[serde(rename = "plan-b")]
24 PlanB = 2,
25
26 #[serde(rename = "unified-plan-with-fallback")]
30 UnifiedPlanWithFallback = 3,
31}
32
33const SDP_SEMANTICS_UNIFIED_PLAN_WITH_FALLBACK: &str = "unified-plan-with-fallback";
34const SDP_SEMANTICS_UNIFIED_PLAN: &str = "unified-plan";
35const SDP_SEMANTICS_PLAN_B: &str = "plan-b";
36
37impl From<&str> for RTCSdpSemantics {
38 fn from(raw: &str) -> Self {
39 match raw {
40 SDP_SEMANTICS_UNIFIED_PLAN_WITH_FALLBACK => RTCSdpSemantics::UnifiedPlanWithFallback,
41 SDP_SEMANTICS_UNIFIED_PLAN => RTCSdpSemantics::UnifiedPlan,
42 SDP_SEMANTICS_PLAN_B => RTCSdpSemantics::PlanB,
43 _ => RTCSdpSemantics::Unspecified,
44 }
45 }
46}
47
48impl fmt::Display for RTCSdpSemantics {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 let s = match *self {
51 RTCSdpSemantics::UnifiedPlanWithFallback => SDP_SEMANTICS_UNIFIED_PLAN_WITH_FALLBACK,
52 RTCSdpSemantics::UnifiedPlan => SDP_SEMANTICS_UNIFIED_PLAN,
53 RTCSdpSemantics::PlanB => SDP_SEMANTICS_PLAN_B,
54 RTCSdpSemantics::Unspecified => crate::UNSPECIFIED_STR,
55 };
56 write!(f, "{s}")
57 }
58}
59
60#[cfg(test)]
61mod test {
62 use std::collections::HashSet;
63
64 use sdp::description::media::MediaDescription;
65 use sdp::description::session::{SessionDescription, ATTR_KEY_SSRC};
66
67 use super::*;
68
69 #[test]
70 fn test_sdp_semantics_string() {
71 let tests = vec![
72 (RTCSdpSemantics::Unspecified, "Unspecified"),
73 (
74 RTCSdpSemantics::UnifiedPlanWithFallback,
75 "unified-plan-with-fallback",
76 ),
77 (RTCSdpSemantics::PlanB, "plan-b"),
78 (RTCSdpSemantics::UnifiedPlan, "unified-plan"),
79 ];
80
81 for (value, expected_string) in tests {
82 assert_eq!(value.to_string(), expected_string);
83 }
84 }
85
86 fn get_md_names(sdp: &SessionDescription) -> Vec<String> {
89 sdp.media_descriptions
90 .iter()
91 .map(|md| md.media_name.media.clone())
92 .collect()
93 }
94
95 fn extract_ssrc_list(md: &MediaDescription) -> Vec<String> {
96 let mut ssrcs = HashSet::new();
97 for attr in &md.attributes {
98 if attr.key == ATTR_KEY_SSRC {
99 if let Some(value) = &attr.value {
100 let fields: Vec<&str> = value.split_whitespace().collect();
101 if let Some(ssrc) = fields.first() {
102 ssrcs.insert(*ssrc);
103 }
104 }
105 }
106 }
107 ssrcs
108 .into_iter()
109 .map(|ssrc| ssrc.to_owned())
110 .collect::<Vec<String>>()
111 }
112}