@@ -438,19 +438,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
438438tuple_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 ) ;
439439tuple_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 ) ;
440440
441+ unsafe impl < ' bytes , T : Abomonation < ' bytes > > Abomonation < ' bytes > for [ T ] {
442+ unsafe fn entomb < W : Write > ( & self , write : & mut W ) -> IOResult < ( ) > {
443+ for element in self { T :: entomb ( element, write) ?; }
444+ Ok ( ( ) )
445+ }
446+
447+ unsafe fn exhume ( self_ : NonNull < Self > , bytes : & ' bytes mut [ u8 ] ) -> Option < & ' bytes mut [ u8 ] > {
448+ // FIXME: This constructs an &[T] to invalid data, which is UB.
449+ // I'm not sure if this can be fully resolved without relying on slice implementation details.
450+ let self_len = self_. as_ref ( ) . len ( ) ;
451+ exhume_slice ( self_. as_ptr ( ) as * mut T , self_len, bytes)
452+ }
453+
454+ fn extent ( & self ) -> usize {
455+ self . iter ( ) . map ( T :: extent) . sum ( )
456+ }
457+ }
458+
441459macro_rules! array_abomonate {
442460 ( $size: expr) => (
443461 unsafe impl <' bytes, T : Abomonation <' bytes>> Abomonation <' bytes> for [ T ; $size] {
444462 unsafe fn entomb<W : Write >( & self , write: & mut W ) -> IOResult <( ) > {
445- entomb_slice ( & self [ ..] , write)
463+ < [ T ] > :: entomb ( & self [ ..] , write)
446464 }
447465
448466 unsafe fn exhume( self_: NonNull <Self >, bytes: & ' bytes mut [ u8 ] ) -> Option <& ' bytes mut [ u8 ] > {
449467 exhume_slice( self_. as_ptr( ) as * mut T , $size, bytes)
450468 }
451469
452470 fn extent( & self ) -> usize {
453- slice_extent ( & self [ ..] )
471+ < [ T ] > :: extent ( & self [ ..] )
454472 }
455473 }
456474 )
@@ -550,30 +568,64 @@ unsafe impl<'bytes> Abomonation<'bytes> for String {
550568 }
551569}
552570
553- unsafe impl < ' bytes , T : Abomonation < ' bytes > > Abomonation < ' bytes > for Vec < T > {
571+ unsafe impl < ' target , ' bytes : ' target , T : Abomonation < ' bytes > > Abomonation < ' bytes > for & ' target [ T ] {
554572 unsafe fn entomb < W : Write > ( & self , write : & mut W ) -> IOResult < ( ) > {
555573 write. write_all ( typed_to_bytes ( & self [ ..] ) ) ?;
556- entomb_slice ( & self [ ..] , write)
574+ <[ T ] >:: entomb ( & self [ ..] , write)
575+ }
576+
577+ #[ inline]
578+ unsafe fn exhume ( self_ : NonNull < Self > , bytes : & ' bytes mut [ u8 ] ) -> Option < & ' bytes mut [ u8 ] > {
579+ // FIXME: This (briefly) constructs an &[T] to invalid data, which is UB.
580+ // I'm not sure if this can be fully resolved without relying on slice implementation details.
581+ let self_len = self_. as_ref ( ) . len ( ) ;
582+ let ( s, rest) = exhume_slice_ref ( self_len, bytes) ?;
583+ self_. as_ptr ( ) . write ( s) ;
584+ Some ( rest)
585+ }
586+
587+ fn extent ( & self ) -> usize {
588+ mem:: size_of :: < T > ( ) * self . len ( ) + <[ T ] >:: extent ( & self [ ..] )
589+ }
590+ }
591+
592+ unsafe impl < ' target , ' bytes : ' target , T : Abomonation < ' bytes > > Abomonation < ' bytes > for & ' target mut [ T ] {
593+ unsafe fn entomb < W : Write > ( & self , write : & mut W ) -> IOResult < ( ) > {
594+ <& [ T ] >:: entomb ( & & self [ ..] , write)
595+ }
596+
597+ #[ inline]
598+ unsafe fn exhume ( self_ : NonNull < Self > , bytes : & ' bytes mut [ u8 ] ) -> Option < & ' bytes mut [ u8 ] > {
599+ // FIXME: This (briefly) constructs an &mut [T] to invalid data, which is UB.
600+ // I'm not sure if this can be fully resolved without relying on slice implementation details.
601+ let self_len = self_. as_ref ( ) . len ( ) ;
602+ let ( s, rest) = exhume_slice_ref ( self_len, bytes) ?;
603+ self_. as_ptr ( ) . write ( s) ;
604+ Some ( rest)
605+ }
606+
607+ fn extent ( & self ) -> usize {
608+ <& [ T ] >:: extent ( & & self [ ..] )
609+ }
610+ }
611+
612+ unsafe impl < ' bytes , T : Abomonation < ' bytes > > Abomonation < ' bytes > for Vec < T > {
613+ unsafe fn entomb < W : Write > ( & self , write : & mut W ) -> IOResult < ( ) > {
614+ <& [ T ] >:: entomb ( & & self [ ..] , write)
557615 }
558616
559617 #[ inline]
560618 unsafe fn exhume ( self_ : NonNull < Self > , bytes : & ' bytes mut [ u8 ] ) -> Option < & ' bytes mut [ u8 ] > {
561619 // FIXME: This (briefly) constructs an &Vec<T> to invalid data, which is UB.
562620 // I'm not sure if this can be fully resolved without relying on Vec implementation details.
563621 let self_len = self_. as_ref ( ) . len ( ) ;
564- let binary_len = self_len * mem:: size_of :: < T > ( ) ;
565- if binary_len > bytes. len ( ) { None }
566- else {
567- let ( mine, mut rest) = bytes. split_at_mut ( binary_len) ;
568- let first_ptr = mine. as_mut_ptr ( ) as * mut T ;
569- rest = exhume_slice ( first_ptr, self_len, rest) ?;
570- self_. as_ptr ( ) . write ( Vec :: from_raw_parts ( first_ptr, self_len, self_len) ) ;
571- Some ( rest)
572- }
622+ let ( s, rest) = exhume_slice_ref ( self_len, bytes) ?;
623+ self_. as_ptr ( ) . write ( Vec :: from_raw_parts ( s. as_mut_ptr ( ) , self_len, self_len) ) ;
624+ Some ( rest)
573625 }
574626
575627 fn extent ( & self ) -> usize {
576- mem :: size_of :: < T > ( ) * self . len ( ) + slice_extent ( & self [ ..] )
628+ < & [ T ] > :: extent ( & & self [ ..] )
577629 }
578630}
579631
@@ -631,14 +683,8 @@ unsafe fn typed_to_bytes<T>(slice: &[T]) -> &[u8] {
631683 std:: slice:: from_raw_parts ( slice. as_ptr ( ) as * const u8 , slice. len ( ) * mem:: size_of :: < T > ( ) )
632684}
633685
634- // Common subset of "entomb" for all [T]-like types
635- unsafe fn entomb_slice < ' a , T : Abomonation < ' a > , W : Write > ( slice : & [ T ] , write : & mut W ) -> IOResult < ( ) > {
636- for element in slice { T :: entomb ( element, write) ?; }
637- Ok ( ( ) )
638- }
639-
640686// Common subset of "exhume" for all [T]-like types
641- // (I'd gladly take a NonNull< [T]> , but it is too difficult to build raw pointers to slices )
687+ // (I'd gladly move this to [T]::exhume , but building a NonNull<[T]> is currently too difficult )
642688#[ inline]
643689unsafe fn exhume_slice < ' bytes , T : Abomonation < ' bytes > > (
644690 first_ptr : * mut T ,
@@ -652,9 +698,17 @@ unsafe fn exhume_slice<'bytes, T: Abomonation<'bytes>>(
652698 Some ( bytes)
653699}
654700
655- // Common subset of "extent" for all [T]-like types
656- fn slice_extent < ' a , T : Abomonation < ' a > > ( slice : & [ T ] ) -> usize {
657- slice. iter ( ) . map ( T :: extent) . sum ( )
701+ // Common subset of "exhume" for all &[T]-like types
702+ #[ inline]
703+ unsafe fn exhume_slice_ref < ' target , ' bytes : ' target , T : Abomonation < ' bytes > > ( length : usize , bytes : & ' bytes mut [ u8 ] ) -> Option < ( & ' target mut [ T ] , & ' bytes mut [ u8 ] ) > {
704+ let binary_len = length * mem:: size_of :: < T > ( ) ;
705+ if binary_len > bytes. len ( ) { None }
706+ else {
707+ let ( mine, mut rest) = bytes. split_at_mut ( binary_len) ;
708+ let first_ptr = mine. as_mut_ptr ( ) as * mut T ;
709+ rest = exhume_slice ( first_ptr, length, rest) ?;
710+ Some ( ( std:: slice:: from_raw_parts_mut ( first_ptr, length) . into ( ) , rest) )
711+ }
658712}
659713
660714// Common subset of "exhume" for all &mut T-like types
0 commit comments