@@ -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///
@@ -613,6 +615,110 @@ macro_rules! impl_array_size {
613615 } ;
614616}
615617
618+ /// Defines trait for concatenation.
619+ pub trait Concat < T , M : ArraySize > {
620+ /// Part to be appended to `self`
621+ type Suffix ;
622+
623+ /// Result of the concatenation.
624+ type Output ;
625+
626+ /// Concatenates `self` with `suffix`.
627+ fn concat ( self , suffix : Self :: Suffix ) -> Self :: Output ;
628+ }
629+
630+ impl < T , M , N > Concat < T , M > for Array < T , N >
631+ where
632+ N : ArraySize + Add < M > ,
633+ M : ArraySize ,
634+ Sum < N , M > : ArraySize ,
635+ {
636+ type Suffix = Array < T , M > ;
637+ type Output = Array < T , Sum < N , M > > ;
638+
639+ fn concat ( self , suffix : Self :: Suffix ) -> Self :: Output {
640+ let mut output: MaybeUninit < Self :: Output > = MaybeUninit :: uninit ( ) ;
641+ let out_ptr = output. as_mut_ptr ( ) as * mut Self ;
642+
643+ unsafe {
644+ ptr:: write ( out_ptr, self ) ;
645+ ptr:: write ( out_ptr. add ( 1 ) as * mut _ , suffix) ;
646+ output. assume_init ( )
647+ }
648+ }
649+ }
650+
651+ /// Defines trait for splitting.
652+ pub trait Split < T , K : ArraySize > {
653+ /// First part of the split.
654+ type Head ;
655+ /// Second part of the split.
656+ type Tail ;
657+
658+ /// Splits `self` in two parts.
659+ fn split ( self ) -> ( Self :: Head , Self :: Tail ) ;
660+ }
661+
662+ impl < T , N , K > Split < T , K > for Array < T , N >
663+ where
664+ N : ArraySize ,
665+ K : ArraySize ,
666+ N : Sub < K > ,
667+ Diff < N , K > : ArraySize ,
668+ {
669+ type Head = Array < T , K > ;
670+ type Tail = Array < T , Diff < N , K > > ;
671+
672+ fn split ( self ) -> ( Self :: Head , Self :: Tail ) {
673+ unsafe {
674+ let array = ManuallyDrop :: new ( self ) ;
675+ let head = ptr:: read ( array. as_ptr ( ) as * const _ ) ;
676+ let tail = ptr:: read ( array. as_ptr ( ) . add ( K :: USIZE ) as * const _ ) ;
677+ ( head, tail)
678+ }
679+ }
680+ }
681+
682+ impl < ' a , T , N , K > Split < T , K > for & ' a Array < T , N >
683+ where
684+ N : ArraySize ,
685+ K : ArraySize ,
686+ N : Sub < K > ,
687+ Diff < N , K > : ArraySize ,
688+ {
689+ type Head = & ' a Array < T , K > ;
690+ type Tail = & ' a Array < T , Diff < N , K > > ;
691+
692+ fn split ( self ) -> ( Self :: Head , Self :: Tail ) {
693+ unsafe {
694+ let array_ptr: * const T = self . as_ptr ( ) ;
695+ let head = & * ( array_ptr as * const _ ) ;
696+ let tail = & * ( array_ptr. add ( K :: USIZE ) as * const _ ) ;
697+ ( head, tail)
698+ }
699+ }
700+ }
701+
702+ impl < ' a , T , N , K > Split < T , K > for & ' a mut Array < T , N >
703+ where
704+ N : ArraySize ,
705+ K : ArraySize ,
706+ N : Sub < K > ,
707+ Diff < N , K > : ArraySize ,
708+ {
709+ type Head = & ' a mut Array < T , K > ;
710+ type Tail = & ' a mut Array < T , Diff < N , K > > ;
711+
712+ fn split ( self ) -> ( Self :: Head , Self :: Tail ) {
713+ unsafe {
714+ let array_ptr: * mut T = self . as_mut_ptr ( ) ;
715+ let head = & mut * ( array_ptr as * mut _ ) ;
716+ let tail = & mut * ( array_ptr. add ( K :: USIZE ) as * mut _ ) ;
717+ ( head, tail)
718+ }
719+ }
720+ }
721+
616722impl_array_size ! {
617723 0 => U0 ,
618724 1 => U1 ,
@@ -696,9 +802,9 @@ impl_array_size! {
696802
697803#[ cfg( test) ]
698804mod tests {
699- use super :: ByteArray ;
805+ use super :: { ByteArray , Concat , Split } ;
700806 use crate :: Array ;
701- use typenum:: { U0 , U3 , U6 , U7 } ;
807+ use typenum:: { U0 , U2 , U3 , U4 , U6 , U7 } ;
702808
703809 const EXAMPLE_SLICE : & [ u8 ] = & [ 1 , 2 , 3 , 4 , 5 , 6 ] ;
704810
@@ -729,4 +835,23 @@ mod tests {
729835
730836 assert ! ( <& ByteArray :: <U7 >>:: try_from( EXAMPLE_SLICE ) . is_err( ) ) ;
731837 }
838+
839+ #[ test]
840+ fn concat ( ) {
841+ let prefix = ByteArray :: < U2 > :: clone_from_slice ( & EXAMPLE_SLICE [ ..2 ] ) ;
842+ let suffix = ByteArray :: < U4 > :: clone_from_slice ( & EXAMPLE_SLICE [ 2 ..] ) ;
843+
844+ let array = prefix. concat ( suffix) ;
845+ assert_eq ! ( array. as_slice( ) , EXAMPLE_SLICE ) ;
846+ }
847+
848+ #[ test]
849+ fn split ( ) {
850+ let array = ByteArray :: < U6 > :: clone_from_slice ( EXAMPLE_SLICE ) ;
851+
852+ let ( prefix, suffix) = Split :: < _ , U2 > :: split ( array) ;
853+
854+ assert_eq ! ( prefix. as_slice( ) , & EXAMPLE_SLICE [ ..2 ] ) ;
855+ assert_eq ! ( suffix. as_slice( ) , & EXAMPLE_SLICE [ 2 ..] ) ;
856+ }
732857}
0 commit comments