@@ -349,7 +349,7 @@ pub mod indexed {
349349/// A container of either typed columns, or serialized bytes that can be borrowed as the former.
350350pub mod stash {
351351
352- use alloc:: { vec:: Vec , string:: String , boxed :: Box } ;
352+ use alloc:: { vec:: Vec , string:: String } ;
353353 use crate :: { Len , FromBytes } ;
354354 /// A container of either typed columns, or serialized bytes that can be borrowed as the former.
355355 ///
@@ -380,7 +380,7 @@ pub mod stash {
380380 ///
381381 /// Most commonly this works around misaligned binary data, but it can also be useful if the `B`
382382 /// type is a scarce resource that should be released.
383- Align ( Box < [ u64 ] > ) ,
383+ Align ( alloc :: sync :: Arc < [ u64 ] > ) ,
384384 }
385385
386386 impl < C : Default , B > Default for Stash < C , B > { fn default ( ) -> Self { Self :: Typed ( Default :: default ( ) ) } }
@@ -412,7 +412,7 @@ pub mod stash {
412412 ///
413413 /// // Serialize to bytes.
414414 /// let mut bytes: Vec<u8> = Vec::new();
415- /// stash.into_bytes (&mut bytes);
415+ /// stash.write_bytes (&mut bytes);
416416 ///
417417 /// // Reconstruct from bytes, with validation.
418418 /// let stash: Stash<ContainerOf<(u64, String)>, Vec<u8>> =
@@ -455,6 +455,44 @@ pub mod stash {
455455 #[ inline( always) ] fn len ( & self ) -> usize { self . borrow ( ) . len ( ) }
456456 }
457457
458+ impl < C : crate :: Container + crate :: ContainerBytes , B : core:: ops:: Deref < Target =[ u8 ] > > Stash < C , B > {
459+ /// Converts the stash to the `Typed` variant, by copying the borrowed data into a new container.
460+ pub fn to_typed ( & self ) -> Self {
461+ let borrowed = self . borrow ( ) ;
462+ let len = borrowed. len ( ) ;
463+ let mut container = C :: with_capacity_for ( core:: iter:: once ( borrowed) ) ;
464+ container. extend_from_self ( borrowed, 0 ..len) ;
465+ Self :: Typed ( container)
466+ }
467+ /// Converts the stash to the `Align` variant, by serializing the borrowed data into aligned words.
468+ pub fn to_aligned ( & self ) -> Self {
469+ let borrowed = self . borrow ( ) ;
470+ let mut store = Vec :: with_capacity ( crate :: bytes:: indexed:: length_in_words ( & borrowed) ) ;
471+ crate :: bytes:: indexed:: encode ( & mut store, & borrowed) ;
472+ Self :: Align ( store. into ( ) )
473+ }
474+ /// Ensures the stash is in the `Typed` variant, converting in place if needed, and returns a mutable reference.
475+ pub fn make_typed ( & mut self ) -> & mut C {
476+ if !matches ! ( self , Self :: Typed ( _) ) {
477+ * self = self . to_typed ( ) ;
478+ }
479+ match self {
480+ Stash :: Typed ( t) => t,
481+ _ => unreachable ! ( ) ,
482+ }
483+ }
484+ /// Ensures the stash is in the `Align` variant, converting in place if needed, and returns a reference.
485+ pub fn make_aligned ( & mut self ) -> & alloc:: sync:: Arc < [ u64 ] > {
486+ if !matches ! ( self , Self :: Align ( _) ) {
487+ * self = self . to_aligned ( ) ;
488+ }
489+ match self {
490+ Stash :: Align ( a) => a,
491+ _ => unreachable ! ( ) ,
492+ }
493+ }
494+ }
495+
458496 impl < C : crate :: ContainerBytes , B : core:: ops:: Deref < Target =[ u8 ] > > Stash < C , B > {
459497 /// Borrows the contents, either from a typed container or by decoding serialized bytes.
460498 ///
@@ -482,7 +520,7 @@ pub mod stash {
482520 }
483521 }
484522 /// Write the contents into a [`WriteBytes`](crate::bytes::WriteBytes) destination.
485- pub fn into_bytes < W : crate :: bytes:: WriteBytes > ( & self , writer : & mut W ) -> Result < ( ) , W :: Error > {
523+ pub fn write_bytes < W : crate :: bytes:: WriteBytes > ( & self , writer : & mut W ) -> Result < ( ) , W :: Error > {
486524 match self {
487525 Stash :: Typed ( t) => { crate :: bytes:: indexed:: write ( writer, & t. borrow ( ) ) ?; } ,
488526 Stash :: Bytes ( b) => writer. write_all ( & b[ ..] ) ?,
@@ -492,11 +530,13 @@ pub mod stash {
492530 }
493531 }
494532
495- impl < T , C : crate :: Container + crate :: Push < T > , B > crate :: Push < T > for Stash < C , B > {
533+ // This implementation converts to owned data if it is not already, which can be expensive.
534+ impl < T , C : crate :: Container + crate :: ContainerBytes + crate :: Push < T > , B : core:: ops:: Deref < Target =[ u8 ] > > crate :: Push < T > for Stash < C , B > {
496535 fn push ( & mut self , item : T ) {
536+ self . make_typed ( ) ;
497537 match self {
498538 Stash :: Typed ( t) => t. push ( item) ,
499- Stash :: Bytes ( _ ) | Stash :: Align ( _ ) => unimplemented ! ( ) ,
539+ _ => unreachable ! ( ) ,
500540 }
501541 }
502542 }
0 commit comments