]> git.mikk.net Git - mtbl-rs/commitdiff
Modify filter_map to only map values
authorChris Mikkelson <cmikk@fsi.io>
Mon, 29 Apr 2024 01:44:00 +0000 (20:44 -0500)
committerChris Mikkelson <cmikk@fsi.io>
Mon, 29 Apr 2024 01:44:00 +0000 (20:44 -0500)
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
src/seekable/filter_map.rs

index d8bdde9947efdc6c6e591a8c806631b6b797d83d..a5c916272982f4449e0a24eec7239f46b8a18af9 100644 (file)
@@ -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<F, K, V>(self, func: F) -> FilterMap<Self, F, K, V>
+    fn filter_map<F, V>(self, func: F) -> FilterMap<Self, F, V>
     where
-        K: Ord + AsRef<Self::Key>,
-        F: FnMut((Self::Key, Self::Value), &mut Self) -> Option<(K, V)>,
+        F: FnMut(&Self::Key, Self::Value, &mut Self) -> Option<V>,
     {
         FilterMap { next: self, func }
     }
index b483199ff69682331d51250b299ac911a4de8441..2246f6b0925877b20db8d005fa5c3feb2b1e157a 100644 (file)
@@ -1,51 +1,93 @@
 use crate::seekable::{Iter, Seekable};
 
-pub struct FilterMap<S, F, K, V>
+pub struct FilterMap<S, F, V>
 where
     S: Seekable,
-    K: Ord + AsRef<S::Key>,
-    F: FnMut((S::Key, S::Value), &mut S) -> Option<(K, V)>,
+    F: FnMut(&S::Key, S::Value, &mut S) -> Option<V>,
 {
     pub(crate) next: S,
     pub(crate) func: F,
 }
 
-impl<S, F, K, V> IntoIterator for FilterMap<S, F, K, V>
+impl<S, F, V> IntoIterator for FilterMap<S, F, V>
 where
     S: Seekable,
-    K: Ord + AsRef<S::Key>,
-    F: FnMut((S::Key, S::Value), &mut S) -> Option<(K, V)>,
+    F: FnMut(&S::Key, S::Value, &mut S) -> Option<V>,
 {
-    type Item = (K, V);
+    type Item = (S::Key, V);
     type IntoIter = Iter<Self>;
     fn into_iter(self) -> Iter<Self> {
         Iter(self)
     }
 }
 
-impl<S, F, K, V> Seekable for FilterMap<S, F, K, V>
+impl<S, F, V> Seekable for FilterMap<S, F, V>
 where
     S: Seekable,
-    K: Ord + AsRef<S::Key>,
-    F: FnMut((S::Key, S::Value), &mut S) -> Option<(K, V)>,
+    F: FnMut(&S::Key, S::Value, &mut S) -> Option<V>,
 {
-    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::<Vec<i32>>());
+        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::<Vec<(i32, &str)>>();
+        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")))
     }
 }