@@ -336,6 +336,7 @@ unsafe impl Abomonation for bool { }
336336unsafe impl Abomonation for ( ) { }
337337
338338unsafe impl Abomonation for char { }
339+ unsafe impl Abomonation for str { }
339340
340341unsafe impl Abomonation for :: std:: time:: Duration { }
341342
@@ -480,26 +481,63 @@ array_abomonate!(30);
480481array_abomonate ! ( 31 ) ;
481482array_abomonate ! ( 32 ) ;
482483
483- unsafe impl Abomonation for String {
484+ unsafe impl Abomonation for & ' _ str {
484485 unsafe fn entomb < W : Write > ( & self , write : & mut W ) -> IOResult < ( ) > {
485486 write. write_all ( self . as_bytes ( ) )
486487 }
487488
489+ #[ inline]
490+ unsafe fn exhume < ' a > ( self_ : NonNull < Self > , bytes : & ' a mut [ u8 ] ) -> Option < & ' a mut [ u8 ] > {
491+ // FIXME: This (briefly) constructs an &str to invalid data, which is UB.
492+ // I'm not sure if this can be fully resolved without relying on &str implementation details.
493+ let self_len = self_. as_ref ( ) . len ( ) ;
494+ let ( s, rest) = exhume_str_ref ( self_len, bytes) ?;
495+ self_. as_ptr ( ) . write ( s) ;
496+ Some ( rest)
497+ }
498+
499+ fn extent ( & self ) -> usize {
500+ self . len ( )
501+ }
502+ }
503+
504+ unsafe impl Abomonation for & ' _ mut str {
505+ unsafe fn entomb < W : Write > ( & self , write : & mut W ) -> IOResult < ( ) > {
506+ <& str >:: entomb ( & self . as_ref ( ) , write)
507+ }
508+
509+ #[ inline]
510+ unsafe fn exhume < ' a > ( self_ : NonNull < Self > , bytes : & ' a mut [ u8 ] ) -> Option < & ' a mut [ u8 ] > {
511+ // FIXME: This (briefly) constructs an &mut str to invalid data, which is UB.
512+ // I'm not sure if this can be fully resolved without relying on &str implementation details.
513+ let self_len = self_. as_ref ( ) . len ( ) ;
514+ let ( s, rest) = exhume_str_ref ( self_len, bytes) ?;
515+ self_. as_ptr ( ) . write ( s) ;
516+ Some ( rest)
517+ }
518+
519+ fn extent ( & self ) -> usize {
520+ <& str >:: extent ( & self . as_ref ( ) )
521+ }
522+ }
523+
524+ unsafe impl Abomonation for String {
525+ unsafe fn entomb < W : Write > ( & self , write : & mut W ) -> IOResult < ( ) > {
526+ <& str >:: entomb ( & self . as_ref ( ) , write)
527+ }
528+
488529 #[ inline]
489530 unsafe fn exhume < ' a > ( self_ : NonNull < Self > , bytes : & ' a mut [ u8 ] ) -> Option < & ' a mut [ u8 ] > {
490531 // FIXME: This (briefly) constructs an &String to invalid data, which is UB.
491532 // I'm not sure if this can be fully resolved without relying on String implementation details.
492533 let self_len = self_. as_ref ( ) . len ( ) ;
493- if self_len > bytes. len ( ) { None }
494- else {
495- let ( mine, rest) = bytes. split_at_mut ( self_len) ;
496- self_. as_ptr ( ) . write ( String :: from_raw_parts ( mine. as_mut_ptr ( ) , self_len, self_len) ) ;
497- Some ( rest)
498- }
534+ let ( s, rest) = exhume_str_ref ( self_len, bytes) ?;
535+ self_. as_ptr ( ) . write ( String :: from_raw_parts ( s. as_mut_ptr ( ) , s. len ( ) , s. len ( ) ) ) ;
536+ Some ( rest)
499537 }
500538
501539 fn extent ( & self ) -> usize {
502- self . len ( )
540+ < & str > :: extent ( & self . as_ref ( ) )
503541 }
504542}
505543
@@ -618,6 +656,15 @@ unsafe fn exhume_ptr<'a, T: Abomonation>(bytes: &'a mut [u8]) -> Option<(NonNull
618656 }
619657}
620658
659+ // Common subset of "exhume" for all &str-like types
660+ unsafe fn exhume_str_ref < ' a > ( length : usize , bytes : & ' a mut [ u8 ] ) -> Option < ( & ' a mut str , & ' a mut [ u8 ] ) > {
661+ if length > bytes. len ( ) { None }
662+ else {
663+ let ( mine, rest) = bytes. split_at_mut ( length) ;
664+ Some ( ( std:: str:: from_utf8_unchecked_mut ( mine) , rest) )
665+ }
666+ }
667+
621668mod network {
622669 use Abomonation ;
623670 use std:: net:: { SocketAddr , SocketAddrV4 , SocketAddrV6 , IpAddr , Ipv4Addr , Ipv6Addr } ;
0 commit comments