66//! to the heap for larger allocations. This can be a useful optimization for improving cache
77//! locality and reducing allocator traffic for workloads that fit within the inline buffer.
88
9+ extern crate heapsize;
10+
911use std:: borrow:: { Borrow , BorrowMut } ;
1012use std:: cmp;
1113use std:: fmt;
1214use std:: hash:: { Hash , Hasher } ;
1315use std:: iter:: { IntoIterator , FromIterator } ;
1416use std:: mem;
17+ use std:: os:: raw:: c_void;
1518use std:: ops;
1619use std:: ptr;
1720use std:: slice;
1821
22+ use heapsize:: { HeapSizeOf , heap_size_of} ;
1923use SmallVecData :: { Inline , Heap } ;
2024
2125/// Common operations implemented by both `Vec` and `SmallVec`.
@@ -478,6 +482,12 @@ impl<A: Array> SmallVec<A> {
478482}
479483
480484impl < A : Array > SmallVec < A > where A :: Item : Copy {
485+ pub fn from_slice ( slice : & [ A :: Item ] ) -> Self {
486+ let mut vec = Self :: new ( ) ;
487+ vec. extend_from_slice ( slice) ;
488+ vec
489+ }
490+
481491 pub fn insert_from_slice ( & mut self , index : usize , slice : & [ A :: Item ] ) {
482492 self . reserve ( slice. len ( ) ) ;
483493
@@ -500,6 +510,19 @@ impl<A: Array> SmallVec<A> where A::Item: Copy {
500510 }
501511}
502512
513+ impl < A : Array > HeapSizeOf for SmallVec < A > where A :: Item : HeapSizeOf {
514+ fn heap_size_of_children ( & self ) -> usize {
515+ match self . data {
516+ Inline { .. } => 0 ,
517+ Heap { ptr, .. } => {
518+ self . iter ( ) . fold (
519+ unsafe { heap_size_of ( ptr as * const c_void ) } ,
520+ |n, elem| n + elem. heap_size_of_children ( ) )
521+ } ,
522+ }
523+ }
524+ }
525+
503526impl < A : Array > ops:: Deref for SmallVec < A > {
504527 type Target = [ A :: Item ] ;
505528 #[ inline]
@@ -823,15 +846,17 @@ macro_rules! impl_array(
823846 }
824847) ;
825848
826- impl_array ! ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 20 , 24 , 32 ,
849+ impl_array ! ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 20 , 24 , 32 , 36 ,
827850 0x40 , 0x80 , 0x100 , 0x200 , 0x400 , 0x800 , 0x1000 , 0x2000 , 0x4000 , 0x8000 ,
828851 0x10000 , 0x20000 , 0x40000 , 0x80000 , 0x100000 ) ;
829852
830853#[ cfg( test) ]
831854pub mod tests {
832855 use SmallVec ;
856+ use heapsize:: HeapSizeOf ;
833857 use std:: borrow:: ToOwned ;
834858 use std:: iter:: FromIterator ;
859+ use std:: mem:: size_of;
835860
836861 // We heap allocate all these strings so that double frees will show up under valgrind.
837862
@@ -1248,6 +1273,35 @@ pub mod tests {
12481273 assert_eq ! ( & SmallVec :: <[ u32 ; 2 ] >:: from( & [ 1 , 2 , 3 ] [ ..] ) [ ..] , [ 1 , 2 , 3 ] ) ;
12491274 }
12501275
1276+ #[ test]
1277+ fn test_from_slice ( ) {
1278+ assert_eq ! ( & SmallVec :: <[ u32 ; 2 ] >:: from_slice( & [ 1 ] [ ..] ) [ ..] , [ 1 ] ) ;
1279+ assert_eq ! ( & SmallVec :: <[ u32 ; 2 ] >:: from_slice( & [ 1 , 2 , 3 ] [ ..] ) [ ..] , [ 1 , 2 , 3 ] ) ;
1280+ }
1281+
1282+ #[ test]
1283+ fn test_heap_size_of_children ( ) {
1284+ let mut vec = SmallVec :: < [ u32 ; 2 ] > :: new ( ) ;
1285+ assert_eq ! ( vec. heap_size_of_children( ) , 0 ) ;
1286+ vec. push ( 1 ) ;
1287+ vec. push ( 2 ) ;
1288+ assert_eq ! ( vec. heap_size_of_children( ) , 0 ) ;
1289+ vec. push ( 3 ) ;
1290+ assert_eq ! ( vec. heap_size_of_children( ) , 16 ) ;
1291+
1292+ // Now check with reserved space
1293+ let mut vec = SmallVec :: < [ u32 ; 2 ] > :: new ( ) ;
1294+ vec. reserve ( 10 ) ; // Rounds up to 16
1295+ assert_eq ! ( vec. heap_size_of_children( ) , 64 ) ;
1296+
1297+ // Check with nested heap structures
1298+ let mut vec = SmallVec :: < [ Vec < u32 > ; 2 ] > :: new ( ) ;
1299+ vec. reserve ( 10 ) ;
1300+ vec. push ( vec ! [ 2 , 3 , 4 ] ) ;
1301+ assert_eq ! ( vec. heap_size_of_children( ) ,
1302+ vec![ 2 , 3 , 4 ] . heap_size_of_children( ) + 16 * size_of:: <Vec <u32 >>( ) ) ;
1303+ }
1304+
12511305 #[ test]
12521306 fn test_exact_size_iterator ( ) {
12531307 let mut vec = SmallVec :: < [ u32 ; 2 ] > :: from ( & [ 1 , 2 , 3 ] [ ..] ) ;
0 commit comments