11use alloc:: collections:: VecDeque ;
2- use core:: cmp;
2+ use core:: { cmp, mem :: MaybeUninit } ;
33
44pub struct RingBuffer {
55 buf : VecDeque < u8 > ,
@@ -78,7 +78,7 @@ impl RingBuffer {
7878
7979 /// Copies elements from the provided range to the end of the buffer.
8080 #[ 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 ) {
8282 if start + len > self . len ( ) {
8383 panic ! (
8484 "Calls to this functions must respect start ({}) + len ({}) <= self.len() ({})!" ,
@@ -88,126 +88,55 @@ impl RingBuffer {
8888 ) ;
8989 }
9090
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+ }
97121 }
98122
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;
100136 }
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 ) ;
163137 }
164138}
165139
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-
211140#[ cfg( test) ]
212141mod tests {
213142 use std:: vec:: Vec ;
0 commit comments