rtcp_types/feedback/
pli.rs1use crate::feedback::FciFeedbackPacketType;
4use crate::{prelude::*, RtcpParseError, RtcpWriteError};
5
6#[derive(Debug)]
8pub struct Pli<'a> {
9 _data: &'a [u8],
10}
11
12impl Pli<'_> {
13 pub fn builder() -> PliBuilder {
15 PliBuilder {}
16 }
17}
18
19impl<'a> FciParser<'a> for Pli<'a> {
20 const PACKET_TYPE: FciFeedbackPacketType = FciFeedbackPacketType::PAYLOAD;
21 const FCI_FORMAT: u8 = 1;
22
23 fn parse(data: &'a [u8]) -> Result<Self, RtcpParseError> {
24 if !data.is_empty() {
25 return Err(RtcpParseError::TooLarge {
26 expected: 0,
27 actual: data.len(),
28 });
29 }
30 Ok(Self { _data: data })
31 }
32}
33
34#[derive(Debug)]
36pub struct PliBuilder {}
37
38impl FciBuilder<'_> for PliBuilder {
39 fn format(&self) -> u8 {
40 1
41 }
42
43 fn supports_feedback_type(&self) -> FciFeedbackPacketType {
44 FciFeedbackPacketType::PAYLOAD
45 }
46}
47
48impl RtcpPacketWriter for PliBuilder {
49 fn calculate_size(&self) -> Result<usize, RtcpWriteError> {
50 Ok(0)
51 }
52
53 fn write_into_unchecked(&self, _buf: &mut [u8]) -> usize {
54 0
55 }
56
57 fn get_padding(&self) -> Option<u8> {
58 None
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65 use crate::feedback::{PayloadFeedback, TransportFeedback};
66
67 #[test]
68 fn pli_build_parse() {
69 const REQ_LEN: usize = PayloadFeedback::MIN_PACKET_LEN;
70 let mut data = [0; REQ_LEN];
71 let pli = {
72 let fci = Pli::builder();
73 PayloadFeedback::builder_owned(fci)
74 .sender_ssrc(0x98765432)
75 .media_ssrc(0x10fedcba)
76 };
77 assert_eq!(pli.calculate_size().unwrap(), REQ_LEN);
78 let len = pli.write_into(&mut data).unwrap();
79 assert_eq!(len, REQ_LEN);
80 assert_eq!(
81 data,
82 [0x81, 0xce, 0x00, 0x02, 0x98, 0x76, 0x54, 0x32, 0x10, 0xfe, 0xdc, 0xba,]
83 );
84
85 let fb = PayloadFeedback::parse(&data).unwrap();
86
87 assert_eq!(fb.sender_ssrc(), 0x98765432);
88 assert_eq!(fb.media_ssrc(), 0x10fedcba);
89 let _pli = fb.parse_fci::<Pli>().unwrap();
90 }
91
92 #[test]
93 fn pli_build_ref() {
94 const REQ_LEN: usize = PayloadFeedback::MIN_PACKET_LEN;
95 let mut data = [0; REQ_LEN];
96 let fci = Pli::builder();
97 let pli = PayloadFeedback::builder(&fci)
98 .sender_ssrc(0x98765432)
99 .media_ssrc(0x10fedcba);
100 assert_eq!(pli.calculate_size().unwrap(), REQ_LEN);
101 let len = pli.write_into(&mut data).unwrap();
102 assert_eq!(len, REQ_LEN);
103 assert_eq!(
104 data,
105 [0x81, 0xce, 0x00, 0x02, 0x98, 0x76, 0x54, 0x32, 0x10, 0xfe, 0xdc, 0xba,]
106 );
107 }
108
109 #[test]
110 fn pli_parse_wrong_packet() {
111 let fb = TransportFeedback::parse(&[
112 0x81, 0xcd, 0x00, 0x02, 0x98, 0x76, 0x54, 0x32, 0x10, 0xfe, 0xdc, 0xba,
113 ])
114 .unwrap();
115 assert!(matches!(
116 fb.parse_fci::<Pli>(),
117 Err(RtcpParseError::WrongImplementation),
118 ));
119 }
120
121 #[test]
122 fn pli_build_wrong_packet_type() {
123 const REQ_LEN: usize = TransportFeedback::MIN_PACKET_LEN;
124 let mut data = [0; REQ_LEN];
125 let fci = Pli::builder();
126 let pli = TransportFeedback::builder(&fci)
127 .sender_ssrc(0x98765432)
128 .media_ssrc(0x10fedcba);
129 assert!(matches!(
130 pli.calculate_size(),
131 Err(RtcpWriteError::FciWrongFeedbackPacketType)
132 ));
133 assert!(matches!(
134 pli.write_into(&mut data),
135 Err(RtcpWriteError::FciWrongFeedbackPacketType)
136 ));
137 }
138
139 #[test]
140 fn pli_parse_with_data() {
141 let pli = PayloadFeedback::parse(&[
142 0x81, 0xce, 0x00, 0x03, 0x98, 0x76, 0x54, 0x32, 0x10, 0xfe, 0xdc, 0xba, 0x00, 0x00,
143 0x00, 0x00,
144 ])
145 .unwrap();
146 assert!(matches!(
147 pli.parse_fci::<Pli>(),
148 Err(RtcpParseError::TooLarge {
149 expected: 0,
150 actual: 4
151 })
152 ));
153 }
154}