circular_resources/
lib.rs1use std::collections::HashMap;
6
7#[derive(Clone, Copy, PartialEq, Eq, Hash)]
8pub struct PositionID(u64);
9
10impl PositionID {
11 pub const ZERO: PositionID = PositionID(0);
12}
13
14pub struct Circular<T> {
15 vec: Vec<T>,
16 positions: HashMap<PositionID, Option<usize>>,
17 next_pos_id: PositionID,
18}
19
20impl<T> Circular<T> {
24 pub fn new() -> Self {
25 Self {
26 vec: Vec::new(),
27 positions: HashMap::new(),
28 next_pos_id: PositionID(0),
29 }
30 }
31 fn my_assert(&self) {
32 for p in self.positions.values() {
33 debug_assert!(p.is_none() || p.unwrap() < self.len())
34 }
35 }
36 pub fn vec(&self) -> &Vec<T> {
37 &self.vec
38 }
39 pub fn push(&mut self, value: T) {
40 self.vec.push(value)
41 }
42 pub fn append(&mut self, other: &mut Vec<T>) {
43 self.vec.append(other);
44 self.my_assert();
45 }
46 pub fn remove_unsafe(&mut self, index: usize) -> T {
47 assert!(index < self.len());
48 self.my_assert();
49 let result = self.vec.remove(index);
50 let new_len = self.len();
51 let empty = self.is_empty();
52 for position in self.positions.values_mut() {
53 if empty {
54 *position = None;
55 } else if let Some(ref mut pos) = *position {
56 if *pos > index {
57 *pos -= 1;
58 } else if *pos == new_len {
59 *pos = 0;
60 }
61 }
62 }
63 self.my_assert();
64 result
65 }
66 pub fn remove_by_pos_id(&mut self, pos_id: PositionID) -> Option<T> {
67 if let Some(pos) = self.positions[&pos_id] {
68 self.my_assert();
69 Some(self.remove_unsafe(pos))
70 } else {
71 self.my_assert();
72 None
73 }
74 }
75
76 pub fn is_empty(&self) -> bool {
77 self.vec.is_empty()
78 }
79 pub fn len(&self) -> usize {
80 self.vec.len()
81 }
82
83 pub fn positions_is_empty(&self) -> bool {
84 self.positions.is_empty()
85 }
86 pub fn positions_len(&self) -> usize {
87 self.positions.len()
88 }
89
90 pub fn iter(&self) -> std::slice::Iter<T> {
91 self.vec.iter()
92 }
93 pub fn iter_mut(&mut self) -> std::slice::IterMut<T> {
94 self.vec.iter_mut()
95 }
96 pub fn create_position(&mut self) -> PositionID {
97 let result = self.next_pos_id;
98 self.positions.insert(self.next_pos_id, None);
99 self.next_pos_id.0 += 1;
100 self.my_assert();
101 result
102 }
103 pub fn destroy_position(&mut self, pos_id: PositionID) {
104 self.positions.remove(&pos_id);
105 self.my_assert();
106 }
107 pub fn get_position(&self, pos_id: PositionID) -> &Option<usize> {
108 &self.positions[&pos_id]
109 }
110 pub fn set_position_unsafe(&mut self, pos_id: PositionID, index: Option<usize>) {
111 self.positions.insert(pos_id, index);
112 self.my_assert();
113 }
114 pub fn get_by_pos_id(&self, pos_id: PositionID) -> Option<&T> {
115 self.positions[&pos_id].map(|pos| &self.vec[pos])
116 }
117 pub fn get_by_pos_id_mut(&mut self, pos_id: PositionID) -> Option<&mut T> {
118 self.positions[&pos_id].map(|pos| &mut self.vec[pos])
119 }
120 pub fn force_get_by_pos_id_mut(&mut self, pos_id: PositionID) -> Option<&mut T> {
122 if let Some(pos) = self.positions[&pos_id] {
123 self.my_assert();
124 Some(&mut self.vec[pos])
125 } else {
126 self.init_position(pos_id)
127 }
128 }
129 pub fn clear(&mut self) {
130 self.vec.clear();
131 for p in self.positions.values_mut() {
132 *p = None;
133 }
134 self.my_assert();
135 }
136
137 pub fn next(&mut self, pos_id: PositionID) -> Option<&T> {
138 let pos = self.positions[&pos_id];
139 if let Some(pos) = pos {
140 self.positions.insert(pos_id, Some(if pos + 1 == self.vec.len() {
141 0
142 } else {
143 pos + 1
144 }));
145 debug_assert!(pos < self.vec.len());
146 Some(&self.vec[pos.clone()])
147 } else {
148 self.init_position(pos_id).map(|r| &*r)
149 }
150 }
151 fn init_position(&mut self, pos_id: PositionID) -> Option<&mut T> {
152 if self.vec.is_empty() {
153 self.positions.insert(pos_id, None);
154 self.my_assert();
155 None
156 } else {
157 self.positions.insert(pos_id, Some(0));
158 self.my_assert();
159 Some(&mut self.vec[0])
160 }
161 }
162}
163
164#[cfg(test)]
166mod tests {
167 use crate::{Circular};
168
169 #[test]
170 fn one_position_middle() {
171 let mut v = Circular::new();
172 let mut input = (0..10).collect::<Vec<i32>>();
173 v.append(&mut input);
174 v.set_position_unsafe(Some(5));
175 v.remove_current();
176 assert_eq!(v.iter().map(|n| *n).collect::<Vec<i32>>(), vec![0, 1, 2, 3, 4, 6, 7, 8, 9]);
177 assert_eq!(v.get_position(), Some(5));
178 }
179}