@@ -39,7 +39,7 @@ pub struct Buffer<T: Copy> {
3939 data : * mut T ,
4040 len : usize ,
4141 capacity : usize ,
42- extend_from_slice : extern "C" fn ( Buffer < T > , Slice < ' _ , T > ) -> Buffer < T > ,
42+ reserve : extern "C" fn ( Buffer < T > , usize ) -> Buffer < T > ,
4343 drop : extern "C" fn ( Buffer < T > ) ,
4444}
4545
@@ -78,18 +78,44 @@ impl<T: Copy> Buffer<T> {
7878 mem:: take ( self )
7979 }
8080
81+ // We have the array method separate from extending from a slice. This is
82+ // because in the case of small arrays, codegen can be more efficient
83+ // (avoiding a memmove call). With extend_from_slice, LLVM at least
84+ // currently is not able to make that optimization.
85+ pub ( super ) fn extend_from_array < const N : usize > ( & mut self , xs : & [ T ; N ] ) {
86+ if xs. len ( ) > ( self . capacity - self . len ) {
87+ let b = self . take ( ) ;
88+ * self = ( b. reserve ) ( b, xs. len ( ) ) ;
89+ }
90+ unsafe {
91+ xs. as_ptr ( ) . copy_to_nonoverlapping ( self . data . add ( self . len ) , xs. len ( ) ) ;
92+ self . len += xs. len ( ) ;
93+ }
94+ }
95+
8196 pub ( super ) fn extend_from_slice ( & mut self , xs : & [ T ] ) {
82- // Fast path to avoid going through an FFI call.
83- if let Some ( final_len) = self . len . checked_add ( xs. len ( ) ) {
84- if final_len <= self . capacity {
85- let dst = unsafe { slice:: from_raw_parts_mut ( self . data , self . capacity ) } ;
86- dst[ self . len ..] [ ..xs. len ( ) ] . copy_from_slice ( xs) ;
87- self . len = final_len;
88- return ;
89- }
97+ if xs. len ( ) > ( self . capacity - self . len ) {
98+ let b = self . take ( ) ;
99+ * self = ( b. reserve ) ( b, xs. len ( ) ) ;
100+ }
101+ unsafe {
102+ xs. as_ptr ( ) . copy_to_nonoverlapping ( self . data . add ( self . len ) , xs. len ( ) ) ;
103+ self . len += xs. len ( ) ;
104+ }
105+ }
106+
107+ pub ( super ) fn push ( & mut self , v : T ) {
108+ // The code here is taken from Vec::push, and we know that reserve()
109+ // will panic if we're exceeding isize::MAX bytes and so there's no need
110+ // to check for overflow.
111+ if self . len == self . capacity {
112+ let b = self . take ( ) ;
113+ * self = ( b. reserve ) ( b, 1 ) ;
114+ }
115+ unsafe {
116+ * self . data . add ( self . len ) = v;
117+ self . len += 1 ;
90118 }
91- let b = self . take ( ) ;
92- * self = ( b. extend_from_slice ) ( b, Slice :: from ( xs) ) ;
93119 }
94120}
95121
@@ -131,16 +157,16 @@ impl<T: Copy> From<Vec<T>> for Buffer<T> {
131157 }
132158 }
133159
134- extern "C" fn extend_from_slice < T : Copy > ( b : Buffer < T > , xs : Slice < ' _ , T > ) -> Buffer < T > {
160+ extern "C" fn reserve < T : Copy > ( b : Buffer < T > , additional : usize ) -> Buffer < T > {
135161 let mut v = to_vec ( b) ;
136- v. extend_from_slice ( & xs ) ;
162+ v. reserve ( additional ) ;
137163 Buffer :: from ( v)
138164 }
139165
140166 extern "C" fn drop < T : Copy > ( b : Buffer < T > ) {
141167 mem:: drop ( to_vec ( b) ) ;
142168 }
143169
144- Buffer { data, len, capacity, extend_from_slice , drop }
170+ Buffer { data, len, capacity, reserve , drop }
145171 }
146172}
0 commit comments