@@ -1710,268 +1710,6 @@ pub mod raw {
1710
1710
}
1711
1711
}
1712
1712
1713
- /// An owned, partially type-converted vector.
1714
- ///
1715
- /// This struct takes two type parameters `T` and `U` which must be of the
1716
- /// same, non-zero size having the same minimal alignment.
1717
- ///
1718
- /// No allocations are performed by usage, only a deallocation happens in the
1719
- /// destructor which should only run when unwinding.
1720
- ///
1721
- /// It can be used to convert a vector of `T`s into a vector of `U`s, by
1722
- /// converting the individual elements one-by-one.
1723
- ///
1724
- /// You may call the `push` method as often as you get a `Some(t)` from `pop`.
1725
- /// After pushing the same number of `U`s as you got `T`s, you can `unwrap` the
1726
- /// vector.
1727
- ///
1728
- /// # Example
1729
- ///
1730
- /// ```ignore
1731
- /// let pv = PartialVec::from_vec(vec![0u32, 1]);
1732
- /// assert_eq!(pv.pop(), Some(0));
1733
- /// assert_eq!(pv.pop(), Some(1));
1734
- /// assert_eq!(pv.pop(), None);
1735
- /// pv.push(2u32);
1736
- /// pv.push(3);
1737
- /// assert_eq!(pv.into_vec().as_slice(), &[2, 3]);
1738
- /// ```
1739
- //
1740
- // Upheld invariants:
1741
- //
1742
- // (a) `vec` isn't modified except when the `PartialVec` goes out of scope, the
1743
- // only thing it is used for is keeping the memory which the `PartialVec`
1744
- // uses for the inplace conversion.
1745
- //
1746
- // (b) `start_u` points to the start of the vector.
1747
- //
1748
- // (c) `end_u` points to one element beyond the vector.
1749
- //
1750
- // (d) `start_u` <= `end_u` <= `start_t` <= `end_t`.
1751
- //
1752
- // (e) From `start_u` (incl.) to `end_u` (excl.) there are sequential instances
1753
- // of type `U`.
1754
- //
1755
- // (f) From `start_t` (incl.) to `end_t` (excl.) there are sequential instances
1756
- // of type `T`.
1757
- //
1758
- // (g) The size of `T` and `U` is equal and non-zero.
1759
- //
1760
- // (h) The `min_align_of` of `T` and `U` is equal.
1761
-
1762
- struct PartialVec < T , U > {
1763
- vec : Vec < T > ,
1764
-
1765
- start_u : * mut U ,
1766
- end_u : * mut U ,
1767
- start_t : * mut T ,
1768
- end_t : * mut T ,
1769
- }
1770
-
1771
- impl < T , U > PartialVec < T , U > {
1772
- /// Creates a `PartialVec` from a `Vec`.
1773
- ///
1774
- /// # Failure
1775
- ///
1776
- /// Fails if `T` and `U` have differing sizes, are zero-sized or have
1777
- /// differing minimal alignments.
1778
- fn from_vec ( mut vec : Vec < T > ) -> PartialVec < T , U > {
1779
- // FIXME: Assert statically that the types `T` and `U` have the same
1780
- // size.
1781
- //
1782
- // These asserts make sure (g) and (h) are satisfied.
1783
- assert ! ( mem:: size_of:: <T >( ) != 0 ) ;
1784
- assert ! ( mem:: size_of:: <U >( ) != 0 ) ;
1785
- assert ! ( mem:: size_of:: <T >( ) == mem:: size_of:: <U >( ) ) ;
1786
- assert ! ( mem:: min_align_of:: <T >( ) == mem:: min_align_of:: <U >( ) ) ;
1787
-
1788
- let start = vec. as_mut_ptr ( ) ;
1789
-
1790
- // This `as int` cast is safe, because the size of the elements of the
1791
- // vector is not 0, and:
1792
- //
1793
- // 1) If the size of the elements in the vector is 1, the `int` may
1794
- // overflow, but it has the correct bit pattern so that the
1795
- // `.offset()` function will work.
1796
- //
1797
- // Example:
1798
- // Address space 0x0-0xF.
1799
- // `u8` array at: 0x1.
1800
- // Size of `u8` array: 0x8.
1801
- // Calculated `offset`: -0x8.
1802
- // After `array.offset(offset)`: 0x9.
1803
- // (0x1 + 0x8 = 0x1 - 0x8)
1804
- //
1805
- // 2) If the size of the elements in the vector is >1, the `uint` ->
1806
- // `int` conversion can't overflow.
1807
- let offset = vec. len ( ) as int ;
1808
-
1809
- let start_u = start as * mut U ;
1810
- let end_u = start as * mut U ;
1811
- let start_t = start;
1812
-
1813
- // This points inside the vector, as the vector has length `offset`.
1814
- let end_t = unsafe { start_t. offset ( offset) } ;
1815
-
1816
- // (b) is satisfied, `start_u` points to the start of `vec`.
1817
- //
1818
- // (c) is also satisfied, `end_t` points to the end of `vec`.
1819
- //
1820
- // `start_u == end_u == start_t <= end_t`, so also `start_u <= end_u <=
1821
- // start_t <= end_t`, thus (b).
1822
- //
1823
- // As `start_u == end_u`, it is represented correctly that there are no
1824
- // instances of `U` in `vec`, thus (e) is satisfied.
1825
- //
1826
- // At start, there are only elements of type `T` in `vec`, so (f) is
1827
- // satisfied, as `start_t` points to the start of `vec` and `end_t` to
1828
- // the end of it.
1829
-
1830
- PartialVec {
1831
- // (a) is satisfied, `vec` isn't modified in the function.
1832
- vec : vec,
1833
- start_u : start_u,
1834
- end_u : end_u,
1835
- start_t : start_t,
1836
- end_t : end_t,
1837
- }
1838
- }
1839
-
1840
- /// Pops a `T` from the `PartialVec`.
1841
- ///
1842
- /// Removes the next `T` from the vector and returns it as `Some(T)`, or
1843
- /// `None` if there are none left.
1844
- fn pop ( & mut self ) -> Option < T > {
1845
- // The `if` ensures that there are more `T`s in `vec`.
1846
- if self . start_t < self . end_t {
1847
- let result;
1848
- unsafe {
1849
- // (f) is satisfied before, so in this if branch there actually
1850
- // is a `T` at `start_t`. After shifting the pointer by one,
1851
- // (f) is again satisfied.
1852
- result = ptr:: read ( self . start_t as * const T ) ;
1853
- self . start_t = self . start_t . offset ( 1 ) ;
1854
- }
1855
- Some ( result)
1856
- } else {
1857
- None
1858
- }
1859
- }
1860
-
1861
- /// Pushes a new `U` to the `PartialVec`.
1862
- ///
1863
- /// # Failure
1864
- ///
1865
- /// Fails if not enough `T`s were popped to have enough space for the new
1866
- /// `U`.
1867
- fn push ( & mut self , value : U ) {
1868
- // The assert assures that still `end_u <= start_t` (d) after
1869
- // the function.
1870
- assert ! ( self . end_u as * const ( ) < self . start_t as * const ( ) ,
1871
- "writing more elements to PartialVec than reading from it" )
1872
- unsafe {
1873
- // (e) is satisfied before, and after writing one `U`
1874
- // to `end_u` and shifting it by one, it's again
1875
- // satisfied.
1876
- ptr:: write ( self . end_u , value) ;
1877
- self . end_u = self . end_u . offset ( 1 ) ;
1878
- }
1879
- }
1880
-
1881
- /// Unwraps the new `Vec` of `U`s after having pushed enough `U`s and
1882
- /// popped all `T`s.
1883
- ///
1884
- /// # Failure
1885
- ///
1886
- /// Fails if not all `T`s were popped, also fails if not the same amount of
1887
- /// `U`s was pushed before calling `unwrap`.
1888
- fn into_vec ( mut self ) -> Vec < U > {
1889
- // If `self.end_u == self.end_t`, we know from (e) that there are no
1890
- // more `T`s in `vec`, we also know that the whole length of `vec` is
1891
- // now used by `U`s, thus we can just interpret `vec` as a vector of
1892
- // `U` safely.
1893
-
1894
- assert ! ( self . end_u as * const ( ) == self . end_t as * const ( ) ,
1895
- "trying to unwrap a PartialVec before completing the writes to it" ) ;
1896
-
1897
- // Extract `vec` and prevent the destructor of `PartialVec` from
1898
- // running. Note that none of the function calls can fail, thus no
1899
- // resources can be leaked (as the `vec` member of `PartialVec` is the
1900
- // only one which holds allocations -- and it is returned from this
1901
- // function.
1902
- unsafe {
1903
- let vec_len = self . vec . len ( ) ;
1904
- let vec_cap = self . vec . capacity ( ) ;
1905
- let vec_ptr = self . vec . as_mut_ptr ( ) as * mut U ;
1906
- mem:: forget ( self ) ;
1907
- Vec :: from_raw_parts ( vec_len, vec_cap, vec_ptr)
1908
- }
1909
- }
1910
- }
1911
-
1912
- #[ unsafe_destructor]
1913
- impl < T , U > Drop for PartialVec < T , U > {
1914
- fn drop ( & mut self ) {
1915
- unsafe {
1916
- // As per (a) `vec` hasn't been modified until now. As it has a
1917
- // length currently, this would run destructors of `T`s which might
1918
- // not be there. So at first, set `vec`s length to `0`. This must
1919
- // be done at first to remain memory-safe as the destructors of `U`
1920
- // or `T` might cause unwinding where `vec`s destructor would be
1921
- // executed.
1922
- self . vec . set_len ( 0 ) ;
1923
-
1924
- // As per (e) and (f) we have instances of `U`s and `T`s in `vec`.
1925
- // Destruct them.
1926
- while self . start_u < self . end_u {
1927
- let _ = ptr:: read ( self . start_u as * const U ) ; // Run a `U` destructor.
1928
- self . start_u = self . start_u . offset ( 1 ) ;
1929
- }
1930
- while self . start_t < self . end_t {
1931
- let _ = ptr:: read ( self . start_t as * const T ) ; // Run a `T` destructor.
1932
- self . start_t = self . start_t . offset ( 1 ) ;
1933
- }
1934
- // After this destructor ran, the destructor of `vec` will run,
1935
- // deallocating the underlying memory.
1936
- }
1937
- }
1938
- }
1939
-
1940
- impl < T > Vec < T > {
1941
- /// Converts a `Vec<T>` to a `Vec<U>` where `T` and `U` have the same
1942
- /// non-zero size and the same minimal alignment.
1943
- ///
1944
- /// # Failure
1945
- ///
1946
- /// Fails if `T` and `U` have differing sizes, are zero-sized or have
1947
- /// differing minimal alignments.
1948
- ///
1949
- /// # Example
1950
- ///
1951
- /// ```
1952
- /// let v = vec![0u, 1, 2];
1953
- /// let w = v.map_in_place(|i| i + 3);
1954
- /// assert_eq!(w.as_slice(), [3, 4, 5].as_slice());
1955
- ///
1956
- /// #[deriving(PartialEq, Show)]
1957
- /// struct Newtype(u8);
1958
- /// let bytes = vec![0x11, 0x22];
1959
- /// let newtyped_bytes = bytes.map_in_place(|x| Newtype(x));
1960
- /// assert_eq!(newtyped_bytes.as_slice(), [Newtype(0x11), Newtype(0x22)].as_slice());
1961
- /// ```
1962
- pub fn map_in_place < U > ( self , f: |T | -> U ) -> Vec < U > {
1963
- let mut pv = PartialVec :: from_vec ( self ) ;
1964
- loop {
1965
- let maybe_t = pv. pop ( ) ;
1966
- match maybe_t {
1967
- Some ( t) => pv. push ( f ( t) ) ,
1968
- None => return pv. into_vec ( ) ,
1969
- } ;
1970
- }
1971
- }
1972
- }
1973
-
1974
-
1975
1713
#[ cfg( test) ]
1976
1714
mod tests {
1977
1715
extern crate test;
@@ -2303,19 +2041,6 @@ mod tests {
2303
2041
assert_eq ! ( vec. len( ) , 0 ) ;
2304
2042
}
2305
2043
2306
- #[ test]
2307
- #[ should_fail]
2308
- fn test_map_inp_lace_incompatible_types_fail ( ) {
2309
- let v = vec ! [ 0 u, 1 , 2 ] ;
2310
- v. map_in_place ( |_| ( ) ) ;
2311
- }
2312
-
2313
- #[ test]
2314
- fn test_map_in_place ( ) {
2315
- let v = vec ! [ 0 u, 1 , 2 ] ;
2316
- assert_eq ! ( v. map_in_place( |i: uint| i as int - 1 ) . as_slice( ) , [ -1 i, 0 , 1 ] . as_slice( ) ) ;
2317
- }
2318
-
2319
2044
#[ bench]
2320
2045
fn bench_new ( b : & mut Bencher ) {
2321
2046
b. iter ( || {
0 commit comments