use std::{fmt::Debug,
ops::{Deref, DerefMut}};
use crate::{Index, Length, idx};
#[derive(Clone, Copy, PartialEq, Debug, Default)]
pub struct CurIndex(pub Option<Index>);
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum CurIndexLoc {
EmptyHistory,
Start,
End(Index),
Middle(Index),
}
impl CurIndexLoc {
#[must_use]
pub fn locate(cur_index: &CurIndex, versions_len: Length) -> CurIndexLoc {
if versions_len.as_usize() == 0 {
return CurIndexLoc::EmptyHistory;
}
match cur_index.0 {
None => {
CurIndexLoc::Start
}
Some(inner) => {
if inner == versions_len.convert_to_index() {
CurIndexLoc::End(inner)
} else {
CurIndexLoc::Middle(inner)
}
}
}
}
pub fn inc(cur_index: &mut CurIndex, versions_len: Length) {
match Self::locate(cur_index, versions_len) {
Self::EmptyHistory | Self::End(_) => {
}
Self::Start => {
cur_index.0 = Some(idx(0));
}
Self::Middle(_) => {
if let Some(index) = cur_index.0 {
cur_index.0 = Some(index + idx(1));
}
}
}
}
pub fn dec(cur_index: &mut CurIndex, versions_len: Length) {
match Self::locate(cur_index, versions_len) {
Self::EmptyHistory => {
}
Self::Start => {
cur_index.0 = None;
}
Self::End(_) | Self::Middle(_) => {
if let Some(index) = cur_index.0 {
if index > idx(0) {
cur_index.0 = Some(index - idx(1));
} else {
cur_index.0 = None;
}
}
}
}
}
}
impl CurIndex {
#[must_use]
pub fn as_index(self) -> Index { self.0.unwrap_or(idx(0)) }
pub fn clear(&mut self) { self.0 = None; }
}
mod ops {
use super::{CurIndex, Deref, DerefMut, Index};
impl Deref for CurIndex {
type Target = Option<Index>;
fn deref(&self) -> &Self::Target { &self.0 }
}
impl DerefMut for CurIndex {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
}
mod convert {
use super::{CurIndex, Index};
impl From<usize> for CurIndex {
fn from(val: usize) -> Self { CurIndex(Some(Index(val.into()))) }
}
impl From<isize> for CurIndex {
fn from(val: isize) -> Self { CurIndex(Some(Index(val.into()))) }
}
impl From<i32> for CurIndex {
fn from(val: i32) -> Self { CurIndex(Some(Index(val.into()))) }
}
impl From<i16> for CurIndex {
fn from(val: i16) -> Self { CurIndex(Some(Index(val.into()))) }
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{EditorContent, len};
#[test]
fn test_cur_index_locate_empty() {
let versions = Vec::<EditorContent>::new();
let cur_index = CurIndex::default();
assert_eq!(
CurIndexLoc::locate(&cur_index, len(versions.len())),
CurIndexLoc::EmptyHistory
);
}
#[test]
fn test_cur_index_locate_start() {
let versions = vec![EditorContent::default()];
let cur_index = CurIndex::default();
assert_eq!(
CurIndexLoc::locate(&cur_index, len(versions.len())),
CurIndexLoc::Start
);
}
#[test]
fn test_cur_index_locate_end() {
let versions = vec![EditorContent::default()];
let cur_index = CurIndex::from(0);
assert_eq!(
CurIndexLoc::locate(&cur_index, len(versions.len())),
CurIndexLoc::End(cur_index.as_index())
);
}
#[test]
fn test_cur_index_locate_middle() {
let versions = vec![EditorContent::default(), EditorContent::default()];
let cur_index = CurIndex::from(0);
assert_eq!(
CurIndexLoc::locate(&cur_index, len(versions.len())),
CurIndexLoc::Middle(cur_index.as_index())
);
}
}