1use std::{
4 cmp, fmt,
5 ops::{ControlFlow, RangeBounds},
6 ptr,
7};
8
9use glib::translate::*;
10
11use crate::{ffi, Buffer, BufferRef};
12
13mini_object_wrapper!(BufferList, BufferListRef, ffi::GstBufferList, || {
14 ffi::gst_buffer_list_get_type()
15});
16
17impl BufferList {
18 #[doc(alias = "gst_buffer_list_new")]
19 pub fn new() -> Self {
20 assert_initialized_main_thread!();
21 unsafe { from_glib_full(ffi::gst_buffer_list_new()) }
22 }
23
24 #[doc(alias = "gst_buffer_list_new_sized")]
25 pub fn new_sized(size: usize) -> Self {
26 assert_initialized_main_thread!();
27 unsafe { from_glib_full(ffi::gst_buffer_list_new_sized(u32::try_from(size).unwrap())) }
28 }
29}
30
31impl BufferListRef {
32 #[doc(alias = "gst_buffer_list_insert")]
33 pub fn insert(&mut self, idx: impl Into<Option<usize>>, buffer: Buffer) {
34 unsafe {
35 let len = self.len();
36 debug_assert!(len <= u32::MAX as usize);
37
38 let idx = idx.into();
39 let idx = cmp::min(idx.unwrap_or(len), len) as i32;
40 ffi::gst_buffer_list_insert(self.as_mut_ptr(), idx, buffer.into_glib_ptr());
41 }
42 }
43
44 #[doc(alias = "gst_buffer_list_add")]
45 pub fn add(&mut self, buffer: Buffer) {
46 self.insert(None, buffer);
47 }
48
49 #[doc(alias = "gst_buffer_list_copy_deep")]
50 pub fn copy_deep(&self) -> BufferList {
51 unsafe { from_glib_full(ffi::gst_buffer_list_copy_deep(self.as_ptr())) }
52 }
53
54 fn buffer_range_to_start_end_idx(&self, range: impl RangeBounds<usize>) -> (usize, usize) {
55 let n = self.len();
56 debug_assert!(n <= u32::MAX as usize);
57
58 let start_idx = match range.start_bound() {
59 std::ops::Bound::Included(idx) => *idx,
60 std::ops::Bound::Excluded(idx) => idx.checked_add(1).unwrap(),
61 std::ops::Bound::Unbounded => 0,
62 };
63 assert!(start_idx < n);
64
65 let end_idx = match range.end_bound() {
66 std::ops::Bound::Included(idx) => idx.checked_add(1).unwrap(),
67 std::ops::Bound::Excluded(idx) => *idx,
68 std::ops::Bound::Unbounded => n,
69 };
70 assert!(end_idx <= n);
71
72 (start_idx, end_idx)
73 }
74
75 #[doc(alias = "gst_buffer_list_remove")]
76 pub fn remove(&mut self, range: impl RangeBounds<usize>) {
77 let (start_idx, end_idx) = self.buffer_range_to_start_end_idx(range);
78
79 unsafe {
80 ffi::gst_buffer_list_remove(
81 self.as_mut_ptr(),
82 start_idx as u32,
83 (end_idx - start_idx) as u32,
84 )
85 }
86 }
87
88 #[doc(alias = "gst_buffer_list_get")]
89 pub fn get(&self, idx: usize) -> Option<&BufferRef> {
90 unsafe {
91 if idx >= self.len() {
92 return None;
93 }
94 let ptr = ffi::gst_buffer_list_get(self.as_mut_ptr(), idx as u32);
95 Some(BufferRef::from_ptr(ptr))
96 }
97 }
98
99 #[doc(alias = "gst_buffer_list_get")]
100 pub fn get_owned(&self, idx: usize) -> Option<Buffer> {
101 unsafe {
102 if idx >= self.len() {
103 return None;
104 }
105 let ptr = ffi::gst_buffer_list_get(self.as_mut_ptr(), idx as u32);
106 Some(from_glib_none(ptr))
107 }
108 }
109
110 #[doc(alias = "gst_buffer_list_get_writable")]
111 #[doc(alias = "get_writable")]
112 pub fn get_mut(&mut self, idx: usize) -> Option<&mut BufferRef> {
113 unsafe {
114 if idx >= self.len() {
115 return None;
116 }
117 let ptr = ffi::gst_buffer_list_get_writable(self.as_mut_ptr(), idx as u32);
118 Some(BufferRef::from_mut_ptr(ptr))
119 }
120 }
121
122 #[doc(alias = "gst_buffer_list_length")]
123 pub fn len(&self) -> usize {
124 unsafe { ffi::gst_buffer_list_length(self.as_mut_ptr()) as usize }
125 }
126
127 #[doc(alias = "gst_buffer_list_calculate_size")]
128 pub fn calculate_size(&self) -> usize {
129 unsafe { ffi::gst_buffer_list_calculate_size(self.as_mut_ptr()) }
130 }
131
132 pub fn is_empty(&self) -> bool {
133 self.len() == 0
134 }
135
136 pub fn iter(&self) -> Iter {
137 Iter::new(self)
138 }
139
140 pub fn iter_owned(&self) -> IterOwned {
141 IterOwned::new(self)
142 }
143
144 #[doc(alias = "gst_buffer_list_foreach")]
145 pub fn foreach<F: FnMut(&Buffer, usize) -> ControlFlow<(), ()>>(&self, func: F) -> bool {
146 unsafe extern "C" fn trampoline<F: FnMut(&Buffer, usize) -> ControlFlow<(), ()>>(
147 buffer: *mut *mut ffi::GstBuffer,
148 idx: u32,
149 user_data: glib::ffi::gpointer,
150 ) -> glib::ffi::gboolean {
151 let func = user_data as *mut F;
152 let res = (*func)(&Buffer::from_glib_borrow(*buffer), idx as usize);
153
154 matches!(res, ControlFlow::Continue(_)).into_glib()
155 }
156
157 unsafe {
158 let mut func = func;
159 let func_ptr: &mut F = &mut func;
160
161 from_glib(ffi::gst_buffer_list_foreach(
162 self.as_ptr() as *mut _,
163 Some(trampoline::<F>),
164 func_ptr as *mut _ as *mut _,
165 ))
166 }
167 }
168
169 #[doc(alias = "gst_buffer_list_foreach")]
170 pub fn foreach_mut<F: FnMut(Buffer, usize) -> ControlFlow<Option<Buffer>, Option<Buffer>>>(
171 &mut self,
172 func: F,
173 ) -> bool {
174 unsafe extern "C" fn trampoline<
175 F: FnMut(Buffer, usize) -> ControlFlow<Option<Buffer>, Option<Buffer>>,
176 >(
177 buffer: *mut *mut ffi::GstBuffer,
178 idx: u32,
179 user_data: glib::ffi::gpointer,
180 ) -> glib::ffi::gboolean {
181 let func = user_data as *mut F;
182 let res = (*func)(
183 Buffer::from_glib_full(ptr::replace(
184 buffer as *mut *const ffi::GstBuffer,
185 ptr::null_mut::<ffi::GstBuffer>(),
186 )),
187 idx as usize,
188 );
189
190 let (cont, res_buffer) = match res {
191 ControlFlow::Continue(res_buffer) => (true, res_buffer),
192 ControlFlow::Break(res_buffer) => (false, res_buffer),
193 };
194
195 match res_buffer {
196 None => {
197 *buffer = ptr::null_mut();
198 }
199 Some(new_buffer) => {
200 *buffer = new_buffer.into_glib_ptr();
201 }
202 }
203
204 cont.into_glib()
205 }
206
207 unsafe {
208 let mut func = func;
209 let func_ptr: &mut F = &mut func;
210
211 from_glib(ffi::gst_buffer_list_foreach(
212 self.as_ptr() as *mut _,
213 Some(trampoline::<F>),
214 func_ptr as *mut _ as *mut _,
215 ))
216 }
217 }
218
219 pub fn drain(&mut self, range: impl RangeBounds<usize>) -> Drain<'_> {
220 let (start_idx, end_idx) = self.buffer_range_to_start_end_idx(range);
221 Drain {
222 list: self,
223 start_idx,
224 end_idx,
225 }
226 }
227}
228
229impl Default for BufferList {
230 fn default() -> Self {
231 Self::new()
232 }
233}
234
235impl fmt::Debug for BufferList {
236 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
237 BufferListRef::fmt(self, f)
238 }
239}
240
241impl fmt::Debug for BufferListRef {
242 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
243 use crate::{utils::Displayable, ClockTime};
244
245 let size = self.iter().map(|b| b.size()).sum::<usize>();
246 let (pts, dts) = self
247 .get(0)
248 .map(|b| (b.pts(), b.dts()))
249 .unwrap_or((ClockTime::NONE, ClockTime::NONE));
250
251 f.debug_struct("BufferList")
252 .field("ptr", &self.as_ptr())
253 .field("buffers", &self.len())
254 .field("pts", &pts.display())
255 .field("dts", &dts.display())
256 .field("size", &size)
257 .finish()
258 }
259}
260
261macro_rules! define_iter(
262 ($name:ident, $styp:ty, $get_item:expr) => {
263 #[derive(Debug)]
264 pub struct $name<'a> {
265 list: &'a BufferListRef,
266 idx: usize,
267 size: usize,
268 }
269
270 impl<'a> $name<'a> {
271 fn new(list: &'a BufferListRef) -> $name<'a> {
272 skip_assert_initialized!();
273 $name {
274 list,
275 idx: 0,
276 size: list.len(),
277 }
278 }
279 }
280
281 #[allow(clippy::redundant_closure_call)]
282 impl<'a> Iterator for $name<'a> {
283 type Item = $styp;
284
285 fn next(&mut self) -> Option<Self::Item> {
286 if self.idx >= self.size {
287 return None;
288 }
289
290 let item = $get_item(self.list, self.idx).unwrap();
291 self.idx += 1;
292
293 Some(item)
294 }
295
296 fn size_hint(&self) -> (usize, Option<usize>) {
297 let remaining = self.size - self.idx;
298
299 (remaining, Some(remaining))
300 }
301
302 fn count(self) -> usize {
303 self.size - self.idx
304 }
305
306 fn nth(&mut self, n: usize) -> Option<Self::Item> {
307 let (end, overflow) = self.idx.overflowing_add(n);
308 if end >= self.size || overflow {
309 self.idx = self.size;
310 None
311 } else {
312 self.idx = end + 1;
313 Some($get_item(self.list, end).unwrap())
314 }
315 }
316
317 fn last(self) -> Option<Self::Item> {
318 if self.idx == self.size {
319 None
320 } else {
321 Some($get_item(self.list, self.size - 1).unwrap())
322 }
323 }
324 }
325
326 #[allow(clippy::redundant_closure_call)]
327 impl<'a> DoubleEndedIterator for $name<'a> {
328 fn next_back(&mut self) -> Option<Self::Item> {
329 if self.idx == self.size {
330 return None;
331 }
332
333 self.size -= 1;
334 Some($get_item(self.list, self.size).unwrap())
335 }
336
337 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
338 let (end, overflow) = self.size.overflowing_sub(n);
339 if end <= self.idx || overflow {
340 self.idx = self.size;
341 None
342 } else {
343 self.size = end - 1;
344 Some($get_item(self.list, self.size).unwrap())
345 }
346 }
347 }
348
349 impl<'a> ExactSizeIterator for $name<'a> {}
350 impl<'a> std::iter::FusedIterator for $name<'a> {}
351 }
352);
353
354define_iter!(Iter, &'a BufferRef, |list: &'a BufferListRef, idx| {
355 list.get(idx)
356});
357
358define_iter!(IterOwned, Buffer, |list: &BufferListRef, idx| {
359 list.get_owned(idx)
360});
361
362#[derive(Debug)]
363pub struct Drain<'a> {
364 list: &'a mut BufferListRef,
365 start_idx: usize,
366 end_idx: usize,
367}
368
369impl Iterator for Drain<'_> {
370 type Item = Buffer;
371
372 #[inline]
373 fn next(&mut self) -> Option<Self::Item> {
374 if self.start_idx >= self.end_idx {
375 return None;
376 }
377
378 let buffer = unsafe {
379 let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
380 self.list.as_mut_ptr(),
381 self.start_idx as u32,
382 ));
383 ffi::gst_buffer_list_remove(self.list.as_mut_ptr(), self.start_idx as u32, 1);
384 buffer
385 };
386
387 self.end_idx -= 1;
388
389 Some(buffer)
390 }
391
392 #[inline]
393 fn size_hint(&self) -> (usize, Option<usize>) {
394 let remaining = self.end_idx - self.start_idx;
395
396 (remaining, Some(remaining))
397 }
398
399 #[inline]
400 fn count(self) -> usize {
401 self.end_idx - self.start_idx
402 }
403
404 #[inline]
405 fn nth(&mut self, n: usize) -> Option<Self::Item> {
406 let (end, overflow) = self.start_idx.overflowing_add(n);
407 if end >= self.end_idx || overflow {
408 unsafe {
409 ffi::gst_buffer_list_remove(
410 self.list.as_mut_ptr(),
411 self.start_idx as u32,
412 (self.end_idx - self.start_idx) as u32,
413 );
414 }
415 self.start_idx = self.end_idx;
416 None
417 } else {
418 let buffer = unsafe {
419 let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
420 self.list.as_mut_ptr(),
421 end as u32,
422 ));
423 ffi::gst_buffer_list_remove(
424 self.list.as_mut_ptr(),
425 self.start_idx as u32,
426 n as u32,
427 );
428 buffer
429 };
430 self.end_idx -= n;
431 Some(buffer)
432 }
433 }
434
435 #[inline]
436 fn last(mut self) -> Option<Self::Item> {
437 if self.start_idx == self.end_idx {
438 None
439 } else {
440 let buffer = unsafe {
441 let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
442 self.list.as_mut_ptr(),
443 self.end_idx as u32 - 1,
444 ));
445 ffi::gst_buffer_list_remove(
446 self.list.as_mut_ptr(),
447 self.start_idx as u32,
448 (self.end_idx - self.start_idx) as u32,
449 );
450 buffer
451 };
452 self.end_idx = self.start_idx;
453 Some(buffer)
454 }
455 }
456}
457
458impl DoubleEndedIterator for Drain<'_> {
459 #[inline]
460 fn next_back(&mut self) -> Option<Self::Item> {
461 if self.start_idx == self.end_idx {
462 return None;
463 }
464
465 self.end_idx -= 1;
466 let buffer = unsafe {
467 let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
468 self.list.as_mut_ptr(),
469 self.end_idx as u32,
470 ));
471 ffi::gst_buffer_list_remove(self.list.as_mut_ptr(), self.end_idx as u32, 1);
472 buffer
473 };
474
475 Some(buffer)
476 }
477
478 #[inline]
479 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
480 let (end, overflow) = self.end_idx.overflowing_sub(n);
481 if end <= self.start_idx || overflow {
482 unsafe {
483 ffi::gst_buffer_list_remove(
484 self.list.as_mut_ptr(),
485 self.start_idx as u32,
486 (self.end_idx - self.start_idx) as u32,
487 );
488 }
489 self.start_idx = self.end_idx;
490 None
491 } else {
492 self.end_idx = end - 1;
493 let buffer = unsafe {
494 let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
495 self.list.as_mut_ptr(),
496 self.end_idx as u32,
497 ));
498 ffi::gst_buffer_list_remove(self.list.as_mut_ptr(), self.end_idx as u32, n as u32);
499 buffer
500 };
501
502 Some(buffer)
503 }
504 }
505}
506
507impl ExactSizeIterator for Drain<'_> {}
508
509impl std::iter::FusedIterator for Drain<'_> {}
510
511impl Drop for Drain<'_> {
512 fn drop(&mut self) {
513 if self.start_idx >= self.end_idx {
514 return;
515 }
516
517 unsafe {
518 ffi::gst_buffer_list_remove(
519 self.list.as_mut_ptr(),
520 self.start_idx as u32,
521 (self.end_idx - self.start_idx) as u32,
522 );
523 }
524 }
525}
526
527impl<'a> IntoIterator for &'a BufferListRef {
528 type IntoIter = Iter<'a>;
529 type Item = &'a BufferRef;
530
531 fn into_iter(self) -> Self::IntoIter {
532 self.iter()
533 }
534}
535
536impl From<Buffer> for BufferList {
537 fn from(value: Buffer) -> Self {
538 skip_assert_initialized!();
539
540 let mut list = BufferList::new_sized(1);
541 {
542 let list = list.get_mut().unwrap();
543 list.add(value);
544 }
545 list
546 }
547}
548
549impl<const N: usize> From<[Buffer; N]> for BufferList {
550 fn from(value: [Buffer; N]) -> Self {
551 skip_assert_initialized!();
552
553 let mut list = BufferList::new_sized(N);
554 {
555 let list = list.get_mut().unwrap();
556 value.into_iter().for_each(|b| list.add(b));
557 }
558 list
559 }
560}
561
562impl std::iter::FromIterator<Buffer> for BufferList {
563 fn from_iter<T: IntoIterator<Item = Buffer>>(iter: T) -> Self {
564 assert_initialized_main_thread!();
565
566 let iter = iter.into_iter();
567
568 let mut list = BufferList::new_sized(iter.size_hint().0);
569
570 {
571 let list = list.get_mut().unwrap();
572 iter.for_each(|b| list.add(b));
573 }
574
575 list
576 }
577}
578
579impl std::iter::Extend<Buffer> for BufferListRef {
580 fn extend<T: IntoIterator<Item = Buffer>>(&mut self, iter: T) {
581 iter.into_iter().for_each(|b| self.add(b));
582 }
583}
584
585#[cfg(test)]
586mod tests {
587 use super::*;
588 use crate::ClockTime;
589
590 fn make_buffer_list(size: usize) -> BufferList {
591 skip_assert_initialized!();
592
593 let mut buffer_list = BufferList::new();
594 {
595 let buffer_list = buffer_list.get_mut().unwrap();
596 for i in 0..size {
597 let mut buffer = Buffer::new();
598 buffer
599 .get_mut()
600 .unwrap()
601 .set_pts(ClockTime::SECOND * i as u64);
602 buffer_list.add(buffer);
603 }
604 }
605 buffer_list
606 }
607
608 #[test]
609 fn test_foreach() {
610 crate::init().unwrap();
611
612 let buffer_list = make_buffer_list(2);
613
614 let mut res = vec![];
615 buffer_list.foreach(|buffer, idx| {
616 res.push((buffer.pts(), idx));
617 ControlFlow::Continue(())
618 });
619
620 assert_eq!(
621 res,
622 &[(Some(ClockTime::ZERO), 0), (Some(ClockTime::SECOND), 1)]
623 );
624 }
625
626 #[test]
627 fn test_foreach_mut() {
628 crate::init().unwrap();
629
630 let mut buffer_list = make_buffer_list(3);
631
632 let mut res = vec![];
633 buffer_list.get_mut().unwrap().foreach_mut(|buffer, idx| {
634 res.push((buffer.pts(), idx));
635
636 if let Some(ClockTime::ZERO) = buffer.pts() {
637 ControlFlow::Continue(Some(buffer))
638 } else if let Some(ClockTime::SECOND) = buffer.pts() {
639 ControlFlow::Continue(None)
640 } else {
641 let mut new_buffer = Buffer::new();
642 new_buffer.get_mut().unwrap().set_pts(3 * ClockTime::SECOND);
643 ControlFlow::Continue(Some(new_buffer))
644 }
645 });
646
647 assert_eq!(
648 res,
649 &[
650 (Some(ClockTime::ZERO), 0),
651 (Some(ClockTime::SECOND), 1),
652 (Some(2 * ClockTime::SECOND), 1)
653 ]
654 );
655
656 let mut res = vec![];
657 buffer_list.foreach(|buffer, idx| {
658 res.push((buffer.pts(), idx));
659 ControlFlow::Continue(())
660 });
661
662 assert_eq!(
663 res,
664 &[(Some(ClockTime::ZERO), 0), (Some(3 * ClockTime::SECOND), 1)]
665 );
666
667 let mut buffer_list = BufferList::new();
669 for i in 0..10 {
670 let buffer_list = buffer_list.get_mut().unwrap();
671 let mut buffer = Buffer::new();
672 buffer.get_mut().unwrap().set_pts(i * ClockTime::SECOND);
673 buffer_list.add(buffer);
674 }
675
676 assert_eq!(buffer_list.len(), 10);
677
678 let buffer_list_ref = buffer_list.make_mut();
679
680 buffer_list_ref.foreach_mut(|buf, _n| {
681 let keep_packet = (buf.pts().unwrap() / ClockTime::SECOND) % 3 != 0;
682 ControlFlow::Continue(keep_packet.then_some(buf))
683 });
684
685 assert_eq!(buffer_list.len(), 6);
686
687 let res = buffer_list
688 .iter()
689 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
690 .collect::<Vec<_>>();
691
692 assert_eq!(res, &[1, 2, 4, 5, 7, 8]);
693 }
694
695 #[test]
696 fn test_remove() {
697 crate::init().unwrap();
698
699 let mut buffer_list = make_buffer_list(10);
700
701 buffer_list.make_mut().remove(0..2);
702
703 let buffers_left = buffer_list
704 .iter()
705 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
706 .collect::<Vec<_>>();
707
708 assert_eq!(buffers_left, &[2, 3, 4, 5, 6, 7, 8, 9]);
709
710 buffer_list.make_mut().remove(0..=2);
711
712 let buffers_left = buffer_list
713 .iter()
714 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
715 .collect::<Vec<_>>();
716
717 assert_eq!(buffers_left, &[5, 6, 7, 8, 9]);
718
719 buffer_list.make_mut().remove(2..);
720
721 let buffers_left = buffer_list
722 .iter()
723 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
724 .collect::<Vec<_>>();
725
726 assert_eq!(buffers_left, &[5, 6]);
727
728 buffer_list.make_mut().remove(..);
729
730 assert!(buffer_list.is_empty());
731 }
732
733 #[test]
734 fn test_drain() {
735 crate::init().unwrap();
736
737 let mut buffer_list = make_buffer_list(10);
738
739 let buffers_removed = buffer_list
740 .make_mut()
741 .drain(0..2)
742 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
743 .collect::<Vec<_>>();
744
745 assert_eq!(buffers_removed, &[0, 1]);
746
747 let buffers_left = buffer_list
748 .iter()
749 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
750 .collect::<Vec<_>>();
751
752 assert_eq!(buffers_left, &[2, 3, 4, 5, 6, 7, 8, 9]);
753
754 let buffers_removed = buffer_list
755 .make_mut()
756 .drain(0..=2)
757 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
758 .collect::<Vec<_>>();
759
760 assert_eq!(buffers_removed, &[2, 3, 4]);
761
762 let buffers_left = buffer_list
763 .iter()
764 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
765 .collect::<Vec<_>>();
766
767 assert_eq!(buffers_left, &[5, 6, 7, 8, 9]);
768
769 let buffers_removed = buffer_list
770 .make_mut()
771 .drain(2..)
772 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
773 .collect::<Vec<_>>();
774
775 assert_eq!(buffers_removed, &[7, 8, 9]);
776
777 let buffers_left = buffer_list
778 .iter()
779 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
780 .collect::<Vec<_>>();
781
782 assert_eq!(buffers_left, &[5, 6]);
783
784 let buffers_removed = buffer_list
785 .make_mut()
786 .drain(..)
787 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
788 .collect::<Vec<_>>();
789
790 assert_eq!(buffers_removed, &[5, 6]);
791
792 assert!(buffer_list.is_empty());
793 }
794
795 #[test]
796 fn test_drain_drop() {
797 crate::init().unwrap();
798
799 let mut buffer_list = make_buffer_list(10);
800
801 buffer_list.make_mut().drain(0..2);
802
803 let buffers_left = buffer_list
804 .iter()
805 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
806 .collect::<Vec<_>>();
807
808 assert_eq!(buffers_left, &[2, 3, 4, 5, 6, 7, 8, 9]);
809
810 buffer_list.make_mut().drain(0..=2);
811
812 let buffers_left = buffer_list
813 .iter()
814 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
815 .collect::<Vec<_>>();
816
817 assert_eq!(buffers_left, &[5, 6, 7, 8, 9]);
818
819 buffer_list.make_mut().drain(2..);
820
821 let buffers_left = buffer_list
822 .iter()
823 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
824 .collect::<Vec<_>>();
825
826 assert_eq!(buffers_left, &[5, 6]);
827
828 buffer_list.make_mut().drain(..);
829
830 assert!(buffer_list.is_empty());
831 }
832}