Skip to main content

mbox/
mbox.rs

1//! `malloc`-based Box.
2
3#[cfg(feature = "stable_deref_trait")]
4use stable_deref_trait::StableDeref;
5
6use std::cmp::Ordering;
7use std::convert::{AsMut, AsRef};
8use std::fmt::{Debug, Display, Formatter, Pointer, Result as FormatResult};
9use std::hash::{Hash, Hasher};
10use std::iter::{DoubleEndedIterator, FromIterator, IntoIterator};
11use std::marker::Unpin;
12use std::mem::{forget, MaybeUninit};
13use std::ops::{Deref, DerefMut};
14use std::pin::Pin;
15use std::ptr::{copy_nonoverlapping, drop_in_place, read, write};
16use std::slice::{Iter, IterMut};
17use std::str::{from_utf8, Utf8Error};
18use std::{
19    borrow::{Borrow, BorrowMut},
20    ptr::NonNull,
21};
22
23use crate::internal::{gen_free, gen_malloc, gen_realloc, Unique};
24
25#[cfg(all(test, not(windows)))]
26use crate::internal::DropCounter;
27#[cfg(test)]
28use crate::internal::PanicOnClone;
29#[cfg(test)]
30use std::iter::{once, repeat};
31#[cfg(all(test, not(windows)))]
32use std::mem::size_of;
33
34#[cfg(feature = "nightly")]
35use std::marker::Unsize;
36#[cfg(feature = "nightly")]
37use std::ops::CoerceUnsized;
38
39use crate::free::Free;
40
41//{{{ Basic structure -----------------------------------------------------------------------------
42
43/// A malloc-backed box. This structure allows Rust to exchange objects with C without cloning.
44pub struct MBox<T: ?Sized + Free>(Unique<T>);
45
46impl<T: ?Sized + Free> MBox<T> {
47    /// Constructs a new malloc-backed box from a pointer allocated by `malloc`.
48    ///
49    /// # Safety
50    ///
51    /// The `ptr` must be allocated via `malloc()`, `calloc()` or similar C functions that is
52    /// expected to be deallocated using `free()`. It must be aligned and not null. The content of the pointer
53    /// must be already initialized. The pointer's ownership is passed into the box, and thus should
54    /// not be used after this function returns.
55    ///
56    /// Note that even when `T` is zero-sized, the input `ptr` is *still* expected to be released using
57    /// `free()`. Therefore, you must not use a conceived dangling pointer such as `NonNull::dangling()`
58    /// here. Consider using `malloc(1)` in case of ZSTs.
59    pub unsafe fn from_raw(ptr: *mut T) -> Self {
60        Self::from_non_null_raw(NonNull::new_unchecked(ptr))
61    }
62
63    /// Constructs a new malloc-backed box from a non-null pointer allocated by `malloc`.
64    ///
65    /// # Safety
66    ///
67    /// The `ptr` must be allocated via `malloc()`, `calloc()` or similar C functions that is
68    /// expected to be deallocated using `free()`. The content of the pointer must be already
69    /// initialized. The pointer's ownership is passed into the box, and thus should not be used
70    /// after this function returns.
71    ///
72    /// Note that even when `T` is zero-sized, the input `ptr` is *still* expected to be released using
73    /// `free()`. Therefore, you must not use a conceived dangling pointer such as `NonNull::dangling()`
74    /// here. Consider using `malloc(1)` in case of ZSTs.
75    pub unsafe fn from_non_null_raw(ptr: NonNull<T>) -> Self {
76        Self(Unique::new(ptr))
77    }
78
79    /// Obtains the pointer owned by the box.
80    pub fn as_ptr(boxed: &Self) -> *const T {
81        boxed.0.as_non_null_ptr().as_ptr()
82    }
83
84    /// Obtains the mutable pointer owned by the box.
85    pub fn as_mut_ptr(boxed: &mut Self) -> *mut T {
86        boxed.0.as_non_null_ptr().as_ptr()
87    }
88
89    /// Consumes the box and returns the original pointer.
90    ///
91    /// The caller is responsible for `free`ing the pointer after this.
92    pub fn into_raw(boxed: Self) -> *mut T {
93        Self::into_non_null_raw(boxed).as_ptr()
94    }
95
96    /// Consumes the box and returns the original non-null pointer.
97    ///
98    /// The caller is responsible for `free`ing the pointer after this.
99    pub fn into_non_null_raw(boxed: Self) -> NonNull<T> {
100        let ptr = boxed.0.as_non_null_ptr();
101        forget(boxed);
102        ptr
103    }
104}
105
106impl<T: ?Sized + Free> Drop for MBox<T> {
107    fn drop(&mut self) {
108        // SAFETY: the pointer is assumed to be obtained from `malloc()`.
109        unsafe { T::free(self.0.as_non_null_ptr()) };
110    }
111}
112
113impl<T: ?Sized + Free> Deref for MBox<T> {
114    type Target = T;
115    fn deref(&self) -> &T {
116        unsafe { &*Self::as_ptr(self) }
117    }
118}
119
120#[cfg(feature = "stable_deref_trait")]
121unsafe impl<T: ?Sized + Free> StableDeref for MBox<T> {}
122
123impl<T: ?Sized + Free> Unpin for MBox<T> {}
124
125impl<T: ?Sized + Free> DerefMut for MBox<T> {
126    fn deref_mut(&mut self) -> &mut T {
127        unsafe { &mut *Self::as_mut_ptr(self) }
128    }
129}
130
131impl<T: ?Sized + Free> AsRef<T> for MBox<T> {
132    fn as_ref(&self) -> &T {
133        self
134    }
135}
136
137impl<T: ?Sized + Free> AsMut<T> for MBox<T> {
138    fn as_mut(&mut self) -> &mut T {
139        self
140    }
141}
142
143impl<T: ?Sized + Free> Borrow<T> for MBox<T> {
144    fn borrow(&self) -> &T {
145        self
146    }
147}
148
149impl<T: ?Sized + Free> BorrowMut<T> for MBox<T> {
150    fn borrow_mut(&mut self) -> &mut T {
151        self
152    }
153}
154
155#[cfg(feature = "nightly")]
156impl<T: ?Sized + Free + Unsize<U>, U: ?Sized + Free> CoerceUnsized<MBox<U>> for MBox<T> {}
157
158impl<T: ?Sized + Free> Pointer for MBox<T> {
159    fn fmt(&self, formatter: &mut Formatter) -> FormatResult {
160        Pointer::fmt(&Self::as_ptr(self), formatter)
161    }
162}
163
164impl<T: ?Sized + Free + Debug> Debug for MBox<T> {
165    fn fmt(&self, formatter: &mut Formatter) -> FormatResult {
166        self.deref().fmt(formatter)
167    }
168}
169
170impl<T: ?Sized + Free + Display> Display for MBox<T> {
171    fn fmt(&self, formatter: &mut Formatter) -> FormatResult {
172        self.deref().fmt(formatter)
173    }
174}
175
176impl<T: ?Sized + Free + Hash> Hash for MBox<T> {
177    fn hash<H: Hasher>(&self, state: &mut H) {
178        self.deref().hash(state)
179    }
180}
181
182impl<U: ?Sized + Free, T: ?Sized + Free + PartialEq<U>> PartialEq<MBox<U>> for MBox<T> {
183    fn eq(&self, other: &MBox<U>) -> bool {
184        self.deref().eq(other.deref())
185    }
186}
187
188impl<T: ?Sized + Free + Eq> Eq for MBox<T> {}
189
190impl<U: ?Sized + Free, T: ?Sized + Free + PartialOrd<U>> PartialOrd<MBox<U>> for MBox<T> {
191    fn partial_cmp(&self, other: &MBox<U>) -> Option<Ordering> {
192        self.deref().partial_cmp(other.deref())
193    }
194}
195
196impl<T: ?Sized + Free + Ord> Ord for MBox<T> {
197    fn cmp(&self, other: &Self) -> Ordering {
198        self.deref().cmp(other.deref())
199    }
200}
201
202//}}}
203
204//{{{ Single object -------------------------------------------------------------------------------
205
206impl<T> MBox<T> {
207    /// Constructs a new malloc-backed box, and move an initialized value into it.
208    pub fn new(value: T) -> Self {
209        let storage = gen_malloc(1);
210        // SAFETY: the `storage` is uninitialized and enough to store T.
211        // this pointer is obtained via `malloc` and thus good for `from_raw`.
212        unsafe {
213            write(storage.as_ptr(), value);
214            Self::from_non_null_raw(storage)
215        }
216    }
217
218    /// Constructs a new malloc-backed box with uninitialized content.
219    pub fn new_uninit() -> MBox<MaybeUninit<T>> {
220        let storage = gen_malloc(1);
221        // SAFETY: The storage is allowed to be uninitialized.
222        unsafe { MBox::from_non_null_raw(storage) }
223    }
224
225    /// Constructs a new `Pin<MBox<T>>`. If `T` does not implement `Unpin`, then `value` will be
226    /// pinned in memory and cannot be moved.
227    pub fn pin(value: T) -> Pin<Self> {
228        Self::into_pin(Self::new(value))
229    }
230
231    /// Converts an `MBox<T>` into a single-item `MBox<[T]>`.
232    ///
233    /// This conversion does not allocate on the heap and happens in place.
234    pub fn into_boxed_slice(boxed: Self) -> MBox<[T]> {
235        // SAFETY: free() only cares about the allocated size, and `T` and
236        // `[T; 1]` are equivalent in terms of drop() and free().
237        unsafe { MBox::from_raw_parts(Self::into_raw(boxed), 1) }
238    }
239
240    /// Consumes the `MBox`, returning the wrapped value.
241    pub fn into_inner(boxed: Self) -> T {
242        let mut dst = MaybeUninit::uninit();
243        let src = Self::into_non_null_raw(boxed);
244        // SAFETY: after calling `into_raw` above, we have the entire ownership of the malloc'ed
245        // pointer `src`. The content is moved into the destination. After that, we can free `src`
246        // without touching the content. So there is a single copy of the content fully initialized
247        // into `dst` which is safe to assume_init.
248        unsafe {
249            copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), 1);
250            gen_free(src);
251            dst.assume_init()
252        }
253    }
254
255    /// Converts an `MBox<T>` into a `Pin<MBox<T>>`.
256    ///
257    /// This conversion does not allocate on the heap and happens in place.
258    pub fn into_pin(boxed: Self) -> Pin<Self> {
259        // SAFETY: Same reason as why `Box::into_pin` is safe.
260        unsafe { Pin::new_unchecked(boxed) }
261    }
262
263    /// Consumes and leaks the `MBox`, returning a mutable reference, `&'a mut T`.
264    pub fn leak<'a>(boxed: Self) -> &'a mut T
265    where
266        T: 'a,
267    {
268        // SAFETY: into_raw takes the ownership of the box, which is then immediately leaked. Thus,
269        // no one is able to call `gen_free` on this pointer and thus safe to be used in the rest of
270        // its lifetime.
271        unsafe { &mut *Self::into_non_null_raw(boxed).as_ptr() }
272    }
273}
274
275impl<T> MBox<MaybeUninit<T>> {
276    /// Converts into an initialized box.
277    ///
278    /// # Safety
279    ///
280    /// The caller should guarantee `*self` is indeed initialized.
281    pub unsafe fn assume_init(self) -> MBox<T> {
282        MBox::from_non_null_raw(Self::into_non_null_raw(self).cast())
283    }
284}
285
286impl<T> From<T> for MBox<T> {
287    fn from(value: T) -> MBox<T> {
288        MBox::new(value)
289    }
290}
291
292impl<T: Clone> Clone for MBox<T> {
293    fn clone(&self) -> MBox<T> {
294        Self::new(self.deref().clone())
295    }
296
297    fn clone_from(&mut self, source: &Self) {
298        self.deref_mut().clone_from(source);
299    }
300}
301
302impl<T: Default> Default for MBox<T> {
303    fn default() -> MBox<T> {
304        MBox::new(T::default())
305    }
306}
307
308#[cfg(not(windows))]
309#[test]
310fn test_single_object() {
311    let counter = DropCounter::default();
312    {
313        let mbox = MBox::new(counter.clone());
314        counter.assert_eq(0);
315        drop(mbox);
316    }
317    counter.assert_eq(1);
318}
319
320#[test]
321fn test_into_raw() {
322    let mbox = MBox::new(66u8);
323    let raw = MBox::into_raw(mbox);
324    unsafe {
325        assert_eq!(*raw, 66u8);
326        gen_free(NonNull::new(raw).unwrap());
327    }
328}
329
330#[cfg(not(windows))]
331#[test]
332fn test_clone() {
333    let counter = DropCounter::default();
334    {
335        let first_mbox = MBox::new(counter.clone());
336        {
337            let second_mbox = first_mbox.clone();
338            counter.assert_eq(0);
339            drop(second_mbox);
340        }
341        counter.assert_eq(1);
342    }
343    counter.assert_eq(2);
344}
345
346#[cfg(not(windows))]
347#[test]
348fn test_clone_from() {
349    let counter = DropCounter::default();
350    {
351        let first_mbox = MBox::new(counter.clone());
352        {
353            let mut second_mbox = MBox::new(counter.clone());
354            counter.assert_eq(0);
355            second_mbox.clone_from(&first_mbox);
356            counter.assert_eq(1);
357        }
358        counter.assert_eq(2);
359    }
360    counter.assert_eq(3);
361}
362
363#[cfg(not(windows))]
364#[test]
365fn test_no_drop_flag() {
366    fn do_test_for_drop_flag(branch: bool, expected: usize) {
367        let counter = DropCounter::default();
368        let inner_counter = counter.deref().clone();
369        {
370            let mbox;
371            if branch {
372                mbox = MBox::new(counter.clone());
373                let _ = &mbox;
374            }
375            inner_counter.assert_eq(0);
376        }
377        inner_counter.assert_eq(expected);
378    }
379
380    do_test_for_drop_flag(true, 1);
381    do_test_for_drop_flag(false, 0);
382
383    assert_eq!(
384        size_of::<MBox<DropCounter>>(),
385        size_of::<*mut DropCounter>()
386    );
387}
388
389#[cfg(feature = "std")]
390#[test]
391fn test_format() {
392    let a = MBox::new(3u8);
393    assert_eq!(format!("{:p}", a), format!("{:p}", MBox::as_ptr(&a)));
394    assert_eq!(format!("{}", a), "3");
395    assert_eq!(format!("{:?}", a), "3");
396}
397
398#[test]
399fn test_standard_traits() {
400    let mut a = MBox::new(0u8);
401    assert_eq!(*a, 0);
402    *a = 3;
403    assert_eq!(*a, 3);
404    assert_eq!(*a.as_ref(), 3);
405    assert_eq!(*a.as_mut(), 3);
406    assert_eq!(*(a.borrow() as &u8), 3);
407    assert_eq!(*(a.borrow_mut() as &mut u8), 3);
408    assert!(a == MBox::new(3u8));
409    assert!(a != MBox::new(0u8));
410    assert!(a < MBox::new(4u8));
411    assert!(a > MBox::new(2u8));
412    assert!(a <= MBox::new(4u8));
413    assert!(a >= MBox::new(2u8));
414    assert_eq!(a.cmp(&MBox::new(7u8)), Ordering::Less);
415    assert_eq!(MBox::<u8>::default(), MBox::new(0u8));
416}
417
418#[test]
419fn test_zero_sized_type() {
420    let a = MBox::new(());
421    assert!(!MBox::as_ptr(&a).is_null());
422}
423
424#[cfg(not(windows))]
425#[test]
426fn test_non_zero() {
427    let b = 0u64;
428    assert!(!Some(MBox::new(0u64)).is_none());
429    assert!(!Some(MBox::new(())).is_none());
430    assert!(!Some(MBox::new(&b)).is_none());
431
432    assert_eq!(size_of::<Option<MBox<u64>>>(), size_of::<MBox<u64>>());
433    assert_eq!(size_of::<Option<MBox<()>>>(), size_of::<MBox<()>>());
434    assert_eq!(
435        size_of::<Option<MBox<&'static u64>>>(),
436        size_of::<MBox<&'static u64>>()
437    );
438}
439
440#[cfg(not(windows))]
441#[test]
442fn test_aligned() {
443    use std::mem::align_of;
444
445    let b = MBox::new(1u16);
446    assert_eq!(MBox::as_ptr(&b) as usize % align_of::<u16>(), 0);
447
448    let b = MBox::new(1u32);
449    assert_eq!(MBox::as_ptr(&b) as usize % align_of::<u32>(), 0);
450
451    let b = MBox::new(1u64);
452    assert_eq!(MBox::as_ptr(&b) as usize % align_of::<u64>(), 0);
453
454    #[repr(C, align(4096))]
455    struct A(u8);
456
457    let b = MBox::new(A(2));
458    assert_eq!(MBox::as_ptr(&b) as usize % 4096, 0);
459}
460
461//}}}
462
463//{{{ Slice helpers -------------------------------------------------------------------------------
464
465mod slice_helper {
466    use super::*;
467
468    /// A `Vec`-like structure backed by `malloc()`.
469    pub struct MSliceBuilder<T> {
470        ptr: NonNull<T>,
471        cap: usize,
472        len: usize,
473    }
474
475    impl<T> MSliceBuilder<T> {
476        /// Creates a new slice builder with an initial capacity.
477        pub fn with_capacity(cap: usize) -> MSliceBuilder<T> {
478            MSliceBuilder {
479                ptr: gen_malloc(cap),
480                cap,
481                len: 0,
482            }
483        }
484
485        pub fn push(&mut self, obj: T) {
486            if self.len >= self.cap {
487                let new_cap = (self.cap * 2).max(1);
488                // SAFETY:
489                //  - ptr is initialized from gen_malloc() so it can be placed into gen_realloc()
490                unsafe {
491                    self.ptr = gen_realloc(self.ptr, self.cap, new_cap);
492                }
493                self.cap = new_cap;
494            }
495
496            // SAFETY:
497            //  - we guarantee that `ptr `points to an array of nonzero length `cap`, and
498            //    the `if` condition ensures the invariant `self.len < cap`, so
499            //    `ptr.add(self.len)` is always a valid (but uninitialized) object.
500            //  - since `ptr[self.len]` is not yet initialized, we can `write()` into it safely.
501            unsafe {
502                write(self.ptr.as_ptr().add(self.len), obj);
503            }
504            self.len += 1;
505        }
506
507        pub fn into_mboxed_slice(self) -> MBox<[T]> {
508            // SAFETY: `self.ptr` has been allocated by malloc(), and its length is self.cap
509            // (>= self.len).
510            let slice = unsafe { MBox::from_raw_parts(self.ptr.as_ptr(), self.len) };
511            forget(self);
512            slice
513        }
514    }
515
516    impl<T> MSliceBuilder<MaybeUninit<T>> {
517        /// Sets the length of the builder to the same as the capacity. The elements in the
518        /// uninitialized tail remains uninitialized.
519        pub fn set_len_to_cap(&mut self) {
520            self.len = self.cap;
521        }
522    }
523
524    impl<T> Drop for MSliceBuilder<T> {
525        fn drop(&mut self) {
526            // SAFETY: `ptr` has been allocated by `gen_malloc()`.
527            unsafe {
528                gen_free(self.ptr);
529            }
530        }
531    }
532
533    #[repr(C)]
534    struct SliceParts<T> {
535        ptr: *mut T,
536        len: usize,
537    }
538
539    impl<T> Clone for SliceParts<T> {
540        fn clone(&self) -> Self {
541            Self {
542                ptr: self.ptr,
543                len: self.len,
544            }
545        }
546    }
547    impl<T> Copy for SliceParts<T> {}
548
549    #[repr(C)]
550    union SliceTransformer<T> {
551        fat_ptr: *mut [T],
552        parts: SliceParts<T>,
553    }
554
555    // TODO: maybe upgrade Rust to 1.42 to get rid of this function.
556    pub fn slice_from_raw_parts_mut<T>(ptr: *mut T, len: usize) -> *mut [T] {
557        // SAFETY: just the same code of the function from std.
558        unsafe {
559            SliceTransformer {
560                parts: SliceParts { ptr, len },
561            }
562            .fat_ptr
563        }
564    }
565
566    pub fn slice_into_raw_parts_mut<T>(fat_ptr: *mut [T]) -> (*mut T, usize) {
567        let parts = unsafe { SliceTransformer { fat_ptr }.parts };
568        (parts.ptr, parts.len)
569    }
570}
571
572use self::slice_helper::{slice_from_raw_parts_mut, slice_into_raw_parts_mut, MSliceBuilder};
573
574/// The iterator returned from `MBox<[T]>::into_iter()`.
575pub struct MSliceIntoIter<T> {
576    ptr: NonNull<T>,
577    begin: usize,
578    end: usize,
579}
580
581impl<T> Iterator for MSliceIntoIter<T> {
582    type Item = T;
583
584    fn next(&mut self) -> Option<T> {
585        if self.begin == self.end {
586            None
587        } else {
588            unsafe {
589                let ptr = self.ptr.as_ptr().add(self.begin);
590                self.begin += 1;
591                Some(read(ptr))
592            }
593        }
594    }
595
596    fn size_hint(&self) -> (usize, Option<usize>) {
597        let len = self.end - self.begin;
598        (len, Some(len))
599    }
600}
601
602impl<T> DoubleEndedIterator for MSliceIntoIter<T> {
603    fn next_back(&mut self) -> Option<T> {
604        if self.begin == self.end {
605            None
606        } else {
607            unsafe {
608                self.end -= 1;
609                let ptr = self.ptr.as_ptr().add(self.end);
610                Some(read(ptr))
611            }
612        }
613    }
614}
615
616unsafe impl<T: Send> Send for MSliceIntoIter<T> {}
617unsafe impl<T: Sync> Sync for MSliceIntoIter<T> {}
618
619impl<T> ExactSizeIterator for MSliceIntoIter<T> {}
620
621impl<T> Drop for MSliceIntoIter<T> {
622    fn drop(&mut self) {
623        unsafe {
624            let base = self.ptr.as_ptr().add(self.begin);
625            let len = self.end - self.begin;
626            let slice = slice_from_raw_parts_mut(base, len);
627            drop_in_place(slice);
628            gen_free(self.ptr);
629        }
630    }
631}
632
633//}}}
634
635//{{{ Slice ---------------------------------------------------------------------------------------
636
637impl<T> MBox<[T]> {
638    /// Constructs a new malloc-backed slice from the pointer and the length (number of items).
639    ///
640    /// # Safety
641    ///
642    /// `ptr` must be allocated via `malloc()` or similar C functions. It must be aligned and not null.
643    ///
644    /// The `malloc`ed size of the pointer must be at least `len * size_of::<T>()`. The content
645    /// must already been initialized.
646    pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self {
647        Self::from_raw(slice_from_raw_parts_mut(ptr, len))
648    }
649
650    /// Constructs a new boxed slice with uninitialized contents.
651    pub fn new_uninit_slice(len: usize) -> MBox<[MaybeUninit<T>]> {
652        let mut builder = MSliceBuilder::with_capacity(len);
653        builder.set_len_to_cap();
654        builder.into_mboxed_slice()
655    }
656
657    /// Decomposes the boxed slice into a pointer to the first element and the slice length.
658    pub fn into_raw_parts(mut self) -> (*mut T, usize) {
659        let (ptr, len) = slice_into_raw_parts_mut(Self::as_mut_ptr(&mut self));
660        forget(self);
661        (ptr, len)
662    }
663}
664
665impl<T> MBox<[MaybeUninit<T>]> {
666    /// Converts into an initialized boxed slice.
667    ///
668    /// # Safety
669    ///
670    /// The caller should guarantee `*self` is indeed initialized.
671    pub unsafe fn assume_init(self) -> MBox<[T]> {
672        MBox::from_raw(Self::into_raw(self) as *mut [T])
673    }
674}
675
676impl<T> Default for MBox<[T]> {
677    fn default() -> Self {
678        unsafe { Self::from_raw_parts(gen_malloc(0).as_ptr(), 0) }
679    }
680}
681
682impl<T: Clone> Clone for MBox<[T]> {
683    fn clone(&self) -> Self {
684        Self::from_slice(self)
685    }
686}
687
688impl<T: Clone> MBox<[T]> {
689    /// Creates a new `malloc`-boxed slice by cloning the content of an existing slice.
690    pub fn from_slice(slice: &[T]) -> MBox<[T]> {
691        let mut builder = MSliceBuilder::with_capacity(slice.len());
692        for item in slice {
693            builder.push(item.clone());
694        }
695        builder.into_mboxed_slice()
696    }
697}
698
699impl<T> FromIterator<T> for MBox<[T]> {
700    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
701        let iter = iter.into_iter();
702        let (lower_size, upper_size) = iter.size_hint();
703        let initial_capacity = upper_size.unwrap_or(lower_size).max(1);
704        let mut builder = MSliceBuilder::with_capacity(initial_capacity);
705        for item in iter {
706            builder.push(item);
707        }
708        builder.into_mboxed_slice()
709    }
710}
711
712impl<T> IntoIterator for MBox<[T]> {
713    type Item = T;
714    type IntoIter = MSliceIntoIter<T>;
715    fn into_iter(self) -> MSliceIntoIter<T> {
716        let (ptr, len) = self.into_raw_parts();
717        MSliceIntoIter {
718            ptr: unsafe { NonNull::new_unchecked(ptr) },
719            begin: 0,
720            end: len,
721        }
722    }
723}
724
725impl<'a, T> IntoIterator for &'a MBox<[T]> {
726    type Item = &'a T;
727    type IntoIter = Iter<'a, T>;
728    fn into_iter(self) -> Iter<'a, T> {
729        self.iter()
730    }
731}
732
733impl<'a, T> IntoIterator for &'a mut MBox<[T]> {
734    type Item = &'a mut T;
735    type IntoIter = IterMut<'a, T>;
736    fn into_iter(self) -> IterMut<'a, T> {
737        self.iter_mut()
738    }
739}
740
741#[cfg(not(windows))]
742#[test]
743fn test_slice() {
744    unsafe {
745        let slice_content = gen_malloc::<u64>(5).as_ptr();
746        *slice_content.offset(0) = 16458340076686561191;
747        *slice_content.offset(1) = 15635007859502065083;
748        *slice_content.offset(2) = 4845947824042606450;
749        *slice_content.offset(3) = 8907026173756975745;
750        *slice_content.offset(4) = 7378932587879886134;
751        let mbox = MBox::from_raw_parts(slice_content, 5);
752        assert_eq!(
753            &mbox as &[u64],
754            &[
755                16458340076686561191,
756                15635007859502065083,
757                4845947824042606450,
758                8907026173756975745,
759                7378932587879886134
760            ]
761        );
762    }
763}
764
765#[cfg(not(windows))]
766#[test]
767fn test_slice_with_drops() {
768    let counter = DropCounter::default();
769    unsafe {
770        let slice_content = gen_malloc::<DropCounter>(3).as_ptr();
771        {
772            write(slice_content.offset(0), counter.clone());
773            write(slice_content.offset(1), counter.clone());
774            write(slice_content.offset(2), counter.clone());
775        }
776        counter.assert_eq(0);
777        let mbox = MBox::from_raw_parts(slice_content, 3);
778        mbox[0].assert_eq(0);
779        mbox[1].assert_eq(0);
780        mbox[2].assert_eq(0);
781        assert_eq!(mbox.len(), 3);
782    }
783    counter.assert_eq(3);
784}
785
786#[cfg(feature = "nightly")]
787#[test]
788fn test_coerce_unsized() {
789    let counter = DropCounter::default();
790    {
791        let pre_box = MBox::new([counter.clone(), counter.clone()]);
792        counter.assert_eq(0);
793        pre_box[0].assert_eq(0);
794        pre_box[1].assert_eq(0);
795        assert_eq!(pre_box.len(), 2);
796
797        let post_box: MBox<[DropCounter]> = pre_box;
798        counter.assert_eq(0);
799        post_box[0].assert_eq(0);
800        post_box[1].assert_eq(0);
801        assert_eq!(post_box.len(), 2);
802    }
803    counter.assert_eq(2);
804}
805
806#[cfg(not(windows))]
807#[test]
808#[allow(useless_ptr_null_checks)]
809fn test_empty_slice() {
810    let mbox = MBox::<[DropCounter]>::default();
811    let sl: &[DropCounter] = &mbox;
812    assert_eq!(sl.len(), 0);
813    assert!(!sl.as_ptr().is_null());
814}
815
816#[cfg(all(feature = "nightly", not(windows)))]
817#[test]
818#[allow(useless_ptr_null_checks)]
819fn test_coerce_from_empty_slice() {
820    let pre_box = MBox::<[DropCounter; 0]>::new([]);
821    assert_eq!(pre_box.len(), 0);
822    assert!(!pre_box.as_ptr().is_null());
823
824    let post_box: MBox<[DropCounter]> = pre_box;
825    let sl: &[DropCounter] = &post_box;
826    assert_eq!(sl.len(), 0);
827    assert!(!sl.as_ptr().is_null());
828}
829
830#[cfg(not(windows))]
831#[test]
832fn test_clone_slice() {
833    let counter = DropCounter::default();
834    unsafe {
835        let slice_content = gen_malloc::<DropCounter>(3).as_ptr();
836        {
837            write(slice_content.offset(0), counter.clone());
838            write(slice_content.offset(1), counter.clone());
839            write(slice_content.offset(2), counter.clone());
840        }
841        let mbox = MBox::from_raw_parts(slice_content, 3);
842        assert_eq!(mbox.len(), 3);
843
844        {
845            let cloned_mbox = mbox.clone();
846            counter.assert_eq(0);
847            assert_eq!(cloned_mbox.len(), 3);
848            cloned_mbox[0].assert_eq(0);
849            cloned_mbox[1].assert_eq(0);
850            cloned_mbox[2].assert_eq(0);
851        }
852
853        counter.assert_eq(3);
854        mbox[0].assert_eq(3);
855        mbox[1].assert_eq(3);
856        mbox[2].assert_eq(3);
857    }
858
859    counter.assert_eq(6);
860}
861
862#[cfg(not(windows))]
863#[test]
864fn test_from_iterator() {
865    let counter = DropCounter::default();
866    {
867        let slice = repeat(counter.clone()).take(18).collect::<MBox<[_]>>();
868        counter.assert_eq(1);
869        assert_eq!(slice.len(), 18);
870        for c in &slice {
871            c.assert_eq(1);
872        }
873    }
874    counter.assert_eq(19);
875}
876
877#[test]
878fn test_from_iterator_with_no_size_hint() {
879    struct RedactSizeHint<I>(I);
880
881    impl<I: Iterator> Iterator for RedactSizeHint<I> {
882        type Item = I::Item;
883
884        fn next(&mut self) -> Option<Self::Item> {
885            self.0.next()
886        }
887    }
888
889    let it = RedactSizeHint(b"1234567890".iter().copied());
890    assert_eq!(it.size_hint(), (0, None));
891    let slice = it.collect::<MBox<[u8]>>();
892    assert_eq!(&*slice, b"1234567890");
893}
894
895#[cfg(not(windows))]
896#[test]
897fn test_into_iterator() {
898    let counter = DropCounter::default();
899    {
900        let slice = repeat(counter.clone()).take(18).collect::<MBox<[_]>>();
901        counter.assert_eq(1);
902        assert_eq!(slice.len(), 18);
903        for (c, i) in slice.into_iter().zip(1..) {
904            c.assert_eq(i);
905        }
906    }
907    counter.assert_eq(19);
908}
909
910#[cfg(feature = "std")]
911#[test]
912fn test_iter_properties() {
913    let slice = vec![1i8, 4, 9, 16, 25].into_iter().collect::<MBox<[_]>>();
914    let mut iter = slice.into_iter();
915    assert_eq!(iter.size_hint(), (5, Some(5)));
916    assert_eq!(iter.len(), 5);
917    assert_eq!(iter.next(), Some(1));
918    assert_eq!(iter.next_back(), Some(25));
919    assert_eq!(iter.size_hint(), (3, Some(3)));
920    assert_eq!(iter.len(), 3);
921    assert_eq!(iter.collect::<Vec<_>>(), vec![4, 9, 16]);
922}
923
924#[cfg(not(windows))]
925#[test]
926fn test_iter_drop() {
927    let counter = DropCounter::default();
928    {
929        let slice = repeat(counter.clone()).take(18).collect::<MBox<[_]>>();
930        counter.assert_eq(1);
931        assert_eq!(slice.len(), 18);
932
933        let mut iter = slice.into_iter();
934        counter.assert_eq(1);
935        {
936            iter.next().unwrap().assert_eq(1)
937        };
938        {
939            iter.next().unwrap().assert_eq(2)
940        };
941        {
942            iter.next_back().unwrap().assert_eq(3)
943        };
944        counter.assert_eq(4);
945    }
946    counter.assert_eq(19);
947}
948
949#[test]
950fn test_zst_slice() {
951    let slice = repeat(()).take(7).collect::<MBox<[_]>>();
952    let _ = slice.clone();
953    slice.into_iter();
954}
955
956#[test]
957#[should_panic(expected = "panic on clone")]
958fn test_panic_during_clone() {
959    let mbox = MBox::<PanicOnClone>::default();
960    let _ = mbox.clone();
961}
962
963#[test]
964#[should_panic(expected = "panic on clone")]
965fn test_panic_during_clone_from() {
966    let mut mbox = MBox::<PanicOnClone>::default();
967    let other = MBox::default();
968    mbox.clone_from(&other);
969}
970
971//}}}
972
973//{{{ UTF-8 String --------------------------------------------------------------------------------
974
975impl MBox<str> {
976    /// Constructs a new malloc-backed string from the pointer and the length (number of UTF-8 code
977    /// units).
978    ///
979    /// # Safety
980    ///
981    /// The `malloc`ed size of the pointer must be at least `len`. The content must already been
982    /// initialized and be valid UTF-8.
983    pub unsafe fn from_raw_utf8_parts_unchecked(value: *mut u8, len: usize) -> MBox<str> {
984        Self::from_utf8_unchecked(MBox::from_raw_parts(value, len))
985    }
986
987    /// Constructs a new malloc-backed string from the pointer and the length (number of UTF-8 code
988    /// units). If the content does not contain valid UTF-8, this method returns an `Err`.
989    ///
990    /// # Safety
991    ///
992    /// The `malloc`ed size of the pointer must be at least `len`.
993    /// The content must already been initialized.
994    pub unsafe fn from_raw_utf8_parts(value: *mut u8, len: usize) -> Result<MBox<str>, Utf8Error> {
995        Self::from_utf8(MBox::from_raw_parts(value, len))
996    }
997
998    /// Converts the string into raw bytes.
999    pub fn into_bytes(self) -> MBox<[u8]> {
1000        unsafe { MBox::from_raw(Self::into_raw(self) as *mut [u8]) }
1001    }
1002
1003    /// Creates a string from raw bytes.
1004    ///
1005    /// # Safety
1006    ///
1007    /// The raw bytes must be valid UTF-8.
1008    pub unsafe fn from_utf8_unchecked(bytes: MBox<[u8]>) -> MBox<str> {
1009        Self::from_raw(MBox::into_raw(bytes) as *mut str)
1010    }
1011
1012    /// Creates a string from raw bytes. If the content does not contain valid UTF-8, this method
1013    /// returns an `Err`.
1014    pub fn from_utf8(bytes: MBox<[u8]>) -> Result<MBox<str>, Utf8Error> {
1015        from_utf8(&bytes)?;
1016        unsafe { Ok(Self::from_utf8_unchecked(bytes)) }
1017    }
1018}
1019
1020impl Default for MBox<str> {
1021    fn default() -> Self {
1022        unsafe { Self::from_raw_utf8_parts_unchecked(gen_malloc(0).as_ptr(), 0) }
1023    }
1024}
1025
1026impl Clone for MBox<str> {
1027    fn clone(&self) -> Self {
1028        Self::from(&**self)
1029    }
1030}
1031
1032impl From<&str> for MBox<str> {
1033    /// Creates a new `malloc`-boxed string by cloning the content of an existing string slice.
1034    fn from(string: &str) -> Self {
1035        let len = string.len();
1036        let new_slice = gen_malloc(len).as_ptr();
1037        // SAFETY: `new_slice` is not null, allocated with size fitting `string`,
1038        // and also `string` is guaranteed to be UTF-8.
1039        unsafe {
1040            copy_nonoverlapping(string.as_ptr(), new_slice, len);
1041            Self::from_raw_utf8_parts_unchecked(new_slice, len)
1042        }
1043    }
1044}
1045
1046#[test]
1047fn test_string_from_bytes() {
1048    let bytes = MBox::from_slice(b"abcdef\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89");
1049    let string = MBox::from_utf8(bytes).unwrap();
1050    assert_eq!(&*string, "abcdef一二三");
1051    assert_eq!(string, MBox::<str>::from("abcdef一二三"));
1052    let bytes = string.into_bytes();
1053    assert_eq!(&*bytes, b"abcdef\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89");
1054}
1055
1056#[test]
1057fn test_string_with_internal_nul() {
1058    let string = MBox::<str>::from("ab\0c");
1059    assert_eq!(&*string, "ab\0c");
1060}
1061
1062#[test]
1063fn test_non_utf8() {
1064    let bytes = MBox::from_slice(b"\x88\x88\x88\x88");
1065    let string = MBox::from_utf8(bytes);
1066    assert!(string.is_err());
1067}
1068
1069#[test]
1070fn test_default_str() {
1071    assert_eq!(MBox::<str>::default(), MBox::<str>::from(""));
1072}
1073
1074#[test]
1075#[should_panic(expected = "panic on clone")]
1076fn test_panic_on_clone_slice() {
1077    let mbox: MBox<[PanicOnClone]> = once(PanicOnClone::default()).collect();
1078    let _ = mbox.clone();
1079}
1080
1081//}}}