aligned-vec-0.6.4/.cargo_vcs_info.json0000644000000001360000000000100132210ustar { "git": { "sha1": "6af6c18c831c93395f948a0e6527b8d6b9729784" }, "path_in_vcs": "" }aligned-vec-0.6.4/.gitignore000064400000000000000000000000241046102023000137750ustar 00000000000000/target /Cargo.lock aligned-vec-0.6.4/Cargo.lock0000644000000043640000000000100112030ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 [[package]] name = "aligned-vec" version = "0.6.4" dependencies = [ "bincode", "equator", "serde", ] [[package]] name = "bincode" version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ "serde", ] [[package]] name = "equator" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" dependencies = [ "equator-macro", ] [[package]] name = "equator-macro" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "proc-macro2" version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] [[package]] name = "serde" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "syn" version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" aligned-vec-0.6.4/Cargo.toml0000644000000023500000000000100112170ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "aligned-vec" version = "0.6.4" authors = ["sarah <>"] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Aligned vector and box containers" readme = "README.md" keywords = [ "vec", "allocation", "box", "slice", "alignment", ] license = "MIT" repository = "https://github.com/sarah-ek/aligned-vec/" [package.metadata.docs.rs] all-features = true rustdoc-args = [ "--cfg", "docsrs", ] [features] default = ["std"] serde = ["dep:serde"] std = [] [lib] name = "aligned_vec" path = "src/lib.rs" [dependencies.equator] version = "0.4.1" [dependencies.serde] version = "1.0" optional = true default-features = false [dev-dependencies.bincode] version = "1" aligned-vec-0.6.4/Cargo.toml.orig000064400000000000000000000011171046102023000147000ustar 00000000000000[package] name = "aligned-vec" version = "0.6.4" edition = "2021" authors = ["sarah <>"] description = "Aligned vector and box containers" readme = "README.md" repository = "https://github.com/sarah-ek/aligned-vec/" license = "MIT" keywords = ["vec", "allocation", "box", "slice", "alignment"] [dependencies] equator = "0.4.1" serde = { version = "1.0", optional = true, default-features = false } [dev-dependencies] bincode = { version = "1" } [features] default = ["std"] std = [] serde = ["dep:serde"] [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] aligned-vec-0.6.4/LICENSE000064400000000000000000000020461046102023000130200ustar 00000000000000MIT License Copyright (c) 2022 sarah Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. aligned-vec-0.6.4/README.md000064400000000000000000000011231046102023000132650ustar 00000000000000# aligned-vec This crate provides the `AVec` and `ABox` types, which are intended to have a similar API to `Vec` and `Box`, but align the data they contain to a runtime alignment value. This is useful for situations where the alignment of the data matters, such as when working with numerical data that can get performance benefits from being aligned to a SIMD-compatible memory address. # Features - `std` (default feature): Links this crate to the `std-crate` instead of the `core-crate`. - `serde`: Implements serialization and deserialization features for `ABox` and `AVec`. aligned-vec-0.6.4/src/lib.rs000064400000000000000000001226601046102023000137230ustar 00000000000000#![no_std] #![cfg_attr(docsrs, feature(doc_cfg))] //! # aligned-vec //! //! This crate provides the `AVec` and `ABox` types, which are intended to have a similar API //! to `Vec` and `Box`, but align the data they contain to a runtime alignment value. //! //! This is useful for situations where the alignment of the data matters, such as when working with //! numerical data that can get performance benefits from being aligned to a SIMD-compatible memory address. //! //! # Features //! //! - `std` (default feature): Links this crate to the `std-crate` instead of the `core-crate`. //! - `serde`: Implements serialization and deserialization features for `ABox` and `AVec`. use core::{ alloc::Layout, fmt::Debug, marker::PhantomData, mem::{align_of, size_of, ManuallyDrop}, ops::{Deref, DerefMut}, ptr::{null_mut, NonNull}, }; use equator::assert; use raw::ARawVec; mod raw; extern crate alloc; // https://rust-lang.github.io/hashbrown/src/crossbeam_utils/cache_padded.rs.html#128-130 pub const CACHELINE_ALIGN: usize = { #[cfg(any( target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64", ))] { 128 } #[cfg(any( target_arch = "arm", target_arch = "mips", target_arch = "mips64", target_arch = "riscv64", ))] { 32 } #[cfg(target_arch = "s390x")] { 256 } #[cfg(not(any( target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64", target_arch = "arm", target_arch = "mips", target_arch = "mips64", target_arch = "riscv64", target_arch = "s390x", )))] { 64 } }; mod private { pub trait Seal {} } /// Trait for types that wrap an alignment value. pub trait Alignment: Copy + private::Seal { /// Takes an alignment value and a minimum valid alignment, /// and returns an alignment wrapper that contains a power of two alignment that is greater /// than `minimum_align`, and if possible, greater than `align`. #[must_use] fn new(align: usize, minimum_align: usize) -> Self; /// Takes a minimum valid alignment, /// and returns an alignment wrapper that contains a power of two alignment that is greater /// than `minimum_align`, and if possible, greater than the contained value. #[must_use] fn alignment(self, minimum_align: usize) -> usize; } /// Type wrapping a runtime alignment value. #[derive(Copy, Clone)] pub struct RuntimeAlign { align: usize, } /// Type wrapping a compile-time alignment value. #[derive(Copy, Clone)] pub struct ConstAlign; impl private::Seal for RuntimeAlign {} impl private::Seal for ConstAlign {} impl core::convert::From> for AVec { #[inline] fn from(value: ABox<[T], A>) -> Self { let len = (*value).len(); let (ptr, align) = ABox::into_raw_parts(value); unsafe { AVec::::from_raw_parts(ptr as *mut T, align, len, len) } } } impl Alignment for RuntimeAlign { #[inline] #[track_caller] fn new(align: usize, minimum_align: usize) -> Self { if align != 0 { assert!( align.is_power_of_two(), "alignment ({align}) is not a power of two.", ); } RuntimeAlign { align: fix_alignment(align, minimum_align), } } #[inline] fn alignment(self, minimum_align: usize) -> usize { let _ = minimum_align; self.align } } impl Alignment for ConstAlign { #[inline] #[track_caller] fn new(align: usize, minimum_align: usize) -> Self { let _ = minimum_align; let max = Ord::max; if align != 0 { assert!( align.is_power_of_two(), "alignment ({align}) is not a power of two.", ); } assert!( ALIGN.is_power_of_two(), "alignment ({ALIGN}) is not a power of two.", ); assert!( align <= max(ALIGN, minimum_align), "provided alignment ({align}) is greater than the specified constant value ({ALIGN})", ); ConstAlign:: } #[inline] fn alignment(self, minimum_align: usize) -> usize { fix_alignment(ALIGN, minimum_align) } } /// Aligned vector. See [`Vec`] for more info. /// /// Note: passing an alignment value of `0` or a power of two that is less than the minimum alignment will cause the vector to use the minimum valid alignment for the type `T` and alignment type `A`. pub struct AVec> { buf: ARawVec, len: usize, } /// Aligned box. See [`Box`] for more info. /// /// Note: passing an alignment value of `0` or a power of two that is less than the minimum alignment will cause the vector to use the minimum valid alignment for the type `T` and alignment type `A`. pub struct ABox> { ptr: NonNull, align: A, _marker: PhantomData, } impl Deref for ABox { type Target = T; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*self.ptr.as_ptr() } } } impl DerefMut for ABox { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *self.ptr.as_ptr() } } } impl AsRef for ABox { #[inline] fn as_ref(&self) -> &T { &**self } } impl AsMut for ABox { #[inline] fn as_mut(&mut self) -> &mut T { &mut **self } } struct AllocDrop { ptr: *mut u8, size_bytes: usize, align: usize, } impl Drop for AllocDrop { #[inline] fn drop(&mut self) { if self.size_bytes > 0 { unsafe { alloc::alloc::dealloc( self.ptr, alloc::alloc::Layout::from_size_align_unchecked(self.size_bytes, self.align), ) } } } } impl Drop for ABox { #[inline] fn drop(&mut self) { let size_bytes = core::mem::size_of_val(self.deref_mut()); let align_bytes = core::mem::align_of_val(self.deref_mut()); let ptr = self.deref_mut() as *mut T; let _alloc_drop = AllocDrop { ptr: ptr as *mut u8, size_bytes, align: self.align.alignment(align_bytes), }; unsafe { ptr.drop_in_place() }; } } impl Deref for AVec { type Target = [T]; #[inline] fn deref(&self) -> &Self::Target { self.as_slice() } } impl DerefMut for AVec { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_slice() } } impl AsRef<[T]> for AVec { #[inline] fn as_ref(&self) -> &[T] { &**self } } impl AsMut<[T]> for AVec { #[inline] fn as_mut(&mut self) -> &mut [T] { &mut **self } } impl ABox { /// Creates a new [`ABox`] containing `value` at an address aligned to `align` bytes. #[inline] #[track_caller] pub fn new(align: usize, value: T) -> Self { let align = A::new(align, align_of::()).alignment(align_of::()); let ptr = if size_of::() == 0 { null_mut::().wrapping_add(align) as *mut T } else { unsafe { raw::with_capacity_unchecked(1, align, size_of::()) as *mut T } }; unsafe { ptr.write(value) }; unsafe { Self::from_raw_parts(align, ptr) } } /// Returns the alignment of the box. #[inline] pub fn alignment(&self) -> usize { self.align.alignment(align_of::()) } } impl ABox { /// Creates a new [`ABox`] from its raw parts. /// /// # Safety /// /// The arguments to this function must be acquired from a previous call to /// [`Self::into_raw_parts`]. #[inline] #[track_caller] pub unsafe fn from_raw_parts(align: usize, ptr: *mut T) -> Self { Self { ptr: NonNull::::new_unchecked(ptr), align: A::new(align, core::mem::align_of_val(&*ptr)), _marker: PhantomData, } } /// Decomposes a [`ABox`] into its raw parts: `(ptr, alignment)`. #[inline] pub fn into_raw_parts(this: Self) -> (*mut T, usize) { let this = ManuallyDrop::new(this); let align = core::mem::align_of_val(unsafe { &*this.ptr.as_ptr() }); (this.ptr.as_ptr(), this.align.alignment(align)) } } impl Drop for AVec { #[inline] fn drop(&mut self) { // SAFETY: dropping initialized elements unsafe { (self.as_mut_slice() as *mut [T]).drop_in_place() } } } #[inline] fn fix_alignment(align: usize, base_align: usize) -> usize { align.max(base_align) } #[derive(Copy, Clone, Debug)] pub enum TryReserveError { CapacityOverflow, AllocError { layout: Layout }, } impl AVec { /// Returns a new [`AVec`] with the provided alignment. #[inline] #[must_use] #[track_caller] pub fn new(align: usize) -> Self { unsafe { Self { buf: ARawVec::new_unchecked( A::new(align, align_of::()).alignment(align_of::()), ), len: 0, } } } /// Creates a new empty vector with enough capacity for at least `capacity` elements to /// be inserted in the vector. If `capacity` is 0, the vector will not allocate. /// /// # Panics /// /// Panics if the capacity exceeds `isize::MAX` bytes. #[inline] #[must_use] #[track_caller] pub fn with_capacity(align: usize, capacity: usize) -> Self { unsafe { Self { buf: ARawVec::with_capacity_unchecked( capacity, A::new(align, align_of::()).alignment(align_of::()), ), len: 0, } } } /// Returns a new [`AVec`] from its raw parts. /// /// # Safety /// /// The arguments to this function must be acquired from a previous call to /// [`Self::into_raw_parts`]. #[inline] #[must_use] pub unsafe fn from_raw_parts(ptr: *mut T, align: usize, len: usize, capacity: usize) -> Self { Self { buf: ARawVec::from_raw_parts(ptr, capacity, align), len, } } /// Decomposes an [`AVec`] into its raw parts: `(ptr, alignment, length, capacity)`. #[inline] pub fn into_raw_parts(self) -> (*mut T, usize, usize, usize) { let mut this = ManuallyDrop::new(self); let len = this.len(); let cap = this.capacity(); let align = this.alignment(); let ptr = this.as_mut_ptr(); (ptr, align, len, cap) } /// Returns the length of the vector. #[inline] #[must_use] pub fn len(&self) -> usize { self.len } /// Returns `true` if the vector's length is equal to `0`, and false otherwise. #[inline] #[must_use] pub fn is_empty(&self) -> bool { self.len() == 0 } /// Returns the number of elements the vector can hold without needing to reallocate. #[inline] #[must_use] pub fn capacity(&self) -> usize { self.buf.capacity() } /// Reserves enough capacity for at least `additional` more elements to be inserted in the /// vector. After this call to `reserve`, capacity will be greater than or equal to `self.len() + additional`. /// Does nothing if the capacity is already sufficient. /// /// # Panics /// /// Panics if the new capacity exceeds `isize::MAX` bytes. #[inline] pub fn reserve(&mut self, additional: usize) { if additional > self.capacity().wrapping_sub(self.len) { unsafe { self.buf.grow_amortized(self.len, additional) }; } } pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { if additional > self.capacity().wrapping_sub(self.len) { unsafe { self.buf.try_grow_amortized(self.len, additional) } } else { Ok(()) } } /// Reserves enough capacity for exactly `additional` more elements to be inserted in the /// vector. After this call to `reserve`, capacity will be greater than or equal to `self.len() + additional`. /// Does nothing if the capacity is already sufficient. /// /// # Panics /// /// Panics if the new capacity exceeds `isize::MAX` bytes. #[inline] pub fn reserve_exact(&mut self, additional: usize) { if additional > self.capacity().wrapping_sub(self.len) { unsafe { self.buf.grow_exact(self.len, additional) }; } } pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { if additional > self.capacity().wrapping_sub(self.len) { unsafe { self.buf.try_grow_exact(self.len, additional) } } else { Ok(()) } } /// Returns the alignment of the vector. #[inline] #[must_use] pub fn alignment(&self) -> usize { self.buf.align() } /// Returns a pointer to the objects held by the vector. #[inline] #[must_use] pub fn as_ptr(&self) -> *const T { self.buf.as_ptr() } /// Returns a mutable pointer to the objects held by the vector. #[inline] #[must_use] pub fn as_mut_ptr(&mut self) -> *mut T { self.buf.as_mut_ptr() } /// Returns a reference to a slice over the objects held by the vector. #[inline] #[must_use] pub fn as_slice(&self) -> &[T] { let len = self.len(); let ptr = self.as_ptr(); // ptr points to `len` initialized elements and is properly aligned since // self.align is at least `align_of::()` unsafe { core::slice::from_raw_parts(ptr, len) } } /// Returns a mutable reference to a slice over the objects held by the vector. #[inline] #[must_use] pub fn as_mut_slice(&mut self) -> &mut [T] { let len = self.len(); let ptr = self.as_mut_ptr(); // ptr points to `len` initialized elements and is properly aligned since // self.align is at least `align_of::()` unsafe { core::slice::from_raw_parts_mut(ptr, len) } } /// Push the given value to the end of the vector, reallocating if needed. #[inline] pub fn push(&mut self, value: T) { if self.len == self.capacity() { unsafe { self.buf.grow_amortized(self.len, 1) }; } // SAFETY: self.capacity is greater than self.len so the write is valid unsafe { let past_the_end = self.as_mut_ptr().add(self.len); past_the_end.write(value); self.len += 1; } } /// Remove the last value from the vector if it exists, otherwise returns `None`. #[inline] pub fn pop(&mut self) -> Option { if self.len == 0 { None } else { self.len -= 1; // SAFETY: the len was greater than one so we had one valid element at the last address Some(unsafe { self.as_mut_ptr().add(self.len()).read() }) } } /// Shrinks the capacity of the vector with a lower bound. /// The capacity will remain at least as large as both the length and the supplied value. /// If the current capacity is less than the lower limit, this is a no-op. #[inline] pub fn shrink_to(&mut self, min_capacity: usize) { let min_capacity = min_capacity.max(self.len()); if self.capacity() > min_capacity { unsafe { self.buf.shrink_to(min_capacity) }; } } /// Shrinks the capacity of the vector as much as possible without dropping any elements. #[inline] pub fn shrink_to_fit(&mut self) { if self.capacity() > self.len { unsafe { self.buf.shrink_to(self.len) }; } } /// Drops the last elements of the vector until its length is equal to `len`. /// If `len` is greater than or equal to `self.len()`, this is a no-op. #[inline] pub fn truncate(&mut self, len: usize) { if len < self.len { let old_len = self.len; self.len = len; unsafe { let ptr = self.as_mut_ptr(); core::ptr::slice_from_raw_parts_mut(ptr.add(len), old_len - len).drop_in_place() } } } /// Drops the all the elements of the vector, setting its length to `0`. #[inline] pub fn clear(&mut self) { let old_len = self.len; self.len = 0; unsafe { let ptr = self.as_mut_ptr(); core::ptr::slice_from_raw_parts_mut(ptr, old_len).drop_in_place() } } /// Converts the vector into [`ABox`]. /// This will drop any excess capacity. #[inline] pub fn into_boxed_slice(self) -> ABox<[T], A> { let mut this = self; this.shrink_to_fit(); let (ptr, align, len, _) = this.into_raw_parts(); unsafe { ABox::<[T], A>::from_raw_parts(align, core::ptr::slice_from_raw_parts_mut(ptr, len)) } } /// Inserts an element at position `index` within the vector, shifting all elements after it to the right. /// /// # Panics /// /// Panics if `index > len`. #[track_caller] pub fn insert(&mut self, index: usize, element: T) { // Copied somewhat from the standard library #[cold] #[inline(never)] #[track_caller] fn assert_failed(index: usize, len: usize) -> ! { panic!("insertion index (is {index}) should be <= len (is {len})"); } let len = self.len(); // Add space for the new element self.reserve(1); unsafe { let p = self.as_mut_ptr().add(index); if index < len { // Shift everything over to make space. (Duplicating the // `index`th element into two consecutive places.) core::ptr::copy(p, p.add(1), len - index); } else if index == len { // No elements need shifting. } else { assert_failed(index, len); } core::ptr::write(p, element); self.len += 1; } } /// Removes and returns the element at position `index` within the vector, /// shifting all elements after it to the left. /// /// # Panics /// /// Panics if `index` is out of bounds. #[track_caller] pub fn remove(&mut self, index: usize) -> T { // Copied somewhat from the standard library #[cold] #[inline(never)] #[track_caller] fn assert_failed(index: usize, len: usize) -> ! { panic!("removal index (is {index}) should be < len (is {len})"); } let len = self.len(); if index >= len { assert_failed(index, len); } unsafe { // The place we are taking from. let ptr = self.as_mut_ptr().add(index); // Copy it out, unsafely having a copy of the value on // the stack and in the vector at the same time. let ret = core::ptr::read(ptr); // Shift everything down to fill in that spot. core::ptr::copy(ptr.add(1), ptr, len - index - 1); self.len -= 1; ret } } /// Collects an iterator into an [`AVec`] with the provided alignment. #[inline] pub fn from_iter>(align: usize, iter: I) -> Self { Self::from_iter_impl(iter.into_iter(), align) } /// Collects a slice into an [`AVec`] with the provided alignment. #[inline] pub fn from_slice(align: usize, slice: &[T]) -> Self where T: Clone, { let len = slice.len(); let mut vec = AVec::with_capacity(align, len); { let len = &mut vec.len; let ptr: *mut T = vec.buf.ptr.as_ptr(); for (i, item) in slice.iter().enumerate() { unsafe { ptr.add(i).write(item.clone()) }; *len += 1; } } vec } fn from_iter_impl>(mut iter: I, align: usize) -> Self { let (lower_bound, upper_bound) = iter.size_hint(); let mut this = Self::with_capacity(align, lower_bound); if upper_bound == Some(lower_bound) { let len = &mut this.len; let ptr = this.buf.ptr.as_ptr(); let first_chunk = iter.take(lower_bound); first_chunk.enumerate().for_each(|(i, item)| { unsafe { ptr.add(i).write(item) }; *len += 1; }); } else { let len = &mut this.len; let ptr = this.buf.ptr.as_ptr(); let first_chunk = (&mut iter).take(lower_bound); first_chunk.enumerate().for_each(|(i, item)| { unsafe { ptr.add(i).write(item) }; *len += 1; }); iter.for_each(|item| { this.push(item); }); } this } #[inline] pub unsafe fn set_len(&mut self, new_len: usize) { self.len = new_len; } pub fn append(&mut self, other: &mut AVec) { unsafe { let len = self.len(); let count = other.len(); self.reserve(count); core::ptr::copy_nonoverlapping(other.as_ptr(), self.as_mut_ptr().add(len), count); self.len += count; other.len = 0; } } #[inline(always)] #[doc(hidden)] pub fn __from_elem(align: usize, elem: T, count: usize) -> Self where T: Clone, { Self::from_iter(align, core::iter::repeat(elem).take(count)) } #[inline(always)] #[doc(hidden)] /// this is unsafe do not call this in user code pub fn __copy_from_ptr(align: usize, src: *const T, len: usize) -> Self { let mut v = Self::with_capacity(align, len); let dst = v.as_mut_ptr(); unsafe { core::ptr::copy_nonoverlapping(src, dst, len) }; v.len = len; v } } impl AVec { /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. /// /// If `new_len` is greater than `len`, the `Vec` is extended by the /// difference, with each additional slot filled with `value`. /// If `new_len` is less than `len`, the `Vec` is simply truncated. pub fn resize(&mut self, new_len: usize, value: T) { // Copied somewhat from the standard library let len = self.len(); if new_len > len { self.extend_with(new_len - len, value) } else { self.truncate(new_len); } } /// Extend the vector by `n` clones of value. fn extend_with(&mut self, n: usize, value: T) { // Copied somewhat from the standard library self.reserve(n); unsafe { let mut ptr = self.as_mut_ptr().add(self.len()); // Write all elements except the last one for _ in 1..n { core::ptr::write(ptr, value.clone()); ptr = ptr.add(1); // Increment the length in every step in case clone() panics self.len += 1; } if n > 0 { // We can write the last element directly without cloning needlessly core::ptr::write(ptr, value); self.len += 1; } } } /// Clones and appends all elements in a slice to the `Vec`. pub fn extend_from_slice(&mut self, other: &[T]) { // Copied somewhat from the standard library let count = other.len(); self.reserve(count); let len = self.len(); unsafe { core::ptr::copy_nonoverlapping(other.as_ptr(), self.as_mut_ptr().add(len), count) }; self.len += count; } } impl Debug for AVec { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_list().entries(self.iter()).finish() } } impl Debug for ABox { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { (&**self).fmt(f) } } impl Clone for AVec { fn clone(&self) -> Self { Self::from_slice(self.alignment(), self.deref()) } } impl Clone for ABox { fn clone(&self) -> Self { ABox::new(self.align.alignment(align_of::()), self.deref().clone()) } } impl Clone for ABox<[T], A> { fn clone(&self) -> Self { AVec::from_slice(self.align.alignment(align_of::()), self.deref()).into_boxed_slice() } } impl PartialEq for AVec { fn eq(&self, other: &Self) -> bool { self.as_slice().eq(other.as_slice()) } } impl Eq for AVec {} impl PartialOrd for AVec { fn partial_cmp(&self, other: &Self) -> Option { self.as_slice().partial_cmp(other.as_slice()) } } impl Ord for AVec { fn cmp(&self, other: &Self) -> core::cmp::Ordering { self.as_slice().cmp(other.as_slice()) } } impl PartialEq for ABox { fn eq(&self, other: &Self) -> bool { (&**self).eq(&**other) } } impl Eq for ABox {} impl PartialOrd for ABox { fn partial_cmp(&self, other: &Self) -> Option { (&**self).partial_cmp(&**other) } } impl Ord for ABox { fn cmp(&self, other: &Self) -> core::cmp::Ordering { (&**self).cmp(&**other) } } unsafe impl Sync for AVec {} unsafe impl Send for AVec {} unsafe impl Sync for ABox {} unsafe impl Send for ABox {} #[cfg(feature = "serde")] mod serde { use super::*; use ::serde::{Deserialize, Serialize}; #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] impl Serialize for ABox { #[inline] fn serialize(&self, serializer: S) -> Result where S: ::serde::Serializer, { (&**self).serialize(serializer) } } #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] impl Serialize for AVec { #[inline] fn serialize(&self, serializer: S) -> Result where S: ::serde::Serializer, { (&**self).serialize(serializer) } } #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] impl<'de, T: Deserialize<'de>, const N: usize> Deserialize<'de> for ABox> { fn deserialize(deserializer: D) -> Result where D: ::serde::Deserializer<'de>, { Ok(ABox::>::new( N, T::deserialize(deserializer)?, )) } } #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] impl<'de, T: Deserialize<'de>, const N: usize> Deserialize<'de> for ABox<[T], ConstAlign> { fn deserialize(deserializer: D) -> Result where D: ::serde::Deserializer<'de>, { Ok(AVec::>::deserialize(deserializer)?.into_boxed_slice()) } } #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] impl<'de, T: Deserialize<'de>, const N: usize> Deserialize<'de> for AVec> { fn deserialize(deserializer: D) -> Result where D: ::serde::Deserializer<'de>, { struct AVecVisitor { _marker: PhantomData AVec>>, } impl<'de, T: Deserialize<'de>, const N: usize> ::serde::de::Visitor<'de> for AVecVisitor { type Value = AVec>; fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { formatter.write_str("a sequence") } fn visit_seq(self, mut seq: S) -> Result where S: ::serde::de::SeqAccess<'de>, { let mut vec = AVec::>::with_capacity(N, cautious::(seq.size_hint())); while let Some(elem) = seq.next_element::()? { vec.push(elem) } Ok(vec) } } deserializer.deserialize_seq(AVecVisitor { _marker: PhantomData, }) } } pub fn cautious(hint: Option) -> usize { use core::{cmp, mem}; const MAX_PREALLOC_BYTES: usize = 1024 * 1024; if mem::size_of::() == 0 { 0 } else { cmp::min( hint.unwrap_or(0), MAX_PREALLOC_BYTES / mem::size_of::(), ) } } } /// Creates a [`AVec`] containing the arguments. /// /// `avec!` follows similar syntax to `vec!` but allows for specifying an alignment value. /// You can either specifiy the alignment value explicitly /// ```rust /// use aligned_vec::{avec, CACHELINE_ALIGN}; /// let v = avec![[64]| 1, 2, 3, 4]; /// assert_eq!(v[0], 1); /// assert_eq!(v.alignment(), 64); /// assert_eq!(v.as_ptr().align_offset(64), 0); /// ``` /// or dont specify it, which will use the default alignment value of `CACHELINE_ALIGN` /// ```rust /// use aligned_vec::{avec, CACHELINE_ALIGN}; /// let v = avec![1, 2, 3, 4]; /// assert_eq!(v[0], 1); /// assert_eq!(v.alignment(), CACHELINE_ALIGN); /// assert_eq!(v.as_ptr().align_offset(CACHELINE_ALIGN), 0); /// ``` #[macro_export] macro_rules! avec { () => { $crate::AVec::<_>::new(0) }; ([$align: expr]| ) => { $crate::AVec::<_, $crate::ConstAlign::<$align>>::new(0) }; ([$align: expr]| $elem: expr; $count: expr) => { $crate::AVec::<_, $crate::ConstAlign::<$align>>::__from_elem(0, $elem, $count) }; ([$align: expr]| $($elem: expr),*) => { { let __data = &::core::mem::ManuallyDrop::new([$($elem,)*]); let __len = __data.len(); let __ptr = __data.as_ptr(); let mut __aligned_vec = $crate::AVec::<_, $crate::ConstAlign::<$align>>::__copy_from_ptr(0, __ptr, __len); __aligned_vec } }; ($elem: expr; $count: expr) => { $crate::AVec::<_>::__from_elem(0, $elem, $count) }; ($($elem: expr),*) => { { let __data = &::core::mem::ManuallyDrop::new([$($elem,)*]); let __len = __data.len(); let __ptr = __data.as_ptr(); let mut __aligned_vec = $crate::AVec::<_>::__copy_from_ptr(0, __ptr, __len); __aligned_vec } }; } /// Create a vector that is aligned to a runtime alignment value. #[macro_export] macro_rules! avec_rt { ([$align: expr]$(|)?) => { $crate::AVec::<_, $crate::RuntimeAlign>::new($align) }; ([$align: expr]| $elem: expr; $count: expr) => { $crate::AVec::<_, $crate::RuntimeAlign>::__from_elem($align, $elem, $count) }; ([$align: expr]| $($elem: expr),*) => { { let __data = &::core::mem::ManuallyDrop::new([$($elem,)*]); let __len = __data.len(); let __ptr = __data.as_ptr(); let mut __aligned_vec = $crate::AVec::<_>::__copy_from_ptr($align, __ptr, __len); __aligned_vec } }; } #[cfg(test)] mod tests { use super::*; use alloc::vec; use core::iter::repeat; use equator::assert; #[test] fn new() { let v = AVec::::new(32); assert_eq!(v.len(), 0); assert_eq!(v.capacity(), 0); assert_eq!(v.alignment(), CACHELINE_ALIGN); assert_eq!(v.as_ptr().align_offset(CACHELINE_ALIGN), 0); let v = AVec::<()>::new(32); assert_eq!(v.len(), 0); assert_eq!(v.capacity(), usize::MAX); assert_eq!(v.alignment(), CACHELINE_ALIGN); assert_eq!(v.as_ptr().align_offset(CACHELINE_ALIGN), 0); #[repr(align(4096))] struct OverAligned; let v = AVec::::new(32); assert_eq!(v.len(), 0); assert_eq!(v.capacity(), usize::MAX); assert_eq!(v.alignment(), 4096); assert_eq!(v.as_ptr().align_offset(CACHELINE_ALIGN), 0); assert_eq!(v.as_ptr().align_offset(4096), 0); } #[test] fn collect() { let v = AVec::<_>::from_iter(64, 0..4); assert_eq!(&*v, &[0, 1, 2, 3]); let v = AVec::<_>::from_iter(64, repeat(()).take(4)); assert_eq!(&*v, &[(), (), (), ()]); } #[test] fn push() { let mut v = AVec::::new(16); v.push(0); v.push(1); v.push(2); v.push(3); assert_eq!(&*v, &[0, 1, 2, 3]); let mut v = AVec::<_>::from_iter(64, 0..4); v.push(4); v.push(5); v.push(6); v.push(7); assert_eq!(&*v, &[0, 1, 2, 3, 4, 5, 6, 7]); let mut v = AVec::<_>::from_iter(64, repeat(()).take(4)); v.push(()); v.push(()); v.push(()); v.push(()); assert_eq!(&*v, &[(), (), (), (), (), (), (), ()]); } #[test] fn insert() { let mut v = AVec::::new(16); v.insert(0, 1); v.insert(1, 3); v.insert(1, 2); v.insert(0, 0); assert_eq!(&*v, &[0, 1, 2, 3]); let mut v = AVec::<_>::from_iter(64, 0..4); v.insert(0, -1); v.insert(5, 5); v.insert(5, 4); v.insert(1, 0); v.insert(2, 0); assert_eq!(&*v, &[-1, 0, 0, 0, 1, 2, 3, 4, 5]); let mut v = AVec::<_>::from_iter(64, repeat(()).take(4)); v.insert(3, ()); v.insert(0, ()); v.insert(2, ()); v.insert(7, ()); assert_eq!(&*v, &[(), (), (), (), (), (), (), ()]); } #[test] fn pop() { let mut v = AVec::::new(16); v.push(0); v.push(1); v.push(2); v.push(3); assert_eq!(v.pop(), Some(3)); assert_eq!(v.pop(), Some(2)); assert_eq!(v.pop(), Some(1)); assert_eq!(v.pop(), Some(0)); assert_eq!(v.pop(), None); assert_eq!(v.pop(), None); assert_eq!(&*v, &[]); assert!(v.is_empty()); let mut v = AVec::<()>::new(16); v.push(()); v.push(()); v.push(()); v.push(()); assert_eq!(v.pop(), Some(())); assert_eq!(v.pop(), Some(())); assert_eq!(v.pop(), Some(())); assert_eq!(v.pop(), Some(())); assert_eq!(v.pop(), None); assert_eq!(v.pop(), None); assert_eq!(&*v, &[]); assert!(v.is_empty()); } #[test] fn remove() { let mut v = AVec::::new(16); v.push(0); v.push(1); v.push(2); v.push(3); assert_eq!(v.remove(2), 2); assert_eq!(v.remove(2), 3); assert_eq!(v.remove(0), 0); assert_eq!(v.remove(0), 1); assert_eq!(&*v, &[]); assert!(v.is_empty()); let mut v = AVec::<()>::new(16); v.push(()); v.push(()); v.push(()); v.push(()); assert_eq!(v.remove(0), ()); assert_eq!(v.remove(0), ()); assert_eq!(v.remove(0), ()); assert_eq!(v.remove(0), ()); assert_eq!(&*v, &[]); assert!(v.is_empty()); } #[test] fn shrink() { let mut v = AVec::::with_capacity(16, 10); v.push(0); v.push(1); v.push(2); assert_eq!(v.capacity(), 10); v.shrink_to_fit(); assert_eq!(v.len(), 3); assert_eq!(v.capacity(), 3); let mut v = AVec::::with_capacity(16, 10); v.push(0); v.push(1); v.push(2); assert_eq!(v.capacity(), 10); v.shrink_to(0); assert_eq!(v.len(), 3); assert_eq!(v.capacity(), 3); } #[test] fn truncate() { let mut v = AVec::::new(16); v.push(0); v.push(1); v.push(2); v.truncate(1); assert_eq!(v.len(), 1); assert_eq!(&*v, &[0]); v.clear(); assert_eq!(v.len(), 0); assert_eq!(&*v, &[]); let mut v = AVec::<()>::new(16); v.push(()); v.push(()); v.push(()); v.truncate(1); assert_eq!(v.len(), 1); assert_eq!(&*v, &[()]); v.clear(); assert_eq!(v.len(), 0); assert_eq!(&*v, &[]); } #[test] fn extend_from_slice() { let mut v = AVec::::new(16); v.extend_from_slice(&[0, 1, 2, 3]); v.extend_from_slice(&[4, 5, 6, 7, 8]); assert_eq!(&*v, &[0, 1, 2, 3, 4, 5, 6, 7, 8]); let mut v = AVec::<()>::new(16); v.extend_from_slice(&[(), (), (), ()]); v.extend_from_slice(&[(), (), ()]); assert_eq!(&*v, &[(), (), (), (), (), (), ()]); } #[test] fn resize() { let mut v = AVec::::new(16); v.push(0); v.push(1); v.push(2); v.resize(1, 10); assert_eq!(v.len(), 1); assert_eq!(&*v, &[0]); v.resize(3, 20); assert_eq!(v.len(), 3); assert_eq!(&*v, &[0, 20, 20]); let mut v = AVec::<()>::new(16); v.push(()); v.push(()); v.push(()); v.resize(2, ()); assert_eq!(v.len(), 2); assert_eq!(&*v, &[(), ()]); v.resize(3, ()); assert_eq!(v.len(), 3); assert_eq!(&*v, &[(), (), ()]); } #[test] fn into_boxed_slice() { let mut v = AVec::::new(16); v.push(0); v.push(1); v.push(2); let boxed = v.into_boxed_slice(); assert_eq!(&*boxed, &[0, 1, 2]); } #[test] fn box_new() { let boxed = ABox::<_>::new(64, 3); assert_eq!(&*boxed, &3); } #[test] fn box_clone() { let boxed = ABox::<_>::new(64, 3); assert_eq!(boxed, boxed.clone()); } #[test] fn box_slice_clone() { let boxed = AVec::<_>::from_iter(64, 0..123).into_boxed_slice(); assert_eq!(boxed, boxed.clone()); } #[test] fn macros() { let u: AVec<()> = avec![]; assert_eq!(u.len(), 0); assert_eq!(u.as_ptr().align_offset(CACHELINE_ALIGN), 0); let v = avec![0; 4]; assert_eq!(v.len(), 4); assert_eq!(v.as_ptr().align_offset(CACHELINE_ALIGN), 0); let mut w = avec![vec![0, 1], vec![3, 4], vec![5, 6], vec![7, 8]]; w[0].push(2); w[3].pop(); assert_eq!(w.len(), 4); assert_eq!(w.as_ptr().align_offset(CACHELINE_ALIGN), 0); assert_eq!(w[0], vec![0, 1, 2]); assert_eq!(w[1], vec![3, 4]); assert_eq!(w[2], vec![5, 6]); assert_eq!(w[3], vec![7]); } #[test] fn macros_2() { let u: AVec<(), _> = avec![[4096]| ]; assert_eq!(u.len(), 0); assert_eq!(u.as_ptr().align_offset(4096), 0); let v = avec![[4096]| 0; 4]; assert_eq!(v.len(), 4); assert_eq!(v.as_ptr().align_offset(4096), 0); let mut w = avec![[4096] | vec![0, 1], vec![3, 4], vec![5, 6], vec![7, 8]]; w[0].push(2); w[3].pop(); assert_eq!(w.len(), 4); assert_eq!(w.as_ptr().align_offset(4096), 0); assert_eq!(w[0], vec![0, 1, 2]); assert_eq!(w[1], vec![3, 4]); assert_eq!(w[2], vec![5, 6]); assert_eq!(w[3], vec![7]); } #[test] fn macros_rt() { let u: AVec<(), _> = avec_rt![[32]]; assert_eq!(u.len(), 0); assert_eq!(u.as_ptr().align_offset(32), 0); let v = avec_rt![[32]| 0; 4]; assert_eq!(v.len(), 4); assert_eq!(v.as_ptr().align_offset(32), 0); let mut w = avec_rt![[64] | vec![0, 1], vec![3, 4], vec![5, 6], vec![7, 8]]; w[0].push(2); w[3].pop(); assert_eq!(w.len(), 4); assert_eq!(w.as_ptr().align_offset(64), 0); assert_eq!(w[0], vec![0, 1, 2]); assert_eq!(w[1], vec![3, 4]); assert_eq!(w[2], vec![5, 6]); assert_eq!(w[3], vec![7]); } } #[cfg(all(test, feature = "serde"))] mod serde_tests { use super::*; use ::serde::Deserialize; use bincode::{DefaultOptions, Deserializer, Options}; #[test] fn can_limit_deserialization_size() { // Malformed serialized data indicating a sequence of length u64::MAX. let ser = vec![ 253, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1, 1, 1, 1, 1, 1, 1, 1, ]; let options = DefaultOptions::new().with_limit(12); let mut deserializer = Deserializer::from_slice(&ser, options); let result = as Deserialize>::deserialize(&mut deserializer); let err = match result { Ok(_) => panic!("Expected a failure"), Err(e) => e, }; match *err { bincode::ErrorKind::SizeLimit => {} _ => panic!("Expected ErrorKind::SizeLimit, got {err:#?}"), }; } } aligned-vec-0.6.4/src/raw.rs000064400000000000000000000302541046102023000137430ustar 00000000000000use crate::{Alignment, TryReserveError}; use alloc::alloc::{alloc, dealloc, handle_alloc_error, realloc, Layout}; use core::{ marker::PhantomData, mem::{align_of, size_of}, ptr::{null_mut, NonNull}, }; pub struct ARawVec { pub ptr: NonNull, pub capacity: usize, pub align: A, _marker: PhantomData, } impl Drop for ARawVec { #[inline] fn drop(&mut self) { // this can't overflow since we already have this much stored in a slice let size_bytes = self.capacity * size_of::(); if size_bytes > 0 { // SAFETY: memory was allocated with alloc::alloc::alloc unsafe { dealloc( self.ptr.as_ptr() as *mut u8, Layout::from_size_align_unchecked( size_bytes, self.align.alignment(align_of::()), ), ) } } } } pub fn capacity_overflow() -> ! { panic!("capacity overflow") } impl ARawVec { /// # Safety /// /// `align` must be a power of two. /// `align` must be greater than or equal to `core::mem::align_of::()`. #[inline] pub unsafe fn new_unchecked(align: usize) -> Self { let cap = if size_of::() == 0 { usize::MAX } else { 0 }; Self::from_raw_parts(null_mut::().wrapping_add(align) as *mut T, cap, align) } /// # Safety /// /// `align` must be a power of two. /// `align` must be greater than or equal to `core::mem::align_of::()`. #[inline] pub unsafe fn with_capacity_unchecked(capacity: usize, align: usize) -> Self { if capacity == 0 || size_of::() == 0 { Self::new_unchecked(align) } else { Self { ptr: NonNull::::new_unchecked(with_capacity_unchecked( capacity, align, size_of::(), ) as *mut T), capacity, align: A::new(align, align_of::()), _marker: PhantomData, } } } /// # Safety /// /// `align` must be a power of two. /// `align` must be greater than or equal to `core::mem::align_of::()`. #[inline] pub unsafe fn try_with_capacity_unchecked( capacity: usize, align: usize, ) -> Result { if capacity == 0 || size_of::() == 0 { Ok(Self::new_unchecked(align)) } else { Ok(Self { ptr: NonNull::::new_unchecked(try_with_capacity_unchecked( capacity, align, size_of::(), )? as *mut T), capacity, align: A::new(align, align_of::()), _marker: PhantomData, }) } } const MIN_NON_ZERO_CAP: usize = if size_of::() == 1 { 8 } else if size_of::() <= 1024 { 4 } else { 1 }; pub unsafe fn grow_amortized(&mut self, len: usize, additional: usize) { debug_assert!(additional > 0); if self.capacity == 0 { *self = Self::with_capacity_unchecked( additional.max(Self::MIN_NON_ZERO_CAP), self.align.alignment(align_of::()), ); return; } if size_of::() == 0 { debug_assert_eq!(self.capacity, usize::MAX); capacity_overflow(); } let new_cap = match len.checked_add(additional) { Some(cap) => cap, None => capacity_overflow(), }; // self.cap * 2 can't overflow because it's less than isize::MAX let new_cap = new_cap.max(self.capacity * 2); let new_cap = new_cap.max(Self::MIN_NON_ZERO_CAP); let ptr = { grow_unchecked( self.as_mut_ptr() as *mut u8, self.capacity, new_cap, self.align.alignment(align_of::()), size_of::(), ) as *mut T }; self.capacity = new_cap; self.ptr = NonNull::::new_unchecked(ptr); } pub unsafe fn grow_exact(&mut self, len: usize, additional: usize) { debug_assert!(additional > 0); if size_of::() == 0 { debug_assert_eq!(self.capacity, usize::MAX); capacity_overflow(); } if self.capacity == 0 { *self = Self::with_capacity_unchecked(additional, self.align.alignment(align_of::())); return; } let new_cap = match len.checked_add(additional) { Some(cap) => cap, None => capacity_overflow(), }; let ptr = grow_unchecked( self.as_mut_ptr() as *mut u8, self.capacity, new_cap, self.align.alignment(align_of::()), size_of::(), ) as *mut T; self.capacity = new_cap; self.ptr = NonNull::::new_unchecked(ptr); } pub unsafe fn try_grow_amortized( &mut self, len: usize, additional: usize, ) -> Result<(), TryReserveError> { debug_assert!(additional > 0); if self.capacity == 0 { *self = Self::try_with_capacity_unchecked( additional.max(Self::MIN_NON_ZERO_CAP), self.align.alignment(align_of::()), )?; return Ok(()); } if size_of::() == 0 { debug_assert_eq!(self.capacity, usize::MAX); return Err(TryReserveError::CapacityOverflow); } let new_cap = match len.checked_add(additional) { Some(cap) => cap, None => return Err(TryReserveError::CapacityOverflow), }; // self.cap * 2 can't overflow because it's less than isize::MAX let new_cap = new_cap.max(self.capacity * 2); let new_cap = new_cap.max(Self::MIN_NON_ZERO_CAP); let ptr = { try_grow_unchecked( self.as_mut_ptr() as *mut u8, self.capacity, new_cap, self.align.alignment(align_of::()), size_of::(), )? as *mut T }; self.capacity = new_cap; self.ptr = NonNull::::new_unchecked(ptr); Ok(()) } pub unsafe fn try_grow_exact( &mut self, len: usize, additional: usize, ) -> Result<(), TryReserveError> { debug_assert!(additional > 0); if size_of::() == 0 { debug_assert_eq!(self.capacity, usize::MAX); return Err(TryReserveError::CapacityOverflow); } if self.capacity == 0 { *self = Self::try_with_capacity_unchecked( additional, self.align.alignment(align_of::()), )?; return Ok(()); } let new_cap = match len.checked_add(additional) { Some(cap) => cap, None => return Err(TryReserveError::CapacityOverflow), }; let ptr = try_grow_unchecked( self.as_mut_ptr() as *mut u8, self.capacity, new_cap, self.align.alignment(align_of::()), size_of::(), )? as *mut T; self.capacity = new_cap; self.ptr = NonNull::::new_unchecked(ptr); Ok(()) } pub unsafe fn shrink_to(&mut self, len: usize) { if size_of::() == 0 { return; } debug_assert!(len < self.capacity()); let size_of = size_of::(); let old_capacity = self.capacity; let align = self.align; let old_ptr = self.ptr.as_ptr() as *mut u8; // this cannot overflow or exceed isize::MAX bytes since len < cap and the same was true // for cap let new_size_bytes = len * size_of; let old_size_bytes = old_capacity * size_of; let old_layout = Layout::from_size_align_unchecked(old_size_bytes, align.alignment(align_of::())); let ptr = realloc(old_ptr, old_layout, new_size_bytes); let ptr = ptr as *mut T; self.capacity = len; self.ptr = NonNull::::new_unchecked(ptr); } #[inline] pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize, align: usize) -> Self { Self { ptr: NonNull::::new_unchecked(ptr), capacity, align: A::new(align, align_of::()), _marker: PhantomData, } } /// Returns the capacity of the vector. #[inline] pub fn capacity(&self) -> usize { self.capacity } #[inline] pub fn align(&self) -> usize { self.align.alignment(align_of::()) } #[inline] pub fn as_ptr(&self) -> *const T { self.ptr.as_ptr() } #[inline] pub fn as_mut_ptr(&mut self) -> *mut T { self.ptr.as_ptr() } } pub unsafe fn with_capacity_unchecked(capacity: usize, align: usize, size_of: usize) -> *mut u8 { let size_bytes = match capacity.checked_mul(size_of) { Some(size_bytes) => size_bytes, None => capacity_overflow(), }; debug_assert!(size_bytes > 0); let will_overflow = size_bytes > usize::MAX - (align - 1); if will_overflow || !is_valid_alloc(size_bytes) { capacity_overflow(); } let layout = Layout::from_size_align_unchecked(size_bytes, align); let ptr = alloc(layout); if ptr.is_null() { handle_alloc_error(layout); } ptr } unsafe fn grow_unchecked( old_ptr: *mut u8, old_capacity: usize, new_capacity: usize, align: usize, size_of: usize, ) -> *mut u8 { let new_size_bytes = match new_capacity.checked_mul(size_of) { Some(size_bytes) => size_bytes, None => capacity_overflow(), }; let will_overflow = new_size_bytes > usize::MAX - (align - 1); if will_overflow || !is_valid_alloc(new_size_bytes) { capacity_overflow(); } // can't overflow because we already allocated this much let old_size_bytes = old_capacity * size_of; let old_layout = Layout::from_size_align_unchecked(old_size_bytes, align); let ptr = realloc(old_ptr, old_layout, new_size_bytes); if ptr.is_null() { let new_layout = Layout::from_size_align_unchecked(new_size_bytes, align); handle_alloc_error(new_layout); } ptr } pub unsafe fn try_with_capacity_unchecked( capacity: usize, align: usize, size_of: usize, ) -> Result<*mut u8, TryReserveError> { let size_bytes = match capacity.checked_mul(size_of) { Some(size_bytes) => size_bytes, None => return Err(TryReserveError::CapacityOverflow), }; debug_assert!(size_bytes > 0); let will_overflow = size_bytes > usize::MAX - (align - 1); if will_overflow || !is_valid_alloc(size_bytes) { return Err(TryReserveError::CapacityOverflow); } let layout = Layout::from_size_align_unchecked(size_bytes, align); let ptr = alloc(layout); if ptr.is_null() { return Err(TryReserveError::AllocError { layout }); } Ok(ptr) } unsafe fn try_grow_unchecked( old_ptr: *mut u8, old_capacity: usize, new_capacity: usize, align: usize, size_of: usize, ) -> Result<*mut u8, TryReserveError> { let new_size_bytes = match new_capacity.checked_mul(size_of) { Some(size_bytes) => size_bytes, None => return Err(TryReserveError::CapacityOverflow), }; let will_overflow = new_size_bytes > usize::MAX - (align - 1); if will_overflow || !is_valid_alloc(new_size_bytes) { return Err(TryReserveError::CapacityOverflow); } // can't overflow because we already allocated this much let old_size_bytes = old_capacity * size_of; let old_layout = Layout::from_size_align_unchecked(old_size_bytes, align); let ptr = realloc(old_ptr, old_layout, new_size_bytes); if ptr.is_null() { let layout = Layout::from_size_align_unchecked(new_size_bytes, align); return Err(TryReserveError::AllocError { layout }); } Ok(ptr) } #[inline] fn is_valid_alloc(alloc_size: usize) -> bool { !(usize::BITS < 64 && alloc_size > isize::MAX as usize) }