Coverage Report

Created: 2025-02-25 06:39

/rust/registry/src/index.crates.io-6f17d22bba15001f/aligned-vec-0.6.1/src/raw.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Alignment, TryReserveError};
2
use alloc::alloc::{alloc, dealloc, handle_alloc_error, realloc, Layout};
3
use core::{
4
    marker::PhantomData,
5
    mem::{align_of, size_of},
6
    ptr::{null_mut, NonNull},
7
};
8
9
pub struct ARawVec<T, A: Alignment> {
10
    pub ptr: NonNull<T>,
11
    pub capacity: usize,
12
    pub align: A,
13
    _marker: PhantomData<T>,
14
}
15
16
impl<T, A: Alignment> Drop for ARawVec<T, A> {
17
    #[inline]
18
0
    fn drop(&mut self) {
19
0
        // this can't overflow since we already have this much stored in a slice
20
0
        let size_bytes = self.capacity * size_of::<T>();
21
0
        if size_bytes > 0 {
22
            // SAFETY: memory was allocated with alloc::alloc::alloc
23
            unsafe {
24
0
                dealloc(
25
0
                    self.ptr.as_ptr() as *mut u8,
26
0
                    Layout::from_size_align_unchecked(
27
0
                        size_bytes,
28
0
                        self.align.alignment(align_of::<T>()),
29
0
                    ),
30
0
                )
31
            }
32
0
        }
33
0
    }
Unexecuted instantiation: <aligned_vec::raw::ARawVec<u8, aligned_vec::ConstAlign<128>> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <aligned_vec::raw::ARawVec<_, _> as core::ops::drop::Drop>::drop
34
}
35
36
0
pub fn capacity_overflow() -> ! {
37
0
    panic!("capacity overflow")
38
}
39
40
impl<T, A: Alignment> ARawVec<T, A> {
41
    /// # Safety
42
    ///
43
    /// `align` must be a power of two.  
44
    /// `align` must be greater than or equal to `core::mem::align_of::<T>()`.
45
    #[inline]
46
0
    pub unsafe fn new_unchecked(align: usize) -> Self {
47
0
        let cap = if size_of::<T>() == 0 { usize::MAX } else { 0 };
48
0
        Self::from_raw_parts(null_mut::<u8>().wrapping_add(align) as *mut T, cap, align)
49
0
    }
Unexecuted instantiation: <aligned_vec::raw::ARawVec<u8, aligned_vec::ConstAlign<128>>>::new_unchecked
Unexecuted instantiation: <aligned_vec::raw::ARawVec<_, _>>::new_unchecked
50
51
    /// # Safety
52
    ///
53
    /// `align` must be a power of two.  
54
    /// `align` must be greater than or equal to `core::mem::align_of::<T>()`.
55
    #[inline]
56
0
    pub unsafe fn with_capacity_unchecked(capacity: usize, align: usize) -> Self {
57
0
        if capacity == 0 || size_of::<T>() == 0 {
58
0
            Self::new_unchecked(align)
59
        } else {
60
0
            Self {
61
0
                ptr: NonNull::<T>::new_unchecked(with_capacity_unchecked(
62
0
                    capacity,
63
0
                    align,
64
0
                    size_of::<T>(),
65
0
                ) as *mut T),
66
0
                capacity,
67
0
                align: A::new(align, align_of::<T>()),
68
0
                _marker: PhantomData,
69
0
            }
70
        }
71
0
    }
Unexecuted instantiation: <aligned_vec::raw::ARawVec<u8, aligned_vec::ConstAlign<128>>>::with_capacity_unchecked
Unexecuted instantiation: <aligned_vec::raw::ARawVec<_, _>>::with_capacity_unchecked
72
73
    /// # Safety
74
    ///
75
    /// `align` must be a power of two.  
76
    /// `align` must be greater than or equal to `core::mem::align_of::<T>()`.
77
    #[inline]
78
0
    pub unsafe fn try_with_capacity_unchecked(
79
0
        capacity: usize,
80
0
        align: usize,
81
0
    ) -> Result<Self, TryReserveError> {
82
0
        if capacity == 0 || size_of::<T>() == 0 {
83
0
            Ok(Self::new_unchecked(align))
84
        } else {
85
            Ok(Self {
86
0
                ptr: NonNull::<T>::new_unchecked(try_with_capacity_unchecked(
87
0
                    capacity,
88
0
                    align,
89
0
                    size_of::<T>(),
90
0
                )? as *mut T),
91
0
                capacity,
92
0
                align: A::new(align, align_of::<T>()),
93
0
                _marker: PhantomData,
94
            })
95
        }
96
0
    }
97
98
    const MIN_NON_ZERO_CAP: usize = if size_of::<T>() == 1 {
99
        8
100
    } else if size_of::<T>() <= 1024 {
101
        4
102
    } else {
103
        1
104
    };
105
106
0
    pub unsafe fn grow_amortized(&mut self, len: usize, additional: usize) {
107
0
        debug_assert!(additional > 0);
108
0
        if self.capacity == 0 {
109
0
            *self = Self::with_capacity_unchecked(
110
0
                additional.max(Self::MIN_NON_ZERO_CAP),
111
0
                self.align.alignment(align_of::<T>()),
112
0
            );
113
0
            return;
114
0
        }
115
0
116
0
        if size_of::<T>() == 0 {
117
0
            debug_assert_eq!(self.capacity, usize::MAX);
118
0
            capacity_overflow();
119
0
        }
120
121
0
        let new_cap = match len.checked_add(additional) {
122
0
            Some(cap) => cap,
123
0
            None => capacity_overflow(),
124
        };
125
126
        // self.cap * 2 can't overflow because it's less than isize::MAX
127
0
        let new_cap = new_cap.max(self.capacity * 2);
128
0
        let new_cap = new_cap.max(Self::MIN_NON_ZERO_CAP);
129
0
130
0
        let ptr = {
131
0
            grow_unchecked(
132
0
                self.as_mut_ptr() as *mut u8,
133
0
                self.capacity,
134
0
                new_cap,
135
0
                self.align.alignment(align_of::<T>()),
136
0
                size_of::<T>(),
137
0
            ) as *mut T
138
0
        };
139
0
140
0
        self.capacity = new_cap;
141
0
        self.ptr = NonNull::<T>::new_unchecked(ptr);
142
0
    }
143
144
0
    pub unsafe fn grow_exact(&mut self, len: usize, additional: usize) {
145
0
        debug_assert!(additional > 0);
146
0
        if size_of::<T>() == 0 {
147
0
            debug_assert_eq!(self.capacity, usize::MAX);
148
0
            capacity_overflow();
149
0
        }
150
0
151
0
        if self.capacity == 0 {
152
0
            *self =
153
0
                Self::with_capacity_unchecked(additional, self.align.alignment(align_of::<T>()));
154
0
            return;
155
0
        }
156
157
0
        let new_cap = match len.checked_add(additional) {
158
0
            Some(cap) => cap,
159
0
            None => capacity_overflow(),
160
        };
161
162
0
        let ptr = grow_unchecked(
163
0
            self.as_mut_ptr() as *mut u8,
164
0
            self.capacity,
165
0
            new_cap,
166
0
            self.align.alignment(align_of::<T>()),
167
0
            size_of::<T>(),
168
0
        ) as *mut T;
169
0
170
0
        self.capacity = new_cap;
171
0
        self.ptr = NonNull::<T>::new_unchecked(ptr);
172
0
    }
173
174
0
    pub unsafe fn try_grow_amortized(
175
0
        &mut self,
176
0
        len: usize,
177
0
        additional: usize,
178
0
    ) -> Result<(), TryReserveError> {
179
0
        debug_assert!(additional > 0);
180
0
        if self.capacity == 0 {
181
0
            *self = Self::try_with_capacity_unchecked(
182
0
                additional.max(Self::MIN_NON_ZERO_CAP),
183
0
                self.align.alignment(align_of::<T>()),
184
0
            )?;
185
0
            return Ok(());
186
0
        }
187
0
188
0
        if size_of::<T>() == 0 {
189
0
            debug_assert_eq!(self.capacity, usize::MAX);
190
0
            return Err(TryReserveError::CapacityOverflow);
191
0
        }
192
193
0
        let new_cap = match len.checked_add(additional) {
194
0
            Some(cap) => cap,
195
0
            None => return Err(TryReserveError::CapacityOverflow),
196
        };
197
198
        // self.cap * 2 can't overflow because it's less than isize::MAX
199
0
        let new_cap = new_cap.max(self.capacity * 2);
200
0
        let new_cap = new_cap.max(Self::MIN_NON_ZERO_CAP);
201
202
0
        let ptr = {
203
0
            try_grow_unchecked(
204
0
                self.as_mut_ptr() as *mut u8,
205
0
                self.capacity,
206
0
                new_cap,
207
0
                self.align.alignment(align_of::<T>()),
208
0
                size_of::<T>(),
209
0
            )? as *mut T
210
        };
211
212
0
        self.capacity = new_cap;
213
0
        self.ptr = NonNull::<T>::new_unchecked(ptr);
214
0
        Ok(())
215
0
    }
216
217
0
    pub unsafe fn try_grow_exact(
218
0
        &mut self,
219
0
        len: usize,
220
0
        additional: usize,
221
0
    ) -> Result<(), TryReserveError> {
222
0
        debug_assert!(additional > 0);
223
0
        if size_of::<T>() == 0 {
224
0
            debug_assert_eq!(self.capacity, usize::MAX);
225
0
            return Err(TryReserveError::CapacityOverflow);
226
0
        }
227
0
228
0
        if self.capacity == 0 {
229
0
            *self = Self::try_with_capacity_unchecked(
230
0
                additional,
231
0
                self.align.alignment(align_of::<T>()),
232
0
            )?;
233
0
            return Ok(());
234
0
        }
235
236
0
        let new_cap = match len.checked_add(additional) {
237
0
            Some(cap) => cap,
238
0
            None => return Err(TryReserveError::CapacityOverflow),
239
        };
240
241
0
        let ptr = try_grow_unchecked(
242
0
            self.as_mut_ptr() as *mut u8,
243
0
            self.capacity,
244
0
            new_cap,
245
0
            self.align.alignment(align_of::<T>()),
246
0
            size_of::<T>(),
247
0
        )? as *mut T;
248
249
0
        self.capacity = new_cap;
250
0
        self.ptr = NonNull::<T>::new_unchecked(ptr);
251
0
        Ok(())
252
0
    }
253
254
0
    pub unsafe fn shrink_to(&mut self, len: usize) {
255
0
        if size_of::<T>() == 0 {
256
0
            return;
257
0
        }
258
0
259
0
        debug_assert!(len < self.capacity());
260
0
        let size_of = size_of::<T>();
261
0
        let old_capacity = self.capacity;
262
0
        let align = self.align;
263
0
        let old_ptr = self.ptr.as_ptr() as *mut u8;
264
0
265
0
        // this cannot overflow or exceed isize::MAX bytes since len < cap and the same was true
266
0
        // for cap
267
0
        let new_size_bytes = len * size_of;
268
0
        let old_size_bytes = old_capacity * size_of;
269
0
        let old_layout =
270
0
            Layout::from_size_align_unchecked(old_size_bytes, align.alignment(align_of::<T>()));
271
0
272
0
        let ptr = realloc(old_ptr, old_layout, new_size_bytes);
273
0
        let ptr = ptr as *mut T;
274
0
        self.capacity = len;
275
0
        self.ptr = NonNull::<T>::new_unchecked(ptr);
276
0
    }
277
278
    #[inline]
279
0
    pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize, align: usize) -> Self {
280
0
        Self {
281
0
            ptr: NonNull::<T>::new_unchecked(ptr),
282
0
            capacity,
283
0
            align: A::new(align, align_of::<T>()),
284
0
            _marker: PhantomData,
285
0
        }
286
0
    }
Unexecuted instantiation: <aligned_vec::raw::ARawVec<u8, aligned_vec::ConstAlign<128>>>::from_raw_parts
Unexecuted instantiation: <aligned_vec::raw::ARawVec<_, _>>::from_raw_parts
287
288
    /// Returns the capacity of the vector.
289
    #[inline]
290
0
    pub fn capacity(&self) -> usize {
291
0
        self.capacity
292
0
    }
293
294
    #[inline]
295
0
    pub fn align(&self) -> usize {
296
0
        self.align.alignment(align_of::<T>())
297
0
    }
298
299
    #[inline]
300
0
    pub fn as_ptr(&self) -> *const T {
301
0
        self.ptr.as_ptr()
302
0
    }
Unexecuted instantiation: <aligned_vec::raw::ARawVec<u8, aligned_vec::ConstAlign<128>>>::as_ptr
Unexecuted instantiation: <aligned_vec::raw::ARawVec<_, _>>::as_ptr
303
304
    #[inline]
305
0
    pub fn as_mut_ptr(&mut self) -> *mut T {
306
0
        self.ptr.as_ptr()
307
0
    }
Unexecuted instantiation: <aligned_vec::raw::ARawVec<u8, aligned_vec::ConstAlign<128>>>::as_mut_ptr
Unexecuted instantiation: <aligned_vec::raw::ARawVec<_, _>>::as_mut_ptr
308
}
309
310
0
pub unsafe fn with_capacity_unchecked(capacity: usize, align: usize, size_of: usize) -> *mut u8 {
311
0
    let size_bytes = match capacity.checked_mul(size_of) {
312
0
        Some(size_bytes) => size_bytes,
313
0
        None => capacity_overflow(),
314
    };
315
0
    debug_assert!(size_bytes > 0);
316
0
    let will_overflow = size_bytes > usize::MAX - (align - 1);
317
0
    if will_overflow || !is_valid_alloc(size_bytes) {
318
0
        capacity_overflow();
319
0
    }
320
0
321
0
    let layout = Layout::from_size_align_unchecked(size_bytes, align);
322
0
    let ptr = alloc(layout);
323
0
    if ptr.is_null() {
324
0
        handle_alloc_error(layout);
325
0
    }
326
0
    ptr
327
0
}
328
329
0
unsafe fn grow_unchecked(
330
0
    old_ptr: *mut u8,
331
0
    old_capacity: usize,
332
0
    new_capacity: usize,
333
0
    align: usize,
334
0
    size_of: usize,
335
0
) -> *mut u8 {
336
0
    let new_size_bytes = match new_capacity.checked_mul(size_of) {
337
0
        Some(size_bytes) => size_bytes,
338
0
        None => capacity_overflow(),
339
    };
340
0
    let will_overflow = new_size_bytes > usize::MAX - (align - 1);
341
0
    if will_overflow || !is_valid_alloc(new_size_bytes) {
342
0
        capacity_overflow();
343
0
    }
344
0
345
0
    // can't overflow because we already allocated this much
346
0
    let old_size_bytes = old_capacity * size_of;
347
0
    let old_layout = Layout::from_size_align_unchecked(old_size_bytes, align);
348
0
349
0
    let ptr = realloc(old_ptr, old_layout, new_size_bytes);
350
0
351
0
    if ptr.is_null() {
352
0
        let new_layout = Layout::from_size_align_unchecked(old_size_bytes, align);
353
0
        handle_alloc_error(new_layout);
354
0
    }
355
0
356
0
    ptr
357
0
}
358
359
0
pub unsafe fn try_with_capacity_unchecked(
360
0
    capacity: usize,
361
0
    align: usize,
362
0
    size_of: usize,
363
0
) -> Result<*mut u8, TryReserveError> {
364
0
    let size_bytes = match capacity.checked_mul(size_of) {
365
0
        Some(size_bytes) => size_bytes,
366
0
        None => return Err(TryReserveError::CapacityOverflow),
367
    };
368
0
    debug_assert!(size_bytes > 0);
369
0
    let will_overflow = size_bytes > usize::MAX - (align - 1);
370
0
    if will_overflow || !is_valid_alloc(size_bytes) {
371
0
        return Err(TryReserveError::CapacityOverflow);
372
0
    }
373
0
374
0
    let layout = Layout::from_size_align_unchecked(size_bytes, align);
375
0
    let ptr = alloc(layout);
376
0
    if ptr.is_null() {
377
0
        return Err(TryReserveError::AllocError { layout });
378
0
    }
379
0
    Ok(ptr)
380
0
}
381
382
0
unsafe fn try_grow_unchecked(
383
0
    old_ptr: *mut u8,
384
0
    old_capacity: usize,
385
0
    new_capacity: usize,
386
0
    align: usize,
387
0
    size_of: usize,
388
0
) -> Result<*mut u8, TryReserveError> {
389
0
    let new_size_bytes = match new_capacity.checked_mul(size_of) {
390
0
        Some(size_bytes) => size_bytes,
391
0
        None => return Err(TryReserveError::CapacityOverflow),
392
    };
393
0
    let will_overflow = new_size_bytes > usize::MAX - (align - 1);
394
0
    if will_overflow || !is_valid_alloc(new_size_bytes) {
395
0
        return Err(TryReserveError::CapacityOverflow);
396
0
    }
397
0
398
0
    // can't overflow because we already allocated this much
399
0
    let old_size_bytes = old_capacity * size_of;
400
0
    let old_layout = Layout::from_size_align_unchecked(old_size_bytes, align);
401
0
402
0
    let ptr = realloc(old_ptr, old_layout, new_size_bytes);
403
0
404
0
    if ptr.is_null() {
405
0
        let layout = Layout::from_size_align_unchecked(new_size_bytes, align);
406
0
        return Err(TryReserveError::AllocError { layout });
407
0
    }
408
0
409
0
    Ok(ptr)
410
0
}
411
412
#[inline]
413
0
fn is_valid_alloc(alloc_size: usize) -> bool {
414
0
    !(usize::BITS < 64 && alloc_size > isize::MAX as usize)
415
0
}