Skip to main content

gstreamer/
bufferlist.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{
4    cmp, fmt,
5    ops::{ControlFlow, RangeBounds},
6    ptr,
7};
8
9use glib::translate::*;
10
11use crate::{Buffer, BufferRef, ffi};
12
13mini_object_wrapper!(BufferList, BufferListRef, ffi::GstBufferList, || {
14    ffi::gst_buffer_list_get_type()
15});
16
17impl BufferList {
18    /// Creates a new, empty [`BufferList`][crate::BufferList].
19    ///
20    /// # Returns
21    ///
22    /// the new [`BufferList`][crate::BufferList].
23    #[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    /// Creates a new, empty [`BufferList`][crate::BufferList]. The list will have `size` space
30    /// preallocated so that memory reallocations can be avoided.
31    /// ## `size`
32    /// an initial reserved size
33    ///
34    /// # Returns
35    ///
36    /// the new [`BufferList`][crate::BufferList].
37    #[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) {
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            unsafe {
165                let func = user_data as *mut F;
166                let res = (*func)(&Buffer::from_glib_borrow(*buffer), idx as usize);
167
168                matches!(res, ControlFlow::Continue(_)).into_glib()
169            }
170        }
171
172        unsafe {
173            let mut func = func;
174            let func_ptr: &mut F = &mut func;
175
176            let _ = ffi::gst_buffer_list_foreach(
177                self.as_ptr() as *mut _,
178                Some(trampoline::<F>),
179                func_ptr as *mut _ as *mut _,
180            );
181        }
182    }
183
184    #[doc(alias = "gst_buffer_list_foreach")]
185    pub fn foreach_mut<F: FnMut(Buffer, usize) -> ControlFlow<Option<Buffer>, Option<Buffer>>>(
186        &mut self,
187        func: F,
188    ) {
189        unsafe extern "C" fn trampoline<
190            F: FnMut(Buffer, usize) -> ControlFlow<Option<Buffer>, Option<Buffer>>,
191        >(
192            buffer: *mut *mut ffi::GstBuffer,
193            idx: u32,
194            user_data: glib::ffi::gpointer,
195        ) -> glib::ffi::gboolean {
196            unsafe {
197                let func = user_data as *mut F;
198                let res = (*func)(
199                    Buffer::from_glib_full(ptr::replace(
200                        buffer as *mut *const ffi::GstBuffer,
201                        ptr::null_mut::<ffi::GstBuffer>(),
202                    )),
203                    idx as usize,
204                );
205
206                let (cont, res_buffer) = match res {
207                    ControlFlow::Continue(res_buffer) => (true, res_buffer),
208                    ControlFlow::Break(res_buffer) => (false, res_buffer),
209                };
210
211                match res_buffer {
212                    None => {
213                        *buffer = ptr::null_mut();
214                    }
215                    Some(new_buffer) => {
216                        *buffer = new_buffer.into_glib_ptr();
217                    }
218                }
219
220                cont.into_glib()
221            }
222        }
223
224        unsafe {
225            let mut func = func;
226            let func_ptr: &mut F = &mut func;
227
228            let _ = ffi::gst_buffer_list_foreach(
229                self.as_ptr() as *mut _,
230                Some(trampoline::<F>),
231                func_ptr as *mut _ as *mut _,
232            );
233        }
234    }
235
236    pub fn drain(&mut self, range: impl RangeBounds<usize>) -> Drain<'_> {
237        let (start_idx, end_idx) = self.buffer_range_to_start_end_idx(range);
238        Drain {
239            list: self,
240            start_idx,
241            end_idx,
242        }
243    }
244}
245
246impl Default for BufferList {
247    fn default() -> Self {
248        Self::new()
249    }
250}
251
252impl fmt::Debug for BufferList {
253    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
254        BufferListRef::fmt(self, f)
255    }
256}
257
258impl fmt::Debug for BufferListRef {
259    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
260        use crate::{ClockTime, utils::Displayable};
261
262        let size = self.iter().map(|b| b.size()).sum::<usize>();
263        let (pts, dts) = self
264            .get(0)
265            .map(|b| (b.pts(), b.dts()))
266            .unwrap_or((ClockTime::NONE, ClockTime::NONE));
267
268        f.debug_struct("BufferList")
269            .field("ptr", &self.as_ptr())
270            .field("buffers", &self.len())
271            .field("pts", &pts.display())
272            .field("dts", &dts.display())
273            .field("size", &size)
274            .finish()
275    }
276}
277
278macro_rules! define_iter(
279    ($name:ident, $styp:ty, $get_item:expr) => {
280        crate::utils::define_fixed_size_iter!(
281            $name, &'a BufferListRef, $styp,
282            |collection: &BufferListRef| collection.len(),
283            $get_item
284        );
285    }
286);
287
288define_iter!(Iter, &'a BufferRef, |list: &BufferListRef, idx| unsafe {
289    let ptr = ffi::gst_buffer_list_get(list.as_mut_ptr(), idx as u32);
290    BufferRef::from_ptr(ptr)
291});
292
293define_iter!(IterOwned, Buffer, |list: &BufferListRef, idx| unsafe {
294    let ptr = ffi::gst_buffer_list_get(list.as_mut_ptr(), idx as u32);
295    from_glib_none(ptr)
296});
297
298#[derive(Debug)]
299pub struct Drain<'a> {
300    list: &'a mut BufferListRef,
301    start_idx: usize,
302    end_idx: usize,
303}
304
305impl Iterator for Drain<'_> {
306    type Item = Buffer;
307
308    #[inline]
309    fn next(&mut self) -> Option<Self::Item> {
310        if self.start_idx >= self.end_idx {
311            return None;
312        }
313
314        let buffer = unsafe {
315            let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
316                self.list.as_mut_ptr(),
317                self.start_idx as u32,
318            ));
319            ffi::gst_buffer_list_remove(self.list.as_mut_ptr(), self.start_idx as u32, 1);
320            buffer
321        };
322
323        self.end_idx -= 1;
324
325        Some(buffer)
326    }
327
328    #[inline]
329    fn size_hint(&self) -> (usize, Option<usize>) {
330        let remaining = self.end_idx - self.start_idx;
331
332        (remaining, Some(remaining))
333    }
334
335    #[inline]
336    fn count(self) -> usize {
337        self.end_idx - self.start_idx
338    }
339
340    #[inline]
341    fn nth(&mut self, n: usize) -> Option<Self::Item> {
342        let (end, overflow) = self.start_idx.overflowing_add(n);
343        if end >= self.end_idx || overflow {
344            unsafe {
345                ffi::gst_buffer_list_remove(
346                    self.list.as_mut_ptr(),
347                    self.start_idx as u32,
348                    (self.end_idx - self.start_idx) as u32,
349                );
350            }
351            self.start_idx = self.end_idx;
352            None
353        } else {
354            let buffer = unsafe {
355                let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
356                    self.list.as_mut_ptr(),
357                    end as u32,
358                ));
359                ffi::gst_buffer_list_remove(
360                    self.list.as_mut_ptr(),
361                    self.start_idx as u32,
362                    n as u32,
363                );
364                buffer
365            };
366            self.end_idx -= n;
367            Some(buffer)
368        }
369    }
370
371    #[inline]
372    fn last(mut self) -> Option<Self::Item> {
373        if self.start_idx == self.end_idx {
374            None
375        } else {
376            let buffer = unsafe {
377                let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
378                    self.list.as_mut_ptr(),
379                    self.end_idx as u32 - 1,
380                ));
381                ffi::gst_buffer_list_remove(
382                    self.list.as_mut_ptr(),
383                    self.start_idx as u32,
384                    (self.end_idx - self.start_idx) as u32,
385                );
386                buffer
387            };
388            self.end_idx = self.start_idx;
389            Some(buffer)
390        }
391    }
392}
393
394impl DoubleEndedIterator for Drain<'_> {
395    #[inline]
396    fn next_back(&mut self) -> Option<Self::Item> {
397        if self.start_idx == self.end_idx {
398            return None;
399        }
400
401        self.end_idx -= 1;
402        let buffer = unsafe {
403            let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
404                self.list.as_mut_ptr(),
405                self.end_idx as u32,
406            ));
407            ffi::gst_buffer_list_remove(self.list.as_mut_ptr(), self.end_idx as u32, 1);
408            buffer
409        };
410
411        Some(buffer)
412    }
413
414    #[inline]
415    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
416        let (end, overflow) = self.end_idx.overflowing_sub(n);
417        if end <= self.start_idx || overflow {
418            unsafe {
419                ffi::gst_buffer_list_remove(
420                    self.list.as_mut_ptr(),
421                    self.start_idx as u32,
422                    (self.end_idx - self.start_idx) as u32,
423                );
424            }
425            self.start_idx = self.end_idx;
426            None
427        } else {
428            self.end_idx = end - 1;
429            let buffer = unsafe {
430                let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
431                    self.list.as_mut_ptr(),
432                    self.end_idx as u32,
433                ));
434                ffi::gst_buffer_list_remove(self.list.as_mut_ptr(), self.end_idx as u32, n as u32);
435                buffer
436            };
437
438            Some(buffer)
439        }
440    }
441}
442
443impl ExactSizeIterator for Drain<'_> {}
444
445impl std::iter::FusedIterator for Drain<'_> {}
446
447impl Drop for Drain<'_> {
448    fn drop(&mut self) {
449        if self.start_idx >= self.end_idx {
450            return;
451        }
452
453        unsafe {
454            ffi::gst_buffer_list_remove(
455                self.list.as_mut_ptr(),
456                self.start_idx as u32,
457                (self.end_idx - self.start_idx) as u32,
458            );
459        }
460    }
461}
462
463impl<'a> IntoIterator for &'a BufferListRef {
464    type IntoIter = Iter<'a>;
465    type Item = &'a BufferRef;
466
467    fn into_iter(self) -> Self::IntoIter {
468        self.iter()
469    }
470}
471
472impl From<Buffer> for BufferList {
473    fn from(value: Buffer) -> Self {
474        skip_assert_initialized!();
475
476        let mut list = BufferList::new_sized(1);
477        {
478            let list = list.get_mut().unwrap();
479            list.add(value);
480        }
481        list
482    }
483}
484
485impl<const N: usize> From<[Buffer; N]> for BufferList {
486    fn from(value: [Buffer; N]) -> Self {
487        skip_assert_initialized!();
488
489        let mut list = BufferList::new_sized(N);
490        {
491            let list = list.get_mut().unwrap();
492            value.into_iter().for_each(|b| list.add(b));
493        }
494        list
495    }
496}
497
498impl std::iter::FromIterator<Buffer> for BufferList {
499    fn from_iter<T: IntoIterator<Item = Buffer>>(iter: T) -> Self {
500        assert_initialized_main_thread!();
501
502        let iter = iter.into_iter();
503
504        let mut list = BufferList::new_sized(iter.size_hint().0);
505
506        {
507            let list = list.get_mut().unwrap();
508            iter.for_each(|b| list.add(b));
509        }
510
511        list
512    }
513}
514
515impl std::iter::Extend<Buffer> for BufferListRef {
516    fn extend<T: IntoIterator<Item = Buffer>>(&mut self, iter: T) {
517        iter.into_iter().for_each(|b| self.add(b));
518    }
519}
520
521#[cfg(test)]
522mod tests {
523    use super::*;
524    use crate::ClockTime;
525
526    fn make_buffer_list(size: usize) -> BufferList {
527        skip_assert_initialized!();
528
529        let mut buffer_list = BufferList::new();
530        {
531            let buffer_list = buffer_list.get_mut().unwrap();
532            for i in 0..size {
533                let mut buffer = Buffer::new();
534                buffer
535                    .get_mut()
536                    .unwrap()
537                    .set_pts(ClockTime::SECOND * i as u64);
538                buffer_list.add(buffer);
539            }
540        }
541        buffer_list
542    }
543
544    #[test]
545    fn test_foreach() {
546        crate::init().unwrap();
547
548        let buffer_list = make_buffer_list(2);
549
550        let mut res = vec![];
551        buffer_list.foreach(|buffer, idx| {
552            res.push((buffer.pts(), idx));
553            ControlFlow::Continue(())
554        });
555
556        assert_eq!(
557            res,
558            &[(Some(ClockTime::ZERO), 0), (Some(ClockTime::SECOND), 1)]
559        );
560    }
561
562    #[test]
563    fn test_foreach_mut() {
564        crate::init().unwrap();
565
566        let mut buffer_list = make_buffer_list(3);
567
568        let mut res = vec![];
569        buffer_list.get_mut().unwrap().foreach_mut(|buffer, idx| {
570            res.push((buffer.pts(), idx));
571
572            if let Some(ClockTime::ZERO) = buffer.pts() {
573                ControlFlow::Continue(Some(buffer))
574            } else if let Some(ClockTime::SECOND) = buffer.pts() {
575                ControlFlow::Continue(None)
576            } else {
577                let mut new_buffer = Buffer::new();
578                new_buffer.get_mut().unwrap().set_pts(3 * ClockTime::SECOND);
579                ControlFlow::Continue(Some(new_buffer))
580            }
581        });
582
583        assert_eq!(
584            res,
585            &[
586                (Some(ClockTime::ZERO), 0),
587                (Some(ClockTime::SECOND), 1),
588                (Some(2 * ClockTime::SECOND), 1)
589            ]
590        );
591
592        let mut res = vec![];
593        buffer_list.foreach(|buffer, idx| {
594            res.push((buffer.pts(), idx));
595            ControlFlow::Continue(())
596        });
597
598        assert_eq!(
599            res,
600            &[(Some(ClockTime::ZERO), 0), (Some(3 * ClockTime::SECOND), 1)]
601        );
602
603        // Try removing buffers from inside foreach_mut
604        let mut buffer_list = BufferList::new();
605        for i in 0..10 {
606            let buffer_list = buffer_list.get_mut().unwrap();
607            let mut buffer = Buffer::new();
608            buffer.get_mut().unwrap().set_pts(i * ClockTime::SECOND);
609            buffer_list.add(buffer);
610        }
611
612        assert_eq!(buffer_list.len(), 10);
613
614        let buffer_list_ref = buffer_list.make_mut();
615
616        buffer_list_ref.foreach_mut(|buf, _n| {
617            let keep_packet = !(buf.pts().unwrap() / ClockTime::SECOND).is_multiple_of(3);
618            ControlFlow::Continue(keep_packet.then_some(buf))
619        });
620
621        assert_eq!(buffer_list.len(), 6);
622
623        let res = buffer_list
624            .iter()
625            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
626            .collect::<Vec<_>>();
627
628        assert_eq!(res, &[1, 2, 4, 5, 7, 8]);
629    }
630
631    #[test]
632    fn test_remove() {
633        crate::init().unwrap();
634
635        let mut buffer_list = make_buffer_list(10);
636
637        buffer_list.make_mut().remove(0..2);
638
639        let buffers_left = buffer_list
640            .iter()
641            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
642            .collect::<Vec<_>>();
643
644        assert_eq!(buffers_left, &[2, 3, 4, 5, 6, 7, 8, 9]);
645
646        buffer_list.make_mut().remove(0..=2);
647
648        let buffers_left = buffer_list
649            .iter()
650            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
651            .collect::<Vec<_>>();
652
653        assert_eq!(buffers_left, &[5, 6, 7, 8, 9]);
654
655        buffer_list.make_mut().remove(2..);
656
657        let buffers_left = buffer_list
658            .iter()
659            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
660            .collect::<Vec<_>>();
661
662        assert_eq!(buffers_left, &[5, 6]);
663
664        buffer_list.make_mut().remove(..);
665
666        assert!(buffer_list.is_empty());
667    }
668
669    #[test]
670    fn test_drain() {
671        crate::init().unwrap();
672
673        let mut buffer_list = make_buffer_list(10);
674
675        let buffers_removed = buffer_list
676            .make_mut()
677            .drain(0..2)
678            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
679            .collect::<Vec<_>>();
680
681        assert_eq!(buffers_removed, &[0, 1]);
682
683        let buffers_left = buffer_list
684            .iter()
685            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
686            .collect::<Vec<_>>();
687
688        assert_eq!(buffers_left, &[2, 3, 4, 5, 6, 7, 8, 9]);
689
690        let buffers_removed = buffer_list
691            .make_mut()
692            .drain(0..=2)
693            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
694            .collect::<Vec<_>>();
695
696        assert_eq!(buffers_removed, &[2, 3, 4]);
697
698        let buffers_left = buffer_list
699            .iter()
700            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
701            .collect::<Vec<_>>();
702
703        assert_eq!(buffers_left, &[5, 6, 7, 8, 9]);
704
705        let buffers_removed = buffer_list
706            .make_mut()
707            .drain(2..)
708            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
709            .collect::<Vec<_>>();
710
711        assert_eq!(buffers_removed, &[7, 8, 9]);
712
713        let buffers_left = buffer_list
714            .iter()
715            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
716            .collect::<Vec<_>>();
717
718        assert_eq!(buffers_left, &[5, 6]);
719
720        let buffers_removed = buffer_list
721            .make_mut()
722            .drain(..)
723            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
724            .collect::<Vec<_>>();
725
726        assert_eq!(buffers_removed, &[5, 6]);
727
728        assert!(buffer_list.is_empty());
729    }
730
731    #[test]
732    fn test_drain_drop() {
733        crate::init().unwrap();
734
735        let mut buffer_list = make_buffer_list(10);
736
737        buffer_list.make_mut().drain(0..2);
738
739        let buffers_left = buffer_list
740            .iter()
741            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
742            .collect::<Vec<_>>();
743
744        assert_eq!(buffers_left, &[2, 3, 4, 5, 6, 7, 8, 9]);
745
746        buffer_list.make_mut().drain(0..=2);
747
748        let buffers_left = buffer_list
749            .iter()
750            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
751            .collect::<Vec<_>>();
752
753        assert_eq!(buffers_left, &[5, 6, 7, 8, 9]);
754
755        buffer_list.make_mut().drain(2..);
756
757        let buffers_left = buffer_list
758            .iter()
759            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
760            .collect::<Vec<_>>();
761
762        assert_eq!(buffers_left, &[5, 6]);
763
764        buffer_list.make_mut().drain(..);
765
766        assert!(buffer_list.is_empty());
767    }
768}