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