betfair_stream_api/cache/primitives/
available_cache.rs1use alloc::collections::BTreeMap;
4
5use betfair_adapter::betfair_types::price::Price;
6use betfair_adapter::betfair_types::size::Size;
7use betfair_stream_types::response::{Position, UpdateSet2, UpdateSet3};
8use serde::de::DeserializeOwned;
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, PartialEq, PartialOrd, Clone, Serialize, Deserialize, Eq, Hash, Ord)]
13pub struct Available<T: UpdateSet> {
14 pub book: BTreeMap<T::Key, T::Value>,
15}
16
17impl<T: UpdateSet> Available<T> {
18 pub fn new<A: AsRef<[T]>>(prices: A) -> Self {
19 let mut instance = Self {
20 book: BTreeMap::new(),
21 };
22
23 instance.update(prices);
24 instance
25 }
26
27 pub fn update<A: AsRef<[T]>>(&mut self, book_update: A) {
28 for prices in book_update.as_ref() {
29 let key = prices.key(); let value = prices.value(); if prices.should_be_deleted() {
34 self.book.remove(&key);
35 } else {
36 self.book.insert(key, value);
37 }
38 }
39 }
40
41 pub fn clear(&mut self) {
42 self.book.clear();
43 }
44}
45
46pub trait UpdateSet {
49 type Key: core::hash::Hash + PartialEq + Eq + Ord + Serialize + DeserializeOwned;
50 type Value: PartialEq + Serialize + DeserializeOwned;
51 fn value(&self) -> Self::Value;
52 fn key(&self) -> Self::Key;
53 fn should_be_deleted(&self) -> bool;
54}
55
56impl UpdateSet for UpdateSet2 {
57 type Key = Price;
58 type Value = Size;
59
60 fn value(&self) -> Self::Value {
61 self.1
62 }
63
64 fn key(&self) -> Self::Key {
65 self.0
66 }
67
68 fn should_be_deleted(&self) -> bool {
69 self.1 == Size::zero()
70 }
71}
72
73impl UpdateSet for UpdateSet3 {
74 type Key = Position;
75 type Value = (Price, Size);
76
77 fn value(&self) -> Self::Value {
78 (self.1, self.2)
79 }
80
81 fn key(&self) -> Self::Key {
82 self.0
83 }
84
85 fn should_be_deleted(&self) -> bool {
86 self.2 == Size::zero()
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use betfair_adapter::betfair_types::{num, num_u8};
93 use pretty_assertions::assert_eq;
94
95 use super::*;
96
97 fn setup_set3() -> Available<UpdateSet3> {
98 let prices = &[
99 UpdateSet3(
100 Position(num_u8!(1)),
101 Price::new(num!(1.02)).unwrap(),
102 Size::new(num!(34.45)),
103 ),
104 UpdateSet3(
105 Position(num_u8!(0)),
106 Price::new(num!(1.01)).unwrap(),
107 Size::new(num!(12)),
108 ),
109 ];
110 Available::new(prices)
111 }
112
113 #[test]
114 fn test_init() {
115 let init = setup_set3();
116
117 let mut expected = BTreeMap::new();
118 expected.insert(
119 Position(num_u8!(0)),
120 (Price::new(num!(1.01)).unwrap(), Size::new(num!(12))),
121 );
122 expected.insert(
123 Position(num_u8!(1)),
124 (Price::new(num!(1.02)).unwrap(), Size::new(num!(34.45))),
125 );
126
127 assert_eq!(init.book, expected);
128 }
129
130 #[test]
131 fn test_init_2() {
132 let prices = &[
133 UpdateSet2(Price::new(num!(27)).unwrap(), Size::new(num!(0.95))),
134 UpdateSet2(Price::new(num!(13)).unwrap(), Size::new(num!(28.01))),
135 UpdateSet2(Price::new(num!(1.02)).unwrap(), Size::new(num!(1157.21))),
136 ];
137 let init = Available::new(prices);
138
139 let mut expected = BTreeMap::new();
140 expected.insert(Price::new(num!(1.02)).unwrap(), Size::new(num!(1157.21)));
141 expected.insert(Price::new(num!(13)).unwrap(), Size::new(num!(28.01)));
142 expected.insert(Price::new(num!(27)).unwrap(), Size::new(num!(0.95)));
143
144 assert_eq!(init.book, expected);
145 }
146
147 #[test]
148 fn test_clear() {
149 let mut init = setup_set3();
150 init.clear();
151
152 assert_eq!(init.book, BTreeMap::new());
153 }
154
155 #[test]
156 fn test_update_set_2() {
157 let init = Available::new([
158 UpdateSet2(Price::new(num!(27)).unwrap(), Size::new(num!(0.95))),
159 UpdateSet2(Price::new(num!(13)).unwrap(), Size::new(num!(28.01))),
160 UpdateSet2(Price::new(num!(1.02)).unwrap(), Size::new(num!(1157.21))),
161 ]);
162 let update = &[UpdateSet2(
163 Price::new(num!(27)).unwrap(),
164 Size::new(num!(2)),
165 )];
166 let mut expected = BTreeMap::new();
167 expected.insert(Price::new(num!(1.02)).unwrap(), Size::new(num!(1157.21)));
168 expected.insert(Price::new(num!(13)).unwrap(), Size::new(num!(28.01)));
169 expected.insert(Price::new(num!(27)).unwrap(), Size::new(num!(2)));
170
171 let mut actual = init;
172 actual.update(update);
173
174 assert_eq!(actual.book, expected);
175 }
176
177 #[test]
178 fn test_update_set_3() {
179 let init = Available::new([
180 UpdateSet3(
181 Position(num_u8!(1)),
182 Price::new(num!(1.02)).unwrap(),
183 Size::new(num!(34.45)),
184 ),
185 UpdateSet3(
186 Position(num_u8!(0)),
187 Price::new(num!(1.01)).unwrap(),
188 Size::new(num!(12)),
189 ),
190 ]);
191 let update = &[UpdateSet3(
192 Position(num_u8!(1)),
193 Price::new(num!(1.02)).unwrap(),
194 Size::new(num!(22)),
195 )];
196 let mut expected = BTreeMap::new();
197 expected.insert(
198 Position(num_u8!(1)),
199 (Price::new(num!(1.02)).unwrap(), Size::new(num!(22))),
200 );
201 expected.insert(
202 Position(num_u8!(0)),
203 (Price::new(num!(1.01)).unwrap(), Size::new(num!(12))),
204 );
205
206 let mut actual = init;
207 actual.update(update);
208
209 assert_eq!(actual.book, expected);
210 }
211
212 #[test]
213 fn test_update_set_2_delete() {
214 let init = Available::new([
215 UpdateSet2(Price::new(num!(27)).unwrap(), Size::new(num!(0.95))),
216 UpdateSet2(Price::new(num!(13)).unwrap(), Size::new(num!(28.01))),
217 ]);
218 let update = &[UpdateSet2(
219 Price::new(num!(27)).unwrap(),
220 Size::new(num!(0)),
221 )];
222 let mut expected = BTreeMap::new();
223 expected.insert(Price::new(num!(13)).unwrap(), Size::new(num!(28.01)));
224
225 let mut actual = init;
226 actual.update(update);
227
228 assert_eq!(actual.book, expected);
229 }
230
231 #[test]
232 fn test_update_set_3_delete() {
233 let init = Available::new([
234 UpdateSet3(
235 Position(num_u8!(1)),
236 Price::new(num!(1.02)).unwrap(),
237 Size::new(num!(34.45)),
238 ),
239 UpdateSet3(
240 Position(num_u8!(0)),
241 Price::new(num!(1.01)).unwrap(),
242 Size::new(num!(12)),
243 ),
244 ]);
245 let update = &[UpdateSet3(
246 Position(num_u8!(1)),
247 Price::new(num!(1.02)).unwrap(),
248 Size::new(num!(0)),
249 )];
250 let mut expected = BTreeMap::new();
251 expected.insert(
252 Position(num_u8!(0)),
253 (Price::new(num!(1.01)).unwrap(), Size::new(num!(12))),
254 );
255
256 let mut actual = init;
257 actual.update(update);
258
259 assert_eq!(actual.book, expected);
260 }
261}