libtw2_snapshot/
storage.rs1use crate::format;
2use crate::snap;
3use crate::snap::Builder;
4use crate::snap::Delta;
5use crate::snap::Snap;
6use std::collections::VecDeque;
7use warn::wrap;
8use warn::Warn;
9
10#[derive(Clone)]
14struct StoredSnap {
15 snap: Snap,
16 tick: i32,
17}
18
19const MAX_STORED_SNAPSHOT: usize = 100;
20
21#[derive(Clone, Debug, Eq, PartialEq)]
22pub struct UnknownSnap;
23
24#[derive(Clone, Debug, Eq, PartialEq)]
25pub struct WeirdNegativeDeltaTick;
26
27#[derive(Clone, Debug, Eq, PartialEq)]
28pub enum Error {
29 OldDelta,
30 UnknownSnap,
31 InvalidCrc,
32 Unpack(snap::Error),
33}
34
35impl From<snap::Error> for Error {
36 fn from(err: snap::Error) -> Error {
37 Error::Unpack(err)
38 }
39}
40
41#[derive(Clone, Debug, Eq, PartialEq)]
42pub enum Warning {
43 WeirdNegativeDeltaTick,
44 Unpack(format::Warning),
45}
46
47impl From<format::Warning> for Warning {
48 fn from(w: format::Warning) -> Warning {
49 Warning::Unpack(w)
50 }
51}
52
53#[derive(Clone, Default)]
54pub struct Storage {
55 snaps: VecDeque<StoredSnap>,
59 free: Vec<Snap>,
60 ack_tick: Option<i32>,
61 delta: Delta,
62 delta_tick: Option<i32>,
63}
64
65impl Storage {
66 pub fn new() -> Storage {
67 Default::default()
68 }
69 pub fn reset(&mut self) {
70 let self_free = &mut self.free;
71 self.snaps.drain(..).map(|s| self_free.push(s.snap)).count();
73 self.ack_tick = None;
74 }
75 pub fn ack_tick(&self) -> Option<i32> {
76 self.ack_tick
77 }
78 pub fn add_delta<W>(
79 &mut self,
80 warn: &mut W,
81 crc: Option<i32>,
82 delta_tick: i32,
83 tick: i32,
84 delta: &Delta,
85 ) -> Result<&Snap, Error>
86 where
87 W: Warn<Warning>,
88 {
89 if self.snaps.front().map(|s| s.tick).unwrap_or(-1) >= tick {
90 return Err(Error::OldDelta);
91 }
92 {
93 let empty = Snap::empty();
94 let delta_snap;
95 if delta_tick >= 0 {
96 if let Some(i) = self.snaps.iter().position(|s| s.tick < delta_tick) {
97 let self_free = &mut self.free;
98 self.snaps
100 .drain(i..)
101 .map(|s| self_free.push(s.snap))
102 .count();
103 }
104 if let Some(d) = self.snaps.back() {
105 if d.tick == delta_tick {
106 delta_snap = &d.snap;
107 } else {
108 self.ack_tick = None;
109 return Err(Error::UnknownSnap);
110 }
111 } else {
112 self.ack_tick = None;
113 return Err(Error::UnknownSnap);
114 }
115 } else {
116 delta_snap = ∅
117 if delta_tick != -1 {
118 warn.warn(Warning::WeirdNegativeDeltaTick);
119 }
120 }
121 if self.free.is_empty() {
122 self.free.push(Snap::empty());
123 }
124
125 let new_snap: &mut Snap = self.free.last_mut().unwrap();
126 new_snap.read_with_delta(wrap(warn), delta_snap, delta)?;
127 if crc.map(|crc| crc != new_snap.crc()).unwrap_or(false) {
128 self.ack_tick = None;
129 return Err(Error::InvalidCrc);
130 }
131 self.ack_tick = Some(tick);
132 }
133 self.snaps.push_front(StoredSnap {
134 tick: tick,
135 snap: self.free.pop().unwrap(),
136 });
137 if self.snaps.len() > MAX_STORED_SNAPSHOT {
138 self.free.push(self.snaps.pop_back().unwrap().snap);
139 }
140 Ok(&self.snaps.front().unwrap().snap)
141 }
142 pub fn new_builder(&mut self) -> Builder {
143 self.free.pop().unwrap_or_default().recycle()
144 }
145 pub fn set_delta_tick<W>(&mut self, warn: &mut W, tick: i32) -> Result<(), UnknownSnap>
146 where
147 W: Warn<WeirdNegativeDeltaTick>,
148 {
149 if tick < 0 {
150 if tick != -1 {
151 warn.warn(WeirdNegativeDeltaTick);
152 }
153 self.delta_tick = None;
154 return Ok(());
155 }
156 if let Some(i) = self.snaps.iter().position(|s| s.tick < tick) {
157 let self_free = &mut self.free;
158 self.snaps
160 .drain(i..)
161 .map(|s| self_free.push(s.snap))
162 .count();
163 }
164 if !self.snaps.back().map(|s| s.tick == tick).unwrap_or(false) {
165 self.delta_tick = None;
166 return Err(UnknownSnap);
167 }
168 self.delta_tick = Some(tick);
169 Ok(())
170 }
171 pub fn delta_tick(&self) -> Option<i32> {
172 self.delta_tick
173 }
174 pub fn add_snap(&mut self, tick: i32, snap: Snap) -> &Delta {
175 self.snaps.push_front(StoredSnap {
176 snap: snap,
177 tick: tick,
178 });
179 let tmp;
180 let delta_snap = if self.delta_tick.is_some() {
181 &self.snaps.back().unwrap().snap
182 } else {
183 tmp = Snap::empty();
184 &tmp
185 };
186 self.delta
187 .create(delta_snap, &self.snaps.front().unwrap().snap);
188 &self.delta
189 }
190}