@@ -32,10 +32,12 @@ use core::{
32
32
cmp:: Ordering ,
33
33
fmt:: { self , Debug } ,
34
34
hash:: { Hash , Hasher } ,
35
- ops:: { Deref , DerefMut , Index , IndexMut , Range } ,
35
+ mem:: { ManuallyDrop , MaybeUninit } ,
36
+ ops:: { Add , Deref , DerefMut , Index , IndexMut , Range , Sub } ,
37
+ ptr,
36
38
slice:: { Iter , IterMut } ,
37
39
} ;
38
- use typenum:: Unsigned ;
40
+ use typenum:: { Diff , Sum , Unsigned } ;
39
41
40
42
/// Hybrid typenum-based and const generic array type.
41
43
///
@@ -44,6 +46,10 @@ use typenum::Unsigned;
44
46
#[ repr( transparent) ]
45
47
pub struct Array < T , U : ArraySize > ( pub U :: ArrayType < T > ) ;
46
48
49
+ type SplitResult < T , U , N > = ( Array < T , N > , Array < T , Diff < U , N > > ) ;
50
+ type SplitRefResult < ' a , T , U , N > = ( & ' a Array < T , N > , & ' a Array < T , Diff < U , N > > ) ;
51
+ type SplitRefMutResult < ' a , T , U , N > = ( & ' a mut Array < T , N > , & ' a mut Array < T , Diff < U , N > > ) ;
52
+
47
53
impl < T , U > Array < T , U >
48
54
where
49
55
U : ArraySize ,
@@ -126,6 +132,74 @@ where
126
132
{
127
133
Self :: ref_from_slice ( slice) . clone ( )
128
134
}
135
+
136
+ /// Concatenates `self` with `other`.
137
+ #[ inline]
138
+ pub fn concat < N > ( self , other : Array < T , N > ) -> Array < T , Sum < U , N > >
139
+ where
140
+ N : ArraySize ,
141
+ U : Add < N > ,
142
+ Sum < U , N > : ArraySize ,
143
+ {
144
+ let mut result = MaybeUninit :: uninit ( ) ;
145
+ let result_ptr = result. as_mut_ptr ( ) as * mut Self ;
146
+
147
+ unsafe {
148
+ ptr:: write ( result_ptr, self ) ;
149
+ ptr:: write ( result_ptr. add ( 1 ) as * mut _ , other) ;
150
+ result. assume_init ( )
151
+ }
152
+ }
153
+
154
+ /// Splits `self` at index `N` in two arrays.
155
+ ///
156
+ /// New arrays hold the original memory from `self`.
157
+ #[ inline]
158
+ pub fn split < N > ( self ) -> SplitResult < T , U , N >
159
+ where
160
+ U : Sub < N > ,
161
+ N : ArraySize ,
162
+ Diff < U , N > : ArraySize ,
163
+ {
164
+ unsafe {
165
+ let array = ManuallyDrop :: new ( self ) ;
166
+ let head = ptr:: read ( array. as_ptr ( ) as * const _ ) ;
167
+ let tail = ptr:: read ( array. as_ptr ( ) . add ( N :: USIZE ) as * const _ ) ;
168
+ ( head, tail)
169
+ }
170
+ }
171
+
172
+ /// Splits `&self` at index `N` in two array references.
173
+ #[ inline]
174
+ pub fn split_ref < N > ( & self ) -> SplitRefResult < ' _ , T , U , N >
175
+ where
176
+ U : Sub < N > ,
177
+ N : ArraySize ,
178
+ Diff < U , N > : ArraySize ,
179
+ {
180
+ unsafe {
181
+ let array_ptr = self . as_ptr ( ) ;
182
+ let head = & * ( array_ptr as * const _ ) ;
183
+ let tail = & * ( array_ptr. add ( N :: USIZE ) as * const _ ) ;
184
+ ( head, tail)
185
+ }
186
+ }
187
+
188
+ /// Splits `&mut self` at index `N` in two mutable array references.
189
+ #[ inline]
190
+ pub fn split_ref_mut < N > ( & mut self ) -> SplitRefMutResult < ' _ , T , U , N >
191
+ where
192
+ U : Sub < N > ,
193
+ N : ArraySize ,
194
+ Diff < U , N > : ArraySize ,
195
+ {
196
+ unsafe {
197
+ let array_ptr = self . as_mut_ptr ( ) ;
198
+ let head = & mut * ( array_ptr as * mut _ ) ;
199
+ let tail = & mut * ( array_ptr. add ( N :: USIZE ) as * mut _ ) ;
200
+ ( head, tail)
201
+ }
202
+ }
129
203
}
130
204
131
205
impl < T , U , const N : usize > AsRef < [ T ; N ] > for Array < T , U >
@@ -698,7 +772,7 @@ impl_array_size! {
698
772
mod tests {
699
773
use super :: ByteArray ;
700
774
use crate :: Array ;
701
- use typenum:: { U0 , U3 , U6 , U7 } ;
775
+ use typenum:: { U0 , U2 , U3 , U4 , U6 , U7 } ;
702
776
703
777
const EXAMPLE_SLICE : & [ u8 ] = & [ 1 , 2 , 3 , 4 , 5 , 6 ] ;
704
778
@@ -729,4 +803,43 @@ mod tests {
729
803
730
804
assert ! ( <& ByteArray :: <U7 >>:: try_from( EXAMPLE_SLICE ) . is_err( ) ) ;
731
805
}
806
+
807
+ #[ test]
808
+ fn concat ( ) {
809
+ let prefix = ByteArray :: < U2 > :: clone_from_slice ( & EXAMPLE_SLICE [ ..2 ] ) ;
810
+ let suffix = ByteArray :: < U4 > :: clone_from_slice ( & EXAMPLE_SLICE [ 2 ..] ) ;
811
+
812
+ let array = prefix. concat ( suffix) ;
813
+ assert_eq ! ( array. as_slice( ) , EXAMPLE_SLICE ) ;
814
+ }
815
+
816
+ #[ test]
817
+ fn split ( ) {
818
+ let array = ByteArray :: < U6 > :: clone_from_slice ( EXAMPLE_SLICE ) ;
819
+
820
+ let ( prefix, suffix) = array. split :: < U2 > ( ) ;
821
+
822
+ assert_eq ! ( prefix. as_slice( ) , & EXAMPLE_SLICE [ ..2 ] ) ;
823
+ assert_eq ! ( suffix. as_slice( ) , & EXAMPLE_SLICE [ 2 ..] ) ;
824
+ }
825
+
826
+ #[ test]
827
+ fn split_ref ( ) {
828
+ let array = ByteArray :: < U6 > :: clone_from_slice ( EXAMPLE_SLICE ) ;
829
+
830
+ let ( prefix, suffix) = array. split_ref :: < U3 > ( ) ;
831
+
832
+ assert_eq ! ( prefix. as_slice( ) , & EXAMPLE_SLICE [ ..3 ] ) ;
833
+ assert_eq ! ( suffix. as_slice( ) , & EXAMPLE_SLICE [ 3 ..] ) ;
834
+ }
835
+
836
+ #[ test]
837
+ fn split_ref_mut ( ) {
838
+ let array = & mut ByteArray :: < U6 > :: clone_from_slice ( EXAMPLE_SLICE ) ;
839
+
840
+ let ( prefix, suffix) = array. split_ref_mut :: < U4 > ( ) ;
841
+
842
+ assert_eq ! ( prefix. as_slice( ) , & EXAMPLE_SLICE [ ..4 ] ) ;
843
+ assert_eq ! ( suffix. as_slice( ) , & EXAMPLE_SLICE [ 4 ..] ) ;
844
+ }
732
845
}
0 commit comments