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}