safer_ffi/
slice.rs

1#![cfg_attr(rustfmt, rustfmt::skip)]
2//! Logic common to all fat pointers.
3
4use_prelude!();
5use ::core::slice;
6
7#[doc(no_inline)]
8pub use self::{
9    slice_ref as Ref,
10    slice_mut as Mut,
11};
12cfg_alloc! {
13    #[doc(no_inline)]
14    pub use slice_boxed as Box;
15}
16
17/// The phantoms from the crate are not `ReprC`.
18type PhantomCovariantLifetime<'lt> =
19    PhantomData<&'lt ()>
20;
21
22ReprC! {
23    #[repr(C, js)]
24    /// Like [`slice_ref`] and [`slice_mut`], but with any lifetime attached
25    /// whatsoever.
26    ///
27    /// It is only intended to be used as the parameter of a **callback** that
28    /// locally borrows it, due to limitations of the [`ReprC`][
29    /// `trait@crate::layout::ReprC`] design _w.r.t._ higher-rank trait bounds.
30    ///
31    /// # C layout (for some given type T)
32    ///
33    /// ```c
34    /// typedef struct {
35    ///     // Cannot be NULL
36    ///     T * ptr;
37    ///     size_t len;
38    /// } slice_T;
39    /// ```
40    ///
41    /// # Nullable pointer?
42    ///
43    /// If you want to support the above typedef, but where the `ptr` field is
44    /// allowed to be `NULL` (with the contents of `len` then being undefined)
45    /// use the `Option< slice_ptr<_> >` type.
46    #[derive(Debug)]
47    pub
48    struct slice_raw[T] {
49        /// Pointer to the first element (if any).
50        pub
51        ptr: ptr::NonNull<T>,
52
53        /// Element count
54        pub
55        len: usize,
56    }
57}
58
59impl<T> slice_raw<T> {
60    /// # Safety
61    ///
62    ///   - For the duration of the `'borrow`, the pointer must point to the
63    ///     beginning of a valid and immutable null-terminated slice of
64    ///     `len` `T`s.
65    #[inline]
66    pub
67    unsafe
68    fn as_ref<'borrow> (self: &'borrow slice_raw<T>)
69      -> slice_ref<'borrow, T>
70    {
71        slice_ref {
72            ptr: self.ptr.into(),
73            len: self.len,
74            _lt: PhantomCovariantLifetime::default(),
75        }
76    }
77
78    /// # Safety
79    ///
80    ///   - For the duration of the `'borrow`, the pointer must point to the
81    ///     beginning of a valid and immutable null-terminated slice of
82    ///     `len` `T`s.
83    #[inline]
84    pub
85    unsafe
86    fn as_mut<'borrow> (self: &'borrow mut slice_raw<T>)
87      -> slice_mut<'borrow, T>
88    {
89        slice_mut {
90            ptr: self.ptr.into(),
91            len: self.len,
92            _lt: PhantomCovariantLifetime::default(),
93        }
94    }
95}
96
97cfg_alloc! {
98    ReprC! {
99        #[repr(C, js)]
100        #[cfg_attr(all(docs, feature = "nightly"), doc(cfg(feature = "alloc")))]
101        /// [`Box`][`rust::Box`]`<[T]>` (fat pointer to a slice),
102        /// but with a guaranteed `#[repr(C)]` layout.
103        ///
104        /// # C layout (for some given type T)
105        ///
106        /// ```c
107        /// typedef struct {
108        ///     // Cannot be NULL
109        ///     T * ptr;
110        ///     size_t len;
111        /// } slice_T;
112        /// ```
113        ///
114        /// # Nullable pointer?
115        ///
116        /// If you want to support the above typedef, but where the `ptr` field is
117        /// allowed to be `NULL` (with the contents of `len` then being undefined)
118        /// use the `Option< slice_ptr<_> >` type.
119        #[derive(Debug)]
120        pub
121        struct slice_boxed[T] {
122            /// Pointer to the first element (if any).
123            pub(in crate)
124            ptr: ptr::NonNullOwned<T>,
125
126            /// Element count
127            pub(in crate)
128            len: usize,
129        }
130    }
131
132    impl<T> slice_boxed<T> {
133        #[inline]
134        pub
135        fn as_ref<'borrow> (self: &'borrow Self)
136          -> slice_ref<'borrow, T>
137        {
138            Into::into(&self[..])
139        }
140
141        #[inline]
142        pub
143        fn as_mut<'borrow> (self: &'borrow mut Self)
144          -> slice_mut<'borrow, T>
145        {
146            Into::into(&mut self[..])
147        }
148
149        #[inline]
150        pub
151        fn as_slice<'borrow> (self: &'borrow Self)
152          -> &'borrow [T]
153        {
154            self.as_ref().as_slice()
155        }
156
157        #[inline]
158        pub
159        fn as_slice_mut<'borrow> (self: &'borrow mut Self)
160          -> &'borrow mut [T]
161        {
162            self.as_mut().as_slice()
163        }
164    }
165
166    impl<T> From<rust::Box<[T]>>
167        for slice_boxed<T>
168    {
169        #[inline]
170        fn from (boxed_slice: rust::Box<[T]>)
171          -> Self
172        {
173            slice_boxed {
174                len: boxed_slice.len(),
175                ptr: unsafe {
176                    ptr::NonNull::new_unchecked(
177                        rust::Box::leak(boxed_slice).as_mut_ptr()
178                    )
179                }.into(),
180            }
181        }
182    }
183
184    impl<T> From<slice_boxed<T>> for rust::Box<[T]>
185    {
186        #[inline]
187        fn from (value: slice_boxed<T>)
188          -> rust::Box<[T]>
189        {
190            let mut this = mem::ManuallyDrop::new(value);
191            unsafe {
192                rust::Box::from_raw(
193                    slice::from_raw_parts_mut(
194                        this.ptr.as_mut_ptr(),
195                        this.len,
196                    )
197                )
198            }
199        }
200    }
201
202    impl<T> Drop
203        for slice_boxed<T>
204    {
205        #[inline]
206        fn drop (self: &'_ mut Self)
207        {
208            unsafe {
209                drop::<rust::Box<[T]>>(
210                    rust::Box::from_raw(
211                        slice::from_raw_parts_mut(
212                            self.ptr.as_mut_ptr(),
213                            self.len,
214                        )
215                    )
216                );
217            }
218        }
219    }
220
221    impl<T> Deref
222        for slice_boxed<T>
223    {
224        type Target = [T];
225
226        #[inline]
227        fn deref (self: &'_ Self)
228          -> &'_ Self::Target
229        {
230            unsafe {
231                slice::from_raw_parts(self.ptr.as_ptr(), self.len)
232            }
233        }
234    }
235    impl<T> DerefMut
236        for slice_boxed<T>
237    {
238        #[inline]
239        fn deref_mut (self: &'_ mut Self)
240          -> &'_ mut Self::Target
241        {
242            unsafe {
243                slice::from_raw_parts_mut(self.ptr.as_mut_ptr(), self.len)
244            }
245        }
246    }
247
248    unsafe // Safety: equivalent to that of the `where` bound
249        impl<T> Send
250            for slice_boxed<T>
251        where
252            rust::Box<[T]> : Send,
253        {}
254    unsafe // Safety: equivalent to that of the `where` bound
255        impl<T> Sync
256            for slice_boxed<T>
257        where
258            rust::Box<[T]> : Sync,
259        {}
260}
261
262ReprC! {
263    #[repr(C, js)]
264    /// `&'lt [T]` but with a guaranteed `#[repr(C)]` layout.
265    ///
266    /// # C layout (for some given type T)
267    ///
268    /// ```c
269    /// typedef struct {
270    ///     // Cannot be NULL
271    ///     T * ptr;
272    ///     size_t len;
273    /// } slice_T;
274    /// ```
275    ///
276    /// # Nullable pointer?
277    ///
278    /// If you want to support the above typedef, but where the `ptr` field is
279    /// allowed to be `NULL` (with the contents of `len` then being undefined)
280    /// use the `Option< slice_ptr<_> >` type.
281    pub
282    struct slice_ref['lt, T]
283    where {
284        T : 'lt,
285    }
286    {
287        /// Pointer to the first element (if any).
288        pub(in crate)
289        ptr: ptr::NonNullRef<T>,
290
291        /// Element count
292        pub(in crate)
293        len: usize,
294
295        pub(in crate)
296        _lt: PhantomCovariantLifetime<'lt>,
297    }
298}
299
300impl<'lt, T : 'lt> From<&'lt [T]>
301    for slice_ref<'lt, T>
302{
303    #[inline]
304    fn from (slice: &'lt [T])
305      -> slice_ref<'lt, T>
306    {
307        slice_ref {
308            len: slice.len(),
309            ptr: unsafe {
310                ptr::NonNull::new_unchecked(slice.as_ptr() as _)
311            }.into(),
312            _lt: PhantomCovariantLifetime::default(),
313        }
314    }
315}
316
317impl<'lt, T : 'lt> slice_ref<'lt, T> {
318    pub
319    fn as_slice (self: slice_ref<'lt, T>)
320      -> &'lt [T]
321    {
322        unsafe {
323            slice::from_raw_parts(self.ptr.as_ptr(), self.len)
324        }
325    }
326}
327
328impl<'lt, T : 'lt> Copy
329    for slice_ref<'lt, T>
330{}
331
332impl<'lt, T : 'lt> Clone
333    for slice_ref<'lt, T>
334{
335    #[inline]
336    fn clone (self: &'_ slice_ref<'lt, T>)
337      -> slice_ref<'lt, T>
338    {
339        *self
340    }
341}
342
343impl<'lt, T : 'lt> Deref
344    for slice_ref<'lt, T>
345{
346    type Target = [T];
347
348    #[inline]
349    fn deref (self: &'_ slice_ref<'lt, T>)
350      -> &'_ [T]
351    {
352        (*self).as_slice()
353    }
354}
355
356unsafe // Safety: equivalent to that of the `where` bound
357    impl<'lt, T : 'lt> Send
358        for slice_ref<'lt, T>
359    where
360        &'lt [T] : Send,
361    {}
362
363unsafe // Safety: equivalent to that of the `where` bound
364    impl<'lt, T : 'lt> Sync
365        for slice_ref<'lt, T>
366    where
367        &'lt [T] : Sync,
368    {}
369
370impl<T : fmt::Debug> fmt::Debug
371    for slice_ref<'_, T>
372{
373    #[inline]
374    fn fmt (self: &'_ Self, fmt: &'_ mut fmt::Formatter<'_>)
375      -> fmt::Result
376    {
377        <[T] as fmt::Debug>::fmt(self, fmt)
378    }
379}
380
381impl<'lt, T : 'lt> From<slice_ref<'lt, T>>
382    for slice_raw<T>
383{
384    #[inline]
385    fn from (slice_ref { ptr, len, .. }: slice_ref<'lt, T>)
386      -> slice_raw<T>
387    {
388        slice_raw { ptr: ptr.0, len }
389    }
390}
391
392ReprC! {
393    #[repr(C)]
394    /// `&'lt mut [T]` but with a guaranteed `#[repr(C)]` layout.
395    ///
396    /// # C layout (for some given type T)
397    ///
398    /// ```c
399    /// typedef struct {
400    ///     // Cannot be NULL
401    ///     T * ptr;
402    ///     size_t len;
403    /// } slice_T;
404    /// ```
405    ///
406    /// # Nullable pointer?
407    ///
408    /// If you want to support the above typedef, but where the `ptr` field is
409    /// allowed to be `NULL` (with the contents of `len` then being undefined)
410    /// use the `Option< slice_ptr<_> >` type.
411    pub
412    struct slice_mut['lt, T]
413    where {
414        T : 'lt,
415    }
416    {
417        /// Pointer to the first element (if any).
418        pub(in crate)
419        ptr: ptr::NonNullMut<T>,
420
421        /// Element count
422        pub(in crate)
423        len: usize,
424
425        pub(in crate)
426        _lt: PhantomCovariantLifetime<'lt>,
427    }
428}
429
430impl<'lt, T : 'lt> From<&'lt mut [T]>
431    for slice_mut<'lt, T>
432{
433    #[inline]
434    fn from (slice: &'lt mut [T])
435      -> Self
436    {
437        slice_mut {
438            len: slice.len(),
439            ptr: unsafe {
440                ptr::NonNull::new_unchecked(slice.as_mut_ptr())
441            }.into(),
442            _lt: PhantomCovariantLifetime::default(),
443        }
444    }
445}
446
447impl<'lt, T : 'lt> From<slice_mut<'lt, T>>
448    for slice_ref<'lt, T>
449{
450    #[inline]
451    fn from (it: slice_mut<'lt, T>)
452      -> slice_ref<'lt, T>
453    {
454        (&*it.as_slice())
455            .into()
456    }
457}
458
459impl<T> Deref
460    for slice_mut<'_, T>
461{
462    type Target = [T];
463
464    #[inline]
465    fn deref (self: &'_ Self)
466      -> &'_ Self::Target
467    {
468        self.as_ref()
469            .as_slice()
470    }
471}
472
473impl<T> DerefMut
474    for slice_mut<'_, T>
475{
476    #[inline]
477    fn deref_mut (self: &'_ mut Self)
478      -> &'_ mut Self::Target
479    {
480        self.as_mut()
481            .as_slice()
482    }
483}
484
485impl<'lt, T : 'lt> slice_mut<'lt, T> {
486    #[inline]
487    pub
488    fn as_ref<'reborrow> (self: &'reborrow slice_mut<'lt, T>)
489      -> slice_ref<'reborrow, T>
490    where
491        'lt : 'reborrow,
492    {
493        let &slice_mut { ptr: ptr::NonNullMut(ptr, ..), len, _lt } = self;
494        slice_ref {
495            ptr: ptr.into(),
496            len,
497            _lt,
498        }
499    }
500
501    #[inline]
502    pub
503    fn as_mut<'reborrow> (self: &'reborrow mut slice_mut<'lt, T>)
504      -> slice_mut<'reborrow, T>
505    where
506        'lt : 'reborrow,
507    {
508        let &mut slice_mut { ref mut ptr, len, _lt } = self;
509        slice_mut {
510            ptr: ptr.copy(),
511            len,
512            _lt,
513        }
514    }
515
516    #[inline]
517    pub
518    fn as_slice (mut self: slice_mut<'lt, T>)
519      -> &'lt mut [T]
520    {
521        unsafe {
522            slice::from_raw_parts_mut(self.ptr.as_mut_ptr(), self.len)
523        }
524    }
525}
526
527unsafe // Safety: equivalent to that of the `where` bound
528    impl<'lt, T : 'lt> Send
529        for slice_mut<'lt, T>
530    where
531        &'lt mut [T] : Send,
532    {}
533unsafe // Safety: equivalent to that of the `where` bound
534    impl<'lt, T : 'lt> Sync
535        for slice_mut<'lt, T>
536    where
537        &'lt mut [T] : Sync,
538    {}
539
540impl<T : fmt::Debug> fmt::Debug
541    for slice_mut<'_, T>
542{
543    #[inline]
544    fn fmt (self: &'_ Self, fmt: &'_ mut fmt::Formatter<'_>)
545      -> fmt::Result
546    {
547        <[T] as fmt::Debug>::fmt(self, fmt)
548    }
549}
550
551impl<'lt, T : 'lt> From<slice_mut<'lt, T>>
552    for slice_raw<T>
553{
554    #[inline]
555    fn from (slice_mut { ptr, len, .. }: slice_mut<'lt, T>)
556      -> slice_raw<T>
557    {
558        slice_raw { ptr: ptr.0, len }
559    }
560}
561
562/// Extra traits for these `#[repr(C)]` slices.
563const _: () = {
564    use ::core::{
565        hash::{Hash, Hasher},
566        cmp::Ordering,
567    };
568
569    impl<T : Ord> Ord
570        for slice_ref<'_, T>
571    {
572        #[inline]
573        fn cmp (self: &'_ Self, other: &'_ Self)
574          -> Ordering
575        {
576            self[..].cmp(&other[..])
577        }
578    }
579    impl<T : PartialOrd> PartialOrd
580        for slice_ref<'_, T>
581    {
582        #[inline]
583        fn partial_cmp (self: &'_ Self, other: &'_ Self)
584          -> Option<Ordering>
585        {
586            self[..].partial_cmp(&other[..])
587        }
588    }
589    impl<T : Eq> Eq
590        for slice_ref<'_, T>
591    {}
592    impl<T : PartialEq> PartialEq
593        for slice_ref<'_, T>
594    {
595        #[inline]
596        fn eq (self: &'_ Self, other: &'_ Self)
597          -> bool
598        {
599            self[..] == other[..]
600        }
601    }
602    impl<T : Hash> Hash
603        for slice_ref<'_, T>
604    {
605        #[inline]
606        fn hash<H : Hasher> (self: &'_ Self, hasher: &'_ mut H)
607        {
608            self[..].hash(hasher)
609        }
610    }
611    impl<T> Default
612        for slice_ref<'_, T>
613    {
614        #[inline]
615        fn default ()
616          -> Self
617        {
618            (&[][..]).into()
619        }
620    }
621
622    impl<T : Ord> Ord
623        for slice_mut<'_, T>
624    {
625        #[inline]
626        fn cmp (self: &'_ Self, other: &'_ Self)
627          -> Ordering
628        {
629            self[..].cmp(&other[..])
630        }
631    }
632    impl<T : PartialOrd> PartialOrd
633        for slice_mut<'_, T>
634    {
635        #[inline]
636        fn partial_cmp (self: &'_ Self, other: &'_ Self)
637          -> Option<Ordering>
638        {
639            self[..].partial_cmp(&other[..])
640        }
641    }
642    impl<T : Eq> Eq
643        for slice_mut<'_, T>
644    {}
645    impl<T : PartialEq> PartialEq
646        for slice_mut<'_, T>
647    {
648        #[inline]
649        fn eq (self: &'_ Self, other: &'_ Self)
650          -> bool
651        {
652            self[..] == other[..]
653        }
654    }
655    impl<T : Hash> Hash
656        for slice_mut<'_, T>
657    {
658        #[inline]
659        fn hash<H : Hasher> (self: &'_ Self, hasher: &'_ mut H)
660        {
661            self[..].hash(hasher)
662        }
663    }
664    impl<T> Default
665        for slice_mut<'_, T>
666    {
667        #[inline]
668        fn default ()
669          -> Self
670        {
671            (&mut [][..]).into()
672        }
673    }
674
675    cfg_alloc! {
676        impl<T : Ord> Ord
677            for slice_boxed<T>
678        {
679            #[inline]
680            fn cmp (self: &'_ Self, other: &'_ Self)
681              -> Ordering
682            {
683                self[..].cmp(&other[..])
684            }
685        }
686        impl<T : PartialOrd> PartialOrd
687            for slice_boxed<T>
688        {
689            #[inline]
690            fn partial_cmp (self: &'_ Self, other: &'_ Self)
691              -> Option<Ordering>
692            {
693                self[..].partial_cmp(&other[..])
694            }
695        }
696        impl<T : Eq> Eq
697            for slice_boxed<T>
698        {}
699        impl<T : PartialEq> PartialEq
700            for slice_boxed<T>
701        {
702            #[inline]
703            fn eq (self: &'_ Self, other: &'_ Self)
704              -> bool
705            {
706                self[..] == other[..]
707            }
708        }
709        impl<T : Hash> Hash
710            for slice_boxed<T>
711        {
712            #[inline]
713            fn hash<H : Hasher> (self: &'_ Self, hasher: &'_ mut H)
714            {
715                self[..].hash(hasher)
716            }
717        }
718        impl<T> Default
719            for slice_boxed<T>
720        {
721            #[inline]
722            fn default ()
723              -> Self
724            {
725                <rust::Box<[_]>>::into(rust::Box::new([]))
726            }
727        }
728        impl<T : Clone> Clone
729            for slice_boxed<T>
730        {
731            #[inline]
732            fn clone (self: &'_ slice_boxed<T>)
733              -> slice_boxed<T>
734            {
735                rust::Vec::from(self.as_slice()).into_boxed_slice().into()
736            }
737        }
738    }
739};