11//! Provides functions for dynamic array manipulation.
2+ use std:: ops:: { Index , IndexMut , Range } ;
23
34/// Allocate an uninitialized array of a given size.
45///
@@ -9,7 +10,7 @@ pub unsafe fn allocate<T>(len: usize) -> Box<[T]> {
910 vec. into_boxed_slice ( )
1011}
1112
12- /// Copy as many elements as possible from one array to another.
13+ /// Copy as many elements as possible from one slice to another.
1314///
1415/// Returns the number of elements copied.
1516#[ inline]
@@ -19,6 +20,23 @@ pub fn copy<T: Copy>(src: &[T], dest: &mut [T]) -> usize {
1920 len
2021}
2122
23+ /// Copy as many elements as possible from a slice of slices to another.
24+ ///
25+ /// Returns the number of elements copied.
26+ pub fn copy_seq < T : Copy > ( seq : & [ & [ T ] ] , dest : & mut [ T ] ) -> usize {
27+ let mut copied = 0 ;
28+
29+ for slice in seq {
30+ if copied < dest. len ( ) {
31+ copied += copy ( slice, & mut dest[ copied..] ) ;
32+ } else {
33+ break ;
34+ }
35+ }
36+
37+ copied
38+ }
39+
2240/// Extension trait for slices for working with wrapping ranges and indicies.
2341pub trait WrappingSlice < T > {
2442 /// Gets a pair of slices in the given range, wrapping around length.
@@ -47,3 +65,127 @@ impl<T> WrappingSlice<T> for [T] {
4765 }
4866 }
4967}
68+
69+ /// A heap-allocated circular array, useful for implementing ring buffers.
70+ ///
71+ /// This array type uses a _virtual indexing_ system. Indexing into the array applies a virtual mapping such that any
72+ /// index is always mapped to a valid position in the array. More than one virtual index may map to the same position.
73+ pub struct CircularArray < T > {
74+ array : Box < [ T ] > ,
75+ mask : usize ,
76+ }
77+
78+ impl < T > CircularArray < T > {
79+ /// Create a new array of a given length containing uninitialized data.
80+ pub unsafe fn uninitialized ( len : usize ) -> Self {
81+ let len = len. next_power_of_two ( ) ;
82+
83+ Self {
84+ array : allocate ( len) ,
85+ mask : len - 1 ,
86+ }
87+ }
88+
89+ /// Get the length of the array.
90+ #[ inline]
91+ pub fn len ( & self ) -> usize {
92+ self . array . len ( )
93+ }
94+
95+ /// Gets a pair of slices in the given range, wrapping around length.
96+ pub fn as_slices ( & self , range : Range < usize > ) -> [ & [ T ] ; 2 ] {
97+ let start = self . internal_index ( range. start ) ;
98+ let end = self . internal_index ( range. end ) ;
99+
100+ if start < end {
101+ [ & self . array [ start..end] , & [ ] ]
102+ } else {
103+ [ & self . array [ start..] , & self . array [ ..end] ]
104+ }
105+ }
106+
107+ /// Gets a pair of mutable slices in the given range, wrapping around length.
108+ pub fn as_slices_mut ( & mut self , range : Range < usize > ) -> [ & mut [ T ] ; 2 ] {
109+ let start = self . internal_index ( range. start ) ;
110+ let end = self . internal_index ( range. end ) ;
111+
112+ if start < end {
113+ [ & mut self . array [ start..end] , & mut [ ] ]
114+ } else {
115+ let ( mid, right) = self . array . split_at_mut ( start) ;
116+ let left = mid. split_at_mut ( end) . 0 ;
117+ [ right, left]
118+ }
119+ }
120+
121+ // /// Copies elements from this array into
122+ // pub fn copy_to_slice(&self, dest: &mut [T]) -> usize {
123+ // if self.is_empty() {
124+ // return 0;
125+ // }
126+
127+ // let slices = self.array
128+ // .wrapping_range(self.mask(self.head), self.mask(self.tail));
129+
130+ // let mut copied = arrays::copy(slices.0, dest);
131+ // copied += arrays::copy(slices.1, &mut dest[copied..]);
132+
133+ // copied
134+ // }
135+
136+ /// Get the internal index the given virtual index is mapped to.
137+ #[ inline]
138+ fn internal_index ( & self , virtual_index : usize ) -> usize {
139+ virtual_index & self . mask
140+ }
141+ }
142+
143+ impl < T > AsRef < [ T ] > for CircularArray < T > {
144+ fn as_ref ( & self ) -> & [ T ] {
145+ & self . array
146+ }
147+ }
148+
149+ impl < T > AsMut < [ T ] > for CircularArray < T > {
150+ fn as_mut ( & mut self ) -> & mut [ T ] {
151+ & mut self . array
152+ }
153+ }
154+
155+ impl < T > Index < usize > for CircularArray < T > {
156+ type Output = T ;
157+
158+ fn index ( & self , index : usize ) -> & T {
159+ self . array . index ( self . internal_index ( index) )
160+ }
161+ }
162+
163+ impl < T > IndexMut < usize > for CircularArray < T > {
164+ fn index_mut ( & mut self , index : usize ) -> & mut T {
165+ let index = self . internal_index ( index) ;
166+ self . array . index_mut ( index)
167+ }
168+ }
169+
170+ #[ cfg( test) ]
171+ mod tests {
172+ use super :: * ;
173+
174+ #[ test]
175+ fn copy_seq_with_less_elements ( ) {
176+ let chunks: [ & [ i32 ] ; 3 ] = [ & [ ] , & [ 1 , 2 ] , & [ 3 ] ] ;
177+ let mut dest = [ 0 ; 6 ] ;
178+
179+ assert_eq ! ( copy_seq( & chunks, & mut dest) , 3 ) ;
180+ assert_eq ! ( & dest, & [ 1 , 2 , 3 , 0 , 0 , 0 ] ) ;
181+ }
182+
183+ #[ test]
184+ fn copy_seq_with_more_elements ( ) {
185+ let chunks: [ & [ i32 ] ; 5 ] = [ & [ ] , & [ 1 , 2 ] , & [ ] , & [ 3 ] , & [ 4 , 5 , 6 ] ] ;
186+ let mut dest = [ 0 ; 4 ] ;
187+
188+ assert_eq ! ( copy_seq( & chunks, & mut dest) , 4 ) ;
189+ assert_eq ! ( & dest, & [ 1 , 2 , 3 , 4 ] ) ;
190+ }
191+ }
0 commit comments