1
1
use alloc:: collections:: VecDeque ;
2
- use core:: cmp;
2
+ use core:: { cmp, mem :: MaybeUninit } ;
3
3
4
4
pub struct RingBuffer {
5
5
buf : VecDeque < u8 > ,
@@ -78,7 +78,7 @@ impl RingBuffer {
78
78
79
79
/// Copies elements from the provided range to the end of the buffer.
80
80
#[ allow( dead_code) ]
81
- pub fn extend_from_within ( & mut self , mut start : usize , len : usize ) {
81
+ pub fn extend_from_within ( & mut self , start : usize , mut len : usize ) {
82
82
if start + len > self . len ( ) {
83
83
panic ! (
84
84
"Calls to this functions must respect start ({}) + len ({}) <= self.len() ({})!" ,
@@ -88,126 +88,55 @@ impl RingBuffer {
88
88
) ;
89
89
}
90
90
91
- // Naive and cheaper implementation (for small lengths)
92
- if len <= 12 {
93
- self . reserve ( len) ;
94
- for i in 0 ..len {
95
- let byte = self . get ( start + i) . unwrap ( ) ;
96
- self . push_back ( byte) ;
91
+ self . reserve ( len) ;
92
+
93
+ let mut buf = [ MaybeUninit :: < u8 > :: uninit ( ) ; 2048 ] ;
94
+ let mut start = start;
95
+ while len > 0 {
96
+ let round_len = cmp:: min ( len, buf. len ( ) ) ;
97
+ let mut remaining_len = round_len;
98
+
99
+ let ( a, b) = self . buf . as_slices ( ) ;
100
+ let b = if start < a. len ( ) {
101
+ let a = & a[ start..] ;
102
+ let end = cmp:: min ( a. len ( ) , remaining_len) ;
103
+ unsafe {
104
+ buf. as_mut_ptr ( )
105
+ . cast :: < u8 > ( )
106
+ . copy_from_nonoverlapping ( a. as_ptr ( ) , end) ;
107
+ }
108
+ remaining_len -= end;
109
+ b
110
+ } else {
111
+ unsafe { b. get_unchecked ( start - a. len ( ) ..) }
112
+ } ;
113
+
114
+ if remaining_len > 0 {
115
+ unsafe {
116
+ buf. as_mut_ptr ( )
117
+ . cast :: < u8 > ( )
118
+ . add ( round_len - remaining_len)
119
+ . copy_from_nonoverlapping ( b. as_ptr ( ) , remaining_len) ;
120
+ }
97
121
}
98
122
99
- return ;
123
+ /*
124
+ let mut i = 0;
125
+ self.buf.iter().skip(start).take(len).for_each(|&b| unsafe {
126
+ *buf.get_unchecked_mut(i) = MaybeUninit::new(b);
127
+ i += 1;
128
+ });
129
+ */
130
+
131
+ self . buf . extend ( unsafe {
132
+ std:: slice:: from_raw_parts ( buf. as_ptr ( ) . cast :: < u8 > ( ) , round_len)
133
+ } ) ;
134
+ len -= round_len;
135
+ start += round_len;
100
136
}
101
-
102
- let original_len = self . len ( ) ;
103
- let mut intermediate = {
104
- IntermediateRingBuffer {
105
- this : self ,
106
- original_len,
107
- }
108
- } ;
109
-
110
- intermediate. this . buf . extend ( ( 0 ..len) . map ( |_| 0 ) ) ;
111
- debug_assert_eq ! ( intermediate. this. buf. len( ) , original_len + len) ;
112
-
113
- let ( a, b, a_spare, b_spare) = intermediate. as_slices_spare_mut ( ) ;
114
- debug_assert_eq ! ( a_spare. len( ) + b_spare. len( ) , len) ;
115
-
116
- let skip = cmp:: min ( a. len ( ) , start) ;
117
- start -= skip;
118
- let a = & a[ skip..] ;
119
- let b = & b[ start..] ;
120
-
121
- let mut remaining_copy_len = len;
122
-
123
- // A -> A Spare
124
- let copy_at_least = cmp:: min ( cmp:: min ( a. len ( ) , a_spare. len ( ) ) , remaining_copy_len) ;
125
- copy_bytes_overshooting ( a, a_spare, copy_at_least) ;
126
- remaining_copy_len -= copy_at_least;
127
-
128
- if remaining_copy_len == 0 {
129
- return ;
130
- }
131
-
132
- let a = & a[ copy_at_least..] ;
133
- let a_spare = & mut a_spare[ copy_at_least..] ;
134
-
135
- // A -> B Spare
136
- let copy_at_least = cmp:: min ( cmp:: min ( a. len ( ) , b_spare. len ( ) ) , remaining_copy_len) ;
137
- copy_bytes_overshooting ( a, b_spare, copy_at_least) ;
138
- remaining_copy_len -= copy_at_least;
139
-
140
- if remaining_copy_len == 0 {
141
- return ;
142
- }
143
-
144
- let b_spare = & mut b_spare[ copy_at_least..] ;
145
-
146
- // B -> A Spare
147
- let copy_at_least = cmp:: min ( cmp:: min ( b. len ( ) , a_spare. len ( ) ) , remaining_copy_len) ;
148
- copy_bytes_overshooting ( b, a_spare, copy_at_least) ;
149
- remaining_copy_len -= copy_at_least;
150
-
151
- if remaining_copy_len == 0 {
152
- return ;
153
- }
154
-
155
- let b = & b[ copy_at_least..] ;
156
-
157
- // B -> B Spare
158
- let copy_at_least = cmp:: min ( cmp:: min ( b. len ( ) , b_spare. len ( ) ) , remaining_copy_len) ;
159
- copy_bytes_overshooting ( b, b_spare, copy_at_least) ;
160
- remaining_copy_len -= copy_at_least;
161
-
162
- debug_assert_eq ! ( remaining_copy_len, 0 ) ;
163
137
}
164
138
}
165
139
166
- struct IntermediateRingBuffer < ' a > {
167
- this : & ' a mut RingBuffer ,
168
- original_len : usize ,
169
- }
170
-
171
- impl < ' a > IntermediateRingBuffer < ' a > {
172
- // inspired by `Vec::split_at_spare_mut`
173
- fn as_slices_spare_mut ( & mut self ) -> ( & [ u8 ] , & [ u8 ] , & mut [ u8 ] , & mut [ u8 ] ) {
174
- let ( a, b) = self . this . buf . as_mut_slices ( ) ;
175
- debug_assert ! ( a. len( ) + b. len( ) >= self . original_len) ;
176
-
177
- let mut remaining_init_len = self . original_len ;
178
- let a_mid = cmp:: min ( a. len ( ) , remaining_init_len) ;
179
- remaining_init_len -= a_mid;
180
- let b_mid = remaining_init_len;
181
- debug_assert ! ( b. len( ) >= b_mid) ;
182
-
183
- let ( a, a_spare) = a. split_at_mut ( a_mid) ;
184
- let ( b, b_spare) = b. split_at_mut ( b_mid) ;
185
- debug_assert ! ( a_spare. is_empty( ) || b. is_empty( ) ) ;
186
-
187
- ( a, b, a_spare, b_spare)
188
- }
189
- }
190
-
191
- /// Similar to ptr::copy_nonoverlapping
192
- ///
193
- /// But it might overshoot the desired copy length if deemed useful
194
- ///
195
- /// src and dst specify the entire length they are eligible for reading/writing respectively
196
- /// in addition to the desired copy length.
197
- ///
198
- /// This function will then copy in chunks and might copy up to chunk size - 1 more bytes from src to dst
199
- /// if that operation does not read/write memory that does not belong to src/dst.
200
- ///
201
- /// The chunk size is not part of the contract and may change depending on the target platform.
202
- ///
203
- /// If that isn't possible we just fall back to ptr::copy_nonoverlapping
204
- fn copy_bytes_overshooting ( src : & [ u8 ] , dst : & mut [ u8 ] , copy_at_least : usize ) {
205
- let src = & src[ ..copy_at_least] ;
206
- let dst = & mut dst[ ..copy_at_least] ;
207
-
208
- dst. copy_from_slice ( src) ;
209
- }
210
-
211
140
#[ cfg( test) ]
212
141
mod tests {
213
142
use std:: vec:: Vec ;
0 commit comments