]> git.mikk.net Git - mtbl-rs/commitdiff
Add map capability to Source, SeekableIter back-to-impl master
authorChris Mikkelson <chris@mikk.net>
Wed, 9 Apr 2025 19:51:06 +0000 (14:51 -0500)
committerChris Mikkelson <chris@mikk.net>
Wed, 9 Apr 2025 19:51:06 +0000 (14:51 -0500)
src/iter.rs
src/lib.rs
src/map.rs [new file with mode: 0644]
src/source.rs

index e72a2873fbc960bb35efff5b13d37a8cff2e0ea8..67a92dc05621a7d3fc8a8ec3c2fbf01ebb5a09a6 100644 (file)
@@ -1,5 +1,6 @@
 use crate::dupsort::DupsortIter;
 use crate::filter::FilterIter;
 use crate::dupsort::DupsortIter;
 use crate::filter::FilterIter;
+use crate::map::MapIter;
 use crate::merge::MergeIter;
 use crate::Entry;
 use std::cmp::Ordering;
 use crate::merge::MergeIter;
 use crate::Entry;
 use std::cmp::Ordering;
@@ -31,6 +32,14 @@ pub trait SeekableIter: Iterator {
     {
         FilterIter::new(self, filter_func)
     }
     {
         FilterIter::new(self, filter_func)
     }
+
+    fn map_func<F, O>(self, map_func: F) -> MapIter<Self, F, O>
+    where
+        F: FnMut(Self::Item) -> O,
+        Self: Sized,
+    {
+        MapIter::new(self, map_func)
+    }
 }
 
 impl<I: SeekableIter + ?Sized> SeekableIter for Box<I> {
 }
 
 impl<I: SeekableIter + ?Sized> SeekableIter for Box<I> {
index 7b47e6fa89313f063d3ff747366c96f0a1827269..d8060fb78da751a976d363b5b3889fb839a547dc 100644 (file)
@@ -3,6 +3,7 @@ mod dupsort;
 mod entry;
 mod filter;
 mod iter;
 mod entry;
 mod filter;
 mod iter;
+mod map;
 mod merge;
 mod merger;
 pub mod reader;
 mod merge;
 mod merger;
 pub mod reader;
diff --git a/src/map.rs b/src/map.rs
new file mode 100644 (file)
index 0000000..a2f746b
--- /dev/null
@@ -0,0 +1,117 @@
+use crate::{SeekableIter, Source};
+
+pub struct MapIter<I, F, O>
+where
+    I: SeekableIter,
+    F: FnMut(I::Item) -> O,
+{
+    iter: I,
+    mapf: F,
+}
+
+impl<I, F, O> MapIter<I, F, O>
+where
+    I: SeekableIter,
+    F: FnMut(I::Item) -> O,
+{
+    pub fn new(iter: I, mapf: F) -> Self {
+        Self { iter, mapf }
+    }
+}
+
+impl<I, F, O> Iterator for MapIter<I, F, O>
+where
+    I: SeekableIter,
+    F: FnMut(I::Item) -> O,
+{
+    type Item = O;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let item = self.iter.next()?;
+        Some((self.mapf)(item))
+    }
+}
+
+impl<I, F, O> SeekableIter for MapIter<I, F, O>
+where
+    I: SeekableIter,
+    F: FnMut(I::Item) -> O,
+{
+    fn seek(&mut self, key: &[u8]) {
+        self.iter.seek(key);
+    }
+}
+
+pub struct MapSource<S, O>
+where
+    S: Source,
+{
+    source: S,
+    #[allow(clippy::type_complexity)]
+    map: Box<dyn Fn(S::Item) -> O>,
+}
+
+impl<S, O> MapSource<S, O>
+where
+    S: Source,
+{
+    pub fn new<F>(source: S, map: F) -> Self
+    where
+        F: Fn(S::Item) -> O + 'static,
+    {
+        Self {
+            source,
+            map: Box::new(map),
+        }
+    }
+}
+
+impl<S, O> Source for MapSource<S, O>
+where
+    S: Source,
+{
+    type Item = O;
+    fn iter(&self) -> impl SeekableIter<Item = Self::Item> {
+        self.source.iter().map_func(&self.map)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use crate::source::test_source::TestSource;
+    use crate::Entry;
+    use crate::Source;
+
+    struct CompVec(Vec<u8>);
+    impl PartialEq<[u8]> for CompVec {
+        fn eq(&self, other: &[u8]) -> bool {
+            self.0.as_slice().eq(other)
+        }
+    }
+    impl PartialOrd<[u8]> for CompVec {
+        fn partial_cmp(&self, other: &[u8]) -> Option<std::cmp::Ordering> {
+            self.0.as_slice().partial_cmp(other)
+        }
+    }
+
+    #[test]
+    fn test_mapsource() {
+        let ts = TestSource((0u8..10).map(|i| Entry::new(vec![i], vec![])).collect())
+            .map(|e| CompVec(Vec::from(e.key())));
+        assert_eq!(
+            ts.iter().map(|cv| cv.0).collect::<Vec<_>>(),
+            (0u8..10).map(|i| vec![i]).collect::<Vec<_>>()
+        );
+        assert_eq!(
+            ts.get_range(&[2u8], &[7u8])
+                .map(|cv| cv.0)
+                .collect::<Vec<_>>(),
+            (2u8..8)
+                .map(|i| {
+                    println!("{i}");
+                    vec![i]
+                })
+                .collect::<Vec<_>>()
+        )
+    }
+}
index 04d9dd3b06da243f88831c00b3db09049d64b9e2..4efbb296fcbf5c0f0f65794df785a48d06fe16a9 100644 (file)
@@ -1,6 +1,7 @@
 use crate::dupsort::DupsortSource;
 use crate::filter::FilterSource;
 use crate::iter::{PrefixIter, RangeIter};
 use crate::dupsort::DupsortSource;
 use crate::filter::FilterSource;
 use crate::iter::{PrefixIter, RangeIter};
+use crate::map::MapSource;
 use crate::merge::MergeSource;
 use crate::{Entry, SeekableIter};
 
 use crate::merge::MergeSource;
 use crate::{Entry, SeekableIter};
 
@@ -51,6 +52,14 @@ pub trait Source {
         FilterSource::new(self, filter_func)
     }
 
         FilterSource::new(self, filter_func)
     }
 
+    fn map<F, O>(self, map_func: F) -> MapSource<Self, O>
+    where
+        Self: Sized,
+        F: Fn(Self::Item) -> O + 'static,
+    {
+        MapSource::new(self, map_func)
+    }
+
     fn into_boxed(self) -> Box<dyn DynSource<Item = Self::Item>>
     where
         Self: Sized + 'static,
     fn into_boxed(self) -> Box<dyn DynSource<Item = Self::Item>>
     where
         Self: Sized + 'static,