Skip to content

Instantly share code, notes, and snippets.

@alxarch
Created April 6, 2020 10:56
Show Gist options
  • Save alxarch/4370df25af2c312339a59226bd16b6bb to your computer and use it in GitHub Desktop.
Save alxarch/4370df25af2c312339a59226bd16b6bb to your computer and use it in GitHub Desktop.
Effing cursor
pub mod cursor {
use std::ops::Deref;
pub struct Cursor<S> {
src: S,
cursor: Index,
}
enum Index {
Asc(usize),
Desc(usize),
None,
}
impl<S> Cursor<S> {
pub fn new(src: S) -> Self {
Self {
src,
cursor: Index::None,
}
}
}
impl<S, T> Cursor<S>
where
S: Deref<Target=[T]>,
{
pub fn get(&self) -> Option<&T> {
match self.cursor {
Index::Asc(i) => {
let i = if i > 0 {
i - 1
} else {
self.src.len().wrapping_sub(1)
};
self.src.get(i)
}
Index::Desc(i) => self.src.get(i),
Index::None => self.src.first(),
}
}
pub fn next(&mut self) -> Option<&T> {
match self.cursor {
Index::Asc(i) => {
if i < self.src.len() {
self.cursor = Index::Asc(i + 1);
self.src.get(i)
} else {
self.cursor = Index::Asc(1);
self.src.first()
}
}
Index::Desc(i) => {
if i < self.src.len() {
self.cursor = Index::Asc(i + 1);
} else {
self.cursor = Index::Asc(self.src.len())
}
self.next()
}
Index::None => {
self.cursor = Index::Asc(0);
self.next()
}
}
}
pub fn prev(&mut self) -> Option<&T> {
match self.cursor {
Index::Desc(i) => {
let i = if i > 0 {
i - 1
} else {
self.src.len().wrapping_sub(1)
};
self.cursor = Index::Desc(i);
self.src.get(i)
}
Index::Asc(i) => {
if 0 < i {
self.cursor = Index::Desc(i - 1);
} else {
self.cursor = Index::Desc(self.src.len())
}
self.prev()
}
Index::None => {
self.cursor = Index::Desc(0);
self.prev()
}
}
}
}
#[test]
fn test_cursor() {
let mut c = Cursor::new(vec![1, 2, 3, 4]);
assert_eq!(c.prev(), Some(&4));
assert_eq!(c.prev(), Some(&3));
assert_eq!(c.prev(), Some(&2));
assert_eq!(c.prev(), Some(&1));
assert_eq!(c.prev(), Some(&4));
assert_eq!(c.prev(), Some(&3));
assert_eq!(c.prev(), Some(&2));
assert_eq!(c.prev(), Some(&1));
let mut c = Cursor::new(vec![1, 2, 3, 4]);
assert_eq!(c.next(), Some(&1));
assert_eq!(c.next(), Some(&2));
assert_eq!(c.next(), Some(&3));
assert_eq!(c.next(), Some(&4));
assert_eq!(c.next(), Some(&1));
assert_eq!(c.next(), Some(&2));
assert_eq!(c.next(), Some(&3));
assert_eq!(c.next(), Some(&4));
assert_eq!(c.prev(), Some(&3));
assert_eq!(c.next(), Some(&4));
assert_eq!(c.next(), Some(&1));
assert_eq!(c.prev(), Some(&4));
let values = vec![1, 2, 3, 4];
let mut c = Cursor::new(values.as_slice());
assert_eq!(c.next(), Some(&1));
assert_eq!(c.next(), Some(&2));
assert_eq!(c.next(), Some(&3));
assert_eq!(c.next(), Some(&4));
assert_eq!(c.next(), Some(&1));
assert_eq!(c.next(), Some(&2));
assert_eq!(c.next(), Some(&3));
assert_eq!(c.next(), Some(&4));
assert_eq!(c.prev(), Some(&3));
assert_eq!(c.next(), Some(&4));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment