Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ReadItem: CopyOnto<Self> #2

Merged
merged 1 commit into from
Feb 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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<_>>());
}
}
Loading