aboutsummaryrefslogtreecommitdiff
path: root/database/src/iterator.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-12-19 21:52:59 +0100
committermetamuffin <metamuffin@disroot.org>2025-12-19 21:52:59 +0100
commiteac0de36221440571fe686074b04b71bf98cf727 (patch)
tree76bad4c937e203bc13b6adcced9ed0b41432c2ae /database/src/iterator.rs
parentda985cc06e4caa7501222dbf54f212536fd42b0c (diff)
downloadjellything-eac0de36221440571fe686074b04b71bf98cf727.tar
jellything-eac0de36221440571fe686074b04b71bf98cf727.tar.bz2
jellything-eac0de36221440571fe686074b04b71bf98cf727.tar.zst
things
Diffstat (limited to 'database/src/iterator.rs')
-rw-r--r--database/src/iterator.rs70
1 files changed, 70 insertions, 0 deletions
diff --git a/database/src/iterator.rs b/database/src/iterator.rs
new file mode 100644
index 0000000..2db349b
--- /dev/null
+++ b/database/src/iterator.rs
@@ -0,0 +1,70 @@
+/*
+ This file is part of jellything (https://codeberg.org/metamuffin/jellything)
+ which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
+ Copyright (C) 2025 metamuffin <metamuffin.org>
+*/
+
+use crate::backends::ReadTransaction;
+use anyhow::Result;
+use std::{borrow::Cow, ops::Range};
+
+pub struct PrefixIterator<'a> {
+ db: &'a dyn ReadTransaction,
+ prefix: &'a [u8],
+ cursor: Cow<'a, [u8]>,
+}
+impl Iterator for PrefixIterator<'_> {
+ type Item = Result<Vec<u8>>;
+ fn next(&mut self) -> Option<Self::Item> {
+ match self.db.next(&self.cursor) {
+ Err(e) => Some(Err(e)),
+ Ok(None) => None,
+ Ok(Some(next)) => {
+ if next.starts_with(self.prefix) {
+ self.cursor = next.clone().into();
+ Some(Ok(next))
+ } else {
+ None
+ }
+ }
+ }
+ }
+}
+
+pub struct RangeIterator<'a> {
+ db: &'a dyn ReadTransaction,
+ range: Range<Cow<'a, [u8]>>,
+}
+impl Iterator for RangeIterator<'_> {
+ type Item = Result<Vec<u8>>;
+ fn next(&mut self) -> Option<Self::Item> {
+ match self.db.next(&self.range.start) {
+ Err(e) => Some(Err(e)),
+ Ok(None) => None,
+ Ok(Some(next)) => {
+ if next.as_slice() < self.range.end.as_ref() {
+ self.range.start = next.clone().into();
+ Some(Ok(next))
+ } else {
+ None
+ }
+ }
+ }
+ }
+}
+impl DoubleEndedIterator for RangeIterator<'_> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ match self.db.prev(&self.range.end) {
+ Err(e) => Some(Err(e)),
+ Ok(None) => None,
+ Ok(Some(prev)) => {
+ if prev.as_slice() >= self.range.start.as_ref() {
+ self.range.end = prev.clone().into();
+ Some(Ok(prev))
+ } else {
+ None
+ }
+ }
+ }
+ }
+}