pub enum Stash<C, B> {
Typed(C),
Bytes(B),
Align(Arc<[u64]>),
}Expand description
A container of either typed columns, or serialized bytes that can be borrowed as the former.
When B dereferences to a byte slice, the container can be borrowed as if the container type C.
This container inherents the readable properties of C through borrowing, but does not implement
the traits itself.
The container can be cleared and pushed into. When cleared it reverts to a typed variant, and when pushed into if the typed variant it will accept the item, and if not it will panic.
The best ways to construct a Stash is with either the Default implementation to get an empty
writeable version, or with the try_from_bytes method that attempts to install a type that dereferences
to a byte slice in the Bytes variant, after validating some structural properties.
One can form a Stash directly by loading the variants, which are public. Do so with care,
as loading mis-aligned B into the Bytes variant can result in a run-time panic, and
loading structurally invalid data into either the Bytes or Align variant can produce
incorrect results at runtime (clamped index accesses, for example). The validation does not
confirm that the internal structure of types are valid, for example that all vector bounds
are in-bounds for their values, and these may result in panics at runtime for invalid data.
Variants§
Typed(C)
The typed variant of the container.
Bytes(B)
The bytes variant of the container.
Align(Arc<[u64]>)
Relocated, aligned binary data, if Bytes doesn’t work for some reason.
Most commonly this works around misaligned binary data, but it can also be useful if the B
type is a scarce resource that should be released.
Implementations§
Source§impl<C: ContainerBytes, B: Deref<Target = [u8]>> Stash<C, B>
impl<C: ContainerBytes, B: Deref<Target = [u8]>> Stash<C, B>
Sourcepub fn try_from_bytes(bytes: B) -> Result<Self, String>
pub fn try_from_bytes(bytes: B) -> Result<Self, String>
An analogue of TryFrom for any B: Deref<Target=[u8]>, avoiding coherence issues.
This is the recommended way to form a Stash, as it performs certain structural validation
steps that the stash will then skip in future borrowing and indexing operations. If the data
are structurally invalid, e.g. the wrong framing header, the wrong number of slices for C,
this will return an error. If this returns a Stash then all accesses that do not panic should
be correct. The resulting Stash may still panic if the internal structure of the data
are inconsistent, for example if any vector bounds are out-of-bounds for their values slice.
There is no unsafe that is called through this type, and invalid data can result in panics
or incorrect results, but not undefined behavior.
§Example
use columnar::{Columnar, Borrow, ContainerOf};
use columnar::common::{Push, Index};
use columnar::bytes::stash::Stash;
// Build a typed container and populate it.
let mut stash: Stash<ContainerOf<(u64, String)>, Vec<u8>> = Default::default();
stash.push(&(0u64, format!("hello")));
stash.push(&(1u64, format!("world")));
// Serialize to bytes.
let mut bytes: Vec<u8> = Vec::new();
stash.write_bytes(&mut bytes);
// Reconstruct from bytes, with validation.
let stash: Stash<ContainerOf<(u64, String)>, Vec<u8>> =
Stash::try_from_bytes(bytes).expect("valid data");
// Borrow and index into individual columns.
let borrowed = stash.borrow();
assert_eq!(*Index::get(&borrowed.0, 0), 0u64);
assert_eq!(borrowed.1.get(1), b"world");Source§impl<C: Container + ContainerBytes, B: Deref<Target = [u8]>> Stash<C, B>
impl<C: Container + ContainerBytes, B: Deref<Target = [u8]>> Stash<C, B>
Sourcepub fn to_typed(&self) -> Self
pub fn to_typed(&self) -> Self
Converts the stash to the Typed variant, by copying the borrowed data into a new container.
Sourcepub fn to_aligned(&self) -> Self
pub fn to_aligned(&self) -> Self
Converts the stash to the Align variant, by serializing the borrowed data into aligned words.
Sourcepub fn make_typed(&mut self) -> &mut C
pub fn make_typed(&mut self) -> &mut C
Ensures the stash is in the Typed variant, converting in place if needed, and returns a mutable reference.
Sourcepub fn make_aligned(&mut self) -> &Arc<[u64]>
pub fn make_aligned(&mut self) -> &Arc<[u64]>
Ensures the stash is in the Align variant, converting in place if needed, and returns a reference.
Source§impl<C: ContainerBytes, B: Deref<Target = [u8]>> Stash<C, B>
impl<C: ContainerBytes, B: Deref<Target = [u8]>> Stash<C, B>
Sourcepub fn borrow<'a>(&'a self) -> <C as Borrow>::Borrowed<'a>
pub fn borrow<'a>(&'a self) -> <C as Borrow>::Borrowed<'a>
Borrows the contents, either from a typed container or by decoding serialized bytes.
This method is relatively cheap but is not free.
Sourcepub fn length_in_bytes(&self) -> usize
pub fn length_in_bytes(&self) -> usize
The number of bytes needed to write the contents using the [indexed] encoder.
Sourcepub fn write_bytes<W: WriteBytes>(&self, writer: &mut W) -> Result<(), W::Error>
pub fn write_bytes<W: WriteBytes>(&self, writer: &mut W) -> Result<(), W::Error>
Write the contents into a WriteBytes destination.
Trait Implementations§
Source§impl<C: ContainerBytes, B: Deref<Target = [u8]> + Clone + 'static> Borrow for Stash<C, B>
impl<C: ContainerBytes, B: Deref<Target = [u8]> + Clone + 'static> Borrow for Stash<C, B>
Source§type Ref<'a> = <C as Borrow>::Ref<'a>
type Ref<'a> = <C as Borrow>::Ref<'a>
Source§fn borrow<'a>(&'a self) -> Self::Borrowed<'a>
fn borrow<'a>(&'a self) -> Self::Borrowed<'a>
Source§fn reborrow<'b, 'a: 'b>(item: Self::Borrowed<'a>) -> Self::Borrowed<'b>where
Self: 'a,
fn reborrow<'b, 'a: 'b>(item: Self::Borrowed<'a>) -> Self::Borrowed<'b>where
Self: 'a,
Columnar::reborrow for details.Source§fn reborrow_ref<'b, 'a: 'b>(item: Self::Ref<'a>) -> Self::Ref<'b>where
Self: 'a,
fn reborrow_ref<'b, 'a: 'b>(item: Self::Ref<'a>) -> Self::Ref<'b>where
Self: 'a,
Columnar::reborrow for details.