/* 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 */ 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>; fn next(&mut self) -> Option { 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>, } impl Iterator for RangeIterator<'_> { type Item = Result>; fn next(&mut self) -> Option { 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 { 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 } } } } }