Skip to content

Commit 563663e

Browse files
Update Bytes internals/methods (#97)
1 parent f633d2a commit 563663e

File tree

1 file changed

+46
-6
lines changed

1 file changed

+46
-6
lines changed

src/bytes.rs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ pub mod indexed {
349349
/// A container of either typed columns, or serialized bytes that can be borrowed as the former.
350350
pub 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

Comments
 (0)