glib/collections/
ptr_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 `PtrSlice` allocation.
9const MIN_SIZE: usize = 16;
10
11// rustdoc-stripper-ignore-next
12/// Slice of elements of type `T` allocated by the GLib allocator.
13///
14/// The underlying memory is always `NULL`-terminated. [`Slice<T>`](crate::collections::slice::Slice)
15/// can be used for a non-`NULL`-terminated slice.
16///
17/// This can be used like a `&[T]`, `&mut [T]` and `Vec<T>`.
18pub struct PtrSlice<T: TransparentPtrType> {
19    ptr: ptr::NonNull<<T as GlibPtrDefault>::GlibType>,
20    // rustdoc-stripper-ignore-next
21    /// Length without the `NULL`-terminator.
22    len: usize,
23    // rustdoc-stripper-ignore-next
24    /// Capacity **with** the `NULL`-terminator, i.e. the actual allocation size.
25    capacity: usize,
26}
27
28impl<T: fmt::Debug + TransparentPtrType> fmt::Debug for PtrSlice<T> {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        self.as_slice().fmt(f)
31    }
32}
33
34unsafe impl<T: Send + TransparentPtrType> Send for PtrSlice<T> {}
35
36unsafe impl<T: Sync + TransparentPtrType> Sync for PtrSlice<T> {}
37
38impl<T: PartialEq + TransparentPtrType> PartialEq for PtrSlice<T> {
39    #[inline]
40    fn eq(&self, other: &Self) -> bool {
41        self.as_slice() == other.as_slice()
42    }
43}
44
45impl<T: Eq + TransparentPtrType> Eq for PtrSlice<T> {}
46
47impl<T: PartialOrd + TransparentPtrType> PartialOrd for PtrSlice<T> {
48    #[inline]
49    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
50        self.as_slice().partial_cmp(other.as_slice())
51    }
52}
53
54impl<T: Ord + TransparentPtrType> Ord for PtrSlice<T> {
55    #[inline]
56    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
57        self.as_slice().cmp(other.as_slice())
58    }
59}
60
61impl<T: std::hash::Hash + TransparentPtrType> std::hash::Hash for PtrSlice<T> {
62    #[inline]
63    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
64        self.as_slice().hash(state)
65    }
66}
67
68impl<T: PartialEq + TransparentPtrType> PartialEq<[T]> for PtrSlice<T> {
69    #[inline]
70    fn eq(&self, other: &[T]) -> bool {
71        self.as_slice() == other
72    }
73}
74
75impl<T: PartialEq + TransparentPtrType> PartialEq<PtrSlice<T>> for [T] {
76    #[inline]
77    fn eq(&self, other: &PtrSlice<T>) -> bool {
78        self == other.as_slice()
79    }
80}
81
82impl<T: TransparentPtrType> Drop for PtrSlice<T> {
83    #[inline]
84    fn drop(&mut self) {
85        unsafe {
86            if mem::needs_drop::<T>() {
87                for i in 0..self.len {
88                    ptr::drop_in_place::<T>(self.ptr.as_ptr().add(i) as *mut T);
89                }
90            }
91
92            if self.capacity != 0 {
93                ffi::g_free(self.ptr.as_ptr() as ffi::gpointer);
94            }
95        }
96    }
97}
98
99impl<T: TransparentPtrType> AsRef<[T]> for PtrSlice<T> {
100    #[inline]
101    fn as_ref(&self) -> &[T] {
102        self.as_slice()
103    }
104}
105
106impl<T: TransparentPtrType> AsMut<[T]> for PtrSlice<T> {
107    #[inline]
108    fn as_mut(&mut self) -> &mut [T] {
109        self.as_mut_slice()
110    }
111}
112
113impl<T: TransparentPtrType> std::borrow::Borrow<[T]> for PtrSlice<T> {
114    #[inline]
115    fn borrow(&self) -> &[T] {
116        self.as_slice()
117    }
118}
119
120impl<T: TransparentPtrType> std::borrow::BorrowMut<[T]> for PtrSlice<T> {
121    #[inline]
122    fn borrow_mut(&mut self) -> &mut [T] {
123        self.as_mut_slice()
124    }
125}
126
127impl<T: TransparentPtrType> std::ops::Deref for PtrSlice<T> {
128    type Target = [T];
129
130    #[inline]
131    fn deref(&self) -> &[T] {
132        self.as_slice()
133    }
134}
135
136impl<T: TransparentPtrType> std::ops::DerefMut for PtrSlice<T> {
137    #[inline]
138    fn deref_mut(&mut self) -> &mut [T] {
139        self.as_mut_slice()
140    }
141}
142
143impl<T: TransparentPtrType> Default for PtrSlice<T> {
144    #[inline]
145    fn default() -> Self {
146        Self::new()
147    }
148}
149
150impl<T: TransparentPtrType> std::iter::Extend<T> for PtrSlice<T> {
151    #[inline]
152    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
153        let iter = iter.into_iter();
154        self.reserve(iter.size_hint().0);
155
156        for item in iter {
157            self.push(item);
158        }
159    }
160}
161
162impl<'a, T: TransparentPtrType + 'a> std::iter::Extend<&'a T> for PtrSlice<T> {
163    #[inline]
164    fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
165        let iter = iter.into_iter();
166        self.reserve(iter.size_hint().0);
167
168        for item in iter {
169            self.push(item.clone());
170        }
171    }
172}
173
174impl<T: TransparentPtrType> std::iter::FromIterator<T> for PtrSlice<T> {
175    #[inline]
176    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
177        let iter = iter.into_iter();
178        let mut s = Self::with_capacity(iter.size_hint().0);
179        for item in iter {
180            s.push(item);
181        }
182        s
183    }
184}
185
186impl<'a, T: TransparentPtrType> std::iter::IntoIterator for &'a PtrSlice<T> {
187    type Item = &'a T;
188    type IntoIter = std::slice::Iter<'a, T>;
189
190    #[inline]
191    fn into_iter(self) -> Self::IntoIter {
192        self.as_slice().iter()
193    }
194}
195
196impl<'a, T: TransparentPtrType> std::iter::IntoIterator for &'a mut PtrSlice<T> {
197    type Item = &'a mut T;
198    type IntoIter = std::slice::IterMut<'a, T>;
199
200    #[inline]
201    fn into_iter(self) -> Self::IntoIter {
202        self.as_mut_slice().iter_mut()
203    }
204}
205
206impl<T: TransparentPtrType> std::iter::IntoIterator for PtrSlice<T> {
207    type Item = T;
208    type IntoIter = IntoIter<T>;
209
210    #[inline]
211    fn into_iter(self) -> Self::IntoIter {
212        IntoIter::new(self)
213    }
214}
215
216pub struct IntoIter<T: TransparentPtrType> {
217    ptr: ptr::NonNull<<T as GlibPtrDefault>::GlibType>,
218    idx: ptr::NonNull<<T as GlibPtrDefault>::GlibType>,
219    len: usize,
220    empty: bool,
221}
222
223impl<T: TransparentPtrType> IntoIter<T> {
224    #[inline]
225    fn new(slice: PtrSlice<T>) -> Self {
226        let slice = mem::ManuallyDrop::new(slice);
227        IntoIter {
228            ptr: slice.ptr,
229            idx: slice.ptr,
230            len: slice.len,
231            empty: slice.capacity == 0,
232        }
233    }
234
235    // rustdoc-stripper-ignore-next
236    /// Returns the remaining items as slice.
237    #[inline]
238    pub fn as_slice(&self) -> &[T] {
239        unsafe {
240            if self.len == 0 {
241                &[]
242            } else {
243                std::slice::from_raw_parts(self.idx.as_ptr() as *mut T, self.len)
244            }
245        }
246    }
247
248    // rustdoc-stripper-ignore-next
249    /// Returns the remaining items as mutable slice.
250    #[inline]
251    pub fn as_mut_slice(&mut self) -> &mut [T] {
252        unsafe {
253            if self.len == 0 {
254                &mut []
255            } else {
256                std::slice::from_raw_parts_mut(self.idx.as_ptr() as *mut T, self.len)
257            }
258        }
259    }
260}
261
262impl<T: TransparentPtrType> Drop for IntoIter<T> {
263    #[inline]
264    fn drop(&mut self) {
265        unsafe {
266            if mem::needs_drop::<T>() {
267                for i in 0..self.len {
268                    ptr::drop_in_place::<T>(self.idx.as_ptr().add(i) as *mut T);
269                }
270            }
271
272            if !self.empty {
273                ffi::g_free(self.ptr.as_ptr() as ffi::gpointer);
274            }
275        }
276    }
277}
278
279impl<T: TransparentPtrType> Iterator for IntoIter<T> {
280    type Item = T;
281
282    #[inline]
283    fn next(&mut self) -> Option<Self::Item> {
284        if self.len == 0 {
285            return None;
286        }
287
288        unsafe {
289            let p = self.idx.as_ptr();
290            self.len -= 1;
291            self.idx = ptr::NonNull::new_unchecked(p.add(1));
292            Some(ptr::read(p as *mut T))
293        }
294    }
295
296    #[inline]
297    fn size_hint(&self) -> (usize, Option<usize>) {
298        (self.len, Some(self.len))
299    }
300
301    #[inline]
302    fn count(self) -> usize {
303        self.len
304    }
305
306    #[inline]
307    fn last(mut self) -> Option<T> {
308        if self.len == 0 {
309            None
310        } else {
311            self.len -= 1;
312            Some(unsafe { ptr::read(self.idx.as_ptr().add(self.len) as *mut T) })
313        }
314    }
315}
316
317impl<T: TransparentPtrType> DoubleEndedIterator for IntoIter<T> {
318    #[inline]
319    fn next_back(&mut self) -> Option<T> {
320        if self.len == 0 {
321            None
322        } else {
323            self.len -= 1;
324            Some(unsafe { ptr::read(self.idx.as_ptr().add(self.len) as *mut T) })
325        }
326    }
327}
328
329impl<T: TransparentPtrType> ExactSizeIterator for IntoIter<T> {}
330
331impl<T: TransparentPtrType> std::iter::FusedIterator for IntoIter<T> {}
332
333impl<T: TransparentPtrType> From<PtrSlice<T>> for Vec<T> {
334    #[inline]
335    fn from(mut value: PtrSlice<T>) -> Self {
336        unsafe {
337            let mut s = Vec::with_capacity(value.len);
338            ptr::copy_nonoverlapping(value.ptr.as_ptr() as *const T, s.as_mut_ptr(), value.len);
339            s.set_len(value.len);
340            value.len = 0;
341            s
342        }
343    }
344}
345
346impl<T: TransparentPtrType> From<Vec<T>> for PtrSlice<T> {
347    #[inline]
348    fn from(mut value: Vec<T>) -> Self {
349        unsafe {
350            let mut s = Self::with_capacity(value.len());
351            ptr::copy_nonoverlapping(value.as_ptr(), s.ptr.as_ptr() as *mut T, value.len());
352            s.len = value.len();
353            value.set_len(0);
354            ptr::write(
355                s.ptr.as_ptr().add(s.len),
356                Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
357            );
358            s
359        }
360    }
361}
362
363impl<T: TransparentPtrType, const N: usize> From<[T; N]> for PtrSlice<T> {
364    #[inline]
365    fn from(value: [T; N]) -> Self {
366        unsafe {
367            let value = mem::ManuallyDrop::new(value);
368            let len = value.len();
369            let mut s = Self::with_capacity(len);
370            ptr::copy_nonoverlapping(value.as_ptr(), s.ptr.as_ptr() as *mut T, len);
371            s.len = len;
372            ptr::write(
373                s.ptr.as_ptr().add(len),
374                Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
375            );
376            s
377        }
378    }
379}
380
381impl<'a, T: TransparentPtrType> From<&'a [T]> for PtrSlice<T> {
382    #[inline]
383    fn from(value: &'a [T]) -> Self {
384        unsafe {
385            let mut s = Self::with_capacity(value.len());
386            for (i, item) in value.iter().enumerate() {
387                ptr::write(s.ptr.as_ptr().add(i) as *mut T, item.clone());
388            }
389            s.len = value.len();
390            ptr::write(
391                s.ptr.as_ptr().add(s.len),
392                Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
393            );
394            s
395        }
396    }
397}
398
399impl<'a, T: TransparentPtrType> From<&'a [&'a T]> for PtrSlice<T> {
400    #[inline]
401    fn from(value: &'a [&'a T]) -> Self {
402        unsafe {
403            let mut s = Self::with_capacity(value.len());
404            for (i, item) in value.iter().enumerate() {
405                ptr::write(s.ptr.as_ptr().add(i) as *mut T, (*item).clone());
406            }
407            s.len = value.len();
408            ptr::write(
409                s.ptr.as_ptr().add(s.len),
410                Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
411            );
412            s
413        }
414    }
415}
416
417impl<T: TransparentPtrType> Clone for PtrSlice<T> {
418    #[inline]
419    fn clone(&self) -> Self {
420        Self::from(self.as_slice())
421    }
422}
423
424impl<T: TransparentPtrType> PtrSlice<T> {
425    // rustdoc-stripper-ignore-next
426    /// Borrows a C array.
427    #[inline]
428    pub unsafe fn from_glib_borrow<'a>(ptr: *const <T as GlibPtrDefault>::GlibType) -> &'a [T] {
429        unsafe {
430            let mut len = 0;
431            if !ptr.is_null() {
432                while !(*ptr.add(len)).is_null() {
433                    len += 1;
434                }
435            }
436            Self::from_glib_borrow_num(ptr, len)
437        }
438    }
439
440    // rustdoc-stripper-ignore-next
441    /// Borrows a C array.
442    #[inline]
443    pub unsafe fn from_glib_borrow_num<'a>(
444        ptr: *const <T as GlibPtrDefault>::GlibType,
445        len: usize,
446    ) -> &'a [T] {
447        unsafe {
448            debug_assert_eq!(
449                mem::size_of::<T>(),
450                mem::size_of::<<T as GlibPtrDefault>::GlibType>()
451            );
452            debug_assert!(!ptr.is_null() || len == 0);
453
454            if len == 0 {
455                &[]
456            } else {
457                std::slice::from_raw_parts(ptr as *const T, len)
458            }
459        }
460    }
461
462    // rustdoc-stripper-ignore-next
463    /// Create a new `PtrSlice` around a C array.
464    #[inline]
465    pub unsafe fn from_glib_none_num(
466        ptr: *const <T as GlibPtrDefault>::GlibType,
467        len: usize,
468        _null_terminated: bool,
469    ) -> Self {
470        unsafe {
471            debug_assert_eq!(
472                mem::size_of::<T>(),
473                mem::size_of::<<T as GlibPtrDefault>::GlibType>()
474            );
475            debug_assert!(!ptr.is_null() || len == 0);
476
477            if len == 0 {
478                PtrSlice::default()
479            } else {
480                // Need to fully copy the array here.
481                let s = Self::from_glib_borrow_num(ptr, len);
482                Self::from(s)
483            }
484        }
485    }
486
487    // rustdoc-stripper-ignore-next
488    /// Create a new `PtrSlice` around a C array.
489    #[inline]
490    pub unsafe fn from_glib_container_num(
491        ptr: *mut <T as GlibPtrDefault>::GlibType,
492        len: usize,
493        null_terminated: bool,
494    ) -> Self {
495        unsafe {
496            debug_assert_eq!(
497                mem::size_of::<T>(),
498                mem::size_of::<<T as GlibPtrDefault>::GlibType>()
499            );
500            debug_assert!(!ptr.is_null() || len == 0);
501
502            if len == 0 {
503                ffi::g_free(ptr as ffi::gpointer);
504                PtrSlice::default()
505            } else {
506                // Need to clone every item because we don't own it here
507                for i in 0..len {
508                    let p = ptr.add(i) as *mut T;
509                    let clone: T = (*p).clone();
510                    ptr::write(p, clone);
511                }
512
513                // And now it can be handled exactly the same as `from_glib_full_num()`.
514                Self::from_glib_full_num(ptr, len, null_terminated)
515            }
516        }
517    }
518
519    // rustdoc-stripper-ignore-next
520    /// Create a new `PtrSlice` around a C array.
521    #[inline]
522    pub unsafe fn from_glib_full_num(
523        ptr: *mut <T as GlibPtrDefault>::GlibType,
524        len: usize,
525        null_terminated: bool,
526    ) -> Self {
527        unsafe {
528            debug_assert_eq!(
529                mem::size_of::<T>(),
530                mem::size_of::<<T as GlibPtrDefault>::GlibType>()
531            );
532            debug_assert!(!ptr.is_null() || len == 0);
533
534            if len == 0 {
535                ffi::g_free(ptr as ffi::gpointer);
536                PtrSlice::default()
537            } else {
538                if null_terminated {
539                    return PtrSlice {
540                        ptr: ptr::NonNull::new_unchecked(ptr),
541                        len,
542                        capacity: len + 1,
543                    };
544                }
545
546                // Need to re-allocate here for adding the NULL-terminator
547                let capacity = len + 1;
548                assert_ne!(capacity, 0);
549                let ptr = ffi::g_realloc(
550                    ptr as *mut _,
551                    mem::size_of::<T>().checked_mul(capacity).unwrap(),
552                ) as *mut <T as GlibPtrDefault>::GlibType;
553
554                ptr::write(
555                    ptr.add(len),
556                    Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
557                );
558
559                PtrSlice {
560                    ptr: ptr::NonNull::new_unchecked(ptr),
561                    len,
562                    capacity,
563                }
564            }
565        }
566    }
567
568    // rustdoc-stripper-ignore-next
569    /// Create a new `PtrSlice` around a `NULL`-terminated C array.
570    #[inline]
571    pub unsafe fn from_glib_none(ptr: *const <T as GlibPtrDefault>::GlibType) -> Self {
572        unsafe {
573            let mut len = 0;
574            if !ptr.is_null() {
575                while !(*ptr.add(len)).is_null() {
576                    len += 1;
577                }
578            }
579
580            PtrSlice::from_glib_none_num(ptr, len, true)
581        }
582    }
583
584    // rustdoc-stripper-ignore-next
585    /// Create a new `PtrSlice` around a `NULL`-terminated C array.
586    #[inline]
587    pub unsafe fn from_glib_container(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self {
588        unsafe {
589            let mut len = 0;
590            if !ptr.is_null() {
591                while !(*ptr.add(len)).is_null() {
592                    len += 1;
593                }
594            }
595
596            PtrSlice::from_glib_container_num(ptr, len, true)
597        }
598    }
599
600    // rustdoc-stripper-ignore-next
601    /// Create a new `PtrSlice` around a `NULL`-terminated C array.
602    #[inline]
603    pub unsafe fn from_glib_full(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self {
604        unsafe {
605            let mut len = 0;
606            if !ptr.is_null() {
607                while !(*ptr.add(len)).is_null() {
608                    len += 1;
609                }
610            }
611
612            PtrSlice::from_glib_full_num(ptr, len, true)
613        }
614    }
615
616    // rustdoc-stripper-ignore-next
617    /// Creates a new empty slice.
618    #[inline]
619    pub fn new() -> Self {
620        debug_assert_eq!(
621            mem::size_of::<T>(),
622            mem::size_of::<<T as GlibPtrDefault>::GlibType>()
623        );
624
625        PtrSlice {
626            ptr: ptr::NonNull::dangling(),
627            len: 0,
628            capacity: 0,
629        }
630    }
631
632    // rustdoc-stripper-ignore-next
633    /// Creates a new empty slice with the given capacity.
634    #[inline]
635    pub fn with_capacity(capacity: usize) -> Self {
636        let mut s = Self::new();
637        s.reserve(capacity);
638        s
639    }
640
641    // rustdoc-stripper-ignore-next
642    /// Returns the underlying pointer.
643    ///
644    /// This is guaranteed to be `NULL`-terminated.
645    #[inline]
646    pub fn as_ptr(&self) -> *const <T as GlibPtrDefault>::GlibType {
647        if self.len == 0 {
648            static EMPTY: [usize; 1] = [0];
649
650            EMPTY.as_ptr() as *const _
651        } else {
652            self.ptr.as_ptr()
653        }
654    }
655
656    // rustdoc-stripper-ignore-next
657    /// Returns the underlying pointer.
658    ///
659    /// This is guaranteed to be `NULL`-terminated.
660    #[inline]
661    pub fn as_mut_ptr(&mut self) -> *mut <T as GlibPtrDefault>::GlibType {
662        if self.len == 0 {
663            static EMPTY: [usize; 1] = [0];
664
665            EMPTY.as_ptr() as *mut _
666        } else {
667            self.ptr.as_ptr()
668        }
669    }
670
671    // rustdoc-stripper-ignore-next
672    /// Consumes the slice and returns the underlying pointer.
673    ///
674    /// This is guaranteed to be `NULL`-terminated.
675    #[inline]
676    pub fn into_raw(mut self) -> *mut <T as GlibPtrDefault>::GlibType {
677        // Make sure to allocate a valid pointer that points to a
678        // NULL-pointer.
679        if self.len == 0 {
680            self.reserve(0);
681            unsafe {
682                ptr::write(
683                    self.ptr.as_ptr().add(0),
684                    Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
685                );
686            }
687        }
688
689        self.len = 0;
690        self.capacity = 0;
691        self.ptr.as_ptr()
692    }
693
694    // rustdoc-stripper-ignore-next
695    /// Gets the length of the slice.
696    #[inline]
697    pub fn len(&self) -> usize {
698        self.len
699    }
700
701    // rustdoc-stripper-ignore-next
702    /// Returns `true` if the slice is empty.
703    #[inline]
704    pub fn is_empty(&self) -> bool {
705        self.len == 0
706    }
707
708    // rustdoc-stripper-ignore-next
709    /// Returns the capacity of the slice.
710    ///
711    /// This includes the space that is reserved for the `NULL`-terminator.
712    #[inline]
713    pub fn capacity(&self) -> usize {
714        self.capacity
715    }
716
717    // rustdoc-stripper-ignore-next
718    /// Sets the length of the slice to `len`.
719    ///
720    /// # SAFETY
721    ///
722    /// There must be at least `len` valid items and a `NULL`-terminator after the last item.
723    pub unsafe fn set_len(&mut self, len: usize) {
724        self.len = len;
725    }
726
727    // rustdoc-stripper-ignore-next
728    /// Reserves at least this much additional capacity.
729    #[allow(clippy::int_plus_one)]
730    pub fn reserve(&mut self, additional: usize) {
731        // Nothing new to reserve as there's still enough space
732        if additional < self.capacity - self.len {
733            return;
734        }
735
736        let new_capacity =
737            usize::next_power_of_two(std::cmp::max(self.len + additional, MIN_SIZE) + 1);
738        assert_ne!(new_capacity, 0);
739        assert!(new_capacity > self.capacity);
740
741        unsafe {
742            let ptr = if self.capacity == 0 {
743                ptr::null_mut()
744            } else {
745                self.ptr.as_ptr() as *mut _
746            };
747            let new_ptr =
748                ffi::g_realloc(ptr, mem::size_of::<T>().checked_mul(new_capacity).unwrap())
749                    as *mut <T as GlibPtrDefault>::GlibType;
750            if self.capacity == 0 {
751                ptr::write(
752                    new_ptr,
753                    Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
754                );
755            }
756            self.ptr = ptr::NonNull::new_unchecked(new_ptr);
757            self.capacity = new_capacity;
758        }
759    }
760
761    // rustdoc-stripper-ignore-next
762    /// Borrows this slice as a `&[T]`.
763    #[inline]
764    pub fn as_slice(&self) -> &[T] {
765        unsafe {
766            if self.len == 0 {
767                &[]
768            } else {
769                std::slice::from_raw_parts(self.ptr.as_ptr() as *const T, self.len)
770            }
771        }
772    }
773
774    // rustdoc-stripper-ignore-next
775    /// Borrows this slice as a `&mut [T]`.
776    #[inline]
777    pub fn as_mut_slice(&mut self) -> &mut [T] {
778        unsafe {
779            if self.len == 0 {
780                &mut []
781            } else {
782                std::slice::from_raw_parts_mut(self.ptr.as_ptr() as *mut T, self.len)
783            }
784        }
785    }
786
787    // rustdoc-stripper-ignore-next
788    /// Removes all items from the slice.
789    #[inline]
790    pub fn clear(&mut self) {
791        unsafe {
792            if mem::needs_drop::<T>() {
793                for i in 0..self.len {
794                    ptr::drop_in_place::<T>(self.ptr.as_ptr().add(i) as *mut T);
795                }
796            }
797
798            self.len = 0;
799        }
800    }
801
802    // rustdoc-stripper-ignore-next
803    /// Clones and appends all elements in `slice` to the slice.
804    #[inline]
805    pub fn extend_from_slice(&mut self, other: &[T]) {
806        // Nothing new to reserve as there's still enough space
807        if other.len() >= self.capacity - self.len {
808            self.reserve(other.len());
809        }
810
811        unsafe {
812            for item in other {
813                ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item.clone());
814                self.len += 1;
815
816                // Add null terminator on every iteration because `clone`
817                // may panic
818                ptr::write(
819                    self.ptr.as_ptr().add(self.len),
820                    Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
821                );
822            }
823        }
824    }
825
826    // rustdoc-stripper-ignore-next
827    /// Inserts `item` at position `index` of the slice, shifting all elements after it to the
828    /// right.
829    #[inline]
830    pub fn insert(&mut self, index: usize, item: T) {
831        assert!(index <= self.len);
832
833        // Nothing new to reserve as there's still enough space
834        if 1 >= self.capacity - self.len {
835            self.reserve(1);
836        }
837
838        unsafe {
839            if index == self.len {
840                ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item);
841            } else {
842                let p = self.ptr.as_ptr().add(index);
843                ptr::copy(p, p.add(1), self.len - index);
844                ptr::write(self.ptr.as_ptr().add(index) as *mut T, item);
845            }
846
847            self.len += 1;
848
849            ptr::write(
850                self.ptr.as_ptr().add(self.len),
851                Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
852            );
853        }
854    }
855
856    // rustdoc-stripper-ignore-next
857    /// Pushes `item` to the end of the slice.
858    #[inline]
859    pub fn push(&mut self, item: T) {
860        // Nothing new to reserve as there's still enough space
861        if 1 >= self.capacity - self.len {
862            self.reserve(1);
863        }
864
865        unsafe {
866            ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item);
867            self.len += 1;
868
869            ptr::write(
870                self.ptr.as_ptr().add(self.len),
871                Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
872            );
873        }
874    }
875
876    // rustdoc-stripper-ignore-next
877    /// Removes item from position `index` of the slice, shifting all elements after it to the
878    /// left.
879    #[inline]
880    pub fn remove(&mut self, index: usize) -> T {
881        assert!(index < self.len);
882
883        unsafe {
884            let p = self.ptr.as_ptr().add(index);
885            let item = ptr::read(p as *mut T);
886            ptr::copy(p.add(1), p, self.len - index - 1);
887
888            self.len -= 1;
889
890            ptr::write(
891                self.ptr.as_ptr().add(self.len),
892                Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
893            );
894
895            item
896        }
897    }
898
899    // rustdoc-stripper-ignore-next
900    /// Removes the last item of the slice and returns it.
901    #[inline]
902    pub fn pop(&mut self) -> Option<T> {
903        if self.len == 0 {
904            return None;
905        }
906
907        unsafe {
908            self.len -= 1;
909            let p = self.ptr.as_ptr().add(self.len);
910            let item = ptr::read(p as *mut T);
911
912            ptr::write(
913                self.ptr.as_ptr().add(self.len),
914                Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
915            );
916
917            Some(item)
918        }
919    }
920
921    // rustdoc-stripper-ignore-next
922    /// Shortens the slice by keeping the last `len` items.
923    ///
924    /// If there are fewer than `len` items then this has no effect.
925    #[inline]
926    pub fn truncate(&mut self, len: usize) {
927        if self.len <= len {
928            return;
929        }
930
931        unsafe {
932            while self.len > len {
933                self.len -= 1;
934                let p = self.ptr.as_ptr().add(self.len);
935                ptr::drop_in_place::<T>(p as *mut T);
936                ptr::write(
937                    p,
938                    Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
939                );
940            }
941        }
942    }
943}
944
945impl<T: TransparentPtrType>
946    FromGlibContainer<<T as GlibPtrDefault>::GlibType, *mut <T as GlibPtrDefault>::GlibType>
947    for PtrSlice<T>
948{
949    #[inline]
950    unsafe fn from_glib_none_num(ptr: *mut <T as GlibPtrDefault>::GlibType, num: usize) -> Self {
951        unsafe { Self::from_glib_none_num(ptr, num, false) }
952    }
953
954    #[inline]
955    unsafe fn from_glib_container_num(
956        ptr: *mut <T as GlibPtrDefault>::GlibType,
957        num: usize,
958    ) -> Self {
959        unsafe { Self::from_glib_container_num(ptr, num, false) }
960    }
961
962    #[inline]
963    unsafe fn from_glib_full_num(ptr: *mut <T as GlibPtrDefault>::GlibType, num: usize) -> Self {
964        unsafe { Self::from_glib_full_num(ptr, num, false) }
965    }
966}
967
968impl<T: TransparentPtrType>
969    FromGlibContainer<<T as GlibPtrDefault>::GlibType, *const <T as GlibPtrDefault>::GlibType>
970    for PtrSlice<T>
971{
972    unsafe fn from_glib_none_num(ptr: *const <T as GlibPtrDefault>::GlibType, num: usize) -> Self {
973        unsafe { Self::from_glib_none_num(ptr, num, false) }
974    }
975
976    unsafe fn from_glib_container_num(
977        _ptr: *const <T as GlibPtrDefault>::GlibType,
978        _num: usize,
979    ) -> Self {
980        unimplemented!();
981    }
982
983    unsafe fn from_glib_full_num(
984        _ptr: *const <T as GlibPtrDefault>::GlibType,
985        _num: usize,
986    ) -> Self {
987        unimplemented!();
988    }
989}
990
991impl<T: TransparentPtrType>
992    FromGlibPtrContainer<<T as GlibPtrDefault>::GlibType, *mut <T as GlibPtrDefault>::GlibType>
993    for PtrSlice<T>
994{
995    #[inline]
996    unsafe fn from_glib_none(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self {
997        unsafe { Self::from_glib_none(ptr) }
998    }
999
1000    #[inline]
1001    unsafe fn from_glib_container(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self {
1002        unsafe { Self::from_glib_container(ptr) }
1003    }
1004
1005    #[inline]
1006    unsafe fn from_glib_full(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self {
1007        unsafe { Self::from_glib_full(ptr) }
1008    }
1009}
1010
1011impl<T: TransparentPtrType>
1012    FromGlibPtrContainer<<T as GlibPtrDefault>::GlibType, *const <T as GlibPtrDefault>::GlibType>
1013    for PtrSlice<T>
1014{
1015    #[inline]
1016    unsafe fn from_glib_none(ptr: *const <T as GlibPtrDefault>::GlibType) -> Self {
1017        unsafe { Self::from_glib_none(ptr) }
1018    }
1019
1020    unsafe fn from_glib_container(_ptr: *const <T as GlibPtrDefault>::GlibType) -> Self {
1021        unimplemented!();
1022    }
1023
1024    unsafe fn from_glib_full(_ptr: *const <T as GlibPtrDefault>::GlibType) -> Self {
1025        unimplemented!();
1026    }
1027}
1028
1029impl<'a, T: TransparentPtrType + 'a> ToGlibPtr<'a, *mut <T as GlibPtrDefault>::GlibType>
1030    for PtrSlice<T>
1031{
1032    type Storage = PhantomData<&'a Self>;
1033
1034    #[inline]
1035    fn to_glib_none(&'a self) -> Stash<'a, *mut <T as GlibPtrDefault>::GlibType, Self> {
1036        Stash(self.as_ptr() as *mut _, PhantomData)
1037    }
1038
1039    #[inline]
1040    fn to_glib_container(&'a self) -> Stash<'a, *mut <T as GlibPtrDefault>::GlibType, Self> {
1041        unsafe {
1042            let ptr = ffi::g_malloc(mem::size_of::<T>().checked_mul(self.len() + 1).unwrap())
1043                as *mut <T as GlibPtrDefault>::GlibType;
1044            ptr::copy_nonoverlapping(self.as_ptr(), ptr, self.len() + 1);
1045            Stash(ptr, PhantomData)
1046        }
1047    }
1048
1049    #[inline]
1050    fn to_glib_full(&self) -> *mut <T as GlibPtrDefault>::GlibType {
1051        self.clone().into_raw()
1052    }
1053}
1054
1055impl<'a, T: TransparentPtrType + 'a> ToGlibPtr<'a, *const <T as GlibPtrDefault>::GlibType>
1056    for PtrSlice<T>
1057{
1058    type Storage = PhantomData<&'a Self>;
1059
1060    #[inline]
1061    fn to_glib_none(&'a self) -> Stash<'a, *const <T as GlibPtrDefault>::GlibType, Self> {
1062        Stash(self.as_ptr(), PhantomData)
1063    }
1064}
1065
1066impl<'a, T: TransparentPtrType + 'a> ToGlibPtrMut<'a, *mut <T as GlibPtrDefault>::GlibType>
1067    for PtrSlice<T>
1068{
1069    type Storage = PhantomData<&'a mut Self>;
1070
1071    #[inline]
1072    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut <T as GlibPtrDefault>::GlibType, Self> {
1073        StashMut(self.as_mut_ptr(), PhantomData)
1074    }
1075}
1076
1077impl<T: TransparentPtrType> IntoGlibPtr<*mut <T as GlibPtrDefault>::GlibType> for PtrSlice<T> {
1078    #[inline]
1079    fn into_glib_ptr(self) -> *mut <T as GlibPtrDefault>::GlibType {
1080        self.into_raw()
1081    }
1082}
1083
1084impl<T: TransparentPtrType> From<super::Slice<T>> for PtrSlice<T> {
1085    fn from(value: super::Slice<T>) -> Self {
1086        let len = value.len();
1087        let capacity = value.capacity();
1088        unsafe {
1089            let ptr = value.into_raw();
1090            let mut s = PtrSlice::<T> {
1091                ptr: ptr::NonNull::new_unchecked(ptr),
1092                len,
1093                capacity,
1094            };
1095
1096            // Reserve space for the `NULL`-terminator if needed
1097            if len == capacity {
1098                s.reserve(0);
1099            }
1100
1101            ptr::write(
1102                s.ptr.as_ptr().add(s.len()),
1103                Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
1104            );
1105
1106            s
1107        }
1108    }
1109}
1110
1111// rustdoc-stripper-ignore-next
1112/// A trait to accept both `&[T]` or `PtrSlice<T>` as an argument.
1113pub trait IntoPtrSlice<T: TransparentPtrType> {
1114    // rustdoc-stripper-ignore-next
1115    /// Runs the given closure with a `NULL`-terminated array.
1116    fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R;
1117}
1118
1119impl<T: TransparentPtrType> IntoPtrSlice<T> for PtrSlice<T> {
1120    #[inline]
1121    fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R {
1122        <&Self>::run_with_ptr_slice(&self, f)
1123    }
1124}
1125
1126impl<T: TransparentPtrType> IntoPtrSlice<T> for &'_ PtrSlice<T> {
1127    #[inline]
1128    fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R {
1129        f(unsafe { std::slice::from_raw_parts(self.as_ptr() as *mut _, self.len() + 1) })
1130    }
1131}
1132
1133// rustdoc-stripper-ignore-next
1134/// Maximum number of pointers to stack-allocate before falling back to a heap allocation.
1135const MAX_STACK_ALLOCATION: usize = 16;
1136
1137impl<T: TransparentPtrType> IntoPtrSlice<T> for Vec<T> {
1138    #[inline]
1139    fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R {
1140        if self.len() < MAX_STACK_ALLOCATION {
1141            unsafe {
1142                let mut s = mem::MaybeUninit::<
1143                    [<T as GlibPtrDefault>::GlibType; MAX_STACK_ALLOCATION],
1144                >::uninit();
1145                let ptr = s.as_mut_ptr() as *mut <T as GlibPtrDefault>::GlibType;
1146                ptr::copy_nonoverlapping(
1147                    self.as_ptr() as *mut <T as GlibPtrDefault>::GlibType,
1148                    ptr,
1149                    self.len(),
1150                );
1151                ptr::write(
1152                    ptr.add(self.len()),
1153                    Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
1154                );
1155                f(std::slice::from_raw_parts(ptr, self.len() + 1))
1156            }
1157        } else {
1158            PtrSlice::<T>::from(self).run_with_ptr_slice(f)
1159        }
1160    }
1161}
1162
1163impl<T: TransparentPtrType, const N: usize> IntoPtrSlice<T> for [T; N] {
1164    #[inline]
1165    fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R {
1166        if self.len() < MAX_STACK_ALLOCATION {
1167            unsafe {
1168                let mut s = mem::MaybeUninit::<
1169                    [<T as GlibPtrDefault>::GlibType; MAX_STACK_ALLOCATION],
1170                >::uninit();
1171                let ptr = s.as_mut_ptr() as *mut <T as GlibPtrDefault>::GlibType;
1172                ptr::copy_nonoverlapping(
1173                    self.as_ptr() as *mut <T as GlibPtrDefault>::GlibType,
1174                    ptr,
1175                    self.len(),
1176                );
1177                ptr::write(
1178                    ptr.add(self.len()),
1179                    Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
1180                );
1181                f(std::slice::from_raw_parts(ptr, self.len() + 1))
1182            }
1183        } else {
1184            PtrSlice::<T>::from(self).run_with_ptr_slice(f)
1185        }
1186    }
1187}
1188
1189impl<T: TransparentPtrType> IntoPtrSlice<T> for &'_ [T] {
1190    #[inline]
1191    fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R {
1192        if self.len() < MAX_STACK_ALLOCATION {
1193            unsafe {
1194                let mut s = mem::MaybeUninit::<
1195                    [<T as GlibPtrDefault>::GlibType; MAX_STACK_ALLOCATION],
1196                >::uninit();
1197                let ptr = s.as_mut_ptr() as *mut <T as GlibPtrDefault>::GlibType;
1198                ptr::copy_nonoverlapping(
1199                    self.as_ptr() as *mut <T as GlibPtrDefault>::GlibType,
1200                    ptr,
1201                    self.len(),
1202                );
1203                ptr::write(
1204                    ptr.add(self.len()),
1205                    Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()),
1206                );
1207                f(std::slice::from_raw_parts(ptr, self.len() + 1))
1208            }
1209        } else {
1210            PtrSlice::<T>::from(self).run_with_ptr_slice(f)
1211        }
1212    }
1213}
1214
1215#[cfg(test)]
1216mod test {
1217    use super::*;
1218
1219    #[test]
1220    fn test_from_glib_full() {
1221        let items = [
1222            crate::Error::new(crate::FileError::Failed, "Failed 1"),
1223            crate::Error::new(crate::FileError::Noent, "Failed 2"),
1224            crate::Error::new(crate::FileError::Io, "Failed 3"),
1225            crate::Error::new(crate::FileError::Perm, "Failed 4"),
1226        ];
1227
1228        let slice = unsafe {
1229            let ptr = ffi::g_malloc(mem::size_of::<ffi::GDate>() * 4) as *mut *mut ffi::GError;
1230            ptr::write(ptr.add(0), items[0].to_glib_full());
1231            ptr::write(ptr.add(1), items[1].to_glib_full());
1232            ptr::write(ptr.add(2), items[2].to_glib_full());
1233            ptr::write(ptr.add(3), items[3].to_glib_full());
1234
1235            PtrSlice::<crate::Error>::from_glib_full_num(ptr, 4, false)
1236        };
1237
1238        for (a, b) in Iterator::zip(items.iter(), slice.iter()) {
1239            assert_eq!(a.message(), b.message());
1240            assert_eq!(
1241                a.kind::<crate::FileError>().unwrap(),
1242                b.kind::<crate::FileError>().unwrap()
1243            );
1244        }
1245    }
1246
1247    #[test]
1248    fn test_from_glib_none() {
1249        let items = [
1250            crate::Error::new(crate::FileError::Failed, "Failed 1"),
1251            crate::Error::new(crate::FileError::Noent, "Failed 2"),
1252            crate::Error::new(crate::FileError::Io, "Failed 3"),
1253            crate::Error::new(crate::FileError::Perm, "Failed 4"),
1254        ];
1255
1256        let slice = unsafe {
1257            PtrSlice::<crate::Error>::from_glib_none_num(
1258                items.as_ptr() as *const *mut ffi::GError,
1259                4,
1260                false,
1261            )
1262        };
1263
1264        for (a, b) in Iterator::zip(items.iter(), slice.iter()) {
1265            assert_eq!(a.message(), b.message());
1266            assert_eq!(
1267                a.kind::<crate::FileError>().unwrap(),
1268                b.kind::<crate::FileError>().unwrap()
1269            );
1270        }
1271    }
1272
1273    #[test]
1274    fn test_safe_api() {
1275        let items = [
1276            crate::Error::new(crate::FileError::Failed, "Failed 1"),
1277            crate::Error::new(crate::FileError::Noent, "Failed 2"),
1278            crate::Error::new(crate::FileError::Io, "Failed 3"),
1279        ];
1280
1281        let mut slice = PtrSlice::from(&items[..]);
1282        assert_eq!(slice.len(), 3);
1283        slice.push(crate::Error::new(crate::FileError::Perm, "Failed 4"));
1284        assert_eq!(slice.len(), 4);
1285
1286        for (a, b) in Iterator::zip(items.iter(), slice.iter()) {
1287            assert_eq!(a.message(), b.message());
1288            assert_eq!(
1289                a.kind::<crate::FileError>().unwrap(),
1290                b.kind::<crate::FileError>().unwrap()
1291            );
1292        }
1293        assert_eq!(slice[3].message(), "Failed 4");
1294
1295        let vec = Vec::from(slice);
1296        assert_eq!(vec.len(), 4);
1297        for (a, b) in Iterator::zip(items.iter(), vec.iter()) {
1298            assert_eq!(a.message(), b.message());
1299            assert_eq!(
1300                a.kind::<crate::FileError>().unwrap(),
1301                b.kind::<crate::FileError>().unwrap()
1302            );
1303        }
1304        assert_eq!(vec[3].message(), "Failed 4");
1305
1306        let mut slice = PtrSlice::from(vec);
1307        assert_eq!(slice.len(), 4);
1308        let e = slice.pop().unwrap();
1309        assert_eq!(e.message(), "Failed 4");
1310        assert_eq!(slice.len(), 3);
1311        slice.insert(2, e);
1312        assert_eq!(slice.len(), 4);
1313        assert_eq!(slice[0].message(), "Failed 1");
1314        assert_eq!(slice[1].message(), "Failed 2");
1315        assert_eq!(slice[2].message(), "Failed 4");
1316        assert_eq!(slice[3].message(), "Failed 3");
1317        let e = slice.remove(2);
1318        assert_eq!(e.message(), "Failed 4");
1319        assert_eq!(slice.len(), 3);
1320        slice.push(e);
1321        assert_eq!(slice.len(), 4);
1322
1323        let slice2 = crate::Slice::from(slice.clone());
1324
1325        for (a, b) in Iterator::zip(items.iter(), slice.into_iter()) {
1326            assert_eq!(a.message(), b.message());
1327            assert_eq!(
1328                a.kind::<crate::FileError>().unwrap(),
1329                b.kind::<crate::FileError>().unwrap()
1330            );
1331        }
1332
1333        let slice3 = crate::PtrSlice::from(slice2.clone());
1334
1335        for (a, b) in Iterator::zip(items.iter(), slice2.into_iter()) {
1336            assert_eq!(a.message(), b.message());
1337            assert_eq!(
1338                a.kind::<crate::FileError>().unwrap(),
1339                b.kind::<crate::FileError>().unwrap()
1340            );
1341        }
1342
1343        for (a, b) in Iterator::zip(items.iter(), slice3.into_iter()) {
1344            assert_eq!(a.message(), b.message());
1345            assert_eq!(
1346                a.kind::<crate::FileError>().unwrap(),
1347                b.kind::<crate::FileError>().unwrap()
1348            );
1349        }
1350    }
1351
1352    #[test]
1353    fn test_into_ptrslice() {
1354        let items = [
1355            crate::Error::new(crate::FileError::Failed, "Failed 1"),
1356            crate::Error::new(crate::FileError::Noent, "Failed 2"),
1357            crate::Error::new(crate::FileError::Io, "Failed 3"),
1358            crate::Error::new(crate::FileError::Perm, "Failed 4"),
1359        ];
1360
1361        items[..].run_with_ptr_slice(|s| unsafe {
1362            assert!(s[4].is_null());
1363            assert_eq!(s.len(), items.len() + 1);
1364            let s = std::slice::from_raw_parts(s.as_ptr() as *const crate::Error, items.len());
1365            assert_eq!(s, items);
1366        });
1367
1368        Vec::from(&items[..]).run_with_ptr_slice(|s| unsafe {
1369            assert!(s[4].is_null());
1370            assert_eq!(s.len(), items.len() + 1);
1371            let s = std::slice::from_raw_parts(s.as_ptr() as *const crate::Error, items.len());
1372            for (a, b) in Iterator::zip(items.iter(), s.iter()) {
1373                assert_eq!(a.message(), b.message());
1374                assert_eq!(
1375                    a.kind::<crate::FileError>().unwrap(),
1376                    b.kind::<crate::FileError>().unwrap()
1377                );
1378            }
1379        });
1380
1381        PtrSlice::<crate::Error>::from(&items[..]).run_with_ptr_slice(|s| unsafe {
1382            assert!(s[4].is_null());
1383            assert_eq!(s.len(), items.len() + 1);
1384            let s = std::slice::from_raw_parts(s.as_ptr() as *const crate::Error, items.len());
1385            for (a, b) in Iterator::zip(items.iter(), s.iter()) {
1386                assert_eq!(a.message(), b.message());
1387                assert_eq!(
1388                    a.kind::<crate::FileError>().unwrap(),
1389                    b.kind::<crate::FileError>().unwrap()
1390                );
1391            }
1392        });
1393
1394        let v = Vec::from(&items[..]);
1395        items.run_with_ptr_slice(|s| unsafe {
1396            assert!(s[4].is_null());
1397            assert_eq!(s.len(), v.len() + 1);
1398            let s = std::slice::from_raw_parts(s.as_ptr() as *const crate::Error, v.len());
1399            for (a, b) in Iterator::zip(v.iter(), s.iter()) {
1400                assert_eq!(a.message(), b.message());
1401                assert_eq!(
1402                    a.kind::<crate::FileError>().unwrap(),
1403                    b.kind::<crate::FileError>().unwrap()
1404                );
1405            }
1406        });
1407    }
1408}