Skip to content

Commit

Permalink
feat: bounded reverse iteration
Browse files Browse the repository at this point in the history
  • Loading branch information
uint committed Oct 16, 2024
1 parent 3125193 commit 4fd8080
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 1 deletion.
49 changes: 48 additions & 1 deletion packages/storey/src/containers/column.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ pub enum LenError {

#[cfg(test)]
mod tests {
use crate::containers::RevIterableAccessor as _;
use crate::containers::{BoundedRevIterableAccessor as _, RevIterableAccessor as _};

use super::*;

Expand Down Expand Up @@ -657,4 +657,51 @@ mod tests {
vec![1337, 42, 1]
);
}

#[test]
fn bounded_rev_iteration() {
let mut storage = TestStorage::new();

let column = Column::<u64, TestEncoding>::new(0);
let mut access = column.access(&mut storage);

access.push(&1337).unwrap();
access.push(&42).unwrap();
access.push(&9001).unwrap();
access.push(&1).unwrap();
access.push(&2).unwrap();
access.remove(2).unwrap();

// start and end set
assert_eq!(
access
.bounded_rev_pairs(Some(1), Some(4))
.collect::<Result<Vec<_>, _>>()
.unwrap(),
vec![(3, 1), (1, 42)]
);
assert_eq!(
access
.bounded_rev_keys(Some(1), Some(4))
.collect::<Result<Vec<_>, _>>()
.unwrap(),
vec![3, 1]
);
assert_eq!(
access
.bounded_rev_values(Some(1), Some(4))
.collect::<Result<Vec<_>, _>>()
.unwrap(),
vec![1, 42]
);

// end unset
assert_eq!(
access
.bounded_rev_pairs(Some(1), None)
.collect::<Result<Vec<_>, _>>()
.unwrap(),
vec![(4, 2), (3, 1), (1, 42)]
);
}
}
76 changes: 76 additions & 0 deletions packages/storey/src/containers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,82 @@ pub trait BoundedIterableAccessor: IterableAccessor {
}
}

/// This trait extends [`BoundedIterableAccessor`] with methods for bounded reverse iteration.
/// Not every iterable collection supports it, so this trait is separate.
///
/// Bounded reverse iteration allows the user to specify a start and end bound for the iteration,
/// but in reverse order.
///
/// # Why not always support bounded reverse iteration?
///
/// The same reasons as for [bounded iteration](BoundedIterableAccessor) apply.
pub trait BoundedRevIterableAccessor
where
Self: BoundedIterableAccessor,
Self::Storage: RevIterableStorage,
{
/// Iterate over key-value pairs in this collection in reverse order, respecting the given bounds.
fn bounded_rev_pairs<B>(
&self,
start: Option<B>,
end: Option<B>,
) -> StorableIter<Self::Storable, <Self::Storage as RevIterableStorage>::RevPairsIterator<'_>>
where
B: BoundFor<Self::Storable>,
{
let start = start.map(|b| b.into_bytes());
let end = end.map(|b| b.into_bytes());

StorableIter {
inner: self.storage().rev_pairs(start.as_deref(), end.as_deref()),
phantom: PhantomData,
}
}

/// Iterate over keys in this collection in reverse order, respecting the given bounds.
fn bounded_rev_keys<B>(
&self,
start: Option<B>,
end: Option<B>,
) -> StorableKeys<Self::Storable, <Self::Storage as RevIterableStorage>::RevKeysIterator<'_>>
where
B: BoundFor<Self::Storable>,
{
let start = start.map(|b| b.into_bytes());
let end = end.map(|b| b.into_bytes());

StorableKeys {
inner: self.storage().rev_keys(start.as_deref(), end.as_deref()),
phantom: PhantomData,
}
}

/// Iterate over values in this collection in reverse order, respecting the given bounds.
fn bounded_rev_values<B>(
&self,
start: Option<B>,
end: Option<B>,
) -> StorableValues<Self::Storable, <Self::Storage as RevIterableStorage>::RevValuesIterator<'_>>
where
B: BoundFor<Self::Storable>,
{
let start = start.map(|b| b.into_bytes());
let end = end.map(|b| b.into_bytes());

StorableValues {
inner: self.storage().rev_values(start.as_deref(), end.as_deref()),
phantom: PhantomData,
}
}
}

impl<I> BoundedRevIterableAccessor for I
where
I: BoundedIterableAccessor,
I::Storage: RevIterableStorage,
{
}

/// A type that can be used as bounds for iteration over a given collection.
///
/// As an example, a collection `Foo` with string-y keys can accept both `String` and
Expand Down

0 comments on commit 4fd8080

Please sign in to comment.