@@ -595,6 +595,77 @@ impl<T> WrapperTypeDecode for Box<T> {
595595
596596impl < T : DecodeWithMemTracking > DecodeWithMemTracking for Box < T > { }
597597
598+ impl < T : Decode > Decode for Box < [ T ] > {
599+ fn decode < I : Input > ( input : & mut I ) -> Result < Self , Error > {
600+ let len = <Compact < u32 > >:: decode ( input) . map ( |Compact ( len) | len as usize ) ?;
601+
602+ input. descend_ref ( ) ?;
603+
604+ // Placement new is not yet stable, but we can just manually allocate a chunk of memory
605+ // and convert it to a `Box` ourselves.
606+ //
607+ // The explicit types here are written out for clarity.
608+ //
609+ // TODO: Use `Box::new_uninit_slice` once that's stable.
610+ let layout = core:: alloc:: Layout :: array :: < MaybeUninit < T > > ( len)
611+ . map_err ( |_| Error :: from ( "Item is too big and cannot be allocated" ) ) ?;
612+
613+ input. on_before_alloc_mem ( layout. size ( ) ) ?;
614+ let ptr: * mut MaybeUninit < T > = if layout. size ( ) == 0 {
615+ core:: ptr:: NonNull :: dangling ( ) . as_ptr ( )
616+ } else {
617+ // SAFETY: Layout has a non-zero size so calling this is safe.
618+ let ptr = unsafe { crate :: alloc:: alloc:: alloc ( layout) } ;
619+
620+ if ptr. is_null ( ) {
621+ crate :: alloc:: alloc:: handle_alloc_error ( layout) ;
622+ }
623+
624+ ptr. cast ( )
625+ } ;
626+
627+ // SAFETY: Constructing a `Box` from a piece of memory allocated with `std::alloc::alloc`
628+ // is explicitly allowed as long as it was allocated with the global allocator
629+ // and the memory layout matches.
630+ //
631+ // Constructing a `Box` from `NonNull::dangling` is also always safe as long
632+ // as the underlying type is zero-sized.
633+ let mut boxed_slice: Box < [ MaybeUninit < T > ] > = unsafe {
634+ Box :: from_raw ( core:: slice:: from_raw_parts_mut ( ptr, len) )
635+ } ;
636+
637+ for elem in & mut * boxed_slice {
638+ T :: decode_into ( input, elem) ?;
639+ }
640+
641+ // Decoding succeeded, so let's get rid of `MaybeUninit`.
642+ // TODO: Use `Box::assume_init` once that's stable.
643+ let boxed_slice = Vec :: from ( boxed_slice)
644+ . into_iter ( )
645+ . map ( |elem| unsafe { MaybeUninit :: assume_init ( elem) } )
646+ . collect ( ) ;
647+
648+ input. ascend_ref ( ) ;
649+ Ok ( boxed_slice)
650+ }
651+ }
652+
653+ impl < T : DecodeWithMemTracking > DecodeWithMemTracking for Box < [ T ] > { }
654+
655+ impl Decode for Box < str > {
656+ fn decode < I : Input > ( input : & mut I ) -> Result < Self , Error > {
657+ // Guaranteed to create a Vec with capacity == len
658+ let vec = Vec :: from ( Box :: < [ u8 ] > :: decode ( input) ?) ;
659+ // Guaranteed not to reallocate the vec, only transmute to String
660+ let str = String :: from_utf8 ( vec) . map_err ( |_| "Invalid utf8 sequence" ) ?;
661+
662+ assert_eq ! ( str . capacity( ) , str . len( ) ) ;
663+ Ok ( str. into_boxed_str ( ) )
664+ }
665+ }
666+
667+ impl DecodeWithMemTracking for Box < str > { }
668+
598669impl < T > WrapperTypeDecode for Rc < T > {
599670 type Wrapped = T ;
600671
@@ -1717,6 +1788,39 @@ mod tests {
17171788 assert_eq ! ( ( x, y) , Decode :: decode( & mut & encoded[ ..] ) . unwrap( ) ) ;
17181789 }
17191790
1791+ #[ test]
1792+ fn boxed_str_works ( ) {
1793+ let s = "Hello world" . to_owned ( ) ;
1794+ let b = s. clone ( ) . into_boxed_str ( ) ;
1795+
1796+ let encoded = b. encode ( ) ;
1797+ assert_eq ! ( s. encode( ) , encoded) ;
1798+
1799+ assert_eq ! ( * b, * Box :: <str >:: decode( & mut & encoded[ ..] ) . unwrap( ) ) ;
1800+ }
1801+
1802+ #[ test]
1803+ fn boxed_slice_of_primitives_works ( ) {
1804+ let v = vec ! [ 1u32 , 2 , 3 , 4 , 5 , 6 ] ;
1805+ let b = v. clone ( ) . into_boxed_slice ( ) ;
1806+
1807+ let encoded = b. encode ( ) ;
1808+ assert_eq ! ( v. encode( ) , encoded) ;
1809+
1810+ assert_eq ! ( * b, * Box :: <[ u32 ] >:: decode( & mut & b. encode( ) [ ..] ) . unwrap( ) ) ;
1811+ }
1812+
1813+ #[ test]
1814+ fn boxed_slice_of_strings_works ( ) {
1815+ let v = vec ! [ "mine" . to_owned( ) , "yours" . to_owned( ) , "his" . to_owned( ) ] ;
1816+ let b = v. clone ( ) . into_boxed_slice ( ) ;
1817+
1818+ let encoded = b. encode ( ) ;
1819+ assert_eq ! ( v. encode( ) , encoded) ;
1820+
1821+ assert_eq ! ( * b, * Box :: <[ String ] >:: decode( & mut & b. encode( ) [ ..] ) . unwrap( ) ) ;
1822+ }
1823+
17201824 #[ test]
17211825 fn cow_works ( ) {
17221826 let x = & [ 1u32 , 2 , 3 , 4 , 5 , 6 ] [ ..] ;
0 commit comments