diff --git a/README.md b/README.md index 0f5dda5..952aa5e 100644 --- a/README.md +++ b/README.md @@ -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 = < as RegionPreference>::Region>::default(); c.push(&r); -assert_eq!(r, c.index(0)); +assert_eq!(Ok("abc"), c.index(0)); ``` ## Details diff --git a/src/impls.rs b/src/impls.rs index 9380937..d0a2c61 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -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; diff --git a/src/impls/result.rs b/src/impls/result.rs index 99ea871..5e92f5a 100644 --- a/src/impls/result.rs +++ b/src/impls/result.rs @@ -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 RegionPreference for Result { type Owned = Result; @@ -16,93 +19,130 @@ impl RegionPreference for Result /// /// Add results to a result region: /// ``` -/// use flatcontainer::{RegionPreference, Push, Region, ResultRegion}; -/// let mut r = -/// ::Region, ::Region>>::default(); +/// use flatcontainer::{RegionPreference, Push, Region, ResultRegion, Index}; +/// let mut r = 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 { +pub struct ResultRegion, RV = Vec> { + ranks: RankSelect, oks: T, errs: E, } -impl Clone for ResultRegion { +impl Clone for ResultRegion { 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 Region for ResultRegion +impl Region for ResultRegion where T: Region, E: Region, + RC: Region, + RV: Region, { - type Owned = Result; - type ReadItem<'a> = Result, E::ReadItem<'a>> where Self: 'a; - type Index = Result; - #[inline] fn merge_regions<'a>(regions: impl Iterator + 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 + 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 Index for ResultRegion +where + T: Index, + E: Index, + RC: IndexAs + Len, + RV: IndexAs + Len, +{ + type Owned = Result; + type ReadItem<'a> = Result, 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 Clear for ResultRegion +where + T: Clear, + E: Clear, +{ #[inline] fn clear(&mut self) { self.oks.clear(); self.errs.clear(); } +} +impl HeapSize for ResultRegion +where + T: HeapSize, + E: HeapSize, +{ #[inline] fn heap_size(&self, mut callback: F) { self.oks.heap_size(&mut callback); self.errs.heap_size(callback); } +} +impl Len for ResultRegion +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() } } @@ -134,35 +174,51 @@ where } } -impl Push> for ResultRegion +impl Push> for ResultRegion where - TC: Region + Push, - EC: Region + Push, + TC: Push, + EC: Push, + RC: IndexAs + Len + Push, + RV: IndexAs + Len + Push, { #[inline] - fn push(&mut self, item: Result) -> as Region>::Index { + fn push(&mut self, item: Result) { 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> for ResultRegion +impl<'a, T: 'a, TC, E: 'a, EC, RC, RV> Push<&'a Result> for ResultRegion where - TC: Region + Push<&'a T>, - EC: Region + Push<&'a E>, + TC: Push<&'a T>, + EC: Push<&'a E>, + RC: IndexAs + Len + Push, + RV: IndexAs + Len + Push, { #[inline] - fn push(&mut self, item: &'a Result) -> as Region>::Index { + fn push(&mut self, item: &'a Result) { 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 ReserveItems> for ResultRegion +impl ReserveItems> for ResultRegion where TC: Region + ReserveItems, EC: Region + ReserveItems, @@ -177,7 +233,8 @@ where } } -impl<'a, T: 'a, TC, E: 'a, EC> ReserveItems<&'a Result> for ResultRegion +impl<'a, T: 'a, TC, E: 'a, EC, RC, RV> ReserveItems<&'a Result> + for ResultRegion where TC: Region + ReserveItems<&'a T>, EC: Region + ReserveItems<&'a E>, @@ -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 = , MirrorRegion>>::default(); + let mut r = , Vec>>::default(); ReserveItems::reserve_items(&mut r, [Ok(0), Err(1)].iter()); ReserveItems::reserve_items(&mut r, [Ok(0), Err(1)].into_iter()); diff --git a/src/impls/slice.rs b/src/impls/slice.rs index 4780cb1..1cb49f1 100644 --- a/src/impls/slice.rs +++ b/src/impls/slice.rs @@ -50,13 +50,13 @@ type Idx = u64; /// .split(" ") /// .collect::>(); /// -/// 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))] diff --git a/src/lib.rs b/src/lib.rs index 2c7c738..008b721 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; @@ -492,13 +492,13 @@ mod tests { use super::*; - // #[test] - // fn test_readme() { - // let r: Result<_, u16> = Ok("abc"); - // let mut c = FlatStack::default_impl::>(); - // c.copy(r); - // assert_eq!(r, c.get(0)); - // } + #[test] + fn test_readme() { + let r: Result<_, u16> = Ok("abc"); + let mut c = as RegionPreference>::Region::default(); + c.push(r); + assert_eq!(Ok("abc"), c.index(0)); + } #[test] fn test_slice_string_onto() { @@ -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 = >>::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 = >>::default(); + c.push(r); + assert_eq!(Ok("abc"), c.index(0)); + } #[test] fn all_types() { @@ -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, { @@ -658,18 +659,10 @@ mod tests { test_copy::<_, OptionRegion>(Option::<&'static str>::None); test_copy::<_, OptionRegion>(&Option::<&'static str>::None); - // test_copy::<_, ResultRegion>>( - // Result::<&'static str, u8>::Ok("abc"), - // ); - // test_copy::<_, ResultRegion>>( - // &Result::<&'static str, u8>::Ok("abc"), - // ); - // test_copy::<_, ResultRegion>>( - // Result::<&'static str, u8>::Err(1), - // ); - // test_copy::<_, ResultRegion>>( - // Result::<&'static str, u8>::Err(2), - // ); + test_copy::<_, ResultRegion>>(Result::<&'static str, u8>::Ok("abc")); + test_copy::<_, ResultRegion>>(&Result::<&'static str, u8>::Ok("abc")); + test_copy::<_, ResultRegion>>(Result::<&'static str, u8>::Err(1)); + test_copy::<_, ResultRegion>>(Result::<&'static str, u8>::Err(2)); } #[test]