1use std::{iter::FusedIterator, marker::PhantomData, mem, ptr};
4
5use crate::{ffi, translate::*};
6
7#[repr(transparent)]
12pub struct SList<T: TransparentPtrType> {
13 ptr: Option<ptr::NonNull<ffi::GSList>>,
14 phantom: PhantomData<T>,
15}
16
17#[doc(hidden)]
18unsafe impl<T: TransparentPtrType> TransparentPtrType for SList<T> {}
19
20#[doc(hidden)]
21impl<T: TransparentPtrType> GlibPtrDefault for SList<T> {
22 type GlibType = *mut ffi::GSList;
23}
24
25unsafe impl<T: Send + TransparentPtrType> Send for SList<T> {}
26
27unsafe impl<T: Sync + TransparentPtrType> Sync for SList<T> {}
28
29impl<T: TransparentPtrType> SList<T> {
30 #[inline]
33 pub unsafe fn from_glib_none(list: *const ffi::GSList) -> SList<T> {
34 unsafe {
35 let list = if mem::needs_drop::<T>() {
37 unsafe extern "C" fn copy_item<T: TransparentPtrType>(
38 ptr: ffi::gconstpointer,
39 _user_data: ffi::gpointer,
40 ) -> ffi::gpointer {
41 unsafe {
42 let mut item = mem::ManuallyDrop::new(
43 (*(&ptr as *const ffi::gconstpointer as *const T)).clone(),
44 );
45
46 *(&mut *item as *mut T as *mut *mut T::GlibType) as ffi::gpointer
47 }
48 }
49
50 ffi::g_slist_copy_deep(mut_override(list), Some(copy_item::<T>), ptr::null_mut())
51 } else {
52 ffi::g_slist_copy(mut_override(list))
53 };
54
55 SList {
56 ptr: ptr::NonNull::new(list),
57 phantom: PhantomData,
58 }
59 }
60 }
61
62 #[inline]
65 pub unsafe fn from_glib_container(list: *mut ffi::GSList) -> SList<T> {
66 unsafe {
67 if mem::needs_drop::<T>() {
69 unsafe extern "C" fn copy_item<T: TransparentPtrType>(
70 ptr: ffi::gpointer,
71 _user_data: ffi::gpointer,
72 ) {
73 unsafe {
74 let item = (*(&ptr as *const ffi::gpointer as *const T)).clone();
75 ptr::write(ptr as *mut T, item);
76 }
77 }
78
79 ffi::g_slist_foreach(list, Some(copy_item::<T>), ptr::null_mut());
80 }
81
82 SList {
83 ptr: ptr::NonNull::new(list),
84 phantom: PhantomData,
85 }
86 }
87 }
88
89 #[inline]
92 pub unsafe fn from_glib_full(list: *mut ffi::GSList) -> SList<T> {
93 SList {
94 ptr: ptr::NonNull::new(list),
95 phantom: PhantomData,
96 }
97 }
98
99 #[inline]
102 pub fn new() -> Self {
103 SList {
104 ptr: None,
105 phantom: PhantomData,
106 }
107 }
108
109 #[inline]
112 pub fn iter(&self) -> Iter<'_, T> {
113 Iter::new(self)
114 }
115
116 #[inline]
119 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
120 IterMut::new(self)
121 }
122
123 #[inline]
128 pub fn is_empty(&self) -> bool {
129 self.ptr.is_none()
130 }
131
132 #[inline]
137 #[doc(alias = "g_slist_length")]
138 pub fn len(&self) -> usize {
139 self.iter().count()
140 }
141
142 #[inline]
147 #[doc(alias = "g_slist_first")]
148 pub fn front(&self) -> Option<&T> {
149 match self.ptr {
150 None => None,
151 Some(cur) => unsafe {
152 let item = &*(&cur.as_ref().data as *const ffi::gpointer as *const T);
153 Some(item)
154 },
155 }
156 }
157
158 #[inline]
163 #[doc(alias = "g_slist_first")]
164 pub fn front_mut(&mut self) -> Option<&mut T> {
165 match self.ptr {
166 None => None,
167 Some(mut cur) => unsafe {
168 let item = &mut *(&mut cur.as_mut().data as *mut ffi::gpointer as *mut T);
169 Some(item)
170 },
171 }
172 }
173
174 #[inline]
179 pub fn pop_front(&mut self) -> Option<T> {
180 match self.ptr {
181 None => None,
182 Some(mut cur) => unsafe {
183 self.ptr = ptr::NonNull::new(cur.as_ref().next);
184 let item = ptr::read(&mut cur.as_mut().data as *mut ffi::gpointer as *mut T);
185 ffi::g_slist_free_1(cur.as_ptr());
186
187 Some(item)
188 },
189 }
190 }
191
192 #[inline]
197 #[doc(alias = "g_slist_prepend")]
198 pub fn push_front(&mut self, item: T) {
199 unsafe {
200 let ptr = self.ptr.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut());
201 self.ptr = Some(ptr::NonNull::new_unchecked(ffi::g_slist_prepend(
202 ptr,
203 *(&mut *mem::ManuallyDrop::new(item) as *mut T as *mut *mut T::GlibType)
204 as ffi::gpointer,
205 )));
206 }
207 }
208
209 #[inline]
214 #[doc(alias = "g_slist_last")]
215 pub fn back(&self) -> Option<&T> {
216 unsafe {
217 let ptr = self.ptr?.as_ptr();
218 let last_ptr = ffi::g_slist_last(ptr);
219 let item = &*(&(*last_ptr).data as *const ffi::gpointer as *const T);
220 Some(item)
221 }
222 }
223
224 #[inline]
229 #[doc(alias = "g_slist_last")]
230 pub fn back_mut(&mut self) -> Option<&mut T> {
231 unsafe {
232 let ptr = self.ptr?.as_ptr();
233 let last_ptr = ffi::g_slist_last(ptr);
234 let item = &mut *(&mut (*last_ptr).data as *mut ffi::gpointer as *mut T);
235 Some(item)
236 }
237 }
238
239 #[inline]
244 pub fn pop_back(&mut self) -> Option<T> {
245 unsafe {
246 let ptr = self.ptr?.as_ptr();
247 let last_ptr = ffi::g_slist_last(ptr);
248 let item = ptr::read(&mut (*last_ptr).data as *mut ffi::gpointer as *mut T);
249 self.ptr = ptr::NonNull::new(ffi::g_slist_delete_link(ptr, last_ptr));
250
251 Some(item)
252 }
253 }
254
255 #[inline]
260 #[doc(alias = "g_slist_append")]
261 pub fn push_back(&mut self, item: T) {
262 unsafe {
263 let ptr = self.ptr.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut());
264 self.ptr = Some(ptr::NonNull::new_unchecked(ffi::g_slist_append(
265 ptr,
266 *(&mut *mem::ManuallyDrop::new(item) as *mut T as *mut *mut T::GlibType)
267 as ffi::gpointer,
268 )));
269 }
270 }
271
272 #[inline]
277 #[doc(alias = "g_slist_reverse")]
278 pub fn reverse(&mut self) {
279 unsafe {
280 let ptr = match self.ptr {
281 None => return,
282 Some(ptr) => ptr.as_ptr(),
283 };
284
285 self.ptr = Some(ptr::NonNull::new_unchecked(ffi::g_slist_reverse(ptr)));
286 }
287 }
288
289 #[inline]
294 #[doc(alias = "g_slist_sort")]
295 pub fn sort(&mut self)
296 where
297 T: Ord,
298 {
299 self.sort_by(|a, b| a.cmp(b));
300 }
301
302 #[inline]
307 #[doc(alias = "g_slist_sort")]
308 pub fn sort_by<F: FnMut(&T, &T) -> std::cmp::Ordering>(&mut self, mut f: F) {
309 unsafe {
310 let ptr = match self.ptr {
311 None => return,
312 Some(ptr) => ptr.as_ptr(),
313 };
314
315 unsafe extern "C" fn func<
316 T: TransparentPtrType,
317 F: FnMut(&T, &T) -> std::cmp::Ordering,
318 >(
319 a: ffi::gconstpointer,
320 b: ffi::gconstpointer,
321 user_data: ffi::gpointer,
322 ) -> i32 {
323 unsafe {
324 let f = &mut *(user_data as *mut F);
325 let a = &*(&a as *const ffi::gconstpointer as *const T);
326 let b = &*(&b as *const ffi::gconstpointer as *const T);
327 f(a, b).into_glib()
328 }
329 }
330
331 self.ptr = Some(ptr::NonNull::new_unchecked(ffi::g_slist_sort_with_data(
332 ptr,
333 Some(func::<T, F>),
334 &mut f as *mut F as ffi::gpointer,
335 )));
336 }
337 }
338
339 #[inline]
342 pub fn clear(&mut self) {
343 *self = Self::new();
344 }
345
346 #[inline]
349 pub fn retain(&mut self, mut f: impl FnMut(&T) -> bool) {
350 let mut head = self.ptr.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut());
351 unsafe {
352 let mut ptr = head;
353 while !ptr.is_null() {
354 let item = &*(&(*ptr).data as *const ffi::gpointer as *const T);
355 let next = (*ptr).next;
356 if !f(item) {
357 let mut item_ptr = (*ptr).data;
358 head = ffi::g_slist_delete_link(head, ptr);
359 self.ptr = ptr::NonNull::new(head);
360 ptr::drop_in_place(&mut item_ptr as *mut ffi::gpointer as *mut T);
361 }
362 ptr = next;
363 }
364 }
365 }
366
367 #[inline]
370 pub fn as_ptr(&self) -> *const ffi::GSList {
371 self.ptr.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut())
372 }
373
374 #[inline]
377 pub fn as_mut_ptr(&mut self) -> *mut ffi::GSList {
378 self.ptr.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut())
379 }
380
381 #[inline]
384 pub fn into_raw(mut self) -> *mut ffi::GSList {
385 self.ptr
386 .take()
387 .map(|p| p.as_ptr())
388 .unwrap_or(ptr::null_mut())
389 }
390}
391
392impl<T: TransparentPtrType> Default for SList<T> {
393 fn default() -> Self {
394 Self::new()
395 }
396}
397
398impl<T: TransparentPtrType> Clone for SList<T> {
399 fn clone(&self) -> Self {
400 unsafe { Self::from_glib_none(self.ptr.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut())) }
401 }
402}
403
404impl<T: TransparentPtrType> Drop for SList<T> {
405 #[inline]
406 fn drop(&mut self) {
407 if let Some(ptr) = self.ptr.take() {
408 unsafe {
409 if mem::needs_drop::<T>() {
410 unsafe extern "C" fn drop_item<T: TransparentPtrType>(mut ptr: ffi::gpointer) {
411 unsafe {
412 ptr::drop_in_place(&mut ptr as *mut ffi::gpointer as *mut T);
413 }
414 }
415
416 ffi::g_slist_free_full(ptr.as_ptr(), Some(drop_item::<T>));
417 } else {
418 ffi::g_slist_free(ptr.as_ptr());
419 }
420 }
421 }
422 }
423}
424
425impl<T: TransparentPtrType> std::iter::FromIterator<T> for SList<T> {
426 #[inline]
427 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
428 unsafe {
429 let mut iter = iter.into_iter();
430
431 let first = match iter.next() {
432 None => return Self::new(),
433 Some(first) => first,
434 };
435
436 let list = ffi::g_slist_prepend(
437 ptr::null_mut(),
438 *(&mut *mem::ManuallyDrop::new(first) as *mut T as *mut *mut T::GlibType)
439 as ffi::gpointer,
440 );
441 let mut tail = list;
442 for item in iter {
443 let new_tail = ffi::g_slist_alloc();
444
445 (*new_tail).data = *(&mut *mem::ManuallyDrop::new(item) as *mut T
446 as *mut *mut T::GlibType) as ffi::gpointer;
447 (*new_tail).next = ptr::null_mut();
448 (*tail).next = new_tail;
449 tail = new_tail;
450 }
451
452 Self::from_glib_full(list)
453 }
454 }
455}
456
457impl<'a, T: TransparentPtrType> std::iter::IntoIterator for &'a SList<T> {
458 type Item = &'a T;
459 type IntoIter = Iter<'a, T>;
460
461 #[inline]
462 fn into_iter(self) -> Self::IntoIter {
463 self.iter()
464 }
465}
466
467impl<'a, T: TransparentPtrType> std::iter::IntoIterator for &'a mut SList<T> {
468 type Item = &'a mut T;
469 type IntoIter = IterMut<'a, T>;
470
471 #[inline]
472 fn into_iter(self) -> Self::IntoIter {
473 self.iter_mut()
474 }
475}
476
477impl<T: TransparentPtrType> std::iter::IntoIterator for SList<T> {
478 type Item = T;
479 type IntoIter = IntoIter<T>;
480
481 #[inline]
482 fn into_iter(self) -> Self::IntoIter {
483 IntoIter::new(self)
484 }
485}
486
487impl<T: TransparentPtrType> std::iter::Extend<T> for SList<T> {
488 #[inline]
489 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
490 let list = iter.into_iter().collect::<Self>();
491 if list.is_empty() {
492 return;
493 }
494 match self.ptr.map(|p| p.as_ptr()) {
495 Some(ptr1) => {
496 let ptr2 = list.into_raw();
497 let _ = unsafe { ffi::g_slist_concat(ptr1, ptr2) };
498 }
499 None => {
500 self.ptr = ptr::NonNull::new(list.into_raw());
501 }
502 }
503 }
504}
505
506impl<T: TransparentPtrType> FromGlibContainer<<T as GlibPtrDefault>::GlibType, *mut ffi::GSList>
507 for SList<T>
508{
509 #[inline]
510 unsafe fn from_glib_none_num(ptr: *mut ffi::GSList, _num: usize) -> Self {
511 unsafe { Self::from_glib_none(ptr) }
512 }
513
514 #[inline]
515 unsafe fn from_glib_container_num(ptr: *mut ffi::GSList, _num: usize) -> Self {
516 unsafe { Self::from_glib_container(ptr) }
517 }
518
519 #[inline]
520 unsafe fn from_glib_full_num(ptr: *mut ffi::GSList, _num: usize) -> Self {
521 unsafe { Self::from_glib_full(ptr) }
522 }
523}
524
525impl<T: TransparentPtrType> FromGlibContainer<<T as GlibPtrDefault>::GlibType, *const ffi::GSList>
526 for SList<T>
527{
528 #[inline]
529 unsafe fn from_glib_none_num(ptr: *const ffi::GSList, _num: usize) -> Self {
530 unsafe { Self::from_glib_none(ptr) }
531 }
532
533 unsafe fn from_glib_container_num(_ptr: *const ffi::GSList, _num: usize) -> Self {
534 unimplemented!();
535 }
536
537 unsafe fn from_glib_full_num(_ptr: *const ffi::GSList, _num: usize) -> Self {
538 unimplemented!();
539 }
540}
541
542impl<T: TransparentPtrType> FromGlibPtrContainer<<T as GlibPtrDefault>::GlibType, *mut ffi::GSList>
543 for SList<T>
544{
545 #[inline]
546 unsafe fn from_glib_none(ptr: *mut ffi::GSList) -> Self {
547 unsafe { Self::from_glib_none(ptr) }
548 }
549
550 #[inline]
551 unsafe fn from_glib_container(ptr: *mut ffi::GSList) -> Self {
552 unsafe { Self::from_glib_container(ptr) }
553 }
554
555 #[inline]
556 unsafe fn from_glib_full(ptr: *mut ffi::GSList) -> Self {
557 unsafe { Self::from_glib_full(ptr) }
558 }
559}
560
561impl<T: TransparentPtrType>
562 FromGlibPtrContainer<<T as GlibPtrDefault>::GlibType, *const ffi::GSList> for SList<T>
563{
564 #[inline]
565 unsafe fn from_glib_none(ptr: *const ffi::GSList) -> Self {
566 unsafe { Self::from_glib_none(ptr) }
567 }
568
569 unsafe fn from_glib_container(_ptr: *const ffi::GSList) -> Self {
570 unimplemented!();
571 }
572
573 unsafe fn from_glib_full(_ptr: *const ffi::GSList) -> Self {
574 unimplemented!();
575 }
576}
577
578impl<'a, T: TransparentPtrType + 'a> ToGlibPtr<'a, *mut ffi::GSList> for SList<T> {
579 type Storage = PhantomData<&'a Self>;
580
581 #[inline]
582 fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::GSList, Self> {
583 Stash(self.as_ptr() as *mut _, PhantomData)
584 }
585
586 #[inline]
587 fn to_glib_container(&'a self) -> Stash<'a, *mut ffi::GSList, Self> {
588 unsafe {
589 let ptr = ffi::g_malloc(mem::size_of::<T>().checked_mul(self.len() + 1).unwrap())
590 as *mut ffi::GSList;
591 ptr::copy_nonoverlapping(self.as_ptr(), ptr, self.len() + 1);
592 Stash(ptr, PhantomData)
593 }
594 }
595
596 #[inline]
597 fn to_glib_full(&self) -> *mut ffi::GSList {
598 self.clone().into_raw()
599 }
600}
601
602impl<'a, T: TransparentPtrType + 'a> ToGlibPtr<'a, *const ffi::GSList> for SList<T> {
603 type Storage = PhantomData<&'a Self>;
604
605 #[inline]
606 fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GSList, Self> {
607 Stash(self.as_ptr(), PhantomData)
608 }
609}
610
611impl<'a, T: TransparentPtrType + 'a> ToGlibPtrMut<'a, *mut ffi::GSList> for SList<T> {
612 type Storage = PhantomData<&'a mut Self>;
613
614 #[inline]
615 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::GSList, Self> {
616 StashMut(self.as_mut_ptr(), PhantomData)
617 }
618}
619
620impl<T: TransparentPtrType> IntoGlibPtr<*mut ffi::GSList> for SList<T> {
621 #[inline]
622 fn into_glib_ptr(self) -> *mut ffi::GSList {
623 self.into_raw()
624 }
625}
626
627pub struct Iter<'a, T: TransparentPtrType> {
630 ptr: Option<ptr::NonNull<ffi::GSList>>,
631 phantom: PhantomData<&'a T>,
632}
633
634impl<'a, T: TransparentPtrType> Iter<'a, T> {
635 #[inline]
636 fn new(list: &'a SList<T>) -> Iter<'a, T> {
637 debug_assert_eq!(
638 mem::size_of::<T>(),
639 mem::size_of::<<T as GlibPtrDefault>::GlibType>()
640 );
641
642 Iter {
643 ptr: list.ptr,
644 phantom: PhantomData,
645 }
646 }
647}
648
649impl<'a, T: TransparentPtrType> Iterator for Iter<'a, T> {
650 type Item = &'a T;
651
652 #[inline]
653 fn next(&mut self) -> Option<&'a T> {
654 match self.ptr {
655 None => None,
656 Some(cur) => unsafe {
657 self.ptr = ptr::NonNull::new(cur.as_ref().next);
658
659 let item = &*(&cur.as_ref().data as *const ffi::gpointer as *const T);
660
661 Some(item)
662 },
663 }
664 }
665}
666
667impl<T: TransparentPtrType> FusedIterator for Iter<'_, T> {}
668
669pub struct IterMut<'a, T: TransparentPtrType> {
672 ptr: Option<ptr::NonNull<ffi::GSList>>,
673 phantom: PhantomData<&'a mut T>,
674}
675
676impl<'a, T: TransparentPtrType> IterMut<'a, T> {
677 #[inline]
678 fn new(list: &'a mut SList<T>) -> IterMut<'a, T> {
679 debug_assert_eq!(
680 mem::size_of::<T>(),
681 mem::size_of::<<T as GlibPtrDefault>::GlibType>()
682 );
683
684 IterMut {
685 ptr: list.ptr,
686 phantom: PhantomData,
687 }
688 }
689}
690
691impl<'a, T: TransparentPtrType> Iterator for IterMut<'a, T> {
692 type Item = &'a mut T;
693
694 #[inline]
695 fn next(&mut self) -> Option<&'a mut T> {
696 match self.ptr {
697 None => None,
698 Some(mut cur) => unsafe {
699 self.ptr = ptr::NonNull::new(cur.as_ref().next);
700
701 let item = &mut *(&mut cur.as_mut().data as *mut ffi::gpointer as *mut T);
702
703 Some(item)
704 },
705 }
706 }
707}
708
709impl<T: TransparentPtrType> FusedIterator for IterMut<'_, T> {}
710
711pub struct IntoIter<T: TransparentPtrType> {
714 list: SList<T>,
715}
716
717impl<T: TransparentPtrType> IntoIter<T> {
718 #[inline]
719 fn new(list: SList<T>) -> IntoIter<T> {
720 debug_assert_eq!(
721 mem::size_of::<T>(),
722 mem::size_of::<<T as GlibPtrDefault>::GlibType>()
723 );
724
725 IntoIter { list }
726 }
727}
728
729impl<T: TransparentPtrType> Iterator for IntoIter<T> {
730 type Item = T;
731
732 #[inline]
733 fn next(&mut self) -> Option<T> {
734 self.list.pop_front()
735 }
736}
737
738impl<T: TransparentPtrType> FusedIterator for IntoIter<T> {}
739
740#[cfg(test)]
741mod test {
742 use super::*;
743
744 #[test]
745 fn from_glib_full() {
747 let items = [
748 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 12.0).unwrap(),
749 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 13.0).unwrap(),
750 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 14.0).unwrap(),
751 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 15.0).unwrap(),
752 ];
753 let mut list = unsafe {
754 let mut list = ffi::g_slist_append(
755 ptr::null_mut(),
756 ToGlibPtr::<*mut ffi::GDateTime>::to_glib_full(&items[0]) as ffi::gpointer,
757 );
758 list = ffi::g_slist_append(
759 list,
760 ToGlibPtr::<*mut ffi::GDateTime>::to_glib_full(&items[1]) as ffi::gpointer,
761 );
762 list = ffi::g_slist_append(
763 list,
764 ToGlibPtr::<*mut ffi::GDateTime>::to_glib_full(&items[2]) as ffi::gpointer,
765 );
766 list = ffi::g_slist_append(
767 list,
768 ToGlibPtr::<*mut ffi::GDateTime>::to_glib_full(&items[3]) as ffi::gpointer,
769 );
770 SList::<crate::DateTime>::from_glib_full(list)
771 };
772 assert!(!list.is_empty());
773
774 let list_items = list.iter().cloned().collect::<Vec<_>>();
775 assert_eq!(&items[..], &list_items);
776
777 let list_items = list.iter_mut().map(|d| d.clone()).collect::<Vec<_>>();
778 assert_eq!(&items[..], &list_items);
779
780 let list_items = list.into_iter().collect::<Vec<_>>();
781 assert_eq!(&items[..], &list_items);
782
783 let list = unsafe { SList::<crate::DateTime>::from_glib_full(ptr::null_mut()) };
784 assert!(list.is_empty());
785 }
786
787 #[test]
788 fn from_glib_container() {
790 let items = [
791 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 12.0).unwrap(),
792 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 13.0).unwrap(),
793 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 14.0).unwrap(),
794 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 15.0).unwrap(),
795 ];
796 let mut list = unsafe {
797 let mut list = ffi::g_slist_append(
798 ptr::null_mut(),
799 ToGlibPtr::<*mut ffi::GDateTime>::to_glib_none(&items[0]).0 as ffi::gpointer,
800 );
801 list = ffi::g_slist_append(
802 list,
803 ToGlibPtr::<*mut ffi::GDateTime>::to_glib_none(&items[1]).0 as ffi::gpointer,
804 );
805 list = ffi::g_slist_append(
806 list,
807 ToGlibPtr::<*mut ffi::GDateTime>::to_glib_none(&items[2]).0 as ffi::gpointer,
808 );
809 list = ffi::g_slist_append(
810 list,
811 ToGlibPtr::<*mut ffi::GDateTime>::to_glib_none(&items[3]).0 as ffi::gpointer,
812 );
813 SList::<crate::DateTime>::from_glib_container(list)
814 };
815 assert!(!list.is_empty());
816
817 let list_items = list.iter().cloned().collect::<Vec<_>>();
818 assert_eq!(&items[..], &list_items);
819
820 let list_items = list.iter_mut().map(|d| d.clone()).collect::<Vec<_>>();
821 assert_eq!(&items[..], &list_items);
822
823 let list_items = list.into_iter().collect::<Vec<_>>();
824 assert_eq!(&items[..], &list_items);
825
826 let list = unsafe { SList::<crate::DateTime>::from_glib_full(ptr::null_mut()) };
827 assert!(list.is_empty());
828 }
829
830 #[test]
831 fn from_glib_none() {
833 let items = [
834 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 12.0).unwrap(),
835 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 13.0).unwrap(),
836 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 14.0).unwrap(),
837 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 15.0).unwrap(),
838 ];
839 let mut list = unsafe {
840 let mut list = ffi::g_slist_append(
841 ptr::null_mut(),
842 ToGlibPtr::<*mut ffi::GDateTime>::to_glib_none(&items[0]).0 as ffi::gpointer,
843 );
844 list = ffi::g_slist_append(
845 list,
846 ToGlibPtr::<*mut ffi::GDateTime>::to_glib_none(&items[1]).0 as ffi::gpointer,
847 );
848 list = ffi::g_slist_append(
849 list,
850 ToGlibPtr::<*mut ffi::GDateTime>::to_glib_none(&items[2]).0 as ffi::gpointer,
851 );
852 list = ffi::g_slist_append(
853 list,
854 ToGlibPtr::<*mut ffi::GDateTime>::to_glib_none(&items[3]).0 as ffi::gpointer,
855 );
856 let res = SList::<crate::DateTime>::from_glib_none(list);
857 ffi::g_slist_free(list);
858 res
859 };
860 assert!(!list.is_empty());
861
862 let list_items = list.iter().cloned().collect::<Vec<_>>();
863 assert_eq!(&items[..], &list_items);
864
865 let list_items = list.iter_mut().map(|d| d.clone()).collect::<Vec<_>>();
866 assert_eq!(&items[..], &list_items);
867
868 let list_items = list.into_iter().collect::<Vec<_>>();
869 assert_eq!(&items[..], &list_items);
870
871 let list = unsafe { SList::<crate::DateTime>::from_glib_full(ptr::null_mut()) };
872 assert!(list.is_empty());
873 }
874
875 #[test]
876 fn safe_api() {
878 let items = [
879 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 12.0).unwrap(),
880 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 13.0).unwrap(),
881 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 14.0).unwrap(),
882 crate::DateTime::from_utc(2021, 11, 20, 23, 41, 15.0).unwrap(),
883 ];
884
885 let mut list = items[1..3].iter().cloned().collect::<SList<_>>();
886 assert_eq!(list.len(), 2);
887 list.push_front(items[0].clone());
888 assert_eq!(list.len(), 3);
889 list.push_back(items[3].clone());
890 assert_eq!(list.len(), 4);
891
892 let list_items = list.iter().cloned().collect::<Vec<_>>();
893 assert_eq!(&items[..], &list_items);
894
895 assert_eq!(list.front(), Some(&items[0]));
896 assert_eq!(list.back(), Some(&items[3]));
897 assert_eq!(list.pop_front().as_ref(), Some(&items[0]));
898 assert_eq!(list.len(), 3);
899
900 list.reverse();
901 let mut list_items = list.iter().cloned().collect::<Vec<_>>();
902 list_items.reverse();
903 assert_eq!(&items[1..], &list_items);
904
905 let list2 = list.clone();
906 let mut list_items = list2.iter().cloned().collect::<Vec<_>>();
907 list_items.reverse();
908 assert_eq!(&items[1..], &list_items);
909
910 list.reverse();
911 let mut list3 = list.clone();
912 list3.retain(|item| item.seconds() >= 14.0);
913 let list_items = list3.iter().cloned().collect::<Vec<_>>();
914 assert_eq!(&items[2..], &list_items);
915 }
916
917 #[test]
918 fn extend() {
919 let mut list = SList::<crate::DateTime>::new();
920 list.push_back(crate::DateTime::from_unix_utc(11).unwrap());
921 list.push_back(crate::DateTime::from_unix_utc(12).unwrap());
922 list.push_back(crate::DateTime::from_unix_utc(13).unwrap());
923
924 list.extend(vec![
925 crate::DateTime::from_unix_utc(21).unwrap(),
926 crate::DateTime::from_unix_utc(22).unwrap(),
927 ]);
928
929 assert_eq!(
930 list.iter().map(|dt| dt.to_unix()).collect::<Vec<_>>(),
931 vec![11, 12, 13, 21, 22]
932 );
933 }
934
935 #[test]
936 fn extend_empty_with_empty() {
937 let mut list1 = SList::<crate::DateTime>::new();
938 list1.extend(vec![]);
939 assert!(list1.is_empty());
940 }
941
942 #[test]
943 fn extend_with_empty() {
944 let mut list = SList::<crate::DateTime>::new();
945 list.push_back(crate::DateTime::from_unix_utc(11).unwrap());
946 list.push_back(crate::DateTime::from_unix_utc(12).unwrap());
947 list.push_back(crate::DateTime::from_unix_utc(13).unwrap());
948
949 list.extend(vec![]);
950
951 assert_eq!(
952 list.iter().map(|dt| dt.to_unix()).collect::<Vec<_>>(),
953 vec![11, 12, 13]
954 );
955 }
956
957 #[test]
958 fn extend_empty() {
959 let mut list = SList::<crate::DateTime>::new();
960
961 list.extend(vec![
962 crate::DateTime::from_unix_utc(21).unwrap(),
963 crate::DateTime::from_unix_utc(22).unwrap(),
964 ]);
965
966 assert_eq!(
967 list.iter().map(|dt| dt.to_unix()).collect::<Vec<_>>(),
968 vec![21, 22]
969 );
970 }
971
972 #[test]
973 fn retain_deletes_head() {
974 let mut list = SList::<crate::DateTime>::new();
975 let items = [
976 crate::DateTime::from_unix_utc(1).unwrap(),
977 crate::DateTime::from_unix_utc(2).unwrap(),
978 crate::DateTime::from_unix_utc(3).unwrap(),
979 ];
980 for item in &items {
981 list.push_back(item.clone());
982 }
983 assert_eq!(list.len(), 3);
984
985 list.retain(|item| item.to_unix() >= 3);
987
988 assert_eq!(list.len(), 1);
989 assert_eq!(list.pop_front().unwrap().to_unix(), 3);
990 }
991}