Skip to content

Commit

Permalink
Result works
Browse files Browse the repository at this point in the history
Signed-off-by: Moritz Hoffmann <[email protected]>
  • Loading branch information
antiguru committed Nov 8, 2024
1 parent f6a3dc0 commit 429e4db
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 77 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ flatcontainer = "0.6"
## Example

```rust
use flatcontainer::{Index, RegionPreference};
use flatcontainer::{Index, Push, RegionPreference};

let r: Result<_, u16> = Ok("abc");
let mut c = <<Result<&str, u16> as RegionPreference>::Region>::default();
c.push(&r);
assert_eq!(r, c.index(0));
assert_eq!(Ok("abc"), c.index(0));
```

## Details
Expand Down
2 changes: 1 addition & 1 deletion src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// pub mod index;
// pub mod mirror;
pub mod option;
// pub mod result;
pub mod result;
pub mod slice;
pub mod slice_owned;
pub mod string;
Expand Down
145 changes: 101 additions & 44 deletions src/impls/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{IntoOwned, Push, Region, RegionPreference, ReserveItems};
use crate::rank_select::RankSelect;
use crate::{
Clear, HeapSize, Index, IndexAs, IntoOwned, Len, Push, Region, RegionPreference, ReserveItems,
};

impl<T: RegionPreference, E: RegionPreference> RegionPreference for Result<T, E> {
type Owned = Result<T::Owned, E::Owned>;
Expand All @@ -16,93 +19,130 @@ impl<T: RegionPreference, E: RegionPreference> RegionPreference for Result<T, E>
///
/// Add results to a result region:
/// ```
/// use flatcontainer::{RegionPreference, Push, Region, ResultRegion};
/// let mut r =
/// <ResultRegion<<() as RegionPreference>::Region, <String as RegionPreference>::Region>>::default();
/// use flatcontainer::{RegionPreference, Push, Region, ResultRegion, Index};
/// let mut r = <Result<(), String> as RegionPreference>::Region::default();
///
/// let ok_index = r.push(Result::<(), String>::Ok(()));
/// let err_index = r.push(Result::<(), String>::Err("Error".to_string()));
/// r.push(Result::<(), String>::Ok(()));
/// r.push(Result::<(), String>::Err("Error".to_string()));
///
/// assert_eq!(Ok(()), r.index(ok_index));
/// assert_eq!(Err("Error"), r.index(err_index));
/// assert_eq!(Ok(&()), r.index(0));
/// assert_eq!(Err("Error"), r.index(1));
/// ```
#[derive(Default, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ResultRegion<T, E> {
pub struct ResultRegion<T, E, RC = Vec<u64>, RV = Vec<u64>> {
ranks: RankSelect<RC, RV>,
oks: T,
errs: E,
}

impl<T: Clone, E: Clone> Clone for ResultRegion<T, E> {
impl<T: Clone, E: Clone, RC: Clone, RV: Clone> Clone for ResultRegion<T, E, RC, RV> {
fn clone(&self) -> Self {
Self {
ranks: self.ranks.clone(),
oks: self.oks.clone(),
errs: self.errs.clone(),
}
}

fn clone_from(&mut self, source: &Self) {
self.ranks.clone_from(&source.ranks);
self.oks.clone_from(&source.oks);
self.errs.clone_from(&source.errs);
}
}

impl<T, E> Region for ResultRegion<T, E>
impl<T, E, RC, RV> Region for ResultRegion<T, E, RC, RV>
where
T: Region,
E: Region,
RC: Region,
RV: Region,
{
type Owned = Result<T::Owned, E::Owned>;
type ReadItem<'a> = Result<T::ReadItem<'a>, E::ReadItem<'a>> where Self: 'a;
type Index = Result<T::Index, E::Index>;

#[inline]
fn merge_regions<'a>(regions: impl Iterator<Item = &'a Self> + Clone) -> Self
where
Self: 'a,
{
Self {
ranks: RankSelect::merge_regions(regions.clone().map(|r| &r.ranks)),
oks: T::merge_regions(regions.clone().map(|r| &r.oks)),
errs: E::merge_regions(regions.map(|r| &r.errs)),
}
}

#[inline]
fn index(&self, index: Self::Index) -> Self::ReadItem<'_> {
match index {
Ok(index) => Ok(self.oks.index(index)),
Err(index) => Err(self.errs.index(index)),
}
}

#[inline]
fn reserve_regions<'a, I>(&mut self, regions: I)
where
Self: 'a,
I: Iterator<Item = &'a Self> + Clone,
{
self.ranks
.reserve_regions(regions.clone().map(|r| &r.ranks));
self.oks.reserve_regions(regions.clone().map(|r| &r.oks));
self.errs.reserve_regions(regions.map(|r| &r.errs));
}
}

impl<T, E, RC, RV> Index for ResultRegion<T, E, RC, RV>
where
T: Index,
E: Index,
RC: IndexAs<u64> + Len,
RV: IndexAs<u64> + Len,
{
type Owned = Result<T::Owned, E::Owned>;
type ReadItem<'a> = Result<T::ReadItem<'a>, E::ReadItem<'a>> where Self: 'a;

#[inline]
fn index(&self, index: usize) -> Self::ReadItem<'_> {
if self.ranks.index_as(index) {
Ok(self.oks.index(self.ranks.rank(index)))
} else {
Err(self.errs.index(index - self.ranks.rank(index)))
}
}

#[inline]
fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b>
where
Self: 'a,
{
item.map(T::reborrow).map_err(E::reborrow)
}
}

impl<T, E, RC, RV> Clear for ResultRegion<T, E, RC, RV>
where
T: Clear,
E: Clear,
{
#[inline]
fn clear(&mut self) {
self.oks.clear();
self.errs.clear();
}
}

impl<T, E, RC, RV> HeapSize for ResultRegion<T, E, RC, RV>
where
T: HeapSize,
E: HeapSize,
{
#[inline]
fn heap_size<F: FnMut(usize, usize)>(&self, mut callback: F) {
self.oks.heap_size(&mut callback);
self.errs.heap_size(callback);
}
}

impl<T, E, RC, RV> Len for ResultRegion<T, E, RC, RV>
where
RV: Len,
{
#[inline]
fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b>
where
Self: 'a,
{
item.map(T::reborrow).map_err(E::reborrow)
fn len(&self) -> usize {
self.ranks.len()
}
}

Expand Down Expand Up @@ -134,35 +174,51 @@ where
}
}

impl<T, TC, E, EC> Push<Result<T, E>> for ResultRegion<TC, EC>
impl<T, TC, E, EC, RC, RV> Push<Result<T, E>> for ResultRegion<TC, EC, RC, RV>
where
TC: Region + Push<T>,
EC: Region + Push<E>,
TC: Push<T>,
EC: Push<E>,
RC: IndexAs<u64> + Len + Push<u64>,
RV: IndexAs<u64> + Len + Push<u64>,
{
#[inline]
fn push(&mut self, item: Result<T, E>) -> <ResultRegion<TC, EC> as Region>::Index {
fn push(&mut self, item: Result<T, E>) {
match item {
Ok(t) => Ok(self.oks.push(t)),
Err(e) => Err(self.errs.push(e)),
Ok(t) => {
self.ranks.push(true);
self.oks.push(t);
}
Err(r) => {
self.ranks.push(false);
self.errs.push(r);
}
}
}
}

impl<'a, T: 'a, TC, E: 'a, EC> Push<&'a Result<T, E>> for ResultRegion<TC, EC>
impl<'a, T: 'a, TC, E: 'a, EC, RC, RV> Push<&'a Result<T, E>> for ResultRegion<TC, EC, RC, RV>
where
TC: Region + Push<&'a T>,
EC: Region + Push<&'a E>,
TC: Push<&'a T>,
EC: Push<&'a E>,
RC: IndexAs<u64> + Len + Push<u64>,
RV: IndexAs<u64> + Len + Push<u64>,
{
#[inline]
fn push(&mut self, item: &'a Result<T, E>) -> <ResultRegion<TC, EC> as Region>::Index {
fn push(&mut self, item: &'a Result<T, E>) {
match item {
Ok(t) => Ok(self.oks.push(t)),
Err(e) => Err(self.errs.push(e)),
Ok(t) => {
self.ranks.push(true);
self.oks.push(t);
}
Err(r) => {
self.ranks.push(false);
self.errs.push(r);
}
}
}
}

impl<T, TC, E, EC> ReserveItems<Result<T, E>> for ResultRegion<TC, EC>
impl<T, TC, E, EC, RC, RV> ReserveItems<Result<T, E>> for ResultRegion<TC, EC, RC, RV>
where
TC: Region + ReserveItems<T>,
EC: Region + ReserveItems<E>,
Expand All @@ -177,7 +233,8 @@ where
}
}

impl<'a, T: 'a, TC, E: 'a, EC> ReserveItems<&'a Result<T, E>> for ResultRegion<TC, EC>
impl<'a, T: 'a, TC, E: 'a, EC, RC, RV> ReserveItems<&'a Result<T, E>>
for ResultRegion<TC, EC, RC, RV>
where
TC: Region + ReserveItems<&'a T>,
EC: Region + ReserveItems<&'a E>,
Expand All @@ -196,13 +253,13 @@ where

#[cfg(test)]
mod tests {
use crate::{MirrorRegion, OwnedRegion, Region, ReserveItems};
use crate::{OwnedRegion, ReserveItems};

use super::*;

#[test]
fn test_reserve() {
let mut r = <ResultRegion<MirrorRegion<u8>, MirrorRegion<u8>>>::default();
let mut r = <ResultRegion<Vec<u8>, Vec<u8>>>::default();
ReserveItems::reserve_items(&mut r, [Ok(0), Err(1)].iter());

ReserveItems::reserve_items(&mut r, [Ok(0), Err(1)].into_iter());
Expand Down
4 changes: 2 additions & 2 deletions src/impls/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ type Idx = u64;
/// .split(" ")
/// .collect::<Vec<_>>();
///
/// r.push(&panagram_en);
/// r.push(&panagram_de);
/// r.push(&panagram_en);
///
/// assert!(panagram_de.into_iter().eq(r.index(0)));
/// assert!(panagram_en.into_iter().eq(r.index(1)));
///
/// assert_eq!(r.index(1).get(2), "jagen");
/// assert_eq!(r.index(0).get(2), "jagen");
/// ```
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
Expand Down
49 changes: 21 additions & 28 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ mod rank_select;
// pub use impls::columns::ColumnsRegion;
// pub use impls::mirror::MirrorRegion;
pub use impls::option::OptionRegion;
// pub use impls::result::ResultRegion;
pub use impls::result::ResultRegion;
pub use impls::slice::SliceRegion;
pub use impls::slice_owned::OwnedRegion;
pub use impls::string::StringRegion;
Expand Down Expand Up @@ -492,13 +492,13 @@ mod tests {

use super::*;

// #[test]
// fn test_readme() {
// let r: Result<_, u16> = Ok("abc");
// let mut c = FlatStack::default_impl::<Result<&str, u16>>();
// c.copy(r);
// assert_eq!(r, c.get(0));
// }
#[test]
fn test_readme() {
let r: Result<_, u16> = Ok("abc");
let mut c = <Result<&str, u16> as RegionPreference>::Region::default();
c.push(r);
assert_eq!(Ok("abc"), c.index(0));
}

#[test]
fn test_slice_string_onto() {
Expand Down Expand Up @@ -534,13 +534,13 @@ mod tests {
assert!(slice.iter().eq(c.index(0)));
}

// #[test]
// fn test_result() {
// let r: Result<_, u16> = Ok("abc");
// let mut c = <ResultRegion<StringRegion, MirrorRegion<_>>>::default();
// let idx = copy(&mut c, r);
// assert_eq!(r, c.index(idx));
// }
#[test]
fn test_result() {
let r: Result<_, u16> = Ok("abc");
let mut c = <ResultRegion<StringRegion, Vec<_>>>::default();
c.push(r);
assert_eq!(Ok("abc"), c.index(0));
}

#[test]
fn all_types() {
Expand All @@ -553,7 +553,8 @@ mod tests {
+ Index
+ Clone
+ Clear
+ HeapSize + Len,
+ HeapSize
+ Len,
// Make sure that types are debug, even if we don't use this in the test.
for<'a> R::ReadItem<'a>: Debug,
{
Expand Down Expand Up @@ -658,18 +659,10 @@ mod tests {
test_copy::<_, OptionRegion<StringRegion>>(Option::<&'static str>::None);
test_copy::<_, OptionRegion<StringRegion>>(&Option::<&'static str>::None);

// test_copy::<_, ResultRegion<StringRegion, MirrorRegion<u8>>>(
// Result::<&'static str, u8>::Ok("abc"),
// );
// test_copy::<_, ResultRegion<StringRegion, MirrorRegion<u8>>>(
// &Result::<&'static str, u8>::Ok("abc"),
// );
// test_copy::<_, ResultRegion<StringRegion, MirrorRegion<u8>>>(
// Result::<&'static str, u8>::Err(1),
// );
// test_copy::<_, ResultRegion<StringRegion, MirrorRegion<u8>>>(
// Result::<&'static str, u8>::Err(2),
// );
test_copy::<_, ResultRegion<StringRegion, Vec<u8>>>(Result::<&'static str, u8>::Ok("abc"));
test_copy::<_, ResultRegion<StringRegion, Vec<u8>>>(&Result::<&'static str, u8>::Ok("abc"));
test_copy::<_, ResultRegion<StringRegion, Vec<u8>>>(Result::<&'static str, u8>::Err(1));
test_copy::<_, ResultRegion<StringRegion, Vec<u8>>>(Result::<&'static str, u8>::Err(2));
}

#[test]
Expand Down

0 comments on commit 429e4db

Please sign in to comment.