11#![ deny( missing_docs) ]
22
3- //! ThinVec is exactly the same as Vec, except that it stores its `len` and `capacity` in the buffer
3+ //! ` ThinVec` is exactly the same as ` Vec` , except that it stores its `len` and `capacity` in the buffer
44//! it allocates.
55//!
66//! This makes the memory footprint of ThinVecs lower; notably in cases where space is reserved for
77//! a non-existence `ThinVec<T>`. So `Vec<ThinVec<T>>` and `Option<ThinVec<T>>::None` will waste less
88//! space. Being pointer-sized also means it can be passed/stored in registers.
99//!
10- //! Of course, any actually constructed ThinVec will theoretically have a bigger allocation, but
10+ //! Of course, any actually constructed ` ThinVec` will theoretically have a bigger allocation, but
1111//! the fuzzy nature of allocators means that might not actually be the case.
1212//!
13- //! Properties of Vec that are preserved:
13+ //! Properties of ` Vec` that are preserved:
1414//! * `ThinVec::new()` doesn't allocate (it points to a statically allocated singleton)
1515//! * reallocation can be done in place
1616//! * `size_of::<ThinVec<T>>()` == `size_of::<Option<ThinVec<T>>>()`
1717//!
18- //! Properties of Vec that aren't preserved:
18+ //! Properties of ` Vec` that aren't preserved:
1919//! * `ThinVec<T>` can't ever be zero-cost roundtripped to a `Box<[T]>`, `String`, or `*mut T`
2020//! * `from_raw_parts` doesn't exist
21- //! * ThinVec currently doesn't bother to not-allocate for Zero Sized Types (e.g. `ThinVec<()>`),
21+ //! * ` ThinVec` currently doesn't bother to not-allocate for Zero Sized Types (e.g. `ThinVec<()>`),
2222//! but it could be done if someone cared enough to implement it.
2323//!
2424//!
2525//!
2626//! # Gecko FFI
2727//!
28- //! If you enable the gecko-ffi feature, ThinVec will verbatim bridge with the nsTArray type in
29- //! Gecko (Firefox). That is, ThinVec and nsTArray have identical layouts *but not ABIs*,
28+ //! If you enable the gecko-ffi feature, ` ThinVec` will verbatim bridge with the nsTArray type in
29+ //! Gecko (Firefox). That is, ` ThinVec` and nsTArray have identical layouts *but not ABIs*,
3030//! so nsTArrays/ThinVecs an be natively manipulated by C++ and Rust, and ownership can be
3131//! transferred across the FFI boundary (**IF YOU ARE CAREFUL, SEE BELOW!!**).
3232//!
107107//! While relocations are generally predictable if you're very careful, **you should avoid using
108108//! types with significant locations with Rust FFI**.
109109//!
110- //! Specifically, ThinVec will trivially relocate its contents whenever it needs to reallocate its
110+ //! Specifically, ` ThinVec` will trivially relocate its contents whenever it needs to reallocate its
111111//! buffer to change its capacity. This is the default reallocation strategy for nsTArray, and is
112112//! suitable for the vast majority of types. Just be aware of this limitation!
113113//!
114114//! ## Auto Arrays Are Dangerous
115115//!
116- //! ThinVec has *some* support for handling auto arrays which store their buffer on the stack,
116+ //! ` ThinVec` has *some* support for handling auto arrays which store their buffer on the stack,
117117//! but this isn't well tested.
118118//!
119119//! Regardless of how much support we provide, Rust won't be aware of the buffer's limited lifetime,
120- //! so standard auto array safety caveats apply about returning/storing them! ThinVec won't ever
120+ //! so standard auto array safety caveats apply about returning/storing them! ` ThinVec` won't ever
121121//! produce an auto array on its own, so this is only an issue for transferring an nsTArray into
122122//! Rust.
123123//!
135135//! defined. Specifically, we must share the symbol for nsTArray's empty singleton. You will get
136136//! linking errors if that isn't defined.
137137//!
138- //! The gecko-ffi feature also limits ThinVec to the legacy behaviors of nsTArray. Most notably,
138+ //! The gecko-ffi feature also limits ` ThinVec` to the legacy behaviors of nsTArray. Most notably,
139139//! nsTArray has a maximum capacity of i32::MAX (~2.1 billion items). Probably not an issue.
140140//! Probably.
141141//!
@@ -175,7 +175,7 @@ mod impl_details {
175175mod impl_details {
176176 // Support for briding a gecko nsTArray verbatim into a ThinVec.
177177 //
178- // ThinVec can't see copy/move/delete implementations
178+ // ` ThinVec` can't see copy/move/delete implementations
179179 // from C++
180180 //
181181 // The actual layout of an nsTArray is:
@@ -190,15 +190,15 @@ mod impl_details {
190190 //
191191 // Rust doesn't natively support bit-fields, so we manually mask
192192 // and shift the bit. When the "auto" bit is set, the header and buffer
193- // are actually on the stack, meaning the ThinVec pointer-to-header
193+ // are actually on the stack, meaning the ` ThinVec` pointer-to-header
194194 // is essentially an "owned borrow", and therefore dangerous to handle.
195195 // There are no safety guards for this situation.
196196 //
197197 // On little-endian platforms, the auto bit will be the high-bit of
198198 // our capacity u32. On big-endian platforms, it will be the low bit.
199199 // Hence we need some platform-specific CFGs for the necessary masking/shifting.
200200 //
201- // ThinVec won't ever construct an auto array. They only happen when
201+ // ` ThinVec` won't ever construct an auto array. They only happen when
202202 // bridging from C++. This means we don't need to ever set/preserve the bit.
203203 // We just need to be able to read and handle it if it happens to be there.
204204 //
@@ -333,6 +333,11 @@ extern "C" {
333333
334334// Utils for computing layouts of allocations
335335
336+ /// Gets the size necessary to allocate a `ThinVec<T>` with the give capacity.
337+ ///
338+ /// # Panics
339+ ///
340+ /// This will panic if isize::MAX is overflowed at any point.
336341fn alloc_size < T > ( cap : usize ) -> usize {
337342 // Compute "real" header size with pointer math
338343 //
@@ -353,6 +358,7 @@ fn alloc_size<T>(cap: usize) -> usize {
353358 final_size as usize
354359}
355360
361+ /// Gets the padding necessary for the array of a `ThinVec<T>`
356362fn padding < T > ( ) -> usize {
357363 let alloc_align = alloc_align :: < T > ( ) ;
358364 let header_size = mem:: size_of :: < Header > ( ) ;
@@ -370,14 +376,25 @@ fn padding<T>() -> usize {
370376 }
371377}
372378
379+ /// Gets the align necessary to allocate a `ThinVec<T>`
373380fn alloc_align < T > ( ) -> usize {
374381 max ( mem:: align_of :: < T > ( ) , mem:: align_of :: < Header > ( ) )
375382}
376383
384+ /// Gets the layout necessary to allocate a `ThinVec<T>`
385+ ///
386+ /// # Panics
387+ ///
388+ /// Panics if the required size overflows `isize::MAX`.
377389fn layout < T > ( cap : usize ) -> Layout {
378390 unsafe { Layout :: from_size_align_unchecked ( alloc_size :: < T > ( cap) , alloc_align :: < T > ( ) ) }
379391}
380392
393+ /// Allocates a header (and array) for a `ThinVec<T>` with the given capacity.
394+ ///
395+ /// # Panics
396+ ///
397+ /// Panics if the required size overflows `isize::MAX`.
381398fn header_with_capacity < T > ( cap : usize ) -> NonNull < Header > {
382399 debug_assert ! ( cap > 0 ) ;
383400 unsafe {
@@ -467,7 +484,7 @@ impl<T> ThinVec<T> {
467484 /// If it is important to know the exact allocated capacity of a `ThinVec`,
468485 /// always use the [`capacity`] method after construction.
469486 ///
470- /// **NOTE**: unlike Vec, ThinVec **MUST** allocate to keep track of non-zero
487+ /// **NOTE**: unlike ` Vec`, ` ThinVec` **MUST** allocate once to keep track of non-zero
471488 /// lengths. As such, we cannot provide the same guarantees about ThinVecs
472489 /// of ZSTs not allocating. However the allocation never needs to be resized
473490 /// to add more ZSTs, since the underlying array is still length 0.
@@ -1936,7 +1953,7 @@ impl<T> From<Box<[T]>> for ThinVec<T> {
19361953 /// Convert a boxed slice into a vector by transferring ownership of
19371954 /// the existing heap allocation.
19381955 ///
1939- /// **NOTE:** unlike std, this must reallocate to change the layout!
1956+ /// **NOTE:** unlike ` std` , this must reallocate to change the layout!
19401957 ///
19411958 /// # Examples
19421959 ///
@@ -1953,7 +1970,7 @@ impl<T> From<Box<[T]>> for ThinVec<T> {
19531970}
19541971
19551972impl < T > From < Vec < T > > for ThinVec < T > {
1956- /// Convert a std::Vec into a ThinVec.
1973+ /// Convert a ` std::Vec` into a ` ThinVec` .
19571974 ///
19581975 /// **NOTE:** this must reallocate to change the layout!
19591976 ///
@@ -1966,13 +1983,12 @@ impl<T> From<Vec<T>> for ThinVec<T> {
19661983 /// assert_eq!(ThinVec::from(b), thin_vec![1, 2, 3]);
19671984 /// ```
19681985 fn from ( s : Vec < T > ) -> Self {
1969- // Can just lean on the fact that `Box<[T]>` -> `Vec<T>` is Free.
19701986 s. into_iter ( ) . collect ( )
19711987 }
19721988}
19731989
19741990impl < T > From < ThinVec < T > > for Vec < T > {
1975- /// Convert a ThinVec into a std::Vec.
1991+ /// Convert a ` ThinVec` into a ` std::Vec` .
19761992 ///
19771993 /// **NOTE:** this must reallocate to change the layout!
19781994 ///
@@ -1985,7 +2001,6 @@ impl<T> From<ThinVec<T>> for Vec<T> {
19852001 /// assert_eq!(Vec::from(b), vec![1, 2, 3]);
19862002 /// ```
19872003 fn from ( s : ThinVec < T > ) -> Self {
1988- // Can just lean on the fact that `Box<[T]>` -> `Vec<T>` is Free.
19892004 s. into_iter ( ) . collect ( )
19902005 }
19912006}
@@ -1996,7 +2011,7 @@ impl<T> From<ThinVec<T>> for Box<[T]> {
19962011 /// If `v` has excess capacity, its items will be moved into a
19972012 /// newly-allocated buffer with exactly the right capacity.
19982013 ///
1999- /// **NOTE:** unlike std, this must reallocate to change the layout!
2014+ /// **NOTE:** unlike ` std` , this must reallocate to change the layout!
20002015 ///
20012016 /// # Examples
20022017 ///
@@ -2212,7 +2227,7 @@ impl<T> AsRef<[T]> for IntoIter<T> {
22122227impl < T : Clone > Clone for IntoIter < T > {
22132228 #[ allow( clippy:: into_iter_on_ref) ]
22142229 fn clone ( & self ) -> Self {
2215- // Just create a new ThinVec from the remaining elements and IntoIter it
2230+ // Just create a new ` ThinVec` from the remaining elements and IntoIter it
22162231 self . as_slice ( )
22172232 . into_iter ( )
22182233 . cloned ( )
@@ -2301,8 +2316,8 @@ pub struct Drain<'a, T> {
23012316 /// It's ok to use IterMut here because it promises to only take mutable
23022317 /// refs to the parts we haven't yielded yet.
23032318 ///
2304- /// A downside of this (and the *mut below is that it makes this Invariant , when
2305- /// technically it could be covariant?)
2319+ /// A downside of this (and the *mut below) is that it makes this type invariant , when
2320+ /// technically it could be covariant?
23062321 iter : IterMut < ' a , T > ,
23072322 /// The actual ThinVec, which we need to hold onto to undo the leak amplification
23082323 /// and backshift the tail into place. This should only be accessed when we're
@@ -2386,7 +2401,7 @@ impl<'a, T> Drain<'a, T> {
23862401 #[ must_use]
23872402 pub fn as_slice ( & self ) -> & [ T ] {
23882403 // SAFETY: this is A-OK because the elements that the underlying
2389- // iterator still points at are still logically initialized and continguous .
2404+ // iterator still points at are still logically initialized and contiguous .
23902405 self . iter . as_slice ( )
23912406 }
23922407}
0 commit comments