From 3f0e91a735ed70b37f645c6313725d55295af619 Mon Sep 17 00:00:00 2001 From: Chris Mikkelson Date: Sun, 28 Apr 2024 20:44:00 -0500 Subject: [PATCH] Modify filter_map to only map values Mapping keys requires a conversion on seek from the mapped key to the inner key. Since the keys are passed to seek by reference to avoid moves, this complicates consuming the key for a full conversion to the inner key. For now, restrict mapping to values only. This required changing the filter function signature to take a reference to the key so its caller could retain the key for returning. --- src/seekable.rs | 5 ++- src/seekable/filter_map.rs | 74 +++++++++++++++++++++++++++++--------- 2 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/seekable.rs b/src/seekable.rs index d8bdde9..a5c9162 100644 --- a/src/seekable.rs +++ b/src/seekable.rs @@ -14,10 +14,9 @@ pub trait Seekable: Sized { fn next(&mut self) -> Option<(Self::Key, Self::Value)>; fn seek(&mut self, key: &Self::Key); - fn filter_map(self, func: F) -> FilterMap + fn filter_map(self, func: F) -> FilterMap where - K: Ord + AsRef, - F: FnMut((Self::Key, Self::Value), &mut Self) -> Option<(K, V)>, + F: FnMut(&Self::Key, Self::Value, &mut Self) -> Option, { FilterMap { next: self, func } } diff --git a/src/seekable/filter_map.rs b/src/seekable/filter_map.rs index b483199..2246f6b 100644 --- a/src/seekable/filter_map.rs +++ b/src/seekable/filter_map.rs @@ -1,51 +1,93 @@ use crate::seekable::{Iter, Seekable}; -pub struct FilterMap +pub struct FilterMap where S: Seekable, - K: Ord + AsRef, - F: FnMut((S::Key, S::Value), &mut S) -> Option<(K, V)>, + F: FnMut(&S::Key, S::Value, &mut S) -> Option, { pub(crate) next: S, pub(crate) func: F, } -impl IntoIterator for FilterMap +impl IntoIterator for FilterMap where S: Seekable, - K: Ord + AsRef, - F: FnMut((S::Key, S::Value), &mut S) -> Option<(K, V)>, + F: FnMut(&S::Key, S::Value, &mut S) -> Option, { - type Item = (K, V); + type Item = (S::Key, V); type IntoIter = Iter; fn into_iter(self) -> Iter { Iter(self) } } -impl Seekable for FilterMap +impl Seekable for FilterMap where S: Seekable, - K: Ord + AsRef, - F: FnMut((S::Key, S::Value), &mut S) -> Option<(K, V)>, + F: FnMut(&S::Key, S::Value, &mut S) -> Option, { - type Key = K; + type Key = S::Key; type Value = V; - fn next(&mut self) -> Option<(K, V)> { + fn next(&mut self) -> Option<(S::Key, V)> { loop { match self.next.next() { None => return None, Some(v) => { - if let Some(i) = (self.func)(v, &mut self.next) { - return Some(i); + if let Some(i) = (self.func)(&v.0, v.1, &mut self.next) { + return Some((v.0, i)); } } } } } - fn seek(&mut self, key: &K) { - self.next.seek(key.as_ref()) + fn seek(&mut self, key: &S::Key) { + self.next.seek(key) + } +} + +#[cfg(test)] +mod test { + use crate::seekable::SeekableVec; + use crate::Seekable; + use std::cmp::Ordering; + + #[test] + fn test_map() { + let mut v = vec![3i32, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7]; + let sv = SeekableVec::from(v.clone().into_iter().collect::>()); + v.sort(); + assert_eq!( + sv.filter_map(|_k, _v, _s| Some("hello")) + .into_iter() + .cmp(v.into_iter().map(|i| (i, "hello"))), + Ordering::Equal + ); + } + + #[test] + fn test_map_filter_seek() { + let v = vec![3i32, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7] + .into_iter() + .map(|i| (i, "foo")) + .collect::>(); + let mut sv = SeekableVec::from(v.clone()).filter_map(|k, _v, s| { + if k % 5 == 0 { + return None; + } + if *k == 7 { + s.seek(&8); + return None; + } + Some("bar") + }); + sv.seek(&3); + assert_eq!(sv.next(), Some((3, "bar"))); + assert_eq!(sv.next(), Some((3, "bar"))); + + sv.seek(&5); + assert_eq!(sv.next(), Some((6, "bar"))); + assert_eq!(sv.next(), Some((8, "bar"))) } } -- 2.50.1