autocore_std/fb/
datastore.rs1use crate::CommandClient;
2use mechutil::ipc::CommandMessage;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5enum State {
6 Idle,
7 WaitingForResponse,
8}
9
10pub struct DataStoreRead {
12 pub busy: bool,
14 pub done: bool,
16 pub error: bool,
18 pub error_message: String,
20 pub data: Option<serde_json::Value>,
22
23 state: State,
24 start_time: Option<std::time::Instant>,
25 pending_tid: Option<u32>,
26}
27
28impl DataStoreRead {
29 pub fn new() -> Self {
31 Self {
32 busy: false,
33 done: false,
34 error: false,
35 error_message: String::new(),
36 data: None,
37 state: State::Idle,
38 start_time: None,
39 pending_tid: None,
40 }
41 }
42
43 pub fn is_busy(&self) -> bool {
45 self.busy
46 }
47
48 pub fn is_error(&self) -> bool {
50 self.error
51 }
52
53 pub fn start(&mut self, path: &str, client: &mut CommandClient) {
59 self.error = false;
60 self.error_message.clear();
61 self.data = None;
62 self.done = false;
63
64 let msg = CommandMessage::read(&format!("datastore.{}", path));
65 self.pending_tid = Some(client.send_message(msg));
66 self.start_time = Some(std::time::Instant::now());
67 self.busy = true;
68 self.state = State::WaitingForResponse;
69 }
70
71 pub fn reset(&mut self) {
73 self.state = State::Idle;
74 self.busy = false;
75 self.done = false;
76 self.pending_tid = None;
77 }
78
79 pub fn tick(&mut self, timeout_ms: u32, client: &mut CommandClient) {
81 match self.state {
82 State::Idle => {}
83
84 State::WaitingForResponse => {
85 if self.check_timeout(timeout_ms) {
86 return;
87 }
88
89 if let Some(tid) = self.pending_tid {
90 if let Some(resp) = client.take_response(tid) {
91 self.pending_tid = None;
92 self.busy = false;
93
94 if resp.success {
95 self.data = Some(resp.data);
96 self.done = true;
97 self.state = State::Idle;
98 } else {
99 self.set_error(&resp.error_message);
100 }
101 }
102 }
103 }
104 }
105 }
106
107 fn check_timeout(&mut self, timeout_ms: u32) -> bool {
108 if let Some(t) = self.start_time {
109 if t.elapsed().as_millis() as u32 > timeout_ms {
110 self.set_error("Datastore read timeout");
111 return true;
112 }
113 }
114 false
115 }
116
117 fn set_error(&mut self, message: &str) {
118 self.state = State::Idle;
119 self.busy = false;
120 self.error = true;
121 self.error_message = message.to_string();
122 self.pending_tid = None;
123 }
124}
125
126impl Default for DataStoreRead {
127 fn default() -> Self {
128 Self::new()
129 }
130}
131
132
133pub struct DataStoreWrite {
135 pub busy: bool,
137 pub done: bool,
139 pub error: bool,
141 pub error_message: String,
143
144 state: State,
145 start_time: Option<std::time::Instant>,
146 pending_tid: Option<u32>,
147}
148
149impl DataStoreWrite {
150 pub fn new() -> Self {
152 Self {
153 busy: false,
154 done: false,
155 error: false,
156 error_message: String::new(),
157 state: State::Idle,
158 start_time: None,
159 pending_tid: None,
160 }
161 }
162
163 pub fn is_busy(&self) -> bool {
165 self.busy
166 }
167
168 pub fn is_error(&self) -> bool {
170 self.error
171 }
172
173 pub fn start(&mut self, path: &str, data: serde_json::Value, options: serde_json::Value, client: &mut CommandClient) {
181 self.error = false;
182 self.error_message.clear();
183 self.done = false;
184
185 let payload = serde_json::json!({
186 "value": data,
187 "options": options
188 });
189
190 let msg = CommandMessage::write(&format!("datastore.{}", path), payload);
191 self.pending_tid = Some(client.send_message(msg));
192 self.start_time = Some(std::time::Instant::now());
193 self.busy = true;
194 self.state = State::WaitingForResponse;
195 }
196
197 pub fn reset(&mut self) {
199 self.state = State::Idle;
200 self.busy = false;
201 self.done = false;
202 self.pending_tid = None;
203 }
204
205 pub fn tick(&mut self, timeout_ms: u32, client: &mut CommandClient) {
207 match self.state {
208 State::Idle => {}
209
210 State::WaitingForResponse => {
211 if self.check_timeout(timeout_ms) {
212 return;
213 }
214
215 if let Some(tid) = self.pending_tid {
216 if let Some(resp) = client.take_response(tid) {
217 self.pending_tid = None;
218 self.busy = false;
219
220 if resp.success {
221 self.done = true;
222 self.state = State::Idle;
223 } else {
224 self.set_error(&resp.error_message);
225 }
226 }
227 }
228 }
229 }
230 }
231
232 fn check_timeout(&mut self, timeout_ms: u32) -> bool {
233 if let Some(t) = self.start_time {
234 if t.elapsed().as_millis() as u32 > timeout_ms {
235 self.set_error("Datastore write timeout");
236 return true;
237 }
238 }
239 false
240 }
241
242 fn set_error(&mut self, message: &str) {
243 self.state = State::Idle;
244 self.busy = false;
245 self.error = true;
246 self.error_message = message.to_string();
247 self.pending_tid = None;
248 }
249}
250
251impl Default for DataStoreWrite {
252 fn default() -> Self {
253 Self::new()
254 }
255}