@@ -32,10 +32,12 @@ use core::{
3232 cmp:: Ordering ,
3333 fmt:: { self , Debug } ,
3434 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,
3638 slice:: { Iter , IterMut } ,
3739} ;
38- use typenum:: Unsigned ;
40+ use typenum:: { Diff , Sum , Unsigned } ;
3941
4042/// Hybrid typenum-based and const generic array type.
4143///
@@ -44,6 +46,10 @@ use typenum::Unsigned;
4446#[ repr( transparent) ]
4547pub struct Array < T , U : ArraySize > ( pub U :: ArrayType < T > ) ;
4648
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+
4753impl < T , U > Array < T , U >
4854where
4955 U : ArraySize ,
@@ -126,6 +132,74 @@ where
126132 {
127133 Self :: ref_from_slice ( slice) . clone ( )
128134 }
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+ }
129203}
130204
131205impl < T , U , const N : usize > AsRef < [ T ; N ] > for Array < T , U >
@@ -698,7 +772,7 @@ impl_array_size! {
698772mod tests {
699773 use super :: ByteArray ;
700774 use crate :: Array ;
701- use typenum:: { U0 , U3 , U6 , U7 } ;
775+ use typenum:: { U0 , U2 , U3 , U4 , U6 , U7 } ;
702776
703777 const EXAMPLE_SLICE : & [ u8 ] = & [ 1 , 2 , 3 , 4 , 5 , 6 ] ;
704778
@@ -729,4 +803,43 @@ mod tests {
729803
730804 assert ! ( <& ByteArray :: <U7 >>:: try_from( EXAMPLE_SLICE ) . is_err( ) ) ;
731805 }
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+ }
732845}
0 commit comments