@@ -573,6 +573,72 @@ impl<T> WrapperTypeDecode for Box<T> {
573573 }
574574}
575575
576+ impl < T : Decode > Decode for Box < [ T ] > {
577+ fn decode < I : Input > ( input : & mut I ) -> Result < Self , Error > {
578+ let len = <Compact < u32 > >:: decode ( input) . map ( |Compact ( len) | len as usize ) ?;
579+
580+ input. descend_ref ( ) ?;
581+
582+ // Placement new is not yet stable, but we can just manually allocate a chunk of memory
583+ // and convert it to a `Box` ourselves.
584+ //
585+ // The explicit types here are written out for clarity.
586+ //
587+ // TODO: Use `Box::new_uninit_slice` once that's stable.
588+ let layout = core:: alloc:: Layout :: array :: < MaybeUninit < T > > ( len)
589+ . map_err ( |_| Error :: from ( "Item is too big and cannot be allocated" ) ) ?;
590+
591+ let ptr: * mut MaybeUninit < T > = if layout. size ( ) == 0 {
592+ core:: ptr:: NonNull :: dangling ( ) . as_ptr ( )
593+ } else {
594+ // SAFETY: Layout has a non-zero size so calling this is safe.
595+ let ptr = unsafe { crate :: alloc:: alloc:: alloc ( layout) } ;
596+
597+ if ptr. is_null ( ) {
598+ crate :: alloc:: alloc:: handle_alloc_error ( layout) ;
599+ }
600+
601+ ptr. cast ( )
602+ } ;
603+
604+ // SAFETY: Constructing a `Box` from a piece of memory allocated with `std::alloc::alloc`
605+ // is explicitly allowed as long as it was allocated with the global allocator
606+ // and the memory layout matches.
607+ //
608+ // Constructing a `Box` from `NonNull::dangling` is also always safe as long
609+ // as the underlying type is zero-sized.
610+ let mut boxed_slice: Box < [ MaybeUninit < T > ] > = unsafe {
611+ Box :: from_raw ( core:: slice:: from_raw_parts_mut ( ptr, len) )
612+ } ;
613+
614+ for elem in & mut * boxed_slice {
615+ T :: decode_into ( input, elem) ?;
616+ }
617+
618+ // Decoding succeeded, so let's get rid of `MaybeUninit`.
619+ // TODO: Use `Box::assume_init` once that's stable.
620+ let boxed_slice = Vec :: from ( boxed_slice)
621+ . into_iter ( )
622+ . map ( |elem| unsafe { MaybeUninit :: assume_init ( elem) } )
623+ . collect ( ) ;
624+
625+ input. ascend_ref ( ) ;
626+ Ok ( boxed_slice)
627+ }
628+ }
629+
630+ impl Decode for Box < str > {
631+ fn decode < I : Input > ( input : & mut I ) -> Result < Self , Error > {
632+ // Guaranteed to create a Vec with capacity == len
633+ let vec = Vec :: from ( Box :: < [ u8 ] > :: decode ( input) ?) ;
634+ // Guaranteed not to reallocate the vec, only transmute to String
635+ let str = String :: from_utf8 ( vec) . map_err ( |_| "Invalid utf8 sequence" ) ?;
636+
637+ assert_eq ! ( str . capacity( ) , str . len( ) ) ;
638+ Ok ( str. into_boxed_str ( ) )
639+ }
640+ }
641+
576642impl < T > WrapperTypeDecode for Rc < T > {
577643 type Wrapped = T ;
578644
@@ -1612,6 +1678,28 @@ mod tests {
16121678 assert_eq ! ( ( x, y) , Decode :: decode( & mut & encoded[ ..] ) . unwrap( ) ) ;
16131679 }
16141680
1681+ #[ test]
1682+ fn boxed_str_works ( ) {
1683+ let s = "Hello world" . to_owned ( ) ;
1684+ let b = s. clone ( ) . into_boxed_str ( ) ;
1685+
1686+ let encoded = b. encode ( ) ;
1687+ assert_eq ! ( s. encode( ) , encoded) ;
1688+
1689+ assert_eq ! ( * b, * Box :: <str >:: decode( & mut & encoded[ ..] ) . unwrap( ) ) ;
1690+ }
1691+
1692+ #[ test]
1693+ fn boxed_slice_works ( ) {
1694+ let v = vec ! [ 1u32 , 2 , 3 , 4 , 5 , 6 ] ;
1695+ let b = v. clone ( ) . into_boxed_slice ( ) ;
1696+
1697+ let encoded = b. encode ( ) ;
1698+ assert_eq ! ( v. encode( ) , encoded) ;
1699+
1700+ assert_eq ! ( * b, * Box :: <[ u32 ] >:: decode( & mut & b. encode( ) [ ..] ) . unwrap( ) ) ;
1701+ }
1702+
16151703 #[ test]
16161704 fn cow_works ( ) {
16171705 let x = & [ 1u32 , 2 , 3 , 4 , 5 , 6 ] [ ..] ;
0 commit comments