1use crate::toc::{FrameCountCode, OpusTocByte};
23use crate::Error;
24
25pub const MAX_FRAME_BYTES: usize = 1275;
30
31pub const MAX_FRAMES_PER_PACKET: u8 = 48;
36
37#[derive(Debug, Clone, PartialEq, Eq)]
43pub struct OpusPacket<'a> {
44 pub toc: OpusTocByte,
46 frames: Vec<&'a [u8]>,
47 pub padding: usize,
51}
52
53impl<'a> OpusPacket<'a> {
54 pub fn parse(packet: &'a [u8]) -> Result<Self, Error> {
60 if packet.is_empty() {
61 return Err(Error::EmptyPacket);
62 }
63 let toc = OpusTocByte::from_byte(packet[0]);
64 let body = &packet[1..];
65
66 let (frames, padding) = match toc.frame_count_code {
67 FrameCountCode::One => parse_code0(body)?,
68 FrameCountCode::TwoEqual => parse_code1(body)?,
69 FrameCountCode::TwoUnequal => parse_code2(body)?,
70 FrameCountCode::Arbitrary => parse_code3(body)?,
71 };
72
73 Ok(Self {
74 toc,
75 frames,
76 padding,
77 })
78 }
79
80 pub fn frames(&self) -> &[&'a [u8]] {
85 &self.frames
86 }
87
88 pub fn frame_count(&self) -> usize {
91 self.frames.len()
92 }
93
94 pub(crate) fn new_self_delim(toc: OpusTocByte, frames: Vec<&'a [u8]>, padding: usize) -> Self {
102 Self {
103 toc,
104 frames,
105 padding,
106 }
107 }
108}
109
110pub(crate) fn decode_length(bytes: &[u8]) -> Result<(usize, usize), Error> {
120 let first = *bytes.first().ok_or(Error::MalformedPacket)? as usize;
121 if first < 252 {
122 Ok((first, 1))
123 } else {
124 let second = *bytes.get(1).ok_or(Error::MalformedPacket)? as usize;
125 Ok((second * 4 + first, 2))
126 }
127}
128
129fn parse_code0(body: &[u8]) -> Result<(Vec<&[u8]>, usize), Error> {
133 if body.len() > MAX_FRAME_BYTES {
134 return Err(Error::MalformedPacket);
135 }
136 Ok((vec![body], 0))
137}
138
139fn parse_code1(body: &[u8]) -> Result<(Vec<&[u8]>, usize), Error> {
144 if body.len() % 2 != 0 {
145 return Err(Error::MalformedPacket);
146 }
147 let half = body.len() / 2;
148 if half > MAX_FRAME_BYTES {
149 return Err(Error::MalformedPacket);
150 }
151 Ok((vec![&body[..half], &body[half..]], 0))
152}
153
154fn parse_code2(body: &[u8]) -> Result<(Vec<&[u8]>, usize), Error> {
160 let (n1, consumed) = decode_length(body)?;
161 if n1 > MAX_FRAME_BYTES {
162 return Err(Error::MalformedPacket);
163 }
164 let after_len = &body[consumed..];
165 if n1 > after_len.len() {
166 return Err(Error::MalformedPacket);
167 }
168 let frame1 = &after_len[..n1];
169 let frame2 = &after_len[n1..];
170 if frame2.len() > MAX_FRAME_BYTES {
171 return Err(Error::MalformedPacket);
172 }
173 Ok((vec![frame1, frame2], 0))
174}
175
176fn parse_code3(body: &[u8]) -> Result<(Vec<&[u8]>, usize), Error> {
197 let fc = *body.first().ok_or(Error::MalformedPacket)?;
199 let v_bit = fc & 0x01 != 0;
200 let p_bit = fc & 0x02 != 0;
201 let m = fc >> 2;
202 if m == 0 || m > MAX_FRAMES_PER_PACKET {
203 return Err(Error::MalformedPacket);
204 }
205 let mut cursor = 1usize;
206
207 let mut padding_bytes: usize = 0;
213 let mut padding_header_bytes: usize = 0;
214 if p_bit {
215 loop {
216 let byte = *body.get(cursor).ok_or(Error::MalformedPacket)? as usize;
217 cursor += 1;
218 padding_header_bytes += 1;
219 if byte == 255 {
220 padding_bytes += 254;
221 } else {
222 padding_bytes += byte;
223 break;
224 }
225 }
226 }
227 let total_padding = padding_bytes + padding_header_bytes;
228 if total_padding + 1 > body.len() {
232 return Err(Error::MalformedPacket);
233 }
234
235 let m = m as usize;
236 let mut frames: Vec<&[u8]> = Vec::with_capacity(m);
237
238 if v_bit {
239 let mut declared_lengths: Vec<usize> = Vec::with_capacity(m.saturating_sub(1));
242 for _ in 0..m.saturating_sub(1) {
243 let (n, consumed) = decode_length(&body[cursor..])?;
244 if n > MAX_FRAME_BYTES {
245 return Err(Error::MalformedPacket);
246 }
247 declared_lengths.push(n);
248 cursor += consumed;
249 }
250 let remaining = body.len() - cursor;
252 let declared_sum: usize = declared_lengths.iter().copied().sum();
253 if declared_sum + padding_bytes > remaining {
254 return Err(Error::MalformedPacket);
255 }
256 let last_len = remaining - declared_sum - padding_bytes;
257 if last_len > MAX_FRAME_BYTES {
258 return Err(Error::MalformedPacket);
259 }
260 for n in declared_lengths {
261 frames.push(&body[cursor..cursor + n]);
262 cursor += n;
263 }
264 frames.push(&body[cursor..cursor + last_len]);
265 } else {
266 let r = body.len() - cursor - padding_bytes;
272 if r % m != 0 {
273 return Err(Error::MalformedPacket);
274 }
275 let per = r / m;
276 if per > MAX_FRAME_BYTES {
277 return Err(Error::MalformedPacket);
278 }
279 for _ in 0..m {
280 frames.push(&body[cursor..cursor + per]);
281 cursor += per;
282 }
283 }
284
285 Ok((frames, padding_bytes))
286}
287
288#[cfg(test)]
289mod tests {
290 use super::*;
291 use crate::toc::{ChannelMapping, FrameCountCode};
292
293 fn toc(config: u8, stereo: bool, code: u8) -> u8 {
294 (config << 3) | ((stereo as u8) << 2) | (code & 0x03)
295 }
296
297 #[test]
300 fn length_single_byte_values_0_through_251() {
301 for value in [0u8, 1, 100, 200, 251] {
302 let (len, n) = decode_length(&[value]).unwrap();
303 assert_eq!(len, value as usize);
304 assert_eq!(n, 1);
305 }
306 }
307
308 #[test]
309 fn length_two_byte_boundary() {
310 let (len, n) = decode_length(&[252, 0]).unwrap();
312 assert_eq!(len, 252);
313 assert_eq!(n, 2);
314 let (len, n) = decode_length(&[255, 255]).unwrap();
316 assert_eq!(len, MAX_FRAME_BYTES);
317 assert_eq!(n, 2);
318 let (len, n) = decode_length(&[253, 10]).unwrap();
320 assert_eq!(len, 293);
321 assert_eq!(n, 2);
322 }
323
324 #[test]
325 fn length_two_byte_missing_second_rejects() {
326 assert_eq!(decode_length(&[252]), Err(Error::MalformedPacket));
327 assert_eq!(decode_length(&[255]), Err(Error::MalformedPacket));
328 }
329
330 #[test]
331 fn length_empty_rejects() {
332 assert_eq!(decode_length(&[]), Err(Error::MalformedPacket));
333 }
334
335 #[test]
338 fn code0_single_frame_round_trip() {
339 let mut packet = vec![toc(1, false, 0)];
341 packet.extend_from_slice(&[0xAA, 0xBB, 0xCC, 0xDD]);
342 let parsed = OpusPacket::parse(&packet).unwrap();
343 assert_eq!(parsed.frame_count(), 1);
344 assert_eq!(parsed.frames()[0], &[0xAA, 0xBB, 0xCC, 0xDD]);
345 assert_eq!(parsed.padding, 0);
346 assert_eq!(parsed.toc.frame_count_code, FrameCountCode::One);
347 }
348
349 #[test]
350 fn code0_toc_only_yields_empty_frame() {
351 let packet = [toc(1, false, 0)];
355 let parsed = OpusPacket::parse(&packet).unwrap();
356 assert_eq!(parsed.frame_count(), 1);
357 assert!(parsed.frames()[0].is_empty());
358 }
359
360 #[test]
361 fn code0_rejects_oversize_frame() {
362 let mut packet = vec![toc(1, false, 0)];
363 packet.resize(1 + MAX_FRAME_BYTES + 1, 0);
364 assert_eq!(OpusPacket::parse(&packet), Err(Error::MalformedPacket));
365 }
366
367 #[test]
370 fn code1_two_equal_split_at_midpoint() {
371 let mut packet = vec![toc(1, false, 1)];
372 packet.extend_from_slice(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66]);
373 let parsed = OpusPacket::parse(&packet).unwrap();
374 assert_eq!(parsed.frame_count(), 2);
375 assert_eq!(parsed.frames()[0], &[0x11, 0x22, 0x33]);
376 assert_eq!(parsed.frames()[1], &[0x44, 0x55, 0x66]);
377 assert_eq!(parsed.toc.frame_count_code, FrameCountCode::TwoEqual);
378 }
379
380 #[test]
381 fn code1_rejects_odd_body_per_r3() {
382 let mut packet = vec![toc(1, false, 1)];
383 packet.extend_from_slice(&[0x11, 0x22, 0x33]);
384 assert_eq!(OpusPacket::parse(&packet), Err(Error::MalformedPacket));
385 }
386
387 #[test]
388 fn code1_toc_only_two_empty_frames() {
389 let packet = [toc(1, false, 1)];
390 let parsed = OpusPacket::parse(&packet).unwrap();
391 assert_eq!(parsed.frame_count(), 2);
392 assert!(parsed.frames()[0].is_empty());
393 assert!(parsed.frames()[1].is_empty());
394 }
395
396 #[test]
399 fn code2_single_byte_length() {
400 let mut packet = vec![toc(1, false, 2), 3];
402 packet.extend_from_slice(&[0xA1, 0xA2, 0xA3]); packet.extend_from_slice(&[0xB1, 0xB2, 0xB3, 0xB4]); let parsed = OpusPacket::parse(&packet).unwrap();
405 assert_eq!(parsed.frame_count(), 2);
406 assert_eq!(parsed.frames()[0], &[0xA1, 0xA2, 0xA3]);
407 assert_eq!(parsed.frames()[1], &[0xB1, 0xB2, 0xB3, 0xB4]);
408 }
409
410 #[test]
411 fn code2_two_byte_length() {
412 let n1 = 268usize;
414 let mut packet = vec![toc(1, false, 2), 252, 4];
415 packet.extend(std::iter::repeat(0xAA).take(n1));
416 packet.extend_from_slice(&[0xBB; 5]); let parsed = OpusPacket::parse(&packet).unwrap();
418 assert_eq!(parsed.frame_count(), 2);
419 assert_eq!(parsed.frames()[0].len(), n1);
420 assert!(parsed.frames()[0].iter().all(|&b| b == 0xAA));
421 assert_eq!(parsed.frames()[1], &[0xBB; 5]);
422 }
423
424 #[test]
425 fn code2_one_byte_packet_invalid() {
426 let packet = [toc(1, false, 2)];
428 assert_eq!(OpusPacket::parse(&packet), Err(Error::MalformedPacket));
429 }
430
431 #[test]
432 fn code2_two_byte_packet_only_legal_when_lengths_are_zero() {
433 let packet = [toc(1, false, 2), 0];
435 let parsed = OpusPacket::parse(&packet).unwrap();
436 assert_eq!(parsed.frame_count(), 2);
437 assert!(parsed.frames()[0].is_empty());
438 assert!(parsed.frames()[1].is_empty());
439
440 let packet = [toc(1, false, 2), 5];
442 assert_eq!(OpusPacket::parse(&packet), Err(Error::MalformedPacket));
443
444 let packet = [toc(1, false, 2), 253];
446 assert_eq!(OpusPacket::parse(&packet), Err(Error::MalformedPacket));
447 }
448
449 #[test]
450 fn code2_n1_exceeds_remaining_rejected_per_r4() {
451 let mut packet = vec![toc(1, false, 2), 10];
452 packet.extend_from_slice(&[0; 5]);
454 assert_eq!(OpusPacket::parse(&packet), Err(Error::MalformedPacket));
455 }
456
457 #[test]
460 fn code3_cbr_no_padding() {
461 let m: u8 = 3;
463 let fc = m << 2; let mut packet = vec![toc(15, false, 3), fc];
465 packet.extend_from_slice(&[0xA1, 0xA2, 0xA3, 0xA4]);
466 packet.extend_from_slice(&[0xB1, 0xB2, 0xB3, 0xB4]);
467 packet.extend_from_slice(&[0xC1, 0xC2, 0xC3, 0xC4]);
468 let parsed = OpusPacket::parse(&packet).unwrap();
469 assert_eq!(parsed.frame_count(), 3);
470 assert_eq!(parsed.frames()[0], &[0xA1, 0xA2, 0xA3, 0xA4]);
471 assert_eq!(parsed.frames()[1], &[0xB1, 0xB2, 0xB3, 0xB4]);
472 assert_eq!(parsed.frames()[2], &[0xC1, 0xC2, 0xC3, 0xC4]);
473 assert_eq!(parsed.padding, 0);
474 }
475
476 #[test]
477 fn code3_cbr_rejects_non_multiple_of_m_per_r6() {
478 let fc = 3 << 2;
480 let mut packet = vec![toc(15, false, 3), fc];
481 packet.extend_from_slice(&[0; 5]);
482 assert_eq!(OpusPacket::parse(&packet), Err(Error::MalformedPacket));
483 }
484
485 #[test]
486 fn code3_cbr_with_padding() {
487 let m: u8 = 2;
490 let fc = (m << 2) | 0b10; let mut packet = vec![toc(15, false, 3), fc, 5];
492 packet.extend_from_slice(&[0xD1, 0xD2, 0xD3]);
493 packet.extend_from_slice(&[0xE1, 0xE2, 0xE3]);
494 packet.extend_from_slice(&[0x00; 5]);
495 let parsed = OpusPacket::parse(&packet).unwrap();
496 assert_eq!(parsed.frame_count(), 2);
497 assert_eq!(parsed.frames()[0], &[0xD1, 0xD2, 0xD3]);
498 assert_eq!(parsed.frames()[1], &[0xE1, 0xE2, 0xE3]);
499 assert_eq!(parsed.padding, 5);
500 }
501
502 #[test]
503 fn code3_vbr_no_padding() {
504 let m: u8 = 3;
507 let fc = (m << 2) | 0b01;
508 let mut packet = vec![toc(15, false, 3), fc, 2, 4];
509 packet.extend_from_slice(&[0xA1, 0xA2]);
510 packet.extend_from_slice(&[0xB1, 0xB2, 0xB3, 0xB4]);
511 packet.push(0xC1);
512 let parsed = OpusPacket::parse(&packet).unwrap();
513 assert_eq!(parsed.frame_count(), 3);
514 assert_eq!(parsed.frames()[0], &[0xA1, 0xA2]);
515 assert_eq!(parsed.frames()[1], &[0xB1, 0xB2, 0xB3, 0xB4]);
516 assert_eq!(parsed.frames()[2], &[0xC1]);
517 assert_eq!(parsed.padding, 0);
518 }
519
520 #[test]
521 fn code3_vbr_with_padding() {
522 let m: u8 = 4;
530 let fc = (m << 2) | 0b11; let pad_len = 7u8;
532 let sizes = [99u8, 77, 66, 68];
533 let mut packet = vec![toc(15, false, 3), fc, pad_len];
534 packet.extend_from_slice(&sizes[..3]);
536 for &n in sizes.iter() {
537 packet.extend(std::iter::repeat(0xAA).take(n as usize));
538 }
539 packet.extend_from_slice(&[0u8; 7]);
540 let parsed = OpusPacket::parse(&packet).unwrap();
541 assert_eq!(parsed.frame_count(), 4);
542 assert_eq!(parsed.frames()[0].len(), 99);
543 assert_eq!(parsed.frames()[1].len(), 77);
544 assert_eq!(parsed.frames()[2].len(), 66);
545 assert_eq!(parsed.frames()[3].len(), 68);
546 assert_eq!(parsed.padding, 7);
547 assert_eq!(parsed.toc.config, 15);
549 assert_eq!(parsed.toc.channels, ChannelMapping::Mono);
550 assert_eq!(parsed.toc.frame_count_code, FrameCountCode::Arbitrary);
551 }
552
553 #[test]
554 fn code3_padding_chain_255_extension() {
555 let m: u8 = 1;
559 let fc = (m << 2) | 0b10; let mut packet = vec![toc(15, false, 3), fc, 255, 3];
561 packet.extend_from_slice(&[0xF1, 0xF2, 0xF3, 0xF4]);
563 packet.extend(std::iter::repeat(0u8).take(257));
564 let parsed = OpusPacket::parse(&packet).unwrap();
565 assert_eq!(parsed.frame_count(), 1);
566 assert_eq!(parsed.frames()[0], &[0xF1, 0xF2, 0xF3, 0xF4]);
567 assert_eq!(parsed.padding, 257);
568 }
569
570 #[test]
571 fn code3_rejects_m_zero_per_r5() {
572 let fc = 0; let packet = [toc(15, false, 3), fc];
574 assert_eq!(OpusPacket::parse(&packet), Err(Error::MalformedPacket));
575 }
576
577 #[test]
578 fn code3_rejects_missing_frame_count_byte() {
579 let packet = [toc(15, false, 3)];
582 assert_eq!(OpusPacket::parse(&packet), Err(Error::MalformedPacket));
583 }
584
585 #[test]
586 fn code3_rejects_padding_overrunning_body() {
587 let fc = (1 << 2) | 0b10;
590 let mut packet = vec![toc(15, false, 3), fc, 200];
591 packet.extend_from_slice(&[0; 5]);
592 assert_eq!(OpusPacket::parse(&packet), Err(Error::MalformedPacket));
593 }
594
595 #[test]
596 fn code3_vbr_rejects_lengths_exceeding_remaining() {
597 let fc = (3 << 2) | 0b01;
599 let mut packet = vec![toc(15, false, 3), fc, 100, 100];
600 packet.extend_from_slice(&[0; 50]);
601 assert_eq!(OpusPacket::parse(&packet), Err(Error::MalformedPacket));
602 }
603
604 #[test]
605 fn empty_packet_rejected() {
606 assert_eq!(OpusPacket::parse(&[]), Err(Error::EmptyPacket));
607 }
608
609 #[test]
612 fn code3_vbr_max_frame_count_48() {
613 let m: u8 = MAX_FRAMES_PER_PACKET;
616 let fc = (m << 2) | 0b01;
617 let mut packet = vec![toc(16, false, 3), fc];
618 packet.extend(std::iter::repeat(1u8).take(47)); packet.extend(std::iter::repeat(0xCC).take(48));
620 let parsed = OpusPacket::parse(&packet).unwrap();
621 assert_eq!(parsed.frame_count(), 48);
622 for f in parsed.frames() {
623 assert_eq!(f, &[0xCC]);
624 }
625 }
626}