cursorvec/
cursor.rs

1use crate::result;
2use crate::OpResult;
3
4/// Cursor that points value
5#[derive(Debug, PartialEq)]
6pub(crate) struct Cursor {
7    capacity: usize,
8    rotation: bool,
9    index: usize,
10}
11
12impl Cursor {
13    pub fn new(capacity: usize) -> Self {
14        Self {
15            capacity,
16            rotation: false,
17            index: 0,
18        }
19    }
20
21    pub fn set_rotation(&mut self, rotation: bool) {
22        self.rotation = rotation;
23    }
24
25    pub fn get_value(&self) -> usize {
26        self.index
27    }
28
29    pub fn set_value(&mut self, value: usize) -> OpResult {
30        if value > self.capacity {
31            result::error("Cursor out of range")
32        } else {
33            self.index = value;
34            result::ok()
35        }
36    }
37
38    pub fn set_capacity(&mut self, capacity: usize) {
39        self.capacity = capacity;
40        if self.index >= self.capacity {
41            self.index = self.capacity - 1;
42        }
43    }
44
45    pub fn increase(&mut self) -> OpResult {
46        if self.capacity == 0 {
47            return result::error("Empty container");
48        };
49        if self.index == self.capacity - 1 {
50            if self.rotation {
51                self.index = 0;
52                result::ok()
53            } else {
54                result::error("Cursor out of range")
55            }
56        } else {
57            self.index += 1;
58            result::ok()
59        }
60    }
61
62    pub fn decrease(&mut self) -> OpResult {
63        if self.capacity == 0 {
64            return result::error("Empty container");
65        };
66        if self.index == 0 {
67            if self.rotation {
68                self.index = self.capacity - 1;
69                result::ok()
70            } else {
71                result::error("Cursor out of range")
72            }
73        } else {
74            self.index -= 1;
75            result::ok()
76        }
77    }
78}
79
80/// State of a cursor
81///
82/// You can convert cursor state into an option with "value" method
83#[derive(Debug, PartialEq)]
84pub enum CursorState<'container, T> {
85    /// Cursor cannot move previous because it reached minimal index (0)
86    MinOut,
87    /// Cursor cannot point anything because container is empty or cursor's information was not
88    /// updated
89    EmptyContainer,
90    /// Cursor is in valid position. Valid cursor state refers a container value
91    Valid(&'container T),
92    /// Cursor is not in container's range. This is caused by container's manual modification
93    /// without update
94    OutOfRange,
95    /// Cursor cannot move next because it reached maximal index (container.len() - 1)
96    MaxOut,
97}
98
99impl<'container, T> CursorState<'container, T> {
100    /// Try get value from cursor state
101    ///
102    /// This will return none if cursor is in invalid state.
103    ///
104    /// ```rust
105    /// use cursorvec::{CursorVec, CursorState};
106    ///
107    /// let mut vec = CursorVec::new().with_container(vec![1,2,3]);
108    /// vec.set_cursor(2);
109    ///
110    /// // Valid state is evalued as Some(..)
111    /// assert_eq!(CursorState::Valid(&3), vec.get_current());
112    /// assert_eq!(Some(&3), vec.get_current().value());
113    ///
114    /// // Invalid state is evalued as None
115    /// assert_eq!(CursorState::MaxOut, vec.move_next_and_get());
116    /// assert_eq!(None, vec.move_next_and_get().value());
117    /// ```
118    pub fn value(&self) -> Option<&T> {
119        if let Self::Valid(val) = self {
120            Some(*val)
121        } else {
122            None
123        }
124    }
125}