Skip to content

Commit

Permalink
Merge pull request #2 from antiguru/read_item_is_copy_onto
Browse files Browse the repository at this point in the history
  • Loading branch information
antiguru authored Feb 4, 2024
2 parents 0869fec + 1db8f3f commit 82341ab
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 17 deletions.
4 changes: 0 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,3 @@ default = ["serde"]
debug = 2
codegen-units = 1
lto = true

[[bench]]
name = "bench"
harness = false
2 changes: 1 addition & 1 deletion src/impls/mirror.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ impl<T> Default for MirrorRegion<T> {
}
}

impl<T: Index> Region for MirrorRegion<T> {
impl<T: Index + CopyOnto<Self>> Region for MirrorRegion<T> {
type ReadItem<'a> = T where T: 'a;
type Index = T;

Expand Down
66 changes: 58 additions & 8 deletions src/impls/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,18 @@ use crate::{CopyOnto, Region, ReserveItems};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SliceRegion<C: Region> {
// offsets: Vec<usize>,
slices: Vec<C::Index>,
inner: C,
}

impl<C: Region> Region for SliceRegion<C> {
type ReadItem<'a> = (&'a C, &'a [C::Index]) where Self: 'a;
type ReadItem<'a> = ReadSlice<'a, C> where Self: 'a;
type Index = (usize, usize);

#[inline]
fn index(&self, (start, end): Self::Index) -> Self::ReadItem<'_> {
let slice = &self.slices[start..end];
(&self.inner, slice)
ReadSlice(&self.inner, slice)
}

#[inline]
Expand All @@ -37,7 +36,6 @@ impl<C: Region> Region for SliceRegion<C> {

#[inline]
fn clear(&mut self) {
// self.offsets.clear();
self.slices.clear();
self.inner.clear();
}
Expand All @@ -52,6 +50,58 @@ impl<C: Region> Default for SliceRegion<C> {
}
}

/// A helper to read data out of a slice region.
#[derive(Debug)]
pub struct ReadSlice<'a, C: Region>(pub &'a C, pub &'a [C::Index]);

impl<'a, C: Region> ReadSlice<'a, C> {
/// Read the n-th item from the underlying region.
#[inline]
pub fn get(&self, index: usize) -> C::ReadItem<'_> {
self.0.index(self.1[index])
}

/// The number in this slice.
pub fn len(&self) -> usize {
self.1.len()
}

/// Test if this slice is empty.
pub fn is_empty(&self) -> bool {
self.1.is_empty()
}
}

impl<'a, C: Region> Clone for ReadSlice<'a, C> {
#[inline]
fn clone(&self) -> Self {
Self(self.0, self.1)
}
}

impl<'a, C: Region> Copy for ReadSlice<'a, C> {}

impl<'a, C: Region> IntoIterator for ReadSlice<'a, C> {
type Item = C::ReadItem<'a>;
type IntoIter = ReadSliceIter<'a, C>;

fn into_iter(self) -> Self::IntoIter {
ReadSliceIter(self.0, self.1.iter())
}
}

#[derive(Debug, Clone)]
pub struct ReadSliceIter<'a, C: Region>(&'a C, std::slice::Iter<'a, C::Index>);

impl<'a, C: Region> Iterator for ReadSliceIter<'a, C> {
type Item = C::ReadItem<'a>;

#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.1.next().map(|idx| self.0.index(*idx))
}
}

impl<'a, C, T: 'a> CopyOnto<SliceRegion<C>> for &'a [T]
where
C: Region,
Expand Down Expand Up @@ -136,13 +186,13 @@ where
}
}

impl<'a, C: Region + 'a> CopyOnto<SliceRegion<C>> for &'a (&'a C, &'a [C::Index])
impl<'a, C: Region + 'a> CopyOnto<SliceRegion<C>> for ReadSlice<'a, C>
where
C::ReadItem<'a>: CopyOnto<C>,
{
#[inline]
fn copy_onto(self, target: &mut SliceRegion<C>) -> <SliceRegion<C> as Region>::Index {
let (container, indexes) = self;
let ReadSlice(container, indexes) = self;
let start = target.slices.len();
target.slices.extend(
indexes
Expand All @@ -158,10 +208,10 @@ where
{
target
.slices
.reserve(items.clone().map(|(_c, is)| is.len()).sum());
.reserve(items.clone().map(|ReadSlice(_c, is)| is.len()).sum());
CopyOnto::reserve_items(
&mut target.inner,
items.flat_map(|(c, is)| is.iter().map(|i| c.index(*i))),
items.flat_map(|ReadSlice(c, is)| is.iter().map(|i| c.index(*i))),
)
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/impls/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use serde::{Deserialize, Serialize};

use crate::impls::slice_copy::CopyRegion;
use crate::{Containerized, CopyOnto, Region, ReserveItems, SliceRegion};
use crate::{Containerized, CopyOnto, Region, ReserveItems};

/// A region to store strings and read `&str`.
#[derive(Default, Debug, Clone)]
Expand All @@ -13,7 +13,7 @@ pub struct StringRegion {

impl Region for StringRegion {
type ReadItem<'a> = &'a str where Self: 'a ;
type Index = <SliceRegion<CopyRegion<u8>> as Region>::Index;
type Index = <CopyRegion<u8> as Region>::Index;

#[inline]
fn index(&self, index: Self::Index) -> Self::ReadItem<'_> {
Expand Down
20 changes: 18 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl<T: Copy> Index for T {}
/// A region to store data.
pub trait Region: Default {
/// The type of the data that one gets out of the container.
type ReadItem<'a>
type ReadItem<'a>: CopyOnto<Self>
where
Self: 'a;

Expand Down Expand Up @@ -336,12 +336,15 @@ mod tests {

#[test]
fn all_types() {
fn test_copy<T, C: Region>(t: T)
fn test_copy<T, C: Region + Clone>(t: T)
where
T: CopyOnto<C>,
{
let mut c = FlatStack::default();
c.copy(t);

let mut cc = c.clone();
cc.copy(c.get(0));
}

test_copy::<_, StringRegion>(&"a".to_string());
Expand Down Expand Up @@ -413,4 +416,17 @@ mod tests {

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

#[test]
fn slice_region_read_item() {
let mut c = FlatStack::<SliceRegion<MirrorRegion<u8>>>::default();
c.copy(vec![1, 2, 3]);

let mut r = SliceRegion::<MirrorRegion<u8>>::default();
let idx = [1, 2, 3].copy_onto(&mut r);
let read_item = r.index(idx);
let _read_item2 = read_item.clone();
let _read_item3 = read_item;
assert_eq!(vec![1, 2, 3], read_item.into_iter().collect::<Vec<_>>());
}
}

0 comments on commit 82341ab

Please sign in to comment.