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