pub struct Cursor<T> {
left: Vec<T>,
right: Vec<T>,
left_marks: Vec<MarkData>,
right_marks: Vec<MarkData>,
next_mark: usize,
}
struct MarkData {
name: usize,
depth: usize,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Mark(usize);
#[allow(dead_code)]
impl<T> Cursor<T> {
pub fn new() -> Cursor<T> {
Cursor {
left: Vec::new(),
right: Vec::new(),
left_marks: Vec::new(),
right_marks: Vec::new(),
next_mark: 0,
}
}
pub fn from_vec(orig: Vec<T>) -> Cursor<T> {
let mut orig = orig;
orig.reverse();
Cursor {
left: Vec::new(),
right: orig,
left_marks: Vec::new(),
right_marks: Vec::new(),
next_mark: 0,
}
}
pub fn into_vec(mut self) -> Vec<T> {
self.right.reverse();
self.left.append(&mut self.right);
self.left
}
pub fn retract(&mut self) {
let x = self
.left
.pop()
.expect("retract: already at start of buffer");
self.right.push(x);
while self.left_marks.last().map_or(false, |m| m.depth == 0) {
let m = self.left_marks.pop().unwrap();
self.right_marks.push(m);
}
if let Some(m) = self.left_marks.last_mut() {
m.depth -= 1;
}
if let Some(m) = self.right_marks.last_mut() {
m.depth += 1;
}
}
pub fn retract_by(&mut self, n: usize) {
for _ in 0..n {
self.retract();
}
}
pub fn advance(&mut self) {
let x = self.right.pop().expect("advance: already at end of buffer");
self.left.push(x);
while self.right_marks.last().map_or(false, |m| m.depth == 0) {
let m = self.right_marks.pop().unwrap();
self.left_marks.push(m);
}
if let Some(m) = self.right_marks.last_mut() {
m.depth -= 1;
}
if let Some(m) = self.left_marks.last_mut() {
m.depth += 1;
}
}
pub fn advance_by(&mut self, steps: usize) {
for _ in 0..steps {
self.advance();
}
}
pub fn mark(&mut self) -> Mark {
let name = self.next_mark;
self.next_mark += 1;
self.left_marks.push(MarkData {
name,
depth: 0,
});
Mark(name)
}
pub fn seek(&mut self, mark: Mark) {
if let Some(depth) = find_mark_depth(&self.left_marks, mark) {
self.retract_by(depth);
} else if let Some(depth) = find_mark_depth(&self.right_marks, mark) {
self.advance_by(depth);
} else {
panic!("mark is no longer valid for this sequence");
}
}
pub fn eof(&self) -> bool {
self.right.is_empty()
}
pub fn insert(&mut self, x: T) {
self.left.push(x);
if let Some(m) = self.left_marks.last_mut() {
m.depth += 1;
}
}
pub fn insert_multi(&mut self, xs: Vec<T>) {
let n = xs.len();
let mut xs = xs;
self.left.append(&mut xs);
if let Some(m) = self.left_marks.last_mut() {
m.depth += n;
}
}
pub fn remove(&mut self) -> T {
let x = self.right.pop().expect("remove: already at end of buffer");
while self.right_marks.last().map_or(false, |m| m.depth == 0) {
let m = self.right_marks.pop().unwrap();
self.left_marks.push(m);
}
if let Some(m) = self.right_marks.last_mut() {
m.depth -= 1;
}
x
}
pub fn remove_multi(&mut self, n: usize) -> Vec<T> {
assert!(
n <= self.right.len(),
"remove_multi: too close to end of buffer"
);
let at = self.right.len() - n;
let mut xs = self.right.split_off(at);
xs.reverse();
let xs = xs;
while self.right_marks.last().map_or(false, |m| m.depth == 0) {
let m = self.right_marks.pop().unwrap();
self.left_marks.push(m);
}
let mut mark_moves = n;
while self
.right_marks
.last()
.map_or(false, |m| m.depth < mark_moves)
{
let m = self.right_marks.pop().unwrap();
mark_moves -= m.depth;
}
if let Some(m) = self.right_marks.last_mut() {
m.depth -= mark_moves;
}
xs
}
pub fn next(&self) -> &T {
self.right.last().expect("peek: at end of buffer")
}
pub fn advance_until<F: FnMut(&T) -> bool>(&mut self, pred: F) {
let n = if let Some(n) = find_matching_rev(&self.right, pred) {
n
} else {
self.right.len()
};
self.advance_by(n);
}
pub fn remove_to_mark(&mut self, m: Mark) -> Vec<T> {
let depth = if let Some(depth) = find_mark_depth(&self.right_marks, m) {
depth
} else if let Some(depth) = find_mark_depth(&self.left_marks, m) {
if depth == 0 {
0
} else {
panic!("remove_to_mark: mark is earlier in buffer than the current position");
}
} else {
panic!("remove_to_mark: mark is no longer valid for buffer");
};
self.remove_multi(depth)
}
pub fn replace<F>(&mut self, func: F)
where
F: FnOnce(T) -> T,
{
let old = self.right.pop().expect("replace: at end of buffer");
let new = func(old);
self.right.push(new);
}
pub fn replace_range<F>(&mut self, start: Mark, end: Mark, func: F)
where
F: FnOnce(Vec<T>) -> Vec<T>,
{
self.seek(start);
let old = self.remove_to_mark(end);
let new = func(old);
self.insert_multi(new);
}
pub fn advance_until_match<F, R>(&mut self, func: F) -> Option<R>
where
F: FnMut(&T) -> Option<R>,
{
let (n, result) = if let Some((n, r)) = find_matching_result_rev(&self.right, func) {
(n, Some(r))
} else {
(self.right.len(), None)
};
self.advance_by(n);
result
}
#[allow(dead_code)] pub fn debug(&self) {
let pos = self.left.len();
let len = self.left.len() + self.right.len();
info!("cursor debug: at position {} / {}", pos, len);
let mut depth = 0;
for m in &self.left_marks {
depth += m.depth;
info!(
" mark {} at (L) {} / {}",
m.name,
pos - depth as usize,
len
);
}
for m in &self.right_marks {
depth += m.depth;
info!(
" mark {} at (R) {} / {}",
m.name,
pos + depth as usize,
len
);
}
}
}
fn find_mark_depth(marks: &[MarkData], m: Mark) -> Option<usize> {
let mut seen = false;
let mut sum = 0;
for md in marks {
if !seen {
if md.name == m.0 {
sum = md.depth;
seen = true;
}
} else {
sum += md.depth;
}
}
if seen {
Some(sum)
} else {
None
}
}
fn find_matching_rev<T, F: FnMut(&T) -> bool>(buf: &[T], mut pred: F) -> Option<usize> {
for (i, x) in buf.iter().rev().enumerate() {
if pred(x) {
return Some(i);
}
}
None
}
fn find_matching_result_rev<T, F, R>(buf: &[T], mut func: F) -> Option<(usize, R)>
where
F: FnMut(&T) -> Option<R>,
{
for (i, x) in buf.iter().rev().enumerate() {
if let Some(r) = func(x) {
return Some((i, r));
}
}
None
}