@@ -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
@@ -1713,6 +1784,39 @@ mod tests {
17131784 assert_eq ! ( ( x, y) , Decode :: decode( & mut & encoded[ ..] ) . unwrap( ) ) ;
17141785 }
17151786
1787+ #[ test]
1788+ fn boxed_str_works ( ) {
1789+ let s = "Hello world" . to_owned ( ) ;
1790+ let b = s. clone ( ) . into_boxed_str ( ) ;
1791+
1792+ let encoded = b. encode ( ) ;
1793+ assert_eq ! ( s. encode( ) , encoded) ;
1794+
1795+ assert_eq ! ( * b, * Box :: <str >:: decode( & mut & encoded[ ..] ) . unwrap( ) ) ;
1796+ }
1797+
1798+ #[ test]
1799+ fn boxed_slice_of_primitives_works ( ) {
1800+ let v = vec ! [ 1u32 , 2 , 3 , 4 , 5 , 6 ] ;
1801+ let b = v. clone ( ) . into_boxed_slice ( ) ;
1802+
1803+ let encoded = b. encode ( ) ;
1804+ assert_eq ! ( v. encode( ) , encoded) ;
1805+
1806+ assert_eq ! ( * b, * Box :: <[ u32 ] >:: decode( & mut & b. encode( ) [ ..] ) . unwrap( ) ) ;
1807+ }
1808+
1809+ #[ test]
1810+ fn boxed_slice_of_strings_works ( ) {
1811+ let v = vec ! [ "mine" . to_owned( ) , "yours" . to_owned( ) , "his" . to_owned( ) ] ;
1812+ let b = v. clone ( ) . into_boxed_slice ( ) ;
1813+
1814+ let encoded = b. encode ( ) ;
1815+ assert_eq ! ( v. encode( ) , encoded) ;
1816+
1817+ assert_eq ! ( * b, * Box :: <[ String ] >:: decode( & mut & b. encode( ) [ ..] ) . unwrap( ) ) ;
1818+ }
1819+
17161820 #[ test]
17171821 fn cow_works ( ) {
17181822 let x = & [ 1u32 , 2 , 3 , 4 , 5 , 6 ] [ ..] ;
0 commit comments