1use crate::bal::BalIndex;
4use std::vec::Vec;
5
6#[derive(Debug, Default, Clone, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct BalWrites<T: PartialEq + Clone> {
12 pub writes: Vec<(BalIndex, T)>,
14}
15
16impl<T: PartialEq + Clone> BalWrites<T> {
17 pub fn new(mut writes: Vec<(BalIndex, T)>) -> Self {
19 writes.sort_by_key(|(index, _)| *index);
20 Self { writes }
21 }
22
23 #[inline(never)]
25 pub fn get_linear_search(&self, bal_index: BalIndex) -> Option<T> {
26 let mut last_item = None;
27 for (index, item) in self.writes.iter() {
28 if index >= &bal_index {
30 return last_item;
31 }
32 last_item = Some(item.clone());
33 }
34 last_item
35 }
36
37 pub fn get(&self, bal_index: BalIndex) -> Option<T> {
39 if self.writes.len() < 5 {
40 return self.get_linear_search(bal_index);
41 }
42 let i = match self
44 .writes
45 .binary_search_by_key(&bal_index, |(index, _)| *index)
46 {
47 Ok(i) => i,
48 Err(i) => i,
49 };
50 (i != 0).then(|| self.writes[i - 1].1.clone())
52 }
53
54 pub fn extend(&mut self, other: BalWrites<T>) {
56 self.writes.extend(other.writes);
57 }
58
59 pub fn is_empty(&self) -> bool {
61 self.writes.is_empty()
62 }
63
64 #[inline]
72 pub fn force_update(&mut self, index: BalIndex, value: T) {
73 if let Some(last) = self.writes.last_mut() {
74 if index == last.0 {
75 last.1 = value;
76 return;
77 }
78 }
79 self.writes.push((index, value));
80 }
81
82 pub fn update(&mut self, index: BalIndex, original_value: &T, value: T) {
86 self.update_with_key(index, original_value, value, |i| i);
87 }
88
89 #[inline]
95 pub fn update_with_key<K: PartialEq, F>(
96 &mut self,
97 index: BalIndex,
98 original_subvalue: &K,
99 value: T,
100 f: F,
101 ) where
102 F: Fn(&T) -> &K,
103 {
104 if let Some(last) = self.writes.last_mut() {
106 if last.0 != index {
107 if f(&last.1) != f(&value) {
109 self.writes.push((index, value));
110 }
111 return;
112 }
113 }
114
115 let (previous, last) = match self.writes.as_mut_slice() {
117 [.., previous, last] => (f(&previous.1), last),
118 [last] => (original_subvalue, last),
119 [] => {
120 if original_subvalue != f(&value) {
122 self.writes.push((index, value));
123 }
124 return;
125 }
126 };
127
128 if previous == f(&value) {
130 self.writes.pop();
131 return;
132 }
133
134 last.1 = value;
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn test_get() {
145 let bal_writes = BalWrites::new(vec![(0, 1), (1, 2), (2, 3)]);
146 assert_eq!(bal_writes.get(0), None);
147 assert_eq!(bal_writes.get(1), Some(1));
148 assert_eq!(bal_writes.get(2), Some(2));
149 assert_eq!(bal_writes.get(3), Some(3));
150 assert_eq!(bal_writes.get(4), Some(3));
151 }
152
153 fn get_binary_search(threshold: BalIndex) {
154 let entries: Vec<_> = (0..threshold - 1)
156 .map(|i| (i, i + 1))
157 .chain(std::iter::once((threshold, threshold + 1)))
158 .collect();
159
160 let bal_writes = BalWrites::new(entries);
161
162 assert_eq!(bal_writes.get(0), None);
164
165 for i in 1..threshold - 1 {
167 assert_eq!(bal_writes.get(i), Some(i));
168 }
169
170 assert_eq!(bal_writes.get(threshold), Some(threshold - 1));
172
173 assert_eq!(bal_writes.get(threshold + 1), Some(threshold + 1));
175 }
176
177 #[test]
178 fn test_get_binary_search() {
179 get_binary_search(4);
180 get_binary_search(5);
181 get_binary_search(6);
182 get_binary_search(7);
183 }
184}