automerge/rust/automerge/src/query/list_range_at.rs
Alex Good dd3c6d1303
Move rust workspace into ./rust
After some discussion with PVH I realise that the repo structure in the
last reorg was very rust-centric. In an attempt to put each language on
a level footing move the rust code and project files into ./rust
2022-10-16 19:55:51 +01:00

70 lines
2.2 KiB
Rust

use super::VisWindow;
use crate::exid::ExId;
use crate::op_tree::OpTreeNode;
use crate::types::{Clock, ElemId, OpId};
use crate::values::ValueIter;
use crate::{Automerge, Value};
use std::fmt::Debug;
use std::ops::RangeBounds;
#[derive(Debug)]
pub(crate) struct ListRangeAt<'a, R: RangeBounds<usize>> {
range: R,
index: usize,
pos: usize,
last_elemid: Option<ElemId>,
next_result: Option<(usize, Value<'a>, OpId)>,
index_back: usize,
root_child: &'a OpTreeNode,
clock: Clock,
window: VisWindow,
}
impl<'a, R: RangeBounds<usize>> ValueIter<'a> for ListRangeAt<'a, R> {
fn next_value(&mut self, doc: &'a Automerge) -> Option<(Value<'a>, ExId)> {
self.next().map(|(_, val, id)| (val, doc.id_to_exid(id)))
}
}
impl<'a, R: RangeBounds<usize>> ListRangeAt<'a, R> {
pub(crate) fn new(range: R, clock: Clock, root_child: &'a OpTreeNode) -> Self {
Self {
range,
index: 0, // FIXME root_child.seek_to_pos(range.start)
pos: 0, // FIXME range.start
last_elemid: None,
next_result: None,
index_back: root_child.len(),
root_child,
clock,
window: VisWindow::default(),
}
}
}
impl<'a, R: RangeBounds<usize>> Iterator for ListRangeAt<'a, R> {
type Item = (usize, Value<'a>, OpId);
fn next(&mut self) -> Option<Self::Item> {
for i in self.index..self.index_back {
let op = self.root_child.get(i)?;
let visible = self.window.visible_at(op, i, &self.clock);
self.index += 1;
if visible {
if op.elemid() != self.last_elemid {
self.last_elemid = op.elemid();
self.pos += 1;
if self.range.contains(&(self.pos - 1)) {
let result = self.next_result.replace((self.pos - 1, op.value(), op.id));
if result.is_some() {
return result;
}
}
} else if self.pos > 0 && self.range.contains(&(self.pos - 1)) {
self.next_result = Some((self.pos - 1, op.value(), op.id));
}
}
}
self.next_result.take()
}
}