diff --git a/src/impls/columns.rs b/src/impls/columns.rs index 36b09a2..2b17013 100644 --- a/src/impls/columns.rs +++ b/src/impls/columns.rs @@ -95,10 +95,10 @@ where } fn index(&self, index: Self::Index) -> Self::ReadItem<'_> { - ReadColumns { + ReadColumns(Ok(ReadColumnsInner { columns: &self.inner, index: self.indices.index(index), - } + })) } fn reserve_regions<'a, I>(&mut self, regions: I) @@ -156,7 +156,11 @@ where } /// Read the values of a row. -pub struct ReadColumns<'a, R> +pub struct ReadColumns<'a, R>(Result, &'a [R::Owned]>) +where + R: Region; + +struct ReadColumnsInner<'a, R> where R: Region, { @@ -175,7 +179,17 @@ where } } +impl<'a, R> Clone for ReadColumnsInner<'a, R> +where + R: Region, +{ + fn clone(&self) -> Self { + *self + } +} + impl<'a, R> Copy for ReadColumns<'a, R> where R: Region {} +impl<'a, R> Copy for ReadColumnsInner<'a, R> where R: Region {} impl<'a, R> Debug for ReadColumns<'a, R> where @@ -197,6 +211,37 @@ where self.into_iter() } + /// Get the element at `offset`. + #[must_use] + pub fn get(&self, offset: usize) -> R::ReadItem<'a> { + match &self.0 { + Ok(inner) => inner.get(offset), + Err(slice) => IntoOwned::borrow_as(&slice[offset]), + } + } + + /// Returns the length of this row. + #[must_use] + pub fn len(&self) -> usize { + match &self.0 { + Ok(inner) => inner.len(), + Err(slice) => slice.len(), + } + } + + /// Returns `true` if this row is empty. + #[must_use] + pub fn is_empty(&self) -> bool { + match &self.0 { + Ok(inner) => inner.is_empty(), + Err(slice) => slice.is_empty(), + } + } +} +impl<'a, R> ReadColumnsInner<'a, R> +where + R: Region, +{ /// Get the element at `offset`. #[must_use] pub fn get(&self, offset: usize) -> R::ReadItem<'a> { @@ -227,11 +272,15 @@ where } fn clone_onto(self, other: &mut Self::Owned) { - todo!() + let r = std::cmp::min(self.len(), other.len()); + for (item, target) in self.iter().zip(other.iter_mut()) { + item.clone_onto(target); + } + other.extend(self.iter().skip(r).map(IntoOwned::into_owned)); } fn borrow_as(owned: &'a Self::Owned) -> Self { - todo!() + Self(Err(owned.as_slice())) } } @@ -243,14 +292,22 @@ where type IntoIter = ReadColumnsIter<'a, R>; fn into_iter(self) -> Self::IntoIter { - ReadColumnsIter { - iter: self.index.iter().zip(self.columns.iter()), + match self.0 { + Ok(inner) => ReadColumnsIter(Ok(ReadColumnsIterInner { + iter: inner.index.iter().zip(inner.columns.iter()), + })), + Err(slice) => ReadColumnsIter(Err(slice.iter())), } } } /// An iterator over the elements of a row. -pub struct ReadColumnsIter<'a, R: Region> { +pub struct ReadColumnsIter<'a, R: Region>( + Result, std::slice::Iter<'a, R::Owned>>, +); + +/// An iterator over the elements of a row. +pub struct ReadColumnsIterInner<'a, R: Region> { iter: std::iter::Zip, std::slice::Iter<'a, R>>, } @@ -260,6 +317,20 @@ where { type Item = R::ReadItem<'a>; + fn next(&mut self) -> Option { + match &mut self.0 { + Ok(inner) => inner.next(), + Err(slice) => slice.next().map(IntoOwned::borrow_as), + } + } +} + +impl<'a, R> Iterator for ReadColumnsIterInner<'a, R> +where + R: Region, +{ + type Item = R::ReadItem<'a>; + fn next(&mut self) -> Option { self.iter.next().map(|(&i, r)| r.index(i)) } diff --git a/src/impls/option.rs b/src/impls/option.rs index c7387c8..b1d893a 100644 --- a/src/impls/option.rs +++ b/src/impls/option.rs @@ -91,7 +91,9 @@ impl OpinionatedRegion for OptionRegion { } impl<'a, T> IntoOwned<'a> for Option -where T: IntoOwned<'a> { +where + T: IntoOwned<'a>, +{ type Owned = Option; fn into_owned(self) -> Self::Owned { diff --git a/src/impls/slice.rs b/src/impls/slice.rs index b307a50..27e92fb 100644 --- a/src/impls/slice.rs +++ b/src/impls/slice.rs @@ -76,11 +76,11 @@ impl> Region for SliceRegion { #[inline] fn index(&self, (start, end): Self::Index) -> Self::ReadItem<'_> { - ReadSlice { + ReadSlice(Ok(ReadSliceInner { region: self, start, end, - } + })) } #[inline] @@ -144,13 +144,57 @@ impl> Default for SliceRegion { } /// A helper to read data out of a slice region. -pub struct ReadSlice<'a, C: Region, O: OffsetContainer = Vec<::Index>> { +pub struct ReadSlice<'a, C: Region, O: OffsetContainer = Vec<::Index>>( + Result, &'a [C::Owned]>, +); + +struct ReadSliceInner<'a, C: Region, O: OffsetContainer = Vec<::Index>> { region: &'a SliceRegion, start: usize, end: usize, } impl> ReadSlice<'_, C, O> { + /// Read the n-th item from the underlying region. + /// + /// # Panics + /// + /// Panics if the index is out of bounds, i.e., it is larger than the + /// length of this slice representation. + #[inline] + #[must_use] + pub fn get(&self, index: usize) -> C::ReadItem<'_> { + match &self.0 { + Ok(inner) => inner.get(index), + Err(slice) => IntoOwned::borrow_as(&slice[index]), + } + } + + /// The number of elements in this slice. + #[must_use] + pub fn len(&self) -> usize { + match self.0 { + Ok(inner) => inner.len(), + Err(slice) => slice.len(), + } + } + + /// Returns `true` if the slice is empty. + #[must_use] + pub fn is_empty(&self) -> bool { + match self.0 { + Ok(inner) => inner.is_empty(), + Err(slice) => slice.is_empty(), + } + } + + /// Returns an iterator over all contained items. + #[must_use] + pub fn iter(&self) -> ::IntoIter { + self.into_iter() + } +} +impl> ReadSliceInner<'_, C, O> { /// Read the n-th item from the underlying region. /// /// # Panics @@ -183,12 +227,6 @@ impl> ReadSlice<'_, C, O> { pub fn is_empty(&self) -> bool { self.start == self.end } - - /// Returns an iterator over all contained items. - #[must_use] - pub fn iter(&self) -> ::IntoIter { - self.into_iter() - } } impl> Debug for ReadSlice<'_, C, O> @@ -207,23 +245,37 @@ impl> Clone for ReadSlice<'_, C, O> { } } +impl> Clone for ReadSliceInner<'_, C, O> { + #[inline] + fn clone(&self) -> Self { + *self + } +} + impl> Copy for ReadSlice<'_, C, O> {} +impl> Copy for ReadSliceInner<'_, C, O> {} impl<'a, C, O> IntoOwned<'a> for ReadSlice<'a, C, O> -where C: Region, O: OffsetContainer, +where + C: Region, + O: OffsetContainer, { type Owned = Vec; fn into_owned(self) -> Self::Owned { - todo!() + self.iter().map(IntoOwned::into_owned).collect() } fn clone_onto(self, other: &mut Self::Owned) { - todo!() + let r = std::cmp::min(self.len(), other.len()); + for (item, target) in self.iter().zip(other.iter_mut()) { + item.clone_onto(target); + } + other.extend(self.iter().skip(r).map(IntoOwned::into_owned)); } fn borrow_as(owned: &'a Self::Owned) -> Self { - todo!() + Self(Err(owned.as_slice())) } } @@ -232,18 +284,35 @@ impl<'a, C: Region, O: OffsetContainer> IntoIterator for ReadSlice<'a, type IntoIter = ReadSliceIter<'a, C, O>; fn into_iter(self) -> Self::IntoIter { - ReadSliceIter(self.region, self.start..self.end) + match self.0 { + Ok(inner) => { + ReadSliceIter(Ok(ReadSliceIterInner(inner.region, inner.start..inner.end))) + } + Err(slice) => ReadSliceIter(Err(slice.iter())), + } } } /// An iterator over the items read from a slice region. #[derive(Debug)] pub struct ReadSliceIter<'a, C: Region, O: OffsetContainer>( + Result, std::slice::Iter<'a, C::Owned>>, +); + +impl<'a, C: Region, O: OffsetContainer> Clone for ReadSliceIter<'a, C, O> { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +/// An iterator over the items read from a slice region. +#[derive(Debug)] +pub struct ReadSliceIterInner<'a, C: Region, O: OffsetContainer>( &'a SliceRegion, Range, ); -impl<'a, C: Region, O: OffsetContainer> Clone for ReadSliceIter<'a, C, O> { +impl<'a, C: Region, O: OffsetContainer> Clone for ReadSliceIterInner<'a, C, O> { fn clone(&self) -> Self { Self(self.0, self.1.clone()) } @@ -252,6 +321,18 @@ impl<'a, C: Region, O: OffsetContainer> Clone for ReadSliceIter<'a, C, impl<'a, C: Region, O: OffsetContainer> Iterator for ReadSliceIter<'a, C, O> { type Item = C::ReadItem<'a>; + #[inline] + fn next(&mut self) -> Option { + match &mut self.0 { + Ok(inner) => inner.next(), + Err(iter) => iter.next().map(IntoOwned::borrow_as), + } + } +} + +impl<'a, C: Region, O: OffsetContainer> Iterator for ReadSliceIterInner<'a, C, O> { + type Item = C::ReadItem<'a>; + #[inline] fn next(&mut self) -> Option { self.1 @@ -343,7 +424,28 @@ where { #[inline] fn push(&mut self, item: ReadSlice<'a, C, O>) -> as Region>::Index { - let ReadSlice { region, start, end } = item; + match item.0 { + Ok(inner) => self.push(inner), + Err(slice) => { + let start_len = self.slices.len(); + for item in slice.iter().map(IntoOwned::borrow_as) { + let index = self.inner.push(item); + self.slices.push(index); + } + (start_len, self.slices.len()) + } + } + } +} + +impl<'a, C, O> Push> for SliceRegion +where + C: Region + Push<::ReadItem<'a>>, + O: OffsetContainer, +{ + #[inline] + fn push(&mut self, item: ReadSliceInner<'a, C, O>) -> as Region>::Index { + let ReadSliceInner { region, start, end } = item; let start_len = self.slices.len(); for index in start..end { let index = region.slices.index(index); diff --git a/src/impls/slice_copy.rs b/src/impls/slice_copy.rs index 39bff73..ee7618f 100644 --- a/src/impls/slice_copy.rs +++ b/src/impls/slice_copy.rs @@ -33,7 +33,10 @@ pub struct OwnedRegion { slices: Vec, } -impl Region for OwnedRegion where [T]: ToOwned { +impl Region for OwnedRegion +where + [T]: ToOwned, +{ type Owned = <[T] as ToOwned>::Owned; type ReadItem<'a> = &'a [T] where Self: 'a; type Index = (usize, usize); @@ -110,7 +113,10 @@ impl Default for OwnedRegion { } } -impl Push<[T; N]> for OwnedRegion where [T]: ToOwned { +impl Push<[T; N]> for OwnedRegion +where + [T]: ToOwned, +{ #[inline] fn push(&mut self, item: [T; N]) -> as Region>::Index { let start = self.slices.len(); @@ -163,7 +169,10 @@ where } } -impl<'b, T> ReserveItems<&'b [T]> for OwnedRegionwhere [T]: ToOwned { +impl<'b, T> ReserveItems<&'b [T]> for OwnedRegion +where + [T]: ToOwned, +{ fn reserve_items(&mut self, items: I) where I: Iterator + Clone, @@ -172,7 +181,10 @@ impl<'b, T> ReserveItems<&'b [T]> for OwnedRegionwhere [T]: ToOwned { } } -impl Push> for OwnedRegion where [T]: ToOwned { +impl Push> for OwnedRegion +where + [T]: ToOwned, +{ #[inline] fn push(&mut self, mut item: Vec) -> as Region>::Index { let start = self.slices.len(); @@ -188,7 +200,10 @@ impl Push<&Vec> for OwnedRegion { } } -impl<'a, T> ReserveItems<&'a Vec> for OwnedRegion where [T]: ToOwned { +impl<'a, T> ReserveItems<&'a Vec> for OwnedRegion +where + [T]: ToOwned, +{ fn reserve_items(&mut self, items: I) where I: Iterator> + Clone, @@ -206,7 +221,10 @@ impl> Push> for OwnedRegion { } } -impl> ReserveItems> for OwnedRegionwhere [T]: ToOwned { +impl> ReserveItems> for OwnedRegion +where + [T]: ToOwned, +{ fn reserve_items(&mut self, items: I) where I: Iterator> + Clone, diff --git a/src/impls/tuple.rs b/src/impls/tuple.rs index 383997b..acbe4fb 100644 --- a/src/impls/tuple.rs +++ b/src/impls/tuple.rs @@ -109,15 +109,23 @@ macro_rules! tuple_flatcontainer { type Owned = ($($name::Owned,)*); fn into_owned(self) -> Self::Owned { - todo!() + let ($($name,)*) = self; + ( + $($name.into_owned(),)* + ) } fn clone_onto(self, other: &mut Self::Owned) { - todo!() + let ($($name,)*) = self; + let ($([<$name _other>],)*) = other; + $($name.clone_onto([<$name _other>]);)* } fn borrow_as(owned: &'a Self::Owned) -> Self { - todo!() + let ($($name,)*) = owned; + ( + $($name::borrow_as($name),)* + ) } } diff --git a/src/lib.rs b/src/lib.rs index 5da72f3..d28d46c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -475,15 +475,25 @@ mod tests { type Owned = Person; fn into_owned(self) -> Self::Owned { - todo!() + Person { + name: self.name.into_owned(), + age: self.age, + hobbies: self.hobbies.into_owned(), + } } fn clone_onto(self, other: &mut Self::Owned) { - todo!() + 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 { - todo!() + Self { + name: IntoOwned::borrow_as(&owned.name), + age: owned.age, + hobbies: IntoOwned::borrow_as(&owned.hobbies), + } } }