Skip to main content

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