Skip to content

Commit

Permalink
Move complex tests to separate folder (#34)
Browse files Browse the repository at this point in the history
Signed-off-by: Moritz Hoffmann <[email protected]>
  • Loading branch information
antiguru authored May 31, 2024
1 parent 7f45ad8 commit c89c355
Show file tree
Hide file tree
Showing 4 changed files with 486 additions and 334 deletions.
334 changes: 0 additions & 334 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,190 +422,6 @@ mod tests {
assert!(slice.iter().copied().eq(c.index(idx)));
}

struct Person {
name: String,
age: u16,
hobbies: Vec<String>,
}

impl Containerized for Person {
type Region = PersonRegion;
}

#[derive(Default)]
struct PersonRegion {
name_container: <String as Containerized>::Region,
age_container: <u16 as Containerized>::Region,
hobbies: <Vec<String> as Containerized>::Region,
}

#[derive(Debug, Clone, Copy)]
struct PersonRef<'a> {
name: <<String as Containerized>::Region as Region>::ReadItem<'a>,
age: <<u16 as Containerized>::Region as Region>::ReadItem<'a>,
hobbies: <<Vec<String> as Containerized>::Region as Region>::ReadItem<'a>,
}

impl<'a> IntoOwned<'a> for PersonRef<'a> {
type Owned = Person;

fn into_owned(self) -> Self::Owned {
Person {
name: self.name.into_owned(),
age: self.age,
hobbies: self.hobbies.into_owned(),
}
}

fn clone_onto(self, other: &mut Self::Owned) {
self.name.clone_onto(&mut other.name);
other.age = self.age;
self.hobbies.clone_onto(&mut other.hobbies);
}

fn borrow_as(owned: &'a Self::Owned) -> Self {
Self {
name: IntoOwned::borrow_as(&owned.name),
age: owned.age,
hobbies: IntoOwned::borrow_as(&owned.hobbies),
}
}
}

impl Region for PersonRegion {
type Owned = Person;
type ReadItem<'a> = PersonRef<'a> where Self: 'a;
type Index = (
<<String as Containerized>::Region as Region>::Index,
<<u16 as Containerized>::Region as Region>::Index,
<<Vec<String> as Containerized>::Region as Region>::Index,
);

fn merge_regions<'a>(regions: impl Iterator<Item = &'a Self> + Clone) -> Self
where
Self: 'a,
{
Self {
name_container: <String as Containerized>::Region::merge_regions(
regions.clone().map(|r| &r.name_container),
),
age_container: <u16 as Containerized>::Region::merge_regions(
regions.clone().map(|r| &r.age_container),
),
hobbies: <Vec<String> as Containerized>::Region::merge_regions(
regions.map(|r| &r.hobbies),
),
}
}

fn index(&self, (name, age, hobbies): Self::Index) -> Self::ReadItem<'_> {
PersonRef {
name: self.name_container.index(name),
age: self.age_container.index(age),
hobbies: self.hobbies.index(hobbies),
}
}

fn reserve_regions<'a, I>(&mut self, regions: I)
where
Self: 'a,
I: Iterator<Item = &'a Self> + Clone,
{
self.name_container
.reserve_regions(regions.clone().map(|r| &r.name_container));
self.age_container
.reserve_regions(regions.clone().map(|r| &r.age_container));
self.hobbies
.reserve_regions(regions.clone().map(|r| &r.hobbies));
}

fn clear(&mut self) {
self.name_container.clear();
self.age_container.clear();
self.hobbies.clear();
}

fn heap_size<F: FnMut(usize, usize)>(&self, mut callback: F) {
self.name_container.heap_size(&mut callback);
self.age_container.heap_size(&mut callback);
self.hobbies.heap_size(callback);
}

fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b>
where
Self: 'a,
{
PersonRef {
name: <String as Containerized>::Region::reborrow(item.name),
age: <u16 as Containerized>::Region::reborrow(item.age),
hobbies: <Vec<String> as Containerized>::Region::reborrow(item.hobbies),
}
}
}

impl Push<&Person> for PersonRegion {
fn push(&mut self, item: &Person) -> <PersonRegion as Region>::Index {
let name = self.name_container.push(&item.name);
let age = self.age_container.push(item.age);
let hobbies = self.hobbies.push(&item.hobbies);
(name, age, hobbies)
}
}

impl<'a> ReserveItems<&'a Person> for PersonRegion {
fn reserve_items<I>(&mut self, items: I)
where
I: Iterator<Item = &'a Person> + Clone,
{
self.name_container
.reserve_items(items.clone().map(|i| &i.name));
self.age_container
.reserve_items(items.clone().map(|i| &i.age));
self.hobbies.reserve_items(items.map(|i| &i.hobbies));
}
}

impl Push<PersonRef<'_>> for PersonRegion {
fn push(&mut self, item: PersonRef<'_>) -> <PersonRegion as Region>::Index {
let name = self.name_container.push(item.name);
let age = self.age_container.push(item.age);
let hobbies = self.hobbies.push(item.hobbies);
(name, age, hobbies)
}
}

#[test]
fn test_person() {
let hobbies = ["Computers", "Guitar"];
let p = Person {
name: "Moritz".to_string(),
age: 123,
hobbies: hobbies.iter().map(ToString::to_string).collect(),
};

let mut c = FlatStack::default_impl::<Person>();
c.copy(&p);
let person_ref = c.get(0);
assert_eq!("Moritz", person_ref.name);
assert_eq!(123, person_ref.age);
assert_eq!(2, person_ref.hobbies.len());
for (copied_hobby, hobby) in person_ref.hobbies.iter().zip(hobbies) {
assert_eq!(copied_hobby, hobby);
}

let mut cc = FlatStack::default_impl::<Person>();

cc.copy(c.get(0));

let person_ref = cc.get(0);
assert_eq!("Moritz", person_ref.name);
assert_eq!(123, person_ref.age);
assert_eq!(2, person_ref.hobbies.len());
for (copied_hobby, hobby) in person_ref.hobbies.iter().zip(hobbies) {
assert_eq!(copied_hobby, hobby);
}
}

#[test]
fn test_result() {
let r: Result<_, u16> = Ok("abc");
Expand Down Expand Up @@ -809,154 +625,4 @@ mod tests {
// let _ = item == IntoOwned::borrow_as(owned);
let _ = R::reborrow(item) == R::reborrow(IntoOwned::borrow_as(owned));
}

mod cow {
//! What follows is an example of a Cow-like type that can be used to switch between a GAT
//! and an owned type at runtime.
use crate::{FlatStack, IntoOwned, Push, Region, StringRegion};
use std::convert::Infallible;
use std::fmt::{Debug, Formatter};

#[allow(dead_code)]
enum GatCow<'a, B, T> {
Borrowed(B),
Owned(T),
Never(&'a Infallible),
}

impl<'a, B, T> GatCow<'a, B, T>
where
B: IntoOwned<'a, Owned = T> + Copy,
{
pub fn to_mut(&mut self) -> &mut T {
match self {
Self::Borrowed(borrowed) => {
*self = Self::Owned(borrowed.into_owned());
match *self {
Self::Borrowed(..) => unreachable!(),
Self::Owned(ref mut owned) => owned,
Self::Never(_) => unreachable!(),
}
}
Self::Owned(ref mut owned) => owned,
Self::Never(_) => unreachable!(),
}
}
}

impl<'a, B, T> IntoOwned<'a> for GatCow<'a, B, T>
where
B: IntoOwned<'a, Owned = T> + Copy,
{
type Owned = T;

fn into_owned(self) -> T {
match self {
GatCow::Borrowed(b) => b.into_owned(),
GatCow::Owned(o) => o,
Self::Never(_) => unreachable!(),
}
}

fn clone_onto(self, other: &mut T) {
match self {
GatCow::Borrowed(b) => b.clone_onto(other),
GatCow::Owned(o) => *other = o,
Self::Never(_) => unreachable!(),
}
}

fn borrow_as(owned: &'a T) -> Self {
GatCow::Borrowed(IntoOwned::borrow_as(owned))
}
}

impl<B, T> Debug for GatCow<'_, B, T>
where
B: Debug,
T: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
GatCow::Borrowed(b) => b.fmt(f),
GatCow::Owned(o) => o.fmt(f),
Self::Never(_) => unreachable!(),
}
}
}

#[derive(Default, Debug, Clone)]
struct CowRegion<R>(R);

impl<R> Region for CowRegion<R>
where
R: Region,
for<'a> R::ReadItem<'a>: Copy,
{
type Owned = <R as Region>::Owned;
type ReadItem<'a> = GatCow<'a, R::ReadItem<'a>, R::Owned> where Self: 'a;
type Index = R::Index;

fn merge_regions<'a>(regions: impl Iterator<Item = &'a Self> + Clone) -> Self
where
Self: 'a,
{
Self(R::merge_regions(regions.map(|r| &r.0)))
}

fn index(&self, index: Self::Index) -> Self::ReadItem<'_> {
GatCow::Borrowed(self.0.index(index))
}

fn reserve_regions<'a, I>(&mut self, regions: I)
where
Self: 'a,
I: Iterator<Item = &'a Self> + Clone,
{
self.0.reserve_regions(regions.map(|r| &r.0))
}

fn clear(&mut self) {
self.0.clear()
}

fn heap_size<F: FnMut(usize, usize)>(&self, callback: F) {
self.0.heap_size(callback)
}

fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b>
where
Self: 'a,
{
match item {
GatCow::Borrowed(b) => GatCow::Borrowed(R::reborrow(b)),
GatCow::Owned(o) => GatCow::Owned(o),
GatCow::Never(_) => unreachable!(),
}
}
}

impl<R, D> Push<D> for CowRegion<R>
where
R: Region + Push<D>,
for<'a> R::ReadItem<'a>: Copy,
{
fn push(&mut self, item: D) -> Self::Index {
self.0.push(item)
}
}

#[test]
fn test_gat_cow() {
let mut c = <FlatStack<CowRegion<StringRegion>>>::default();
c.copy("abc");

assert_eq!("abc", c.get(0).into_owned());
let mut item = c.get(0);
item.to_mut().push_str("def");
assert_eq!("abcdef", item.into_owned());
assert_eq!("abc", c.get(0).into_owned());
}
}
}
Loading

0 comments on commit c89c355

Please sign in to comment.