@@ -1778,12 +1778,43 @@ impl<'bump, T: 'bump + Clone> Vec<'bump, T> {
1778
1778
}
1779
1779
1780
1780
impl < ' bump , T : ' bump + Copy > Vec < ' bump , T > {
1781
+ /// Helper method to copy all of the items in `other` and append them to the end of `self`.
1782
+ ///
1783
+ /// SAFETY:
1784
+ /// * The caller is responsible for:
1785
+ /// * calling [`reserve`](Self::reserve) beforehand to guarantee that there is enough
1786
+ /// capacity to store `other.len()` more items.
1787
+ /// * guaranteeing that `self` and `other` do not overlap.
1788
+ unsafe fn extend_from_slice_copy_unchecked ( & mut self , other : & [ T ] ) {
1789
+ let old_len = self . len ( ) ;
1790
+ debug_assert ! ( old_len + other. len( ) <= self . capacity( ) ) ;
1791
+
1792
+ // SAFETY:
1793
+ // * `src` is valid for reads of `other.len()` values by virtue of being a `&[T]`.
1794
+ // * `dst` is valid for writes of `other.len()` bytes because the caller of this
1795
+ // method is required to `reserve` capacity to store at least `other.len()` items
1796
+ // beforehand.
1797
+ // * Because `src` is a `&[T]` and dst is a `&[T]` within the `Vec<T>`,
1798
+ // `copy_nonoverlapping`'s alignment requirements are met.
1799
+ // * Caller is required to guarantee that the source and destination ranges cannot overlap
1800
+ unsafe {
1801
+ let src = other. as_ptr ( ) ;
1802
+ let dst = self . as_mut_ptr ( ) . add ( old_len) ;
1803
+ ptr:: copy_nonoverlapping ( src, dst, other. len ( ) ) ;
1804
+ self . set_len ( old_len + other. len ( ) ) ;
1805
+ }
1806
+ }
1807
+
1808
+
1781
1809
/// Copies all elements in the slice `other` and appends them to the `Vec`.
1782
1810
///
1783
1811
/// Note that this function is same as [`extend_from_slice`] except that it is optimized for
1784
1812
/// slices of types that implement the `Copy` trait. If and when Rust gets specialization
1785
1813
/// this function will likely be deprecated (but still available).
1786
1814
///
1815
+ /// To copy and append the data from multiple source slices at once, see
1816
+ /// [`extend_from_slices_copy`].
1817
+ ///
1787
1818
/// # Examples
1788
1819
///
1789
1820
/// ```
@@ -1806,35 +1837,69 @@ impl<'bump, T: 'bump + Copy> Vec<'bump, T> {
1806
1837
/// assert_eq!(vec, "Hello, world!".as_bytes());
1807
1838
/// ```
1808
1839
///
1809
- /// [`extend`]: #method.extend_from_slice
1840
+ /// [`extend_from_slice`]: #method.extend_from_slice
1841
+ /// [`extend_from_slices`]: #method.extend_from_slices
1810
1842
pub fn extend_from_slice_copy ( & mut self , other : & [ T ] ) {
1811
-
1812
1843
// Reserve space in the Vec for the values to be added
1813
- let old_len = self . len ( ) ;
1814
1844
self . reserve ( other. len ( ) ) ;
1815
1845
1816
- let new_len = old_len + other. len ( ) ;
1817
- debug_assert ! ( new_len <= self . capacity( ) ) ;
1818
-
1819
1846
// Copy values into the space that was just reserved
1820
1847
// SAFETY:
1821
- // * `src` is valid for reads of `other.len()` values by virtue of being a `&[T]`.
1822
- // * `dst` is valid for writes of `other.len()` bytes as `self.reserve(other.len())`
1848
+ // * `self` has enough capacity to store `other.len()` more items as `self.reserve(other.len())`
1823
1849
// above guarantees that.
1824
- // * Because `src` is a `&[T]` and dst is a `&[T]` within the `Vec<T>`,
1825
- // `copy_nonoverlapping`'s alignment requirements are met.
1826
- // * Source and destination ranges cannot overlap as we just reserved the destination
1850
+ // * Source and destination data ranges cannot overlap as we just reserved the destination
1827
1851
// range from the bump.
1828
1852
unsafe {
1829
- let src = other. as_ptr ( ) ;
1830
- let dst = self . as_mut_ptr ( ) . add ( old_len) ;
1831
- ptr:: copy_nonoverlapping ( src, dst, other. len ( ) ) ;
1853
+ self . extend_from_slice_copy_unchecked ( other) ;
1832
1854
}
1855
+ }
1856
+
1857
+ /// For each slice in `slices`, copies all elements in the slice and appends them to the `Vec`.
1858
+ ///
1859
+ /// This method is equivalent to calling [`extend_from_slice_copy`] in a loop, but is able
1860
+ /// to precompute the total amount of space to reserve in advance. This reduces the potential
1861
+ /// maximum number of reallocations needed from one-per-slice to just one.
1862
+ ///
1863
+ /// # Examples
1864
+ ///
1865
+ /// ```
1866
+ /// use bumpalo::{Bump, collections::Vec};
1867
+ ///
1868
+ /// let b = Bump::new();
1869
+ ///
1870
+ /// let mut vec = bumpalo::vec![in &b; 1];
1871
+ /// vec.extend_from_slices_copy(&[&[2, 3], &[], &[4]]);
1872
+ /// assert_eq!(vec, [1, 2, 3, 4]);
1873
+ /// ```
1874
+ ///
1875
+ /// ```
1876
+ /// use bumpalo::{Bump, collections::Vec};
1877
+ ///
1878
+ /// let b = Bump::new();
1879
+ ///
1880
+ /// let mut vec = bumpalo::vec![in &b; 'H' as u8];
1881
+ /// vec.extend_from_slices_copy(&["ello,".as_bytes(), &[], " world!".as_bytes()]);
1882
+ /// assert_eq!(vec, "Hello, world!".as_bytes());
1883
+ /// ```
1884
+ ///
1885
+ /// [`extend_from_slice_copy`]: #method.extend_from_slice_copy
1886
+ pub fn extend_from_slices_copy ( & mut self , slices : & [ & [ T ] ] ) {
1887
+ // Reserve the total amount of capacity we'll need to safely append the aggregated contents
1888
+ // of each slice in `slices`.
1889
+ let capacity_to_reserve: usize = slices. iter ( ) . map ( |slice| slice. len ( ) ) . sum ( ) ;
1890
+ self . reserve ( capacity_to_reserve) ;
1833
1891
1834
- // Update length of Vec to include values just pushed
1835
- // SAFETY: We reserved sufficient capacity for the values above.
1836
- // The elements at `old_len..new_len` were initialized by `copy_nonoverlapping` above.
1837
- unsafe { self . set_len ( new_len) } ;
1892
+ // SAFETY:
1893
+ // * `dst` is valid for writes of `capacity_to_reserve` items as
1894
+ // `self.reserve(capacity_to_reserve)` above guarantees that.
1895
+ // * Source and destination ranges cannot overlap as we just reserved the destination
1896
+ // range from the bump.
1897
+ unsafe {
1898
+ // Copy the contents of each slice onto the end of `self`
1899
+ slices. iter ( ) . for_each ( |slice| {
1900
+ self . extend_from_slice_copy_unchecked ( slice) ;
1901
+ } ) ;
1902
+ }
1838
1903
}
1839
1904
}
1840
1905
0 commit comments