@@ -345,6 +345,7 @@ unsafe impl Abomonation<'_> for bool { }
345345unsafe impl Abomonation < ' _ > for ( ) { }
346346
347347unsafe impl Abomonation < ' _ > for char { }
348+ unsafe impl Abomonation < ' _ > for str { }
348349
349350unsafe impl Abomonation < ' _ > for :: std:: time:: Duration { }
350351
@@ -489,26 +490,63 @@ array_abomonate!(30);
489490array_abomonate ! ( 31 ) ;
490491array_abomonate ! ( 32 ) ;
491492
492- unsafe impl < ' bytes > Abomonation < ' bytes > for String {
493+ unsafe impl < ' target , ' bytes : ' target > Abomonation < ' bytes > for & ' target str {
493494 unsafe fn entomb < W : Write > ( & self , write : & mut W ) -> IOResult < ( ) > {
494495 write. write_all ( self . as_bytes ( ) )
495496 }
496497
498+ #[ inline]
499+ unsafe fn exhume ( self_ : NonNull < Self > , bytes : & ' bytes mut [ u8 ] ) -> Option < & ' bytes mut [ u8 ] > {
500+ // FIXME: This (briefly) constructs an &str to invalid data, which is UB.
501+ // I'm not sure if this can be fully resolved without relying on &str implementation details.
502+ let self_len = self_. as_ref ( ) . len ( ) ;
503+ let ( s, rest) = exhume_str_ref ( self_len, bytes) ?;
504+ self_. as_ptr ( ) . write ( s) ;
505+ Some ( rest)
506+ }
507+
508+ fn extent ( & self ) -> usize {
509+ self . len ( )
510+ }
511+ }
512+
513+ unsafe impl < ' target , ' bytes : ' target > Abomonation < ' bytes > for & ' target mut str {
514+ unsafe fn entomb < W : Write > ( & self , write : & mut W ) -> IOResult < ( ) > {
515+ <& str >:: entomb ( & self . as_ref ( ) , write)
516+ }
517+
518+ #[ inline]
519+ unsafe fn exhume ( self_ : NonNull < Self > , bytes : & ' bytes mut [ u8 ] ) -> Option < & ' bytes mut [ u8 ] > {
520+ // FIXME: This (briefly) constructs an &mut str to invalid data, which is UB.
521+ // I'm not sure if this can be fully resolved without relying on &str implementation details.
522+ let self_len = self_. as_ref ( ) . len ( ) ;
523+ let ( s, rest) = exhume_str_ref ( self_len, bytes) ?;
524+ self_. as_ptr ( ) . write ( s) ;
525+ Some ( rest)
526+ }
527+
528+ fn extent ( & self ) -> usize {
529+ <& str >:: extent ( & self . as_ref ( ) )
530+ }
531+ }
532+
533+ unsafe impl < ' bytes > Abomonation < ' bytes > for String {
534+ unsafe fn entomb < W : Write > ( & self , write : & mut W ) -> IOResult < ( ) > {
535+ <& str >:: entomb ( & self . as_ref ( ) , write)
536+ }
537+
497538 #[ inline]
498539 unsafe fn exhume ( self_ : NonNull < Self > , bytes : & ' bytes mut [ u8 ] ) -> Option < & ' bytes mut [ u8 ] > {
499540 // FIXME: This (briefly) constructs an &String to invalid data, which is UB.
500541 // I'm not sure if this can be fully resolved without relying on String implementation details.
501542 let self_len = self_. as_ref ( ) . len ( ) ;
502- if self_len > bytes. len ( ) { None }
503- else {
504- let ( mine, rest) = bytes. split_at_mut ( self_len) ;
505- self_. as_ptr ( ) . write ( String :: from_raw_parts ( mine. as_mut_ptr ( ) , self_len, self_len) ) ;
506- Some ( rest)
507- }
543+ let ( s, rest) = exhume_str_ref ( self_len, bytes) ?;
544+ self_. as_ptr ( ) . write ( String :: from_raw_parts ( s. as_mut_ptr ( ) , s. len ( ) , s. len ( ) ) ) ;
545+ Some ( rest)
508546 }
509547
510548 fn extent ( & self ) -> usize {
511- self . len ( )
549+ < & str > :: extent ( & self . as_ref ( ) )
512550 }
513551}
514552
@@ -631,6 +669,15 @@ unsafe fn exhume_ref<'target, 'bytes: 'target, T: Abomonation<'bytes>>(bytes: &'
631669 }
632670}
633671
672+ // Common subset of "exhume" for all &str-like types
673+ unsafe fn exhume_str_ref < ' target , ' bytes : ' target > ( length : usize , bytes : & ' bytes mut [ u8 ] ) -> Option < ( & ' target mut str , & ' bytes mut [ u8 ] ) > {
674+ if length > bytes. len ( ) { None }
675+ else {
676+ let ( mine, rest) = bytes. split_at_mut ( length) ;
677+ Some ( ( std:: str:: from_utf8_unchecked_mut ( mine) , rest) )
678+ }
679+ }
680+
634681mod network {
635682 use Abomonation ;
636683 use std:: net:: { SocketAddr , SocketAddrV4 , SocketAddrV6 , IpAddr , Ipv4Addr , Ipv6Addr } ;
0 commit comments