diff --git a/src/obikrope/src/cursor.rs b/src/obikrope/src/cursor.rs index 333053c..7a83201 100644 --- a/src/obikrope/src/cursor.rs +++ b/src/obikrope/src/cursor.rs @@ -12,24 +12,24 @@ pub enum SeekMode { // ── shared state ────────────────────────────────────────────────────────────── #[derive(Clone)] -struct CursorState<'a> { - block_idx: Cell, +pub struct CursorState<'a> { + block_idx: Cell, block_start: Cell, - block_end: Cell, - block: Cell<&'a [Cell]>, + block_end: Cell, + block: Cell<&'a [Cell]>, initialized: Cell, - current: Cell>, + current: Cell>, } impl<'a> CursorState<'a> { fn new() -> Self { Self { - block_idx: Cell::new(0), + block_idx: Cell::new(0), block_start: Cell::new(0), - block_end: Cell::new(0), - block: Cell::new(&[]), + block_end: Cell::new(0), + block: Cell::new(&[]), initialized: Cell::new(false), - current: Cell::new(None), + current: Cell::new(None), } } @@ -47,16 +47,19 @@ impl<'a> CursorState<'a> { fn set(&self, rope: &'a Rope, i: usize, value: u8) -> Result<(), RopeError> { if !self.initialized.get() || i < self.block_start.get() || i >= self.block_end.get() { - let (bi, bs, be) = rope.lookup(i).ok_or( - RopeError::OutOfBounds(format!("index out of bounds: i={} > {}", i, rope.len())), - )?; + let (bi, bs, be) = rope.lookup(i).ok_or(RopeError::OutOfBounds(format!( + "index out of bounds: i={} > {}", + i, + rope.len() + )))?; self.block_idx.set(bi); self.block_start.set(bs); self.block_end.set(be); - self.block.set(rope.get_block(bi).ok_or(RopeError::BlockNotFound(format!( - "Cannot find block for index {}", - i - )))?); + self.block + .set(rope.get_block(bi).ok_or(RopeError::BlockNotFound(format!( + "Cannot find block for index {}", + i + )))?); self.initialized.set(true); } self.block.get()[i - self.block_start.get()].set(value); @@ -66,29 +69,59 @@ impl<'a> CursorState<'a> { // ── trait ───────────────────────────────────────────────────────────────────── -pub trait RopeCursor { - fn get(&self, i: usize) -> Option; - fn set(&self, i: usize, value: u8) -> Result<(), RopeError>; - fn peek(&self) -> Option; - fn poke(&self, value: u8) -> Result<(), RopeError>; - fn tell(&self) -> Option; - fn seek(&self, pos: isize, mode: SeekMode) -> Result; - fn rewind(&self, go_back_of: usize) -> Result<(), RopeError>; - fn len(&self) -> usize; +pub trait RopeCursor<'a> { + fn rope(&self) -> &'a Rope; + fn state(&self) -> &CursorState<'a>; + + // Required: differ between Forward and Backward fn read_next(&self) -> Result; + fn seek(&self, pos: isize, mode: SeekMode) -> Result; + + // Defaults: identical for all cursors + fn get(&self, i: usize) -> Option { + self.state().get(self.rope(), i) + } + fn set(&self, i: usize, value: u8) -> Result<(), RopeError> { + self.state().set(self.rope(), i, value) + } + fn tell(&self) -> Option { + self.state().current.get() + } + fn len(&self) -> usize { + self.rope().len() + } + fn peek(&self) -> Option { + self.state().get(self.rope(), self.state().current.get()?) + } + fn poke(&self, value: u8) -> Result<(), RopeError> { + let pos = self.state().current.get().ok_or(RopeError::CurrentNotSet)?; + self.state().set(self.rope(), pos, value) + } + fn rewind(&self, go_back_of: usize) -> Result<(), RopeError> { + self.seek(-(go_back_of as isize), SeekMode::Relative)?; + Ok(()) + } + + fn forward(&self, ahead: usize) -> Result<(), RopeError> { + self.seek(ahead as isize, SeekMode::Relative)?; + Ok(()) + } } // ── ForwardCursor ───────────────────────────────────────────────────────────── #[derive(Clone)] pub struct ForwardCursor<'a> { - rope: &'a Rope, + rope: &'a Rope, state: CursorState<'a>, } impl<'a> ForwardCursor<'a> { pub fn new(rope: &'a Rope) -> Self { - Self { rope, state: CursorState::new() } + Self { + rope, + state: CursorState::new(), + } } pub fn read_ahead(&self, ahead: usize) -> Result { @@ -97,7 +130,9 @@ impl<'a> ForwardCursor<'a> { .get(self.rope, pos + ahead) .ok_or(RopeError::OutOfBounds(format!( "index out of bounds: i={} + {} > {}", - pos, ahead, self.rope.len() + pos, + ahead, + self.rope.len() ))) } @@ -113,42 +148,26 @@ impl<'a> ForwardCursor<'a> { } } -impl<'a> RopeCursor for ForwardCursor<'a> { - fn get(&self, i: usize) -> Option { - self.state.get(self.rope, i) +impl<'a> RopeCursor<'a> for ForwardCursor<'a> { + fn rope(&self) -> &'a Rope { + self.rope } - - fn set(&self, i: usize, value: u8) -> Result<(), RopeError> { - self.state.set(self.rope, i, value) - } - - fn peek(&self) -> Option { - self.state.get(self.rope, self.state.current.get()?) - } - - fn poke(&self, value: u8) -> Result<(), RopeError> { - let pos = self.state.current.get().ok_or(RopeError::CurrentNotSet)?; - self.state.set(self.rope, pos, value) - } - - fn tell(&self) -> Option { - self.state.current.get() - } - - fn len(&self) -> usize { - self.rope.len() + fn state(&self) -> &CursorState<'a> { + &self.state } fn read_next(&self) -> Result { let next_pos = match self.state.current.get() { Some(i) => i + 1, - None => 0, + None => 0, }; - let value = self.state + let value = self + .state .get(self.rope, next_pos) .ok_or(RopeError::OutOfBounds(format!( "index out of bounds: i={} > {}", - next_pos, self.rope.len() + next_pos, + self.rope.len() )))?; self.state.current.set(Some(next_pos)); Ok(value) @@ -156,21 +175,21 @@ impl<'a> RopeCursor for ForwardCursor<'a> { fn seek(&self, pos: isize, mode: SeekMode) -> Result { let pos = match mode { - SeekMode::Absolute => pos, - SeekMode::Relative => self.state.current.get().ok_or(RopeError::CurrentNotSet)? as isize + pos, + SeekMode::Absolute => pos, + SeekMode::Relative => { + self.state.current.get().ok_or(RopeError::CurrentNotSet)? as isize + pos + } SeekMode::RelativeToEnd => self.rope.len() as isize - pos, }; if pos < 0 { - return Err(RopeError::OutOfBounds(format!("index out of bounds: i={} < 0", pos))); + return Err(RopeError::OutOfBounds(format!( + "index out of bounds: i={} < 0", + pos + ))); } self.state.current.set(Some(pos as usize)); Ok(pos as usize) } - - fn rewind(&self, go_back_of: usize) -> Result<(), RopeError> { - self.seek(-(go_back_of as isize), SeekMode::Relative)?; - Ok(()) - } } impl Iterator for ForwardCursor<'_> { @@ -195,13 +214,16 @@ impl Iterator for ForwardIter<'_, '_> { #[derive(Clone)] pub struct BackwardCursor<'a> { - rope: &'a Rope, + rope: &'a Rope, state: CursorState<'a>, } impl<'a> BackwardCursor<'a> { pub fn new(rope: &'a Rope) -> Self { - Self { rope, state: CursorState::new() } + Self { + rope, + state: CursorState::new(), + } } pub fn read_behind(&self, behind: usize) -> Result { @@ -211,13 +233,17 @@ impl<'a> BackwardCursor<'a> { .filter(|&t| t < self.rope.len()) .ok_or(RopeError::OutOfBounds(format!( "index out of bounds: i={} + {} > {}", - pos, behind, self.rope.len() + pos, + behind, + self.rope.len() )))?; self.state .get(self.rope, target) .ok_or(RopeError::OutOfBounds(format!( "index out of bounds: i={} + {} > {}", - pos, behind, self.rope.len() + pos, + behind, + self.rope.len() ))) } @@ -226,43 +252,32 @@ impl<'a> BackwardCursor<'a> { } } -impl<'a> RopeCursor for BackwardCursor<'a> { - fn get(&self, i: usize) -> Option { - self.state.get(self.rope, i) +impl<'a> RopeCursor<'a> for BackwardCursor<'a> { + fn rope(&self) -> &'a Rope { + self.rope } - - fn set(&self, i: usize, value: u8) -> Result<(), RopeError> { - self.state.set(self.rope, i, value) - } - - fn peek(&self) -> Option { - self.state.get(self.rope, self.state.current.get()?) - } - - fn poke(&self, value: u8) -> Result<(), RopeError> { - let pos = self.state.current.get().ok_or(RopeError::CurrentNotSet)?; - self.state.set(self.rope, pos, value) - } - - fn tell(&self) -> Option { - self.state.current.get() - } - - fn len(&self) -> usize { - self.rope.len() + fn state(&self) -> &CursorState<'a> { + &self.state } fn read_next(&self) -> Result { let next_pos = match self.state.current.get() { - None => self.rope.len().checked_sub(1).ok_or(RopeError::OutOfBounds( - "BackwardCursor: rope is empty".to_string(), - ))?, - Some(0) => return Err(RopeError::OutOfBounds( - "BackwardCursor: already at beginning".to_string(), - )), + None => self + .rope + .len() + .checked_sub(1) + .ok_or(RopeError::OutOfBounds( + "BackwardCursor: rope is empty".to_string(), + ))?, + Some(0) => { + return Err(RopeError::OutOfBounds( + "BackwardCursor: already at beginning".to_string(), + )); + } Some(i) => i - 1, }; - let value = self.state + let value = self + .state .get(self.rope, next_pos) .ok_or(RopeError::OutOfBounds(format!( "BackwardCursor: index out of bounds at i={}", @@ -274,21 +289,21 @@ impl<'a> RopeCursor for BackwardCursor<'a> { fn seek(&self, pos: isize, mode: SeekMode) -> Result { let pos = match mode { - SeekMode::Absolute => pos, - SeekMode::Relative => self.state.current.get().ok_or(RopeError::CurrentNotSet)? as isize - pos, + SeekMode::Absolute => pos, + SeekMode::Relative => { + self.state.current.get().ok_or(RopeError::CurrentNotSet)? as isize - pos + } SeekMode::RelativeToEnd => self.rope.len() as isize - pos, }; if pos < 0 { - return Err(RopeError::OutOfBounds(format!("index out of bounds: i={} < 0", pos))); + return Err(RopeError::OutOfBounds(format!( + "index out of bounds: i={} < 0", + pos + ))); } self.state.current.set(Some(pos as usize)); Ok(pos as usize) } - - fn rewind(&self, go_back_of: usize) -> Result<(), RopeError> { - self.seek(-(go_back_of as isize), SeekMode::Relative)?; - Ok(()) - } } impl Iterator for BackwardCursor<'_> {