1use bitflags::bitflags;
7
8bitflags! {
9 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
34 pub struct PacketFlags: u8 {
35 const KEY = 0b001;
37 const CORRUPT = 0b010;
39 const DISCARD = 0b100;
41 }
42}
43
44use crate::Timestamp;
45
46pub struct VideoPacket<E, D> {
56 pts: Option<Timestamp>,
57 dts: Option<Timestamp>,
58 duration: Option<Timestamp>,
59 flags: PacketFlags,
60 data: D,
61 extra: E,
62}
63
64impl<E, D> VideoPacket<E, D> {
65 #[cfg_attr(not(tarpaulin), inline(always))]
68 pub const fn new(data: D, extra: E) -> Self {
69 Self {
70 pts: None,
71 dts: None,
72 duration: None,
73 flags: PacketFlags::empty(),
74 data,
75 extra,
76 }
77 }
78
79 #[cfg_attr(not(tarpaulin), inline(always))]
81 pub const fn pts(&self) -> Option<Timestamp> {
82 self.pts
83 }
84 #[cfg_attr(not(tarpaulin), inline(always))]
86 pub const fn dts(&self) -> Option<Timestamp> {
87 self.dts
88 }
89 #[cfg_attr(not(tarpaulin), inline(always))]
91 pub const fn duration(&self) -> Option<Timestamp> {
92 self.duration
93 }
94 #[cfg_attr(not(tarpaulin), inline(always))]
96 pub const fn flags(&self) -> PacketFlags {
97 self.flags
98 }
99 #[cfg_attr(not(tarpaulin), inline(always))]
101 pub const fn data(&self) -> &D {
102 &self.data
103 }
104 #[cfg_attr(not(tarpaulin), inline(always))]
106 pub const fn extra(&self) -> &E {
107 &self.extra
108 }
109 #[cfg_attr(not(tarpaulin), inline(always))]
111 pub fn extra_mut(&mut self) -> &mut E {
112 &mut self.extra
113 }
114 #[cfg_attr(not(tarpaulin), inline(always))]
116 pub fn into_data(self) -> D {
117 self.data
118 }
119 #[cfg_attr(not(tarpaulin), inline(always))]
121 pub fn into_parts(self) -> (D, E) {
122 (self.data, self.extra)
123 }
124
125 #[cfg_attr(not(tarpaulin), inline(always))]
127 #[must_use]
128 pub const fn with_pts(mut self, v: Option<Timestamp>) -> Self {
129 self.pts = v;
130 self
131 }
132 #[cfg_attr(not(tarpaulin), inline(always))]
134 #[must_use]
135 pub const fn with_dts(mut self, v: Option<Timestamp>) -> Self {
136 self.dts = v;
137 self
138 }
139 #[cfg_attr(not(tarpaulin), inline(always))]
141 #[must_use]
142 pub const fn with_duration(mut self, v: Option<Timestamp>) -> Self {
143 self.duration = v;
144 self
145 }
146 #[cfg_attr(not(tarpaulin), inline(always))]
148 #[must_use]
149 pub const fn with_flags(mut self, v: PacketFlags) -> Self {
150 self.flags = v;
151 self
152 }
153
154 #[cfg_attr(not(tarpaulin), inline(always))]
156 pub const fn set_pts(&mut self, v: Option<Timestamp>) -> &mut Self {
157 self.pts = v;
158 self
159 }
160 #[cfg_attr(not(tarpaulin), inline(always))]
162 pub const fn set_dts(&mut self, v: Option<Timestamp>) -> &mut Self {
163 self.dts = v;
164 self
165 }
166 #[cfg_attr(not(tarpaulin), inline(always))]
168 pub const fn set_duration(&mut self, v: Option<Timestamp>) -> &mut Self {
169 self.duration = v;
170 self
171 }
172 #[cfg_attr(not(tarpaulin), inline(always))]
174 pub const fn set_flags(&mut self, v: PacketFlags) -> &mut Self {
175 self.flags = v;
176 self
177 }
178}
179
180pub struct AudioPacket<E, D> {
182 pts: Option<Timestamp>,
183 dts: Option<Timestamp>,
184 duration: Option<Timestamp>,
185 flags: PacketFlags,
186 data: D,
187 extra: E,
188}
189
190impl<E, D> AudioPacket<E, D> {
191 #[cfg_attr(not(tarpaulin), inline(always))]
193 pub const fn new(data: D, extra: E) -> Self {
194 Self {
195 pts: None,
196 dts: None,
197 duration: None,
198 flags: PacketFlags::empty(),
199 data,
200 extra,
201 }
202 }
203
204 #[cfg_attr(not(tarpaulin), inline(always))]
206 pub const fn pts(&self) -> Option<Timestamp> {
207 self.pts
208 }
209 #[cfg_attr(not(tarpaulin), inline(always))]
211 pub const fn dts(&self) -> Option<Timestamp> {
212 self.dts
213 }
214 #[cfg_attr(not(tarpaulin), inline(always))]
216 pub const fn duration(&self) -> Option<Timestamp> {
217 self.duration
218 }
219 #[cfg_attr(not(tarpaulin), inline(always))]
221 pub const fn flags(&self) -> PacketFlags {
222 self.flags
223 }
224 #[cfg_attr(not(tarpaulin), inline(always))]
226 pub const fn data(&self) -> &D {
227 &self.data
228 }
229 #[cfg_attr(not(tarpaulin), inline(always))]
231 pub const fn extra(&self) -> &E {
232 &self.extra
233 }
234 #[cfg_attr(not(tarpaulin), inline(always))]
236 pub fn extra_mut(&mut self) -> &mut E {
237 &mut self.extra
238 }
239 #[cfg_attr(not(tarpaulin), inline(always))]
241 pub fn into_data(self) -> D {
242 self.data
243 }
244 #[cfg_attr(not(tarpaulin), inline(always))]
246 pub fn into_parts(self) -> (D, E) {
247 (self.data, self.extra)
248 }
249
250 #[cfg_attr(not(tarpaulin), inline(always))]
252 #[must_use]
253 pub const fn with_pts(mut self, v: Option<Timestamp>) -> Self {
254 self.pts = v;
255 self
256 }
257 #[cfg_attr(not(tarpaulin), inline(always))]
259 #[must_use]
260 pub const fn with_dts(mut self, v: Option<Timestamp>) -> Self {
261 self.dts = v;
262 self
263 }
264 #[cfg_attr(not(tarpaulin), inline(always))]
266 #[must_use]
267 pub const fn with_duration(mut self, v: Option<Timestamp>) -> Self {
268 self.duration = v;
269 self
270 }
271 #[cfg_attr(not(tarpaulin), inline(always))]
273 #[must_use]
274 pub const fn with_flags(mut self, v: PacketFlags) -> Self {
275 self.flags = v;
276 self
277 }
278
279 #[cfg_attr(not(tarpaulin), inline(always))]
281 pub const fn set_pts(&mut self, v: Option<Timestamp>) -> &mut Self {
282 self.pts = v;
283 self
284 }
285 #[cfg_attr(not(tarpaulin), inline(always))]
287 pub const fn set_dts(&mut self, v: Option<Timestamp>) -> &mut Self {
288 self.dts = v;
289 self
290 }
291 #[cfg_attr(not(tarpaulin), inline(always))]
293 pub const fn set_duration(&mut self, v: Option<Timestamp>) -> &mut Self {
294 self.duration = v;
295 self
296 }
297 #[cfg_attr(not(tarpaulin), inline(always))]
299 pub const fn set_flags(&mut self, v: PacketFlags) -> &mut Self {
300 self.flags = v;
301 self
302 }
303}
304
305pub struct SubtitlePacket<E, D> {
307 pts: Option<Timestamp>,
308 duration: Option<Timestamp>,
309 flags: PacketFlags,
310 data: D,
311 extra: E,
312}
313
314impl<E, D> SubtitlePacket<E, D> {
315 #[cfg_attr(not(tarpaulin), inline(always))]
317 pub const fn new(data: D, extra: E) -> Self {
318 Self {
319 pts: None,
320 duration: None,
321 flags: PacketFlags::empty(),
322 data,
323 extra,
324 }
325 }
326
327 #[cfg_attr(not(tarpaulin), inline(always))]
329 pub const fn pts(&self) -> Option<Timestamp> {
330 self.pts
331 }
332 #[cfg_attr(not(tarpaulin), inline(always))]
334 pub const fn duration(&self) -> Option<Timestamp> {
335 self.duration
336 }
337 #[cfg_attr(not(tarpaulin), inline(always))]
339 pub const fn flags(&self) -> PacketFlags {
340 self.flags
341 }
342 #[cfg_attr(not(tarpaulin), inline(always))]
344 pub const fn data(&self) -> &D {
345 &self.data
346 }
347 #[cfg_attr(not(tarpaulin), inline(always))]
349 pub const fn extra(&self) -> &E {
350 &self.extra
351 }
352 #[cfg_attr(not(tarpaulin), inline(always))]
354 pub fn extra_mut(&mut self) -> &mut E {
355 &mut self.extra
356 }
357 #[cfg_attr(not(tarpaulin), inline(always))]
359 pub fn into_data(self) -> D {
360 self.data
361 }
362 #[cfg_attr(not(tarpaulin), inline(always))]
364 pub fn into_parts(self) -> (D, E) {
365 (self.data, self.extra)
366 }
367
368 #[cfg_attr(not(tarpaulin), inline(always))]
370 #[must_use]
371 pub const fn with_pts(mut self, v: Option<Timestamp>) -> Self {
372 self.pts = v;
373 self
374 }
375 #[cfg_attr(not(tarpaulin), inline(always))]
377 #[must_use]
378 pub const fn with_duration(mut self, v: Option<Timestamp>) -> Self {
379 self.duration = v;
380 self
381 }
382 #[cfg_attr(not(tarpaulin), inline(always))]
384 #[must_use]
385 pub const fn with_flags(mut self, v: PacketFlags) -> Self {
386 self.flags = v;
387 self
388 }
389
390 #[cfg_attr(not(tarpaulin), inline(always))]
392 pub const fn set_pts(&mut self, v: Option<Timestamp>) -> &mut Self {
393 self.pts = v;
394 self
395 }
396 #[cfg_attr(not(tarpaulin), inline(always))]
398 pub const fn set_duration(&mut self, v: Option<Timestamp>) -> &mut Self {
399 self.duration = v;
400 self
401 }
402 #[cfg_attr(not(tarpaulin), inline(always))]
404 pub const fn set_flags(&mut self, v: PacketFlags) -> &mut Self {
405 self.flags = v;
406 self
407 }
408}
409
410#[cfg(feature = "serde")]
417#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
418mod serde_impls {
419 use serde::{Deserialize, Deserializer, Serialize, Serializer};
435
436 use super::PacketFlags;
437
438 impl Serialize for PacketFlags {
439 #[cfg_attr(not(tarpaulin), inline(always))]
440 fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
441 ser.serialize_u8(self.bits())
442 }
443 }
444
445 impl<'de> Deserialize<'de> for PacketFlags {
446 #[cfg_attr(not(tarpaulin), inline(always))]
447 fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
448 u8::deserialize(de).map(Self::from_bits_retain)
449 }
450 }
451}
452
453#[cfg(feature = "arbitrary")]
454#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
455mod arbitrary_impls {
456 use arbitrary::{Arbitrary, Result, Unstructured};
467
468 use super::PacketFlags;
469
470 impl<'a> Arbitrary<'a> for PacketFlags {
471 fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
472 Ok(Self::from_bits_retain(u8::arbitrary(u)?))
473 }
474 }
475}
476
477#[cfg(feature = "quickcheck")]
478#[cfg_attr(docsrs, doc(cfg(feature = "quickcheck")))]
479mod quickcheck_impls {
480 use quickcheck::{Arbitrary, Gen};
484
485 use super::PacketFlags;
486
487 impl Arbitrary for PacketFlags {
488 fn arbitrary(g: &mut Gen) -> Self {
489 Self::from_bits_retain(u8::arbitrary(g))
490 }
491 }
492}
493
494#[cfg(test)]
495mod tests {
496 use super::*;
497
498 #[test]
499 fn flag_bits_are_stable() {
500 assert_eq!(PacketFlags::KEY.bits(), 0b001);
501 assert_eq!(PacketFlags::CORRUPT.bits(), 0b010);
502 assert_eq!(PacketFlags::DISCARD.bits(), 0b100);
503 }
504
505 #[test]
506 fn flags_combine() {
507 let f = PacketFlags::KEY | PacketFlags::CORRUPT;
508 assert!(f.contains(PacketFlags::KEY));
509 assert!(f.contains(PacketFlags::CORRUPT));
510 assert!(!f.contains(PacketFlags::DISCARD));
511 }
512
513 #[test]
514 fn empty_default() {
515 assert_eq!(PacketFlags::default(), PacketFlags::empty());
516 }
517
518 use crate::Timebase;
519 use core::num::NonZeroI32;
520
521 fn ms_tb() -> Timebase {
522 Timebase::new(1, NonZeroI32::new(1000).unwrap())
523 }
524
525 #[test]
526 fn video_packet_construct_and_access() {
527 let data: &[u8] = &[1, 2, 3];
528 let p: VideoPacket<_, &[u8]> = VideoPacket::new(data, ());
529 assert_eq!(p.pts(), None);
530 assert_eq!(p.flags(), PacketFlags::empty());
531 assert_eq!(*p.data(), data);
532 }
533
534 #[test]
535 fn video_packet_builders_chain() {
536 let pts = crate::Timestamp::new(1500, ms_tb());
537 let p: VideoPacket<_, &[u8]> = VideoPacket::new(&[][..], ())
538 .with_pts(Some(pts))
539 .with_flags(PacketFlags::KEY);
540 assert_eq!(p.pts(), Some(pts));
541 assert!(p.flags().contains(PacketFlags::KEY));
542 }
543
544 #[test]
545 fn video_packet_into_parts() {
546 let p: VideoPacket<_, &[u8]> = VideoPacket::new(&[1u8, 2][..], ());
547 let (data, _extra) = p.into_parts();
548 assert_eq!(data, &[1, 2]);
549 }
550
551 #[test]
552 fn audio_packet_round_trip() {
553 let data: &[u8] = &[7, 8, 9];
554 let p: AudioPacket<_, &[u8]> = AudioPacket::new(data, ()).with_flags(PacketFlags::KEY);
555 assert_eq!(*p.data(), data);
556 assert!(p.flags().contains(PacketFlags::KEY));
557 let (recovered, _) = p.into_parts();
558 assert_eq!(recovered, data);
559 }
560
561 #[test]
562 fn subtitle_packet_round_trip() {
563 let data: &[u8] = b"hi";
564 let p: SubtitlePacket<_, &[u8]> = SubtitlePacket::new(data, ());
565 assert_eq!(*p.data(), data);
566 }
567
568 #[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))]
575 mod serde_tests {
576 extern crate alloc;
582
583 use alloc::string::ToString;
584
585 use super::*;
586
587 #[test]
588 fn the_wire_is_a_number_not_a_flag_grammar() {
589 let flags = PacketFlags::KEY | PacketFlags::CORRUPT;
594 assert_eq!(
595 serde_json::to_string(&flags).expect("flags always serialize"),
596 "3"
597 );
598 assert_eq!(
599 serde_json::to_string(&PacketFlags::empty()).expect("flags always serialize"),
600 "0"
601 );
602 }
603
604 #[test]
605 fn a_name_is_not_a_number() {
606 assert!(serde_json::from_str::<PacketFlags>(r#""KEY""#).is_err());
607 assert!(serde_json::from_str::<PacketFlags>(r#""key|corrupt""#).is_err());
608 }
609
610 #[test]
611 fn every_bit_pattern_round_trips_including_the_unnamed_ones() {
612 for bits in 0..=u8::MAX {
616 let flags = PacketFlags::from_bits_retain(bits);
617 let json = serde_json::to_string(&flags).expect("flags always serialize");
618 assert_eq!(json, bits.to_string());
619 assert_eq!(
620 serde_json::from_str::<PacketFlags>(&json).expect("its own output parses"),
621 flags,
622 "round-trip failed for {bits:#010b}"
623 );
624 }
625 }
626
627 #[test]
628 fn a_value_no_u8_can_hold_is_refused() {
629 assert!(serde_json::from_str::<PacketFlags>("256").is_err());
630 assert!(serde_json::from_str::<PacketFlags>("-1").is_err());
631 }
632 }
633
634 #[cfg(feature = "arbitrary")]
635 mod arbitrary_tests {
636 use arbitrary::{Arbitrary, Unstructured};
637
638 use super::*;
639
640 #[test]
641 fn every_bit_pattern_is_reachable() {
642 let mut seen = [false; 256];
643 for byte in 0..=u8::MAX {
644 let data = [byte];
645 let mut u = Unstructured::new(&data);
646 let flags = PacketFlags::arbitrary(&mut u).expect("the generator is total");
647 seen[flags.bits() as usize] = true;
648 }
649 assert!(
650 seen.iter().all(|&s| s),
651 "a bit pattern the generator never produces"
652 );
653 }
654 }
655
656 #[cfg(feature = "quickcheck")]
657 mod quickcheck_tests {
658 use quickcheck::{Arbitrary, Gen};
659
660 use super::*;
661
662 #[test]
663 fn the_named_flags_and_the_unnamed_bits_are_both_reachable() {
664 let mut g = Gen::new(16);
667 let mut union = PacketFlags::empty();
668 let mut saw_unnamed = false;
669 for _ in 0..4000 {
670 let flags = PacketFlags::arbitrary(&mut g);
671 union |= flags;
672 saw_unnamed |= !PacketFlags::all().contains(flags);
673 }
674 assert_eq!(
675 union,
676 PacketFlags::from_bits_retain(u8::MAX),
677 "a bit the generator never sets"
678 );
679 assert!(saw_unnamed, "an unnamed bit is never produced");
680 }
681 }
682}