@@ -39,7 +39,7 @@ pub struct Buffer<T: Copy> {
39
39
data : * mut T ,
40
40
len : usize ,
41
41
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 > ,
43
43
drop : extern "C" fn ( Buffer < T > ) ,
44
44
}
45
45
@@ -78,18 +78,44 @@ impl<T: Copy> Buffer<T> {
78
78
mem:: take ( self )
79
79
}
80
80
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
+
81
96
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 ;
90
118
}
91
- let b = self . take ( ) ;
92
- * self = ( b. extend_from_slice ) ( b, Slice :: from ( xs) ) ;
93
119
}
94
120
}
95
121
@@ -131,16 +157,16 @@ impl<T: Copy> From<Vec<T>> for Buffer<T> {
131
157
}
132
158
}
133
159
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 > {
135
161
let mut v = to_vec ( b) ;
136
- v. extend_from_slice ( & xs ) ;
162
+ v. reserve ( additional ) ;
137
163
Buffer :: from ( v)
138
164
}
139
165
140
166
extern "C" fn drop < T : Copy > ( b : Buffer < T > ) {
141
167
mem:: drop ( to_vec ( b) ) ;
142
168
}
143
169
144
- Buffer { data, len, capacity, extend_from_slice , drop }
170
+ Buffer { data, len, capacity, reserve , drop }
145
171
}
146
172
}
0 commit comments