glib/collections/
slice.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{fmt, marker::PhantomData, mem, ptr};
4
5use crate::{ffi, translate::*};
6
7// rustdoc-stripper-ignore-next
8/// Minimum size of the `Slice` allocation in bytes.
9const MIN_SIZE: usize = 256;
10
11// rustdoc-stripper-ignore-next
12/// Slice of elements of type `T` allocated by the GLib allocator.
13///
14/// This can be used like a `&[T]`, `&mut [T]` and `Vec<T>`.
15pub struct Slice<T: TransparentType> {
16    ptr: ptr::NonNull<T::GlibType>,
17    len: usize,
18    capacity: usize,
19}
20
21unsafe impl<T: TransparentType + Send> Send for Slice<T> {}
22
23unsafe impl<T: TransparentType + Sync> Sync for Slice<T> {}
24
25impl<T: fmt::Debug + TransparentType> fmt::Debug for Slice<T> {
26    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        self.as_slice().fmt(f)
28    }
29}
30
31impl<T: PartialEq + TransparentType> PartialEq for Slice<T> {
32    #[inline]
33    fn eq(&self, other: &Self) -> bool {
34        self.as_slice() == other.as_slice()
35    }
36}
37
38impl<T: Eq + TransparentType> Eq for Slice<T> {}
39
40impl<T: PartialOrd + TransparentType> PartialOrd for Slice<T> {
41    #[inline]
42    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
43        self.as_slice().partial_cmp(other.as_slice())
44    }
45}
46
47impl<T: Ord + TransparentType> Ord for Slice<T> {
48    #[inline]
49    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
50        self.as_slice().cmp(other.as_slice())
51    }
52}
53
54impl<T: std::hash::Hash + TransparentType> std::hash::Hash for Slice<T> {
55    #[inline]
56    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
57        self.as_slice().hash(state)
58    }
59}
60
61impl<T: PartialEq + TransparentType> PartialEq<[T]> for Slice<T> {
62    #[inline]
63    fn eq(&self, other: &[T]) -> bool {
64        self.as_slice() == other
65    }
66}
67
68impl<T: PartialEq + TransparentType> PartialEq<Slice<T>> for [T] {
69    #[inline]
70    fn eq(&self, other: &Slice<T>) -> bool {
71        self == other.as_slice()
72    }
73}
74
75impl<T: TransparentType> Drop for Slice<T> {
76    #[inline]
77    fn drop(&mut self) {
78        unsafe {
79            if mem::needs_drop::<T>() {
80                for i in 0..self.len {
81                    ptr::drop_in_place::<T>(self.ptr.as_ptr().add(i) as *mut T);
82                }
83            }
84
85            if self.capacity != 0 {
86                ffi::g_free(self.ptr.as_ptr() as ffi::gpointer);
87            }
88        }
89    }
90}
91
92impl<T: TransparentType> AsRef<[T]> for Slice<T> {
93    #[inline]
94    fn as_ref(&self) -> &[T] {
95        self.as_slice()
96    }
97}
98
99impl<T: TransparentType> AsMut<[T]> for Slice<T> {
100    #[inline]
101    fn as_mut(&mut self) -> &mut [T] {
102        self.as_mut_slice()
103    }
104}
105
106impl<T: TransparentType> std::borrow::Borrow<[T]> for Slice<T> {
107    #[inline]
108    fn borrow(&self) -> &[T] {
109        self.as_slice()
110    }
111}
112
113impl<T: TransparentType> std::borrow::BorrowMut<[T]> for Slice<T> {
114    #[inline]
115    fn borrow_mut(&mut self) -> &mut [T] {
116        self.as_mut_slice()
117    }
118}
119
120impl<T: TransparentType> std::ops::Deref for Slice<T> {
121    type Target = [T];
122
123    #[inline]
124    fn deref(&self) -> &[T] {
125        self.as_slice()
126    }
127}
128
129impl<T: TransparentType> std::ops::DerefMut for Slice<T> {
130    #[inline]
131    fn deref_mut(&mut self) -> &mut [T] {
132        self.as_mut_slice()
133    }
134}
135
136impl<T: TransparentType> Default for Slice<T> {
137    #[inline]
138    fn default() -> Self {
139        Self::new()
140    }
141}
142
143impl<T: TransparentType> std::iter::Extend<T> for Slice<T> {
144    #[inline]
145    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
146        let iter = iter.into_iter();
147        self.reserve(iter.size_hint().0);
148
149        for item in iter {
150            self.push(item);
151        }
152    }
153}
154
155impl<'a, T: TransparentType + 'a> std::iter::Extend<&'a T> for Slice<T> {
156    #[inline]
157    fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
158        let iter = iter.into_iter();
159        self.reserve(iter.size_hint().0);
160
161        for item in iter {
162            self.push(item.clone());
163        }
164    }
165}
166
167impl<T: TransparentType> std::iter::FromIterator<T> for Slice<T> {
168    #[inline]
169    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
170        let iter = iter.into_iter();
171        let mut s = Self::with_capacity(iter.size_hint().0);
172        for item in iter {
173            s.push(item);
174        }
175        s
176    }
177}
178
179impl<'a, T: TransparentType> std::iter::IntoIterator for &'a Slice<T> {
180    type Item = &'a T;
181    type IntoIter = std::slice::Iter<'a, T>;
182
183    #[inline]
184    fn into_iter(self) -> Self::IntoIter {
185        self.as_slice().iter()
186    }
187}
188
189impl<'a, T: TransparentType> std::iter::IntoIterator for &'a mut Slice<T> {
190    type Item = &'a mut T;
191    type IntoIter = std::slice::IterMut<'a, T>;
192
193    #[inline]
194    fn into_iter(self) -> Self::IntoIter {
195        self.as_mut_slice().iter_mut()
196    }
197}
198
199impl<T: TransparentType> std::iter::IntoIterator for Slice<T> {
200    type Item = T;
201    type IntoIter = IntoIter<T>;
202
203    #[inline]
204    fn into_iter(self) -> Self::IntoIter {
205        IntoIter::new(self)
206    }
207}
208
209pub struct IntoIter<T: TransparentType> {
210    ptr: ptr::NonNull<T::GlibType>,
211    idx: ptr::NonNull<T::GlibType>,
212    len: usize,
213    empty: bool,
214}
215
216impl<T: TransparentType> IntoIter<T> {
217    #[inline]
218    fn new(slice: Slice<T>) -> Self {
219        let slice = mem::ManuallyDrop::new(slice);
220        IntoIter {
221            ptr: slice.ptr,
222            idx: slice.ptr,
223            len: slice.len,
224            empty: slice.capacity == 0,
225        }
226    }
227
228    // rustdoc-stripper-ignore-next
229    /// Returns the remaining items as slice.
230    #[inline]
231    pub fn as_slice(&self) -> &[T] {
232        unsafe {
233            if self.len == 0 {
234                &[]
235            } else {
236                std::slice::from_raw_parts(self.idx.as_ptr() as *mut T, self.len)
237            }
238        }
239    }
240
241    // rustdoc-stripper-ignore-next
242    /// Returns the remaining items as mutable slice.
243    #[inline]
244    pub fn as_mut_slice(&mut self) -> &mut [T] {
245        unsafe {
246            if self.len == 0 {
247                &mut []
248            } else {
249                std::slice::from_raw_parts_mut(self.idx.as_ptr() as *mut T, self.len)
250            }
251        }
252    }
253}
254
255impl<T: TransparentType> Drop for IntoIter<T> {
256    #[inline]
257    fn drop(&mut self) {
258        unsafe {
259            if mem::needs_drop::<T>() {
260                for i in 0..self.len {
261                    ptr::drop_in_place::<T>(self.idx.as_ptr().add(i) as *mut T);
262                }
263            }
264
265            if !self.empty {
266                ffi::g_free(self.ptr.as_ptr() as ffi::gpointer);
267            }
268        }
269    }
270}
271
272impl<T: TransparentType> Iterator for IntoIter<T> {
273    type Item = T;
274
275    #[inline]
276    fn next(&mut self) -> Option<Self::Item> {
277        if self.len == 0 {
278            return None;
279        }
280
281        unsafe {
282            let p = self.idx.as_ptr();
283            self.len -= 1;
284            self.idx = ptr::NonNull::new_unchecked(p.add(1));
285            Some(ptr::read(p as *mut T))
286        }
287    }
288
289    #[inline]
290    fn size_hint(&self) -> (usize, Option<usize>) {
291        (self.len, Some(self.len))
292    }
293
294    #[inline]
295    fn count(self) -> usize {
296        self.len
297    }
298
299    #[inline]
300    fn last(mut self) -> Option<T> {
301        if self.len == 0 {
302            None
303        } else {
304            self.len -= 1;
305            Some(unsafe { ptr::read(self.idx.as_ptr().add(self.len) as *mut T) })
306        }
307    }
308}
309
310impl<T: TransparentType> DoubleEndedIterator for IntoIter<T> {
311    #[inline]
312    fn next_back(&mut self) -> Option<T> {
313        if self.len == 0 {
314            None
315        } else {
316            self.len -= 1;
317            Some(unsafe { ptr::read(self.idx.as_ptr().add(self.len) as *mut T) })
318        }
319    }
320}
321
322impl<T: TransparentType> ExactSizeIterator for IntoIter<T> {}
323
324impl<T: TransparentType> std::iter::FusedIterator for IntoIter<T> {}
325
326impl<T: TransparentType> From<Slice<T>> for Vec<T> {
327    #[inline]
328    fn from(mut value: Slice<T>) -> Self {
329        unsafe {
330            let mut s = Vec::with_capacity(value.len);
331            ptr::copy_nonoverlapping(value.ptr.as_ptr() as *const T, s.as_mut_ptr(), value.len);
332            s.set_len(value.len);
333            value.len = 0;
334            s
335        }
336    }
337}
338
339impl<T: TransparentType> From<Vec<T>> for Slice<T> {
340    #[inline]
341    fn from(mut value: Vec<T>) -> Self {
342        unsafe {
343            let mut s = Self::with_capacity(value.len());
344            ptr::copy_nonoverlapping(value.as_ptr(), s.ptr.as_ptr() as *mut T, value.len());
345            s.len = value.len();
346            value.set_len(0);
347            s
348        }
349    }
350}
351
352impl<T: TransparentType, const N: usize> From<[T; N]> for Slice<T> {
353    #[inline]
354    fn from(value: [T; N]) -> Self {
355        unsafe {
356            let value = mem::ManuallyDrop::new(value);
357            let len = value.len();
358            let mut s = Self::with_capacity(len);
359            ptr::copy_nonoverlapping(value.as_ptr(), s.ptr.as_ptr() as *mut T, len);
360            s.len = len;
361            s
362        }
363    }
364}
365
366impl<'a, T: TransparentType> From<&'a [T]> for Slice<T> {
367    #[inline]
368    fn from(value: &'a [T]) -> Self {
369        unsafe {
370            let mut s = Self::with_capacity(value.len());
371            for (i, item) in value.iter().enumerate() {
372                ptr::write(s.ptr.as_ptr().add(i) as *mut T, item.clone());
373            }
374            s.len = value.len();
375            s
376        }
377    }
378}
379
380impl<'a, T: TransparentType> From<&'a [&'a T]> for Slice<T> {
381    #[inline]
382    fn from(value: &'a [&'a T]) -> Self {
383        unsafe {
384            let mut s = Self::with_capacity(value.len());
385            for (i, item) in value.iter().enumerate() {
386                ptr::write(s.ptr.as_ptr().add(i) as *mut T, (*item).clone());
387            }
388            s.len = value.len();
389            s
390        }
391    }
392}
393
394impl<T: TransparentType> Clone for Slice<T> {
395    #[inline]
396    fn clone(&self) -> Self {
397        Self::from(self.as_slice())
398    }
399}
400
401impl<T: TransparentType> Slice<T> {
402    // rustdoc-stripper-ignore-next
403    /// Borrows a C array.
404    #[inline]
405    pub unsafe fn from_glib_borrow_num<'a>(ptr: *const T::GlibType, len: usize) -> &'a [T] {
406        unsafe {
407            debug_assert_eq!(mem::size_of::<T>(), mem::size_of::<T::GlibType>());
408            debug_assert!(!ptr.is_null() || len == 0);
409
410            if len == 0 {
411                &[]
412            } else {
413                std::slice::from_raw_parts(ptr as *const T, len)
414            }
415        }
416    }
417
418    // rustdoc-stripper-ignore-next
419    /// Borrows a mutable C array.
420    #[inline]
421    pub unsafe fn from_glib_borrow_num_mut<'a>(ptr: *mut T::GlibType, len: usize) -> &'a mut [T] {
422        unsafe {
423            debug_assert_eq!(mem::size_of::<T>(), mem::size_of::<T::GlibType>());
424            debug_assert!(!ptr.is_null() || len == 0);
425
426            if len == 0 {
427                &mut []
428            } else {
429                std::slice::from_raw_parts_mut(ptr as *mut T, len)
430            }
431        }
432    }
433
434    // rustdoc-stripper-ignore-next
435    /// Borrows a C array of references.
436    #[inline]
437    pub unsafe fn from_glib_ptr_borrow_num<'a>(
438        ptr: *const *const T::GlibType,
439        len: usize,
440    ) -> &'a [&'a T] {
441        unsafe {
442            debug_assert_eq!(mem::size_of::<T>(), mem::size_of::<T::GlibType>());
443            debug_assert!(!ptr.is_null() || len == 0);
444
445            if len == 0 {
446                &[]
447            } else {
448                std::slice::from_raw_parts(ptr as *const &T, len)
449            }
450        }
451    }
452
453    // rustdoc-stripper-ignore-next
454    /// Borrows a mutable C array.
455    #[inline]
456    pub unsafe fn from_glib_ptr_borrow_num_mut<'a>(
457        ptr: *mut *mut T::GlibType,
458        len: usize,
459    ) -> &'a mut [&'a mut T] {
460        unsafe {
461            debug_assert_eq!(mem::size_of::<T>(), mem::size_of::<T::GlibType>());
462            debug_assert!(!ptr.is_null() || len == 0);
463
464            if len == 0 {
465                &mut []
466            } else {
467                std::slice::from_raw_parts_mut(ptr as *mut &mut T, len)
468            }
469        }
470    }
471
472    // rustdoc-stripper-ignore-next
473    /// Create a new `Slice` around a C array.
474    #[inline]
475    pub unsafe fn from_glib_none_num(ptr: *const T::GlibType, len: usize) -> Self {
476        unsafe {
477            debug_assert_eq!(mem::size_of::<T>(), mem::size_of::<T::GlibType>());
478            debug_assert!(!ptr.is_null() || len == 0);
479
480            if len == 0 {
481                Slice::default()
482            } else {
483                // Need to fully copy the array here.
484                let s = Self::from_glib_borrow_num(ptr, len);
485                Self::from(s)
486            }
487        }
488    }
489
490    // rustdoc-stripper-ignore-next
491    /// Create a new `Slice` around a C array.
492    #[inline]
493    pub unsafe fn from_glib_container_num(ptr: *mut T::GlibType, len: usize) -> Self {
494        unsafe {
495            debug_assert_eq!(mem::size_of::<T>(), mem::size_of::<T::GlibType>());
496            debug_assert!(!ptr.is_null() || len == 0);
497
498            if len == 0 {
499                ffi::g_free(ptr as ffi::gpointer);
500                Slice::default()
501            } else {
502                // Need to clone every item because we don't own it here but only
503                // if this type requires explicit drop.
504                if mem::needs_drop::<T>() {
505                    for i in 0..len {
506                        let p = ptr.add(i) as *mut T;
507                        let clone: T = (*p).clone();
508                        ptr::write(p, clone);
509                    }
510                }
511
512                // And now it can be handled exactly the same as `from_glib_full_num()`.
513                Self::from_glib_full_num(ptr, len)
514            }
515        }
516    }
517
518    // rustdoc-stripper-ignore-next
519    /// Create a new `Slice` around a C array.
520    #[inline]
521    pub unsafe fn from_glib_full_num(ptr: *mut T::GlibType, len: usize) -> Self {
522        unsafe {
523            debug_assert_eq!(mem::size_of::<T>(), mem::size_of::<T::GlibType>());
524            debug_assert!(!ptr.is_null() || len == 0);
525
526            if len == 0 {
527                ffi::g_free(ptr as ffi::gpointer);
528                Slice::default()
529            } else {
530                Slice {
531                    ptr: ptr::NonNull::new_unchecked(ptr),
532                    len,
533                    capacity: len,
534                }
535            }
536        }
537    }
538
539    // rustdoc-stripper-ignore-next
540    /// Creates a new empty slice.
541    #[inline]
542    pub fn new() -> Self {
543        debug_assert_eq!(mem::size_of::<T>(), mem::size_of::<T::GlibType>());
544
545        Slice {
546            ptr: ptr::NonNull::dangling(),
547            len: 0,
548            capacity: 0,
549        }
550    }
551
552    // rustdoc-stripper-ignore-next
553    /// Creates a new empty slice with the given capacity.
554    #[inline]
555    pub fn with_capacity(capacity: usize) -> Self {
556        let mut s = Self::new();
557        s.reserve(capacity);
558        s
559    }
560
561    // rustdoc-stripper-ignore-next
562    /// Returns the underlying pointer.
563    #[inline]
564    pub fn as_ptr(&self) -> *const T::GlibType {
565        if self.len == 0 {
566            ptr::null()
567        } else {
568            self.ptr.as_ptr()
569        }
570    }
571
572    // rustdoc-stripper-ignore-next
573    /// Returns the underlying pointer.
574    #[inline]
575    pub fn as_mut_ptr(&mut self) -> *mut T::GlibType {
576        if self.len == 0 {
577            ptr::null_mut()
578        } else {
579            self.ptr.as_ptr()
580        }
581    }
582
583    // rustdoc-stripper-ignore-next
584    /// Consumes the slice and returns the underlying pointer.
585    #[inline]
586    pub fn into_raw(mut self) -> *mut T::GlibType {
587        if self.len == 0 {
588            ptr::null_mut()
589        } else {
590            self.len = 0;
591            self.capacity = 0;
592            self.ptr.as_ptr()
593        }
594    }
595
596    // rustdoc-stripper-ignore-next
597    /// Gets the length of the slice.
598    #[inline]
599    pub fn len(&self) -> usize {
600        self.len
601    }
602
603    // rustdoc-stripper-ignore-next
604    /// Returns `true` if the slice is empty.
605    #[inline]
606    pub fn is_empty(&self) -> bool {
607        self.len == 0
608    }
609
610    // rustdoc-stripper-ignore-next
611    /// Returns the capacity of the slice.
612    #[inline]
613    pub fn capacity(&self) -> usize {
614        self.capacity
615    }
616
617    // rustdoc-stripper-ignore-next
618    /// Sets the length of the slice to `len`.
619    ///
620    /// # SAFETY
621    ///
622    /// There must be at least `len` valid items.
623    pub unsafe fn set_len(&mut self, len: usize) {
624        self.len = len;
625    }
626
627    // rustdoc-stripper-ignore-next
628    /// Reserves at least this much additional capacity.
629    pub fn reserve(&mut self, additional: usize) {
630        // Nothing new to reserve as there's still enough space
631        if additional <= self.capacity - self.len {
632            return;
633        }
634
635        let new_capacity = usize::next_power_of_two(std::cmp::max(
636            self.len + additional,
637            MIN_SIZE / mem::size_of::<T>(),
638        ));
639        assert_ne!(new_capacity, 0);
640        assert!(new_capacity > self.capacity);
641
642        unsafe {
643            let ptr = if self.capacity == 0 {
644                ptr::null_mut()
645            } else {
646                self.ptr.as_ptr() as *mut _
647            };
648            let new_ptr =
649                ffi::g_realloc(ptr, mem::size_of::<T>().checked_mul(new_capacity).unwrap())
650                    as *mut T::GlibType;
651            self.ptr = ptr::NonNull::new_unchecked(new_ptr);
652            self.capacity = new_capacity;
653        }
654    }
655
656    // rustdoc-stripper-ignore-next
657    /// Borrows this slice as a `&[T]`.
658    #[inline]
659    pub fn as_slice(&self) -> &[T] {
660        unsafe {
661            if self.len == 0 {
662                &[]
663            } else {
664                std::slice::from_raw_parts(self.ptr.as_ptr() as *const T, self.len)
665            }
666        }
667    }
668
669    // rustdoc-stripper-ignore-next
670    /// Borrows this slice as a `&mut [T]`.
671    #[inline]
672    pub fn as_mut_slice(&mut self) -> &mut [T] {
673        unsafe {
674            if self.len == 0 {
675                &mut []
676            } else {
677                std::slice::from_raw_parts_mut(self.ptr.as_ptr() as *mut T, self.len)
678            }
679        }
680    }
681
682    // rustdoc-stripper-ignore-next
683    /// Removes all items from the slice.
684    #[inline]
685    pub fn clear(&mut self) {
686        unsafe {
687            if mem::needs_drop::<T>() {
688                for i in 0..self.len {
689                    ptr::drop_in_place::<T>(self.ptr.as_ptr().add(i) as *mut T);
690                }
691            }
692
693            self.len = 0;
694        }
695    }
696
697    // rustdoc-stripper-ignore-next
698    /// Clones and appends all elements in `slice` to the slice.
699    #[inline]
700    pub fn extend_from_slice(&mut self, other: &[T]) {
701        // Nothing new to reserve as there's still enough space
702        if other.len() > self.capacity - self.len {
703            self.reserve(other.len());
704        }
705
706        unsafe {
707            for item in other {
708                ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item.clone());
709                self.len += 1;
710            }
711        }
712    }
713
714    // rustdoc-stripper-ignore-next
715    /// Inserts `item` at position `index` of the slice, shifting all elements after it to the
716    /// right.
717    #[inline]
718    #[allow(clippy::int_plus_one)]
719    pub fn insert(&mut self, index: usize, item: T) {
720        assert!(index <= self.len);
721
722        // Nothing new to reserve as there's still enough space
723        if 1 > self.capacity - self.len {
724            self.reserve(1);
725        }
726
727        unsafe {
728            if index == self.len {
729                ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item);
730            } else {
731                let p = self.ptr.as_ptr().add(index);
732                ptr::copy(p, p.add(1), self.len - index);
733                ptr::write(self.ptr.as_ptr().add(index) as *mut T, item);
734            }
735
736            self.len += 1;
737        }
738    }
739
740    // rustdoc-stripper-ignore-next
741    /// Pushes `item` to the end of the slice.
742    #[inline]
743    #[allow(clippy::int_plus_one)]
744    pub fn push(&mut self, item: T) {
745        // Nothing new to reserve as there's still enough space
746        if 1 > self.capacity - self.len {
747            self.reserve(1);
748        }
749
750        unsafe {
751            ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item);
752            self.len += 1;
753        }
754    }
755
756    // rustdoc-stripper-ignore-next
757    /// Removes item from position `index` of the slice, shifting all elements after it to the
758    /// left.
759    #[inline]
760    pub fn remove(&mut self, index: usize) -> T {
761        assert!(index < self.len);
762
763        unsafe {
764            let p = self.ptr.as_ptr().add(index);
765            let item = ptr::read(p as *mut T);
766            ptr::copy(p.add(1), p, self.len - index - 1);
767
768            self.len -= 1;
769
770            item
771        }
772    }
773
774    // rustdoc-stripper-ignore-next
775    /// Removes the last item of the slice and returns it.
776    #[inline]
777    pub fn pop(&mut self) -> Option<T> {
778        if self.len == 0 {
779            return None;
780        }
781
782        unsafe {
783            self.len -= 1;
784            let p = self.ptr.as_ptr().add(self.len);
785            let item = ptr::read(p as *mut T);
786
787            Some(item)
788        }
789    }
790
791    // rustdoc-stripper-ignore-next
792    /// Shortens the slice by keeping the last `len` items.
793    ///
794    /// If there are fewer than `len` items then this has no effect.
795    #[inline]
796    pub fn truncate(&mut self, len: usize) {
797        if self.len <= len {
798            return;
799        }
800
801        unsafe {
802            while self.len > len {
803                self.len -= 1;
804                let p = self.ptr.as_ptr().add(self.len);
805                ptr::drop_in_place::<T>(p as *mut T);
806            }
807        }
808    }
809}
810
811impl<T: TransparentType + 'static> FromGlibContainer<T::GlibType, *mut T::GlibType> for Slice<T> {
812    unsafe fn from_glib_none_num(ptr: *mut T::GlibType, num: usize) -> Self {
813        unsafe { Self::from_glib_none_num(ptr, num) }
814    }
815
816    #[inline]
817    unsafe fn from_glib_container_num(ptr: *mut T::GlibType, num: usize) -> Self {
818        unsafe { Self::from_glib_container_num(ptr, num) }
819    }
820
821    #[inline]
822    unsafe fn from_glib_full_num(ptr: *mut T::GlibType, num: usize) -> Self {
823        unsafe { Self::from_glib_full_num(ptr, num) }
824    }
825}
826
827impl<T: TransparentType + 'static> FromGlibContainer<T::GlibType, *const T::GlibType> for Slice<T> {
828    unsafe fn from_glib_none_num(ptr: *const T::GlibType, num: usize) -> Self {
829        unsafe { Self::from_glib_none_num(ptr, num) }
830    }
831
832    unsafe fn from_glib_container_num(_ptr: *const T::GlibType, _num: usize) -> Self {
833        unimplemented!();
834    }
835
836    unsafe fn from_glib_full_num(_ptr: *const T::GlibType, _num: usize) -> Self {
837        unimplemented!();
838    }
839}
840
841impl<'a, T: TransparentType + 'a> ToGlibPtr<'a, *mut T::GlibType> for Slice<T> {
842    type Storage = PhantomData<&'a Self>;
843
844    #[inline]
845    fn to_glib_none(&'a self) -> Stash<'a, *mut T::GlibType, Self> {
846        Stash(self.as_ptr() as *mut _, PhantomData)
847    }
848
849    #[inline]
850    fn to_glib_container(&'a self) -> Stash<'a, *mut T::GlibType, Self> {
851        unsafe {
852            let ptr = ffi::g_malloc(mem::size_of::<T>().checked_mul(self.len()).unwrap())
853                as *mut T::GlibType;
854            ptr::copy_nonoverlapping(self.as_ptr(), ptr, self.len());
855            Stash(ptr, PhantomData)
856        }
857    }
858
859    #[inline]
860    fn to_glib_full(&self) -> *mut T::GlibType {
861        self.clone().into_raw()
862    }
863}
864
865impl<'a, T: TransparentType + 'a> ToGlibPtr<'a, *const T::GlibType> for Slice<T> {
866    type Storage = PhantomData<&'a Self>;
867
868    #[inline]
869    fn to_glib_none(&'a self) -> Stash<'a, *const T::GlibType, Self> {
870        Stash(self.as_ptr(), PhantomData)
871    }
872}
873
874impl<'a, T: TransparentType + 'a> ToGlibPtrMut<'a, *mut T::GlibType> for Slice<T> {
875    type Storage = PhantomData<&'a mut Self>;
876
877    #[inline]
878    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut T::GlibType, Self> {
879        StashMut(self.as_mut_ptr(), PhantomData)
880    }
881}
882
883impl<T: TransparentType + 'static> IntoGlibPtr<*mut T::GlibType> for Slice<T> {
884    #[inline]
885    fn into_glib_ptr(self) -> *mut T::GlibType {
886        self.into_raw()
887    }
888}
889
890impl<T: TransparentPtrType> From<super::PtrSlice<T>> for Slice<T> {
891    fn from(value: super::PtrSlice<T>) -> Self {
892        let len = value.len();
893        let capacity = value.capacity();
894        unsafe {
895            let ptr = value.into_raw();
896            Slice::<T> {
897                ptr: ptr::NonNull::new_unchecked(ptr),
898                len,
899                capacity,
900            }
901        }
902    }
903}
904
905#[cfg(test)]
906mod test {
907    use super::*;
908
909    #[test]
910    fn test_from_glib_full() {
911        let items = [
912            crate::Date::from_dmy(20, crate::DateMonth::November, 2021).unwrap(),
913            crate::Date::from_dmy(21, crate::DateMonth::November, 2021).unwrap(),
914            crate::Date::from_dmy(22, crate::DateMonth::November, 2021).unwrap(),
915            crate::Date::from_dmy(23, crate::DateMonth::November, 2021).unwrap(),
916        ];
917
918        let slice = unsafe {
919            let ptr = ffi::g_malloc(mem::size_of::<ffi::GDate>() * 4) as *mut ffi::GDate;
920            ptr::write(ptr.add(0), *items[0].to_glib_none().0);
921            ptr::write(ptr.add(1), *items[1].to_glib_none().0);
922            ptr::write(ptr.add(2), *items[2].to_glib_none().0);
923            ptr::write(ptr.add(3), *items[3].to_glib_none().0);
924
925            Slice::<crate::Date>::from_glib_full_num(ptr, 4)
926        };
927
928        assert_eq!(&items[..], &*slice);
929    }
930
931    #[test]
932    fn test_from_glib_none() {
933        let items = [
934            crate::Date::from_dmy(20, crate::DateMonth::November, 2021).unwrap(),
935            crate::Date::from_dmy(21, crate::DateMonth::November, 2021).unwrap(),
936            crate::Date::from_dmy(22, crate::DateMonth::November, 2021).unwrap(),
937            crate::Date::from_dmy(23, crate::DateMonth::November, 2021).unwrap(),
938        ];
939
940        let slice = unsafe {
941            Slice::<crate::Date>::from_glib_none_num(items.as_ptr() as *const ffi::GDate, 4)
942        };
943
944        assert_eq!(&items[..], &*slice);
945    }
946
947    #[test]
948    fn test_safe_api() {
949        let items = [
950            crate::Date::from_dmy(20, crate::DateMonth::November, 2021).unwrap(),
951            crate::Date::from_dmy(21, crate::DateMonth::November, 2021).unwrap(),
952            crate::Date::from_dmy(22, crate::DateMonth::November, 2021).unwrap(),
953        ];
954
955        let mut slice = Slice::from(&items[..]);
956        assert_eq!(slice.len(), 3);
957        slice.push(crate::Date::from_dmy(23, crate::DateMonth::November, 2021).unwrap());
958        assert_eq!(slice.len(), 4);
959
960        for (a, b) in Iterator::zip(items.iter(), slice.iter()) {
961            assert_eq!(a, b);
962        }
963        assert_eq!(
964            (slice[3].day(), slice[3].month(), slice[3].year()),
965            (23, crate::DateMonth::November, 2021)
966        );
967
968        let vec = Vec::from(slice);
969        assert_eq!(vec.len(), 4);
970        for (a, b) in Iterator::zip(items.iter(), vec.iter()) {
971            assert_eq!(a, b);
972        }
973        assert_eq!(
974            (vec[3].day(), vec[3].month(), vec[3].year()),
975            (23, crate::DateMonth::November, 2021)
976        );
977
978        let mut slice = Slice::from(vec);
979        assert_eq!(slice.len(), 4);
980        let e = slice.pop().unwrap();
981        assert_eq!(
982            (e.day(), e.month(), e.year()),
983            (23, crate::DateMonth::November, 2021)
984        );
985        assert_eq!(slice.len(), 3);
986        slice.insert(2, e);
987        assert_eq!(slice.len(), 4);
988        assert_eq!(slice[0].day(), 20);
989        assert_eq!(slice[1].day(), 21);
990        assert_eq!(slice[2].day(), 23);
991        assert_eq!(slice[3].day(), 22);
992        let e = slice.remove(2);
993        assert_eq!(
994            (e.day(), e.month(), e.year()),
995            (23, crate::DateMonth::November, 2021)
996        );
997        assert_eq!(slice.len(), 3);
998        slice.push(e);
999        assert_eq!(slice.len(), 4);
1000
1001        for (a, b) in Iterator::zip(items.iter(), slice.into_iter()) {
1002            assert_eq!(a, &b);
1003        }
1004    }
1005}