@@ -429,19 +429,37 @@ tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AA AB AC AD
429429tuple_abomonate ! ( A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AA AB AC AD AE ) ;
430430tuple_abomonate ! ( A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AA AB AC AD AE AF ) ;
431431
432+ unsafe impl < T : Abomonation > Abomonation for [ T ] {
433+ unsafe fn entomb < W : Write > ( & self , write : & mut W ) -> IOResult < ( ) > {
434+ for element in self { T :: entomb ( element, write) ?; }
435+ Ok ( ( ) )
436+ }
437+
438+ unsafe fn exhume < ' a > ( self_ : NonNull < Self > , bytes : & ' a mut [ u8 ] ) -> Option < & ' a mut [ u8 ] > {
439+ // FIXME: This constructs an &[T] to invalid data, which is UB.
440+ // I'm not sure if this can be fully resolved without relying on slice implementation details.
441+ let self_len = self_. as_ref ( ) . len ( ) ;
442+ exhume_slice ( self_. as_ptr ( ) as * mut T , self_len, bytes)
443+ }
444+
445+ fn extent ( & self ) -> usize {
446+ self . iter ( ) . map ( T :: extent) . sum ( )
447+ }
448+ }
449+
432450macro_rules! array_abomonate {
433451 ( $size: expr) => (
434452 unsafe impl <T : Abomonation > Abomonation for [ T ; $size] {
435453 unsafe fn entomb<W : Write >( & self , write: & mut W ) -> IOResult <( ) > {
436- entomb_slice ( & self [ ..] , write)
454+ < [ T ] > :: entomb ( & self [ ..] , write)
437455 }
438456
439457 unsafe fn exhume<' a>( self_: NonNull <Self >, bytes: & ' a mut [ u8 ] ) -> Option <& ' a mut [ u8 ] > {
440458 exhume_slice( self_. as_ptr( ) as * mut T , $size, bytes)
441459 }
442460
443461 fn extent( & self ) -> usize {
444- slice_extent ( & self [ ..] )
462+ < [ T ] > :: extent ( & self [ ..] )
445463 }
446464 }
447465 )
@@ -541,30 +559,64 @@ unsafe impl Abomonation for String {
541559 }
542560}
543561
544- unsafe impl < T : Abomonation > Abomonation for Vec < T > {
562+ unsafe impl < T : Abomonation > Abomonation for & ' _ [ T ] {
545563 unsafe fn entomb < W : Write > ( & self , write : & mut W ) -> IOResult < ( ) > {
546564 write. write_all ( typed_to_bytes ( & self [ ..] ) ) ?;
547- entomb_slice ( & self [ ..] , write)
565+ <[ T ] >:: entomb ( & self [ ..] , write)
566+ }
567+
568+ #[ inline]
569+ unsafe fn exhume < ' a > ( self_ : NonNull < Self > , bytes : & ' a mut [ u8 ] ) -> Option < & ' a mut [ u8 ] > {
570+ // FIXME: This (briefly) constructs an &[T] to invalid data, which is UB.
571+ // I'm not sure if this can be fully resolved without relying on slice implementation details.
572+ let self_len = self_. as_ref ( ) . len ( ) ;
573+ let ( s, rest) = exhume_slice_ref ( self_len, bytes) ?;
574+ self_. as_ptr ( ) . write ( s. as_ref ( ) ) ;
575+ Some ( rest)
576+ }
577+
578+ fn extent ( & self ) -> usize {
579+ mem:: size_of :: < T > ( ) * self . len ( ) + <[ T ] >:: extent ( & self [ ..] )
580+ }
581+ }
582+
583+ unsafe impl < T : Abomonation > Abomonation for & ' _ mut [ T ] {
584+ unsafe fn entomb < W : Write > ( & self , write : & mut W ) -> IOResult < ( ) > {
585+ <& [ T ] >:: entomb ( & & self [ ..] , write)
586+ }
587+
588+ #[ inline]
589+ unsafe fn exhume < ' a > ( self_ : NonNull < Self > , bytes : & ' a mut [ u8 ] ) -> Option < & ' a mut [ u8 ] > {
590+ // FIXME: This (briefly) constructs an &mut [T] to invalid data, which is UB.
591+ // I'm not sure if this can be fully resolved without relying on slice implementation details.
592+ let self_len = self_. as_ref ( ) . len ( ) ;
593+ let ( mut s, rest) = exhume_slice_ref ( self_len, bytes) ?;
594+ self_. as_ptr ( ) . write ( s. as_mut ( ) ) ;
595+ Some ( rest)
596+ }
597+
598+ fn extent ( & self ) -> usize {
599+ <& [ T ] >:: extent ( & & self [ ..] )
600+ }
601+ }
602+
603+ unsafe impl < T : Abomonation > Abomonation for Vec < T > {
604+ unsafe fn entomb < W : Write > ( & self , write : & mut W ) -> IOResult < ( ) > {
605+ <& [ T ] >:: entomb ( & & self [ ..] , write)
548606 }
549607
550608 #[ inline]
551609 unsafe fn exhume < ' a > ( self_ : NonNull < Self > , bytes : & ' a mut [ u8 ] ) -> Option < & ' a mut [ u8 ] > {
552610 // FIXME: This (briefly) constructs an &Vec<T> to invalid data, which is UB.
553611 // I'm not sure if this can be fully resolved without relying on Vec implementation details.
554612 let self_len = self_. as_ref ( ) . len ( ) ;
555- let binary_len = self_len * mem:: size_of :: < T > ( ) ;
556- if binary_len > bytes. len ( ) { None }
557- else {
558- let ( mine, mut rest) = bytes. split_at_mut ( binary_len) ;
559- let first_ptr = mine. as_mut_ptr ( ) as * mut T ;
560- rest = exhume_slice ( first_ptr, self_len, rest) ?;
561- self_. as_ptr ( ) . write ( Vec :: from_raw_parts ( first_ptr, self_len, self_len) ) ;
562- Some ( rest)
563- }
613+ let ( mut s, rest) = exhume_slice_ref ( self_len, bytes) ?;
614+ self_. as_ptr ( ) . write ( Vec :: from_raw_parts ( s. as_mut ( ) . as_mut_ptr ( ) , self_len, self_len) ) ;
615+ Some ( rest)
564616 }
565617
566618 fn extent ( & self ) -> usize {
567- mem :: size_of :: < T > ( ) * self . len ( ) + slice_extent ( & self [ ..] )
619+ < & [ T ] > :: extent ( & & self [ ..] )
568620 }
569621}
570622
@@ -622,14 +674,8 @@ unsafe fn typed_to_bytes<T>(slice: &[T]) -> &[u8] {
622674 std:: slice:: from_raw_parts ( slice. as_ptr ( ) as * const u8 , slice. len ( ) * mem:: size_of :: < T > ( ) )
623675}
624676
625- // Common subset of "entomb" for all [T]-like types
626- unsafe fn entomb_slice < T : Abomonation , W : Write > ( slice : & [ T ] , write : & mut W ) -> IOResult < ( ) > {
627- for element in slice { T :: entomb ( element, write) ?; }
628- Ok ( ( ) )
629- }
630-
631677// Common subset of "exhume" for all [T]-like types
632- // (I'd gladly take a NonNull< [T]> , but it is too difficult to build raw pointers to slices )
678+ // (I'd gladly move this to [T]::extent , but building a NonNull<[T]> is currently too difficult )
633679#[ inline]
634680unsafe fn exhume_slice < ' a , T : Abomonation > ( first_ptr : * mut T , length : usize , mut bytes : & ' a mut [ u8 ] ) -> Option < & ' a mut [ u8 ] > {
635681 for i in 0 ..length {
@@ -639,9 +685,17 @@ unsafe fn exhume_slice<'a, T: Abomonation>(first_ptr: *mut T, length: usize, mut
639685 Some ( bytes)
640686}
641687
642- // Common subset of "extent" for all [T]-like types
643- fn slice_extent < T : Abomonation > ( slice : & [ T ] ) -> usize {
644- slice. iter ( ) . map ( T :: extent) . sum ( )
688+ // Common subset of "exhume" for all &[T]-like types
689+ #[ inline]
690+ unsafe fn exhume_slice_ref < ' a , T : Abomonation > ( length : usize , bytes : & ' a mut [ u8 ] ) -> Option < ( NonNull < [ T ] > , & ' a mut [ u8 ] ) > {
691+ let binary_len = length * mem:: size_of :: < T > ( ) ;
692+ if binary_len > bytes. len ( ) { None }
693+ else {
694+ let ( mine, mut rest) = bytes. split_at_mut ( binary_len) ;
695+ let first_ptr = mine. as_mut_ptr ( ) as * mut T ;
696+ rest = exhume_slice ( first_ptr, length, rest) ?;
697+ Some ( ( std:: slice:: from_raw_parts_mut ( first_ptr, length) . into ( ) , rest) )
698+ }
645699}
646700
647701// Common subset of "exhume" for all NonNull<T>-like types
0 commit comments