From 103b677d218a3916439d5c966fe5e75b7b110d59 Mon Sep 17 00:00:00 2001
From: Dmitry <b4tm4n@mail.ru>
Date: Tue, 28 Mar 2023 15:01:14 +0300
Subject: [PATCH] into_iter() for reader

---
 lib/src/db.rs | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/lib/src/db.rs b/lib/src/db.rs
index d2b5396..73b121b 100644
--- a/lib/src/db.rs
+++ b/lib/src/db.rs
@@ -226,6 +226,10 @@ where
     pub fn iter(&self) -> ReaderIter<'_, T> {
         ReaderIter::new(self)
     }
+
+    pub fn into_iter(self) -> ReaderIntoIter<T> {
+        ReaderIntoIter::new(self)
+    }
 }
 
 pub struct ReaderIter<'a, T>
@@ -310,6 +314,100 @@ where
     }
 }
 
+pub struct ReaderIntoIter<T>
+where
+    T: bincode::Decode,
+{
+    reader: Reader<T>,
+    index: Option<usize>,
+}
+
+impl<T> ReaderIntoIter<T>
+where
+    T: bincode::Decode,
+{
+    fn new(reader: Reader<T>) -> Self {
+        Self {
+            reader,
+            index: None,
+        }
+    }
+}
+
+impl<T> Iterator for ReaderIntoIter<T>
+where
+    T: bincode::Decode,
+{
+    type Item = T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.index.is_none() && !self.reader.is_empty() {
+            self.index = Some(0);
+        }
+
+        match self.index {
+            Some(i) if i < self.reader.len() => self.nth(i),
+            _ => None,
+        }
+    }
+
+    fn nth(&mut self, n: usize) -> Option<Self::Item> {
+        if self.reader.len() <= n {
+            return None;
+        }
+        self.index = Some(n + 1);
+
+        let item = self.reader.get(n);
+        match item {
+            Ok(item) => Some(item),
+            Err(_) => None,
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let len = self.reader.len();
+        if self.index.is_none() {
+            return (len, Some(len));
+        }
+
+        let index = self.index.unwrap();
+        let rem = if len > index + 1 {
+            len - (index + 1)
+        } else {
+            0
+        };
+        (rem, Some(rem))
+    }
+
+    fn count(self) -> usize
+    where
+        Self: Sized,
+    {
+        self.reader.len()
+    }
+}
+
+impl<T> ExactSizeIterator for ReaderIntoIter<T>
+where
+    T: bincode::Decode,
+{
+    fn len(&self) -> usize {
+        self.reader.len()
+    }
+}
+
+impl<T> IntoIterator for Reader<T> 
+where
+    T: bincode::Decode,
+{
+    type Item = T;
+    type IntoIter = ReaderIntoIter<Self::Item>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.into_iter()
+    }
+}
+
 #[cfg(test)]
 mod test {
     use super::*;
@@ -380,4 +478,30 @@ mod test {
             assert_eq!(pair.0, pair.1);
         });
     }
+
+    #[test]
+    fn test_write_read_into_iter() {
+        let dir = tempdir().expect("tempdir");
+        let tmpfile = dir.path().join("test.tmp");
+        let opts = WriterOpts {
+            compress_lvl: 1,
+            data_buf_size: 10 * 1024 * 1024,
+            out_buf_size: 10 * 1024 * 1024,
+            current_buf_size: 4096,
+        };
+        let mut writer: Writer<TestData> = Writer::new(&tmpfile, opts).expect("new writer");
+
+        let items_iter = gen_data(10);
+        let items: Vec<TestData> = items_iter.collect();
+
+        writer.load(&mut items.clone().into_iter()).expect("load");
+        writer.finish().expect("finish write");
+
+        let reader: Reader<TestData> = Reader::new(&tmpfile, 2048).expect("new reader");
+        assert_eq!(items.len(), reader.len());
+
+        items.into_iter().zip(reader).for_each(|pair| {
+            assert_eq!(pair.0, pair.1);
+        });
+    }
 }