use super::LinkedList;
use super::selection::SelectionMut;
pub struct CursorMut<'a, T> {
list: &'a mut LinkedList<T>,
index: usize,
}
impl<'a, T> CursorMut<'a, T> {
pub(super) fn new(list: &'a mut LinkedList<T>, index: usize) -> Self {
Self { list, index }
}
pub fn into_selection(self) -> SelectionMut<'a, T> {
SelectionMut::new(self.list, self.index, self.index)
}
pub fn move_prev(&mut self) -> bool {
if self.index == 0 {
return false;
}
self.index -= 1;
true
}
pub fn move_next(&mut self) -> bool {
if self.index == self.list.items.len() {
return false;
}
self.index += 1;
true
}
pub fn peek_before(&self) -> Option<&T> {
let i = self.index.checked_sub(1)?;
self.list.items.get(i)
}
pub fn peek_after(&self) -> Option<&T> {
self.list.items.get(self.index)
}
pub fn peek_before_mut(&mut self) -> Option<&mut T> {
let i = self.index.checked_sub(1)?;
self.list.items.get_mut(i)
}
pub fn peek_after_mut(&mut self) -> Option<&mut T> {
self.list.items.get_mut(self.index)
}
pub fn insert_before(&mut self, value: T) {
self.list.items.insert(self.index, value);
self.index += 1;
}
pub fn insert_after(&mut self, value: T) {
self.list.items.insert(self.index, value);
}
pub fn remove_before(&mut self) -> Option<T> {
if self.index == 0 {
return None;
}
self.index -= 1;
Some(self.list.items.remove(self.index))
}
pub fn remove_after(&mut self) -> Option<T> {
if self.index == self.list.items.len() {
return None;
}
Some(self.list.items.remove(self.index))
}
pub fn splice_before(&mut self, other: LinkedList<T>) {
let len = other.items.len();
self.list.items.splice(self.index..self.index, other.items);
self.index += len;
}
pub fn splice_after(&mut self, other: LinkedList<T>) {
self.list.items.splice(self.index..self.index, other.items);
}
pub fn split_before(&mut self) -> LinkedList<T> {
let after = self.list.items.split_off(self.index);
let before = std::mem::replace(&mut self.list.items, after);
self.index = 0;
LinkedList { items: before }
}
pub fn split_after(&mut self) -> LinkedList<T> {
LinkedList {
items: self.list.items.split_off(self.index),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::list::tests::list_of;
#[test]
fn insert_before_into_empty() {
let mut list = LinkedList::new();
list.cursor_mut_at_start().insert_before(1);
assert_eq!(list.items, [1]);
}
#[test]
fn insert_before_twice_keeps_order() {
let mut list = LinkedList::new();
let mut cursor = list.cursor_mut_at_start();
cursor.insert_before(1);
cursor.insert_before(2);
assert_eq!(list.items, [1, 2]);
}
#[test]
fn insert_after_twice_keeps_order() {
let mut list = LinkedList::new();
let mut cursor = list.cursor_mut_at_start();
cursor.insert_after(2);
cursor.insert_after(1);
assert_eq!(cursor.peek_before(), None);
assert_eq!(cursor.peek_after(), Some(&1));
assert_eq!(list.items, [1, 2]);
}
#[test]
fn peek_around_cursor() {
let mut list = LinkedList::new();
list.cursor_mut_at_start().insert_before(1);
let mut cursor = list.cursor_mut_at_start();
assert_eq!(cursor.peek_before(), None);
assert_eq!(cursor.peek_after(), Some(&1));
cursor.insert_before(0);
assert_eq!(cursor.peek_before(), Some(&0));
assert_eq!(cursor.peek_after(), Some(&1));
}
#[test]
fn peek_mut_modifies_values() {
let mut list = LinkedList::new();
list.cursor_mut_at_start().insert_before(1);
let mut cursor = list.cursor_mut_at_start();
cursor.insert_before(0);
*cursor.peek_before_mut().unwrap() += 10;
*cursor.peek_after_mut().unwrap() += 20;
assert_eq!(list.items, [10, 21]);
}
#[test]
fn split_before_takes_elements_before_cursor() {
let mut list = LinkedList::new();
list.cursor_mut_at_start().insert_before(2);
let mut cursor = list.cursor_mut_at_start();
cursor.insert_before(0);
cursor.insert_before(1);
let before = cursor.split_before();
assert_eq!(cursor.peek_before(), None);
assert_eq!(cursor.peek_after(), Some(&2));
assert_eq!(before.items, [0, 1]);
assert_eq!(list.items, [2]);
}
#[test]
fn split_after_takes_elements_after_cursor() {
let mut list = LinkedList::new();
list.cursor_mut_at_start().insert_before(2);
let mut cursor = list.cursor_mut_at_start();
cursor.insert_before(0);
cursor.insert_before(1);
let after = cursor.split_after();
assert_eq!(cursor.peek_before(), Some(&1));
assert_eq!(cursor.peek_after(), None);
assert_eq!(after.items, [2]);
assert_eq!(list.items, [0, 1]);
}
#[test]
fn cursor_at_end_peeks_last() {
let mut list = list_of(&[0, 1]);
let cursor = list.cursor_mut_at_end();
assert_eq!(cursor.peek_before(), Some(&1));
assert_eq!(cursor.peek_after(), None);
}
#[test]
fn move_stops_at_ends() {
let mut list = list_of(&[0, 1]);
let mut cursor = list.cursor_mut_at_start();
assert!(!cursor.move_prev());
assert!(cursor.move_next());
assert_eq!(cursor.peek_before(), Some(&0));
assert_eq!(cursor.peek_after(), Some(&1));
assert!(cursor.move_next());
assert!(!cursor.move_next());
assert_eq!(cursor.peek_before(), Some(&1));
assert!(cursor.move_prev());
assert_eq!(cursor.peek_after(), Some(&1));
}
#[test]
fn remove_on_each_side() {
let mut list = list_of(&[0, 1, 2]);
let mut cursor = list.cursor_mut_at_start();
cursor.move_next();
assert_eq!(cursor.remove_before(), Some(0));
assert_eq!(cursor.remove_before(), None);
assert_eq!(cursor.remove_after(), Some(1));
assert_eq!(cursor.peek_after(), Some(&2));
assert_eq!(cursor.remove_after(), Some(2));
assert_eq!(cursor.remove_after(), None);
assert!(list.is_empty());
}
#[test]
fn splice_before_puts_cursor_after_spliced() {
let mut list = list_of(&[0, 3]);
let mut cursor = list.cursor_mut_at_start();
cursor.move_next();
cursor.splice_before(list_of(&[1, 2]));
assert_eq!(cursor.peek_before(), Some(&2));
assert_eq!(cursor.peek_after(), Some(&3));
assert_eq!(list.items, [0, 1, 2, 3]);
}
#[test]
fn splice_after_keeps_cursor_before_spliced() {
let mut list = list_of(&[0, 3]);
let mut cursor = list.cursor_mut_at_start();
cursor.move_next();
cursor.splice_after(list_of(&[1, 2]));
assert_eq!(cursor.peek_before(), Some(&0));
assert_eq!(cursor.peek_after(), Some(&1));
assert_eq!(list.items, [0, 1, 2, 3]);
}
}