1 use std::fmt;
2 
3 /// RTPTransceiverDirection indicates the direction of the RTPTransceiver.
4 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
5 pub enum RTCRtpTransceiverDirection {
6     Unspecified,
7 
8     /// Sendrecv indicates the RTPSender will offer
9     /// to send RTP and RTPReceiver the will offer to receive RTP.
10     Sendrecv,
11 
12     /// Sendonly indicates the RTPSender will offer to send RTP.
13     Sendonly,
14 
15     /// Recvonly indicates the RTPReceiver the will offer to receive RTP.
16     Recvonly,
17 
18     /// Inactive indicates the RTPSender won't offer
19     /// to send RTP and RTPReceiver the won't offer to receive RTP.
20     Inactive,
21 }
22 
23 const RTP_TRANSCEIVER_DIRECTION_SENDRECV_STR: &str = "sendrecv";
24 const RTP_TRANSCEIVER_DIRECTION_SENDONLY_STR: &str = "sendonly";
25 const RTP_TRANSCEIVER_DIRECTION_RECVONLY_STR: &str = "recvonly";
26 const RTP_TRANSCEIVER_DIRECTION_INACTIVE_STR: &str = "inactive";
27 
28 /// defines a procedure for creating a new
29 /// RTPTransceiverDirection from a raw string naming the transceiver direction.
30 impl From<&str> for RTCRtpTransceiverDirection {
from(raw: &str) -> Self31     fn from(raw: &str) -> Self {
32         match raw {
33             RTP_TRANSCEIVER_DIRECTION_SENDRECV_STR => RTCRtpTransceiverDirection::Sendrecv,
34             RTP_TRANSCEIVER_DIRECTION_SENDONLY_STR => RTCRtpTransceiverDirection::Sendonly,
35             RTP_TRANSCEIVER_DIRECTION_RECVONLY_STR => RTCRtpTransceiverDirection::Recvonly,
36             RTP_TRANSCEIVER_DIRECTION_INACTIVE_STR => RTCRtpTransceiverDirection::Inactive,
37             _ => RTCRtpTransceiverDirection::Unspecified,
38         }
39     }
40 }
41 
42 impl From<u8> for RTCRtpTransceiverDirection {
from(v: u8) -> Self43     fn from(v: u8) -> Self {
44         match v {
45             1 => RTCRtpTransceiverDirection::Sendrecv,
46             2 => RTCRtpTransceiverDirection::Sendonly,
47             3 => RTCRtpTransceiverDirection::Recvonly,
48             4 => RTCRtpTransceiverDirection::Inactive,
49             _ => RTCRtpTransceiverDirection::Unspecified,
50         }
51     }
52 }
53 
54 impl fmt::Display for RTCRtpTransceiverDirection {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result55     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56         match *self {
57             RTCRtpTransceiverDirection::Sendrecv => {
58                 write!(f, "{RTP_TRANSCEIVER_DIRECTION_SENDRECV_STR}")
59             }
60             RTCRtpTransceiverDirection::Sendonly => {
61                 write!(f, "{RTP_TRANSCEIVER_DIRECTION_SENDONLY_STR}")
62             }
63             RTCRtpTransceiverDirection::Recvonly => {
64                 write!(f, "{RTP_TRANSCEIVER_DIRECTION_RECVONLY_STR}")
65             }
66             RTCRtpTransceiverDirection::Inactive => {
67                 write!(f, "{RTP_TRANSCEIVER_DIRECTION_INACTIVE_STR}")
68             }
69             _ => write!(f, "{}", crate::UNSPECIFIED_STR),
70         }
71     }
72 }
73 
74 impl RTCRtpTransceiverDirection {
75     /// reverse indicate the opposite direction
reverse(&self) -> RTCRtpTransceiverDirection76     pub fn reverse(&self) -> RTCRtpTransceiverDirection {
77         match *self {
78             RTCRtpTransceiverDirection::Sendonly => RTCRtpTransceiverDirection::Recvonly,
79             RTCRtpTransceiverDirection::Recvonly => RTCRtpTransceiverDirection::Sendonly,
80             _ => *self,
81         }
82     }
83 
intersect(&self, other: RTCRtpTransceiverDirection) -> RTCRtpTransceiverDirection84     pub fn intersect(&self, other: RTCRtpTransceiverDirection) -> RTCRtpTransceiverDirection {
85         Self::from_send_recv(
86             self.has_send() && other.has_send(),
87             self.has_recv() && other.has_recv(),
88         )
89     }
90 
from_send_recv(send: bool, recv: bool) -> RTCRtpTransceiverDirection91     pub fn from_send_recv(send: bool, recv: bool) -> RTCRtpTransceiverDirection {
92         match (send, recv) {
93             (true, true) => Self::Sendrecv,
94             (true, false) => Self::Sendonly,
95             (false, true) => Self::Recvonly,
96             (false, false) => Self::Inactive,
97         }
98     }
99 
has_send(&self) -> bool100     pub fn has_send(&self) -> bool {
101         matches!(self, Self::Sendrecv | Self::Sendonly)
102     }
103 
has_recv(&self) -> bool104     pub fn has_recv(&self) -> bool {
105         matches!(self, Self::Sendrecv | Self::Recvonly)
106     }
107 }
108 
109 #[cfg(test)]
110 mod test {
111     use super::*;
112 
113     #[test]
test_new_rtp_transceiver_direction()114     fn test_new_rtp_transceiver_direction() {
115         let tests = vec![
116             ("Unspecified", RTCRtpTransceiverDirection::Unspecified),
117             ("sendrecv", RTCRtpTransceiverDirection::Sendrecv),
118             ("sendonly", RTCRtpTransceiverDirection::Sendonly),
119             ("recvonly", RTCRtpTransceiverDirection::Recvonly),
120             ("inactive", RTCRtpTransceiverDirection::Inactive),
121         ];
122 
123         for (ct_str, expected_type) in tests {
124             assert_eq!(RTCRtpTransceiverDirection::from(ct_str), expected_type);
125         }
126     }
127 
128     #[test]
test_rtp_transceiver_direction_string()129     fn test_rtp_transceiver_direction_string() {
130         let tests = vec![
131             (RTCRtpTransceiverDirection::Unspecified, "Unspecified"),
132             (RTCRtpTransceiverDirection::Sendrecv, "sendrecv"),
133             (RTCRtpTransceiverDirection::Sendonly, "sendonly"),
134             (RTCRtpTransceiverDirection::Recvonly, "recvonly"),
135             (RTCRtpTransceiverDirection::Inactive, "inactive"),
136         ];
137 
138         for (d, expected_string) in tests {
139             assert_eq!(d.to_string(), expected_string);
140         }
141     }
142 
143     #[test]
test_rtp_transceiver_has_send()144     fn test_rtp_transceiver_has_send() {
145         let tests = vec![
146             (RTCRtpTransceiverDirection::Unspecified, false),
147             (RTCRtpTransceiverDirection::Sendrecv, true),
148             (RTCRtpTransceiverDirection::Sendonly, true),
149             (RTCRtpTransceiverDirection::Recvonly, false),
150             (RTCRtpTransceiverDirection::Inactive, false),
151         ];
152 
153         for (d, expected_value) in tests {
154             assert_eq!(d.has_send(), expected_value);
155         }
156     }
157 
158     #[test]
test_rtp_transceiver_has_recv()159     fn test_rtp_transceiver_has_recv() {
160         let tests = vec![
161             (RTCRtpTransceiverDirection::Unspecified, false),
162             (RTCRtpTransceiverDirection::Sendrecv, true),
163             (RTCRtpTransceiverDirection::Sendonly, false),
164             (RTCRtpTransceiverDirection::Recvonly, true),
165             (RTCRtpTransceiverDirection::Inactive, false),
166         ];
167 
168         for (d, expected_value) in tests {
169             assert_eq!(d.has_recv(), expected_value);
170         }
171     }
172 
173     #[test]
test_rtp_transceiver_from_send_recv()174     fn test_rtp_transceiver_from_send_recv() {
175         let tests = vec![
176             (RTCRtpTransceiverDirection::Sendrecv, (true, true)),
177             (RTCRtpTransceiverDirection::Sendonly, (true, false)),
178             (RTCRtpTransceiverDirection::Recvonly, (false, true)),
179             (RTCRtpTransceiverDirection::Inactive, (false, false)),
180         ];
181 
182         for (expected_value, (send, recv)) in tests {
183             assert_eq!(
184                 RTCRtpTransceiverDirection::from_send_recv(send, recv),
185                 expected_value
186             );
187         }
188     }
189 
190     #[test]
test_rtp_transceiver_intersect()191     fn test_rtp_transceiver_intersect() {
192         use RTCRtpTransceiverDirection::*;
193 
194         let tests = vec![
195             ((Sendrecv, Recvonly), Recvonly),
196             ((Sendrecv, Sendonly), Sendonly),
197             ((Sendrecv, Inactive), Inactive),
198             ((Sendonly, Inactive), Inactive),
199             ((Recvonly, Inactive), Inactive),
200             ((Recvonly, Sendrecv), Recvonly),
201             ((Sendonly, Sendrecv), Sendonly),
202             ((Sendonly, Recvonly), Inactive),
203             ((Recvonly, Recvonly), Recvonly),
204         ];
205 
206         for ((a, b), expected_direction) in tests {
207             assert_eq!(a.intersect(b), expected_direction);
208         }
209     }
210 }
211