1use std::{
2 fmt::{Debug, Display},
3 iter,
4 marker::PhantomData,
5 mem,
6};
7
8use num_traits::{CheckedAdd, One, Zero};
9
10pub trait EpochResetArrayIndex: TryFrom<usize> + TryInto<usize> + Display + Copy {}
11
12impl<T: TryFrom<usize> + TryInto<usize> + Display + Copy> EpochResetArrayIndex for T {}
13
14pub trait EpochResetArrayValue: Clone {}
15
16impl<T: Clone> EpochResetArrayValue for T {}
17
18pub trait EpochResetArrayCounter: Zero + One + CheckedAdd + Eq + Copy + Debug {}
19
20impl<T: Zero + One + CheckedAdd + Eq + Copy + Debug> EpochResetArrayCounter for T {}
21
22#[derive(Clone)]
23pub struct EpochResetArray<Index, Value, EpochCounter> {
24 array: Vec<EpochValue<Value, EpochCounter>>,
25 reset_value: Value,
26 epoch_counter: EpochCounter,
27 phantom_data: PhantomData<Index>,
28}
29
30#[derive(Clone)]
31struct EpochValue<Value, EpochCounter> {
32 value: Value,
33 epoch_counter: EpochCounter,
34}
35
36impl<Index: EpochResetArrayIndex, Value: EpochResetArrayValue, EpochCounter: EpochResetArrayCounter>
37 EpochResetArray<Index, Value, EpochCounter>
38{
39 pub fn new(reset_value: Value, len: Index) -> Self {
40 Self {
41 array: Vec::from_iter(
42 iter::repeat_with(|| EpochValue::new(reset_value.clone(), EpochCounter::zero()))
43 .take(index_to_usize(len)),
44 ),
45 reset_value,
46 epoch_counter: EpochCounter::zero(),
47 phantom_data: PhantomData,
48 }
49 }
50
51 pub fn len_usize(&self) -> usize {
52 self.array.len()
53 }
54
55 pub fn len_index(&self) -> Index {
56 usize_to_index(self.array.len())
57 }
58
59 pub fn is_empty(&self) -> bool {
60 self.array.is_empty()
61 }
62
63 pub fn get(&self, index: Index) -> &Value {
64 let epoch_value = &self.array[index_to_usize(index)];
65 if epoch_value.epoch_counter == self.epoch_counter {
66 &epoch_value.value
67 } else {
68 &self.reset_value
69 }
70 }
71
72 pub fn get_mut(&mut self, index: Index) -> &mut Value {
73 let epoch_value = &mut self.array[index_to_usize(index)];
74 if epoch_value.epoch_counter != self.epoch_counter {
75 *epoch_value = EpochValue::new(self.reset_value.clone(), self.epoch_counter);
76 }
77 &mut epoch_value.value
78 }
79
80 pub fn set(&mut self, index: Index, value: Value) -> Option<Value> {
81 let epoch_value = &mut self.array[index_to_usize(index)];
82 if epoch_value.epoch_counter == self.epoch_counter {
83 Some(mem::replace(&mut epoch_value.value, value))
84 } else {
85 *epoch_value = EpochValue::new(value, self.epoch_counter);
86 None
87 }
88 }
89
90 pub fn reset(&mut self) {
91 self.epoch_counter = self
92 .epoch_counter
93 .checked_add(&EpochCounter::one())
94 .unwrap_or_else(|| {
95 self.array.iter_mut().for_each(|epoch_value| {
97 *epoch_value = EpochValue::new(self.reset_value.clone(), EpochCounter::zero());
98 });
99
100 EpochCounter::zero()
101 });
102 }
103}
104
105impl<Value, EpochCounter> EpochValue<Value, EpochCounter> {
106 fn new(value: Value, epoch_counter: EpochCounter) -> Self {
107 Self {
108 value,
109 epoch_counter,
110 }
111 }
112}
113
114fn index_to_usize<Index: EpochResetArrayIndex>(index: Index) -> usize {
115 index
116 .try_into()
117 .unwrap_or_else(|_| panic!("Index {index} cannot be converted to usize"))
118}
119
120fn usize_to_index<Index: EpochResetArrayIndex>(index: usize) -> Index {
121 index
122 .try_into()
123 .unwrap_or_else(|_| panic!("Usize {index} cannot be converted to index type"))
124}