Skip to content

Commit

Permalink
Rename Containerized to RegionPreference and add owned type (#47)
Browse files Browse the repository at this point in the history
Signed-off-by: Moritz Hoffmann <[email protected]>
  • Loading branch information
antiguru authored Jun 26, 2024
1 parent 84f6123 commit 66ed92c
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 69 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ writing down all values.

All region implementations should be considered examples on how to implement specific
regions that are tailored to the needs of the type, and characteristics of the data
encountered in practice. This crate provides a [`Containerized`] trait to let types
encountered in practice. This crate provides a [`RegionPreference`] trait to let types
express their suggested region, but users can select a different region, as long as
it is compatible with the types to be stored. For example, a vector suggests to use
a slice-based region, but a client might know that the inner type is copy, and hence
Expand Down
46 changes: 23 additions & 23 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use flatcontainer::impls::deduplicate::{CollapseSequence, ConsecutiveOffsetPairs
use flatcontainer::impls::offsets::OffsetOptimized;
use flatcontainer::impls::tuple::{TupleABCRegion, TupleABRegion};
use flatcontainer::{
ColumnsRegion, Containerized, FlatStack, MirrorRegion, OwnedRegion, Push, Region, ReserveItems,
SliceRegion, StringRegion,
ColumnsRegion, FlatStack, MirrorRegion, OwnedRegion, Push, Region, RegionPreference,
ReserveItems, SliceRegion, StringRegion,
};
use test::Bencher;

Expand Down Expand Up @@ -265,46 +265,46 @@ fn vec_u_vn_s_prealloc(bencher: &mut Bencher) {

#[bench]
fn empty_copy_flat(bencher: &mut Bencher) {
_bench_copy_flat_containerized(bencher, vec![(); 1024]);
_bench_copy_flat_preference(bencher, vec![(); 1024]);
}
#[bench]
fn u64_copy_flat(bencher: &mut Bencher) {
_bench_copy_flat_containerized(bencher, vec![0u64; 1024]);
_bench_copy_flat_preference(bencher, vec![0u64; 1024]);
}
#[bench]
fn u32x2_copy_flat(bencher: &mut Bencher) {
_bench_copy_flat_containerized(bencher, vec![(0u32, 0u32); 1024]);
_bench_copy_flat_preference(bencher, vec![(0u32, 0u32); 1024]);
}
#[bench]
fn u8_u64_copy_flat(bencher: &mut Bencher) {
_bench_copy_flat_containerized(bencher, vec![(0u8, 0u64); 512]);
_bench_copy_flat_preference(bencher, vec![(0u8, 0u64); 512]);
}
#[bench]
fn str10_copy_flat(bencher: &mut Bencher) {
_bench_copy_flat_containerized(bencher, vec!["grawwwwrr!"; 1024]);
_bench_copy_flat_preference(bencher, vec!["grawwwwrr!"; 1024]);
}
#[bench]
fn str100_copy_flat(bencher: &mut Bencher) {
_bench_copy_flat_containerized(bencher, vec!["grawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrr!!!!!!!!!grawwwwrr!"; 1024]);
_bench_copy_flat_preference(bencher, vec!["grawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrr!!!!!!!!!grawwwwrr!"; 1024]);
}
#[bench]
fn string10_copy_flat(bencher: &mut Bencher) {
_bench_copy_flat_containerized(bencher, vec![format!("grawwwwrr!"); 1024]);
_bench_copy_flat_preference(bencher, vec![format!("grawwwwrr!"); 1024]);
}
#[bench]
fn string20_copy_flat(bencher: &mut Bencher) {
_bench_copy_flat_containerized(bencher, vec![format!("grawwwwrr!!!!!!!!!!!"); 512]);
_bench_copy_flat_preference(bencher, vec![format!("grawwwwrr!!!!!!!!!!!"); 512]);
}
#[bench]
fn vec_u_s_copy_flat(bencher: &mut Bencher) {
_bench_copy_flat_containerized(
_bench_copy_flat_preference(
bencher,
vec![vec![(0u64, "grawwwwrr!".to_string()); 32]; 32],
);
}
#[bench]
fn vec_u_vn_s_copy_flat(bencher: &mut Bencher) {
_bench_copy_flat_containerized(
_bench_copy_flat_preference(
bencher,
vec![vec![(0u64, vec![(); 1 << 40], "grawwwwrr!".to_string()); 32]; 32],
);
Expand Down Expand Up @@ -381,9 +381,9 @@ fn vec_u_vn_s_copy_flat_region_column(bencher: &mut Bencher) {
);
}

fn _bench_copy<T: Containerized + Eq>(bencher: &mut Bencher, record: T)
fn _bench_copy<T: RegionPreference + Eq>(bencher: &mut Bencher, record: T)
where
for<'a> <T as Containerized>::Region: Push<&'a T>,
for<'a> <T as RegionPreference>::Region: Push<&'a T>,
{
// prepare encoded data for bencher.bytes
let mut arena = FlatStack::default_impl::<T>();
Expand Down Expand Up @@ -425,7 +425,7 @@ where
println!("{siz} {cap}");
}

fn _bench_clone<T: Containerized + Eq + Clone>(bencher: &mut Bencher, record: T) {
fn _bench_clone<T: RegionPreference + Eq + Clone>(bencher: &mut Bencher, record: T) {
// prepare encoded data for bencher.bytes
let mut arena = Vec::new();

Expand All @@ -437,9 +437,9 @@ fn _bench_clone<T: Containerized + Eq + Clone>(bencher: &mut Bencher, record: T)
});
}

fn _bench_realloc<T: Containerized + Eq>(bencher: &mut Bencher, record: T)
fn _bench_realloc<T: RegionPreference + Eq>(bencher: &mut Bencher, record: T)
where
for<'a> <T as Containerized>::Region: Push<&'a T>,
for<'a> <T as RegionPreference>::Region: Push<&'a T>,
{
let mut arena = FlatStack::default_impl::<T>();
bencher.iter(|| {
Expand All @@ -457,9 +457,9 @@ where
bencher.bytes = siz as u64;
}

fn _bench_prealloc<T: Containerized + Eq>(bencher: &mut Bencher, record: T)
fn _bench_prealloc<T: RegionPreference + Eq>(bencher: &mut Bencher, record: T)
where
for<'a> <T as Containerized>::Region: ReserveItems<&'a T> + Push<&'a T>,
for<'a> <T as RegionPreference>::Region: ReserveItems<&'a T> + Push<&'a T>,
{
let mut arena = FlatStack::default_impl::<T>();
bencher.iter(|| {
Expand All @@ -478,11 +478,11 @@ where
bencher.bytes = siz as u64;
}

fn _bench_copy_flat_containerized<T>(bencher: &mut Bencher, record: T)
fn _bench_copy_flat_preference<T>(bencher: &mut Bencher, record: T)
where
T: Containerized,
for<'a> <T as Containerized>::Region:
Push<&'a T> + Push<<<T as Containerized>::Region as Region>::ReadItem<'a>> + Clone,
T: RegionPreference,
for<'a> <T as RegionPreference>::Region:
Push<&'a T> + Push<<<T as RegionPreference>::Region as Region>::ReadItem<'a>> + Clone,
{
_bench_copy_flat::<T::Region, T>(bencher, record)
}
Expand Down
5 changes: 3 additions & 2 deletions src/impls/mirror.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::marker::PhantomData;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{Containerized, Index, IntoOwned, Push, Region, ReserveItems};
use crate::{Index, IntoOwned, Push, Region, RegionPreference, ReserveItems};

/// A region for types where the read item type is equal to the index type.
///
Expand Down Expand Up @@ -147,7 +147,8 @@ where

macro_rules! implement_for {
($index_type:ty) => {
impl Containerized for $index_type {
impl RegionPreference for $index_type {
type Owned = Self;
type Region = MirrorRegion<Self>;
}

Expand Down
9 changes: 5 additions & 4 deletions src/impls/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{Containerized, IntoOwned, Push, Region, ReserveItems};
use crate::{IntoOwned, Push, Region, RegionPreference, ReserveItems};

impl<T: Containerized> Containerized for Option<T> {
impl<T: RegionPreference> RegionPreference for Option<T> {
type Owned = Option<T::Owned>;
type Region = OptionRegion<T::Region>;
}

Expand All @@ -15,8 +16,8 @@ impl<T: Containerized> Containerized for Option<T> {
///
/// The region can hold options:
/// ```
/// # use flatcontainer::{Containerized, Push, OptionRegion, Region};
/// let mut r = <OptionRegion<<u8 as Containerized>::Region>>::default();
/// # use flatcontainer::{RegionPreference, Push, OptionRegion, Region};
/// let mut r = <OptionRegion<<u8 as RegionPreference>::Region>>::default();
///
/// let some_index = r.push(Some(123));
/// // Type annotations required for `None`:
Expand Down
9 changes: 5 additions & 4 deletions src/impls/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{Containerized, IntoOwned, Push, Region, ReserveItems};
use crate::{IntoOwned, Push, Region, RegionPreference, ReserveItems};

impl<T: Containerized, E: Containerized> Containerized for Result<T, E> {
impl<T: RegionPreference, E: RegionPreference> RegionPreference for Result<T, E> {
type Owned = Result<T::Owned, E::Owned>;
type Region = ResultRegion<T::Region, E::Region>;
}

Expand All @@ -15,9 +16,9 @@ impl<T: Containerized, E: Containerized> Containerized for Result<T, E> {
///
/// Add results to a result region:
/// ```
/// use flatcontainer::{Containerized, Push, Region, ResultRegion};
/// use flatcontainer::{RegionPreference, Push, Region, ResultRegion};
/// let mut r =
/// <ResultRegion<<() as Containerized>::Region, <String as Containerized>::Region>>::default();
/// <ResultRegion<<() as RegionPreference>::Region, <String as RegionPreference>::Region>>::default();
///
/// let ok_index = r.push(Result::<(), String>::Ok(()));
/// let err_index = r.push(Result::<(), String>::Err("Error".to_string()));
Expand Down
15 changes: 9 additions & 6 deletions src/impls/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@ use std::ops::{Deref, Range};
use serde::{Deserialize, Serialize};

use crate::impls::offsets::OffsetContainer;
use crate::{Containerized, IntoOwned, Push, Region, ReserveItems};
use crate::{IntoOwned, Push, Region, RegionPreference, ReserveItems};

impl<T: Containerized> Containerized for Vec<T> {
impl<T: RegionPreference> RegionPreference for Vec<T> {
type Owned = Vec<T::Owned>;
type Region = SliceRegion<T::Region>;
}

impl<T: Containerized> Containerized for [T] {
impl<T: RegionPreference> RegionPreference for [T] {
type Owned = Vec<T::Owned>;
type Region = SliceRegion<T::Region>;
}

impl<T: Containerized, const N: usize> Containerized for [T; N] {
impl<T: RegionPreference, const N: usize> RegionPreference for [T; N] {
type Owned = Vec<T::Owned>;
type Region = SliceRegion<T::Region>;
}

Expand All @@ -33,8 +36,8 @@ impl<T: Containerized, const N: usize> Containerized for [T; N] {
///
/// We fill some data into a slice region and use the [`ReadSlice`] to extract it later.
/// ```
/// use flatcontainer::{Containerized, Push, Region, SliceRegion};
/// let mut r = <SliceRegion<<String as Containerized>::Region>>::default();
/// use flatcontainer::{RegionPreference, Push, Region, SliceRegion};
/// let mut r = <SliceRegion<<String as RegionPreference>::Region>>::default();
///
/// let panagram_en = "The quick fox jumps over the lazy dog"
/// .split(" ")
Expand Down
10 changes: 6 additions & 4 deletions src/impls/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use serde::{Deserialize, Serialize};

use crate::impls::slice_copy::OwnedRegion;
use crate::{Containerized, Push, Region, ReserveItems};
use crate::{Push, Region, RegionPreference, ReserveItems};

/// A region to store strings and read `&str`.
///
Expand All @@ -18,7 +18,7 @@ use crate::{Containerized, Push, Region, ReserveItems};
///
/// We fill some data into a string region and use extract it later.
/// ```
/// use flatcontainer::{Containerized, Push, OwnedRegion, Region, StringRegion};
/// use flatcontainer::{RegionPreference, Push, OwnedRegion, Region, StringRegion};
/// let mut r = <StringRegion>::default();
///
/// let panagram_en = "The quick fox jumps over the lazy dog";
Expand Down Expand Up @@ -100,11 +100,13 @@ where
}
}

impl Containerized for String {
impl RegionPreference for String {
type Owned = Self;
type Region = StringRegion;
}

impl Containerized for &str {
impl RegionPreference for &str {
type Owned = String;
type Region = StringRegion;
}

Expand Down
5 changes: 3 additions & 2 deletions src/impls/tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ use paste::paste;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{Containerized, IntoOwned, Push, Region, ReserveItems};
use crate::{IntoOwned, Push, Region, RegionPreference, ReserveItems};

/// The macro creates the region implementation for tuples
macro_rules! tuple_flatcontainer {
($($name:ident)+) => (
paste! {
impl<$($name: Containerized),*> Containerized for ($($name,)*) {
impl<$($name: RegionPreference),*> RegionPreference for ($($name,)*) {
type Owned = ($($name::Owned,)*);
type Region = [<Tuple $($name)* Region >]<$($name::Region,)*>;
}

Expand Down
27 changes: 21 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,25 @@ pub trait Region: Default {
Self: 'a;
}

/// A trait to let types express a default container type.
pub trait Containerized {
/// A trait to let types express a default container type and an owned type, which can
/// be used to define regions in simpler terms.
///
/// # Example
///
/// ```
/// # use flatcontainer::{FlatStack, RegionPreference};
/// let _ = FlatStack::<<((Vec<String>, &[usize]), Option<String>, Result<u8, u16>) as RegionPreference>::Region>::default();
/// ```
pub trait RegionPreference {
/// The owned type of the region.
type Owned;
/// The recommended container type.
type Region: Region;
type Region: Region<Owned = Self::Owned>;
}

impl<T: RegionPreference + ?Sized> RegionPreference for &T {
type Owned = T::Owned;
type Region = T::Region;
}

/// Push an item `T` into a region.
Expand Down Expand Up @@ -179,7 +194,7 @@ impl<R: Region> FlatStack<R> {
/// Default implementation based on the preference of type `T`.
#[inline]
#[must_use]
pub fn default_impl<T: Containerized<Region = R>>() -> Self {
pub fn default_impl<T: RegionPreference<Region = R>>() -> Self {
Self::default()
}

Expand Down Expand Up @@ -531,8 +546,8 @@ mod tests {
test_copy::<_, OwnedRegion<_>>([0u8].as_slice());
test_copy::<_, OwnedRegion<_>>(&[0u8].as_slice());

test_copy::<_, <(u8, u8) as Containerized>::Region>((1, 2));
test_copy::<_, <(u8, u8) as Containerized>::Region>(&(1, 2));
test_copy::<_, <(u8, u8) as RegionPreference>::Region>((1, 2));
test_copy::<_, <(u8, u8) as RegionPreference>::Region>(&(1, 2));

test_copy::<_, ConsecutiveOffsetPairs<OwnedRegion<_>>>([1, 2, 3].as_slice());

Expand Down
Loading

0 comments on commit 66ed92c

Please sign in to comment.