allocator_api2/
slice.rs

1use crate::{
2    alloc::{Allocator, Global},
3    vec::Vec,
4};
5
6/// Slice methods that use `Box` and `Vec` from this crate.
7pub trait SliceExt<T> {
8    /// Copies `self` into a new `Vec`.
9    ///
10    /// # Examples
11    ///
12    /// ```
13    /// use allocator_api2::SliceExt;
14    ///
15    /// let s = [10, 40, 30];
16    /// let x = SliceExt::to_vec(&s[..]);
17    /// // Here, `s` and `x` can be modified independently.
18    /// ```
19    #[cfg(not(no_global_oom_handling))]
20    #[inline(always)]
21    fn to_vec(&self) -> Vec<T, Global>
22    where
23        T: Clone,
24    {
25        self.to_vec_in2(Global)
26    }
27    
28    /// Copies `self` into a new `Vec`.
29    ///
30    /// # Examples
31    ///
32    /// ```
33    /// use allocator_api2::SliceExt;
34    ///
35    /// let s = [10, 40, 30];
36    /// let x = s.to_vec2();
37    /// // Here, `s` and `x` can be modified independently.
38    /// ```
39    #[cfg(not(no_global_oom_handling))]
40    #[inline(always)]
41    fn to_vec2(&self) -> Vec<T, Global>
42    where
43        T: Clone,
44    {
45        self.to_vec_in2(Global)
46    }
47
48    /// Copies `self` into a new `Vec` with an allocator.
49    ///
50    /// # Examples
51    ///
52    /// ```
53    /// use allocator_api2::{SliceExt, alloc::System};
54    ///
55    /// let s = [10, 40, 30];
56    /// let x = SliceExt::to_vec_in(&s[..], System);
57    /// // Here, `s` and `x` can be modified independently.
58    /// ```
59    #[cfg(not(no_global_oom_handling))]
60    fn to_vec_in<A: Allocator>(&self, alloc: A) -> Vec<T, A>
61    where
62        T: Clone,
63    {
64        Self::to_vec_in2(self, alloc)
65    }
66
67    /// Copies `self` into a new `Vec` with an allocator.
68    ///
69    /// # Examples
70    ///
71    /// ```
72    /// use allocator_api2::{SliceExt, alloc::System};
73    ///
74    /// let s = [10, 40, 30];
75    /// let x = s.to_vec_in2(System);
76    /// // Here, `s` and `x` can be modified independently.
77    /// ```
78    #[cfg(not(no_global_oom_handling))]
79    fn to_vec_in2<A: Allocator>(&self, alloc: A) -> Vec<T, A>
80    where
81        T: Clone;
82
83    /// Creates a vector by copying a slice `n` times.
84    ///
85    /// # Panics
86    ///
87    /// This function will panic if the capacity would overflow.
88    ///
89    /// # Examples
90    ///
91    /// Basic usage:
92    ///
93    /// ```
94    /// use allocator_api2::{SliceExt, vec};
95    ///
96    /// assert_eq!(SliceExt::repeat(&[1, 2][..], 3), vec![1, 2, 1, 2, 1, 2]);
97    /// ```
98    ///
99    /// A panic upon overflow:
100    ///
101    /// ```should_panic
102    /// // this will panic at runtime
103    /// b"0123456789abcdef".repeat(usize::MAX);
104    /// ```
105    fn repeat(&self, n: usize) -> Vec<T, Global>
106    where
107        T: Copy,
108    {
109        Self::repeat2(self, n)
110    }
111        
112    /// Creates a vector by copying a slice `n` times.
113    ///
114    /// # Panics
115    ///
116    /// This function will panic if the capacity would overflow.
117    ///
118    /// # Examples
119    ///
120    /// Basic usage:
121    ///
122    /// ```
123    /// use allocator_api2::{SliceExt, vec};
124    ///
125    /// assert_eq!([1, 2].repeat2(3), vec![1, 2, 1, 2, 1, 2]);
126    /// ```
127    ///
128    /// A panic upon overflow:
129    ///
130    /// ```should_panic
131    /// // this will panic at runtime
132    /// b"0123456789abcdef".repeat(usize::MAX);
133    /// ```
134    fn repeat2(&self, n: usize) -> Vec<T, Global>
135    where
136        T: Copy;
137}
138
139impl<T> SliceExt<T> for [T] {
140    #[cfg(not(no_global_oom_handling))]
141    #[inline]
142    fn to_vec_in2<A: Allocator>(&self, alloc: A) -> Vec<T, A>
143    where
144        T: Clone,
145    {
146        struct DropGuard<'a, T, A: Allocator> {
147            vec: &'a mut Vec<T, A>,
148            num_init: usize,
149        }
150        impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> {
151            #[inline]
152            fn drop(&mut self) {
153                // SAFETY:
154                // items were marked initialized in the loop below
155                unsafe {
156                    self.vec.set_len(self.num_init);
157                }
158            }
159        }
160
161        let mut vec = Vec::with_capacity_in(self.len(), alloc);
162        let mut guard = DropGuard {
163            vec: &mut vec,
164            num_init: 0,
165        };
166        let slots = guard.vec.spare_capacity_mut();
167        // .take(slots.len()) is necessary for LLVM to remove bounds checks
168        // and has better codegen than zip.
169        for (i, b) in self.iter().enumerate().take(slots.len()) {
170            guard.num_init = i;
171            slots[i].write(b.clone());
172        }
173        core::mem::forget(guard);
174        // SAFETY:
175        // the vec was allocated and initialized above to at least this length.
176        unsafe {
177            vec.set_len(self.len());
178        }
179        vec
180    }
181
182    #[cfg(not(no_global_oom_handling))]
183    #[inline]
184    fn repeat2(&self, n: usize) -> Vec<T, Global>
185    where
186        T: Copy,
187    {
188        if n == 0 {
189            return Vec::new();
190        }
191
192        // If `n` is larger than zero, it can be split as
193        // `n = 2^expn + rem (2^expn > rem, expn >= 0, rem >= 0)`.
194        // `2^expn` is the number represented by the leftmost '1' bit of `n`,
195        // and `rem` is the remaining part of `n`.
196
197        // Using `Vec` to access `set_len()`.
198        let capacity = self.len().checked_mul(n).expect("capacity overflow");
199        let mut buf = Vec::with_capacity(capacity);
200
201        // `2^expn` repetition is done by doubling `buf` `expn`-times.
202        buf.extend(self);
203        {
204            let mut m = n >> 1;
205            // If `m > 0`, there are remaining bits up to the leftmost '1'.
206            while m > 0 {
207                // `buf.extend(buf)`:
208                unsafe {
209                    core::ptr::copy_nonoverlapping(
210                        buf.as_ptr(),
211                        (buf.as_mut_ptr() as *mut T).add(buf.len()),
212                        buf.len(),
213                    );
214                    // `buf` has capacity of `self.len() * n`.
215                    let buf_len = buf.len();
216                    buf.set_len(buf_len * 2);
217                }
218
219                m >>= 1;
220            }
221        }
222
223        // `rem` (`= n - 2^expn`) repetition is done by copying
224        // first `rem` repetitions from `buf` itself.
225        let rem_len = capacity - buf.len(); // `self.len() * rem`
226        if rem_len > 0 {
227            // `buf.extend(buf[0 .. rem_len])`:
228            unsafe {
229                // This is non-overlapping since `2^expn > rem`.
230                core::ptr::copy_nonoverlapping(
231                    buf.as_ptr(),
232                    (buf.as_mut_ptr() as *mut T).add(buf.len()),
233                    rem_len,
234                );
235                // `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`).
236                buf.set_len(capacity);
237            }
238        }
239        buf
240    }
241}