truce_core/
custom_state.rs1pub use crossbeam_utils::atomic::AtomicCell;
31
32pub struct StateCursor<'a> {
34 data: &'a [u8],
35 pos: usize,
36}
37
38impl<'a> StateCursor<'a> {
39 #[must_use]
40 pub fn new(data: &'a [u8]) -> Self {
41 Self { data, pos: 0 }
42 }
43
44 #[must_use]
45 pub fn remaining(&self) -> usize {
46 self.data.len().saturating_sub(self.pos)
47 }
48
49 pub fn read_bytes(&mut self, n: usize) -> Option<&'a [u8]> {
50 if self.pos + n > self.data.len() {
51 return None;
52 }
53 let slice = &self.data[self.pos..self.pos + n];
54 self.pos += n;
55 Some(slice)
56 }
57
58 pub fn skip_field(&mut self) -> bool {
67 if let Some(bytes) = self.read_bytes(4) {
69 let len = u32::from_le_bytes(
73 bytes
74 .try_into()
75 .expect("read_bytes(4) returned a slice of unexpected length"),
76 ) as usize;
77 if self.pos + len <= self.data.len() {
78 self.pos += len;
79 return true;
80 }
81 }
82 false
83 }
84}
85
86pub trait StateField: Sized {
90 fn write_field(&self, buf: &mut Vec<u8>);
91 fn read_field(cursor: &mut StateCursor) -> Option<Self>;
92}
93
94pub trait State: Sized + Default {
99 fn serialize_into(&self, buf: &mut Vec<u8>);
104
105 #[must_use]
109 fn serialize(&self) -> Vec<u8> {
110 let mut buf = Vec::new();
111 self.serialize_into(&mut buf);
112 buf
113 }
114
115 fn deserialize(data: &[u8]) -> Option<Self>;
116}
117
118pub trait PersistField {
127 fn persist_write(&self, buf: &mut Vec<u8>);
129 fn persist_read(&self, cursor: &mut StateCursor);
132}
133
134impl<T: StateField> PersistField for std::sync::RwLock<T> {
135 fn persist_write(&self, buf: &mut Vec<u8>) {
136 if let Ok(guard) = self.read() {
137 guard.write_field(buf);
138 }
139 }
140 fn persist_read(&self, cursor: &mut StateCursor) {
141 if let Some(value) = T::read_field(cursor)
142 && let Ok(mut guard) = self.write()
143 {
144 *guard = value;
145 }
146 }
147}
148
149impl<T: StateField> PersistField for std::sync::Mutex<T> {
150 fn persist_write(&self, buf: &mut Vec<u8>) {
151 if let Ok(guard) = self.lock() {
152 guard.write_field(buf);
153 }
154 }
155 fn persist_read(&self, cursor: &mut StateCursor) {
156 if let Some(value) = T::read_field(cursor)
157 && let Ok(mut guard) = self.lock()
158 {
159 *guard = value;
160 }
161 }
162}
163
164impl<T: StateField + Copy> PersistField for AtomicCell<T> {
169 fn persist_write(&self, buf: &mut Vec<u8>) {
170 self.load().write_field(buf);
171 }
172 fn persist_read(&self, cursor: &mut StateCursor) {
173 if let Some(value) = T::read_field(cursor) {
174 self.store(value);
175 }
176 }
177}
178
179macro_rules! impl_state_field_int {
184 ($($ty:ty),*) => {
185 $(
186 impl StateField for $ty {
187 fn write_field(&self, buf: &mut Vec<u8>) {
188 buf.extend_from_slice(&self.to_le_bytes());
189 }
190 fn read_field(cursor: &mut StateCursor) -> Option<Self> {
191 let bytes = cursor.read_bytes(std::mem::size_of::<Self>())?;
192 Some(Self::from_le_bytes(bytes.try_into().ok()?))
193 }
194 }
195 )*
196 };
197}
198
199impl_state_field_int!(u8, u16, u32, u64, i8, i16, i32, i64, f32, f64);
200
201impl StateField for bool {
202 fn write_field(&self, buf: &mut Vec<u8>) {
203 buf.push(u8::from(*self));
204 }
205 fn read_field(cursor: &mut StateCursor) -> Option<Self> {
206 let b = cursor.read_bytes(1)?;
207 Some(b[0] != 0)
208 }
209}
210
211impl StateField for String {
212 fn write_field(&self, buf: &mut Vec<u8>) {
213 let bytes = self.as_bytes();
214 crate::cast::len_u32(bytes.len()).write_field(buf);
215 buf.extend_from_slice(bytes);
216 }
217 fn read_field(cursor: &mut StateCursor) -> Option<Self> {
218 let len = u32::read_field(cursor)? as usize;
219 let bytes = cursor.read_bytes(len)?;
220 String::from_utf8(bytes.to_vec()).ok()
221 }
222}
223
224impl<T: StateField> StateField for Vec<T> {
225 fn write_field(&self, buf: &mut Vec<u8>) {
226 crate::cast::len_u32(self.len()).write_field(buf);
227 for item in self {
228 item.write_field(buf);
229 }
230 }
231 fn read_field(cursor: &mut StateCursor) -> Option<Self> {
232 let len = u32::read_field(cursor)? as usize;
233 let mut vec = Vec::with_capacity(len.min(1024));
234 for _ in 0..len {
235 vec.push(T::read_field(cursor)?);
236 }
237 Some(vec)
238 }
239}
240
241impl<T: StateField> StateField for Option<T> {
242 fn write_field(&self, buf: &mut Vec<u8>) {
243 match self {
244 Some(val) => {
245 1u8.write_field(buf);
246 val.write_field(buf);
247 }
248 None => {
249 0u8.write_field(buf);
250 }
251 }
252 }
253 fn read_field(cursor: &mut StateCursor) -> Option<Self> {
254 let tag = u8::read_field(cursor)?;
255 if tag == 0 {
256 Some(None)
257 } else {
258 Some(Some(T::read_field(cursor)?))
259 }
260 }
261}
262
263use crate::editor::PluginContext;
268use std::sync::Arc;
269
270pub struct StateBinding<T: State> {
294 cached: T,
295 get_state: Arc<dyn Fn() -> Vec<u8> + Send + Sync>,
296 set_state: Arc<dyn Fn(Vec<u8>) + Send + Sync>,
297}
298
299impl<T: State> StateBinding<T> {
300 #[must_use]
305 pub fn new<P: ?Sized>(context: &PluginContext<P>) -> Self {
306 let bridge_for_get = Arc::clone(context.bridge());
307 let bridge_for_set = Arc::clone(context.bridge());
308 let mut binding = Self {
309 cached: T::default(),
310 get_state: Arc::new(move || bridge_for_get.get_state()),
311 set_state: Arc::new(move |data| bridge_for_set.set_state(data)),
312 };
313 binding.sync();
314 binding
315 }
316
317 pub fn sync(&mut self) {
319 let data = (self.get_state)();
320 if !data.is_empty()
321 && let Some(s) = T::deserialize(&data)
322 {
323 self.cached = s;
324 }
325 }
326
327 pub fn get(&self) -> &T {
329 &self.cached
330 }
331
332 pub fn update(&mut self, f: impl FnOnce(&mut T)) {
334 f(&mut self.cached);
335 let data = self.cached.serialize();
336 (self.set_state)(data);
337 }
338}
339
340impl<T: State> Default for StateBinding<T> {
341 fn default() -> Self {
349 Self {
350 cached: T::default(),
351 get_state: Arc::new(Vec::new),
352 set_state: Arc::new(|_| {}),
353 }
354 }
355}
356
357#[cfg(test)]
362mod tests {
363 use super::*;
364
365 #[test]
366 fn primitives_round_trip() {
367 let mut buf = Vec::new();
368 42u32.write_field(&mut buf);
369 2.5f64.write_field(&mut buf);
370 true.write_field(&mut buf);
371
372 let mut cursor = StateCursor::new(&buf);
373 assert_eq!(u32::read_field(&mut cursor), Some(42));
374 assert_eq!(f64::read_field(&mut cursor), Some(2.5));
375 assert_eq!(bool::read_field(&mut cursor), Some(true));
376 }
377
378 #[test]
379 fn string_round_trip() {
380 let mut buf = Vec::new();
381 "hello world".to_string().write_field(&mut buf);
382
383 let mut cursor = StateCursor::new(&buf);
384 assert_eq!(
385 String::read_field(&mut cursor),
386 Some("hello world".to_string())
387 );
388 }
389
390 #[test]
391 fn vec_round_trip() {
392 let mut buf = Vec::new();
393 vec![1u32, 2, 3].write_field(&mut buf);
394
395 let mut cursor = StateCursor::new(&buf);
396 assert_eq!(Vec::<u32>::read_field(&mut cursor), Some(vec![1, 2, 3]));
397 }
398
399 #[test]
400 fn option_round_trip() {
401 let mut buf = Vec::new();
402 Some(42u32).write_field(&mut buf);
403 None::<u32>.write_field(&mut buf);
404
405 let mut cursor = StateCursor::new(&buf);
406 assert_eq!(Option::<u32>::read_field(&mut cursor), Some(Some(42)));
407 assert_eq!(Option::<u32>::read_field(&mut cursor), Some(None));
408 }
409
410 #[test]
411 fn nested_vec_string() {
412 let mut buf = Vec::new();
413 let v = vec!["foo".to_string(), "bar".to_string()];
414 v.write_field(&mut buf);
415
416 let mut cursor = StateCursor::new(&buf);
417 assert_eq!(Vec::<String>::read_field(&mut cursor), Some(v));
418 }
419
420 #[test]
421 fn persist_field_lock_round_trip() {
422 let src = std::sync::RwLock::new("guitar bus".to_string());
423 let mut buf = Vec::new();
424 src.persist_write(&mut buf);
425
426 let dst = std::sync::RwLock::new(String::new());
427 dst.persist_read(&mut StateCursor::new(&buf));
428 assert_eq!(*dst.read().unwrap(), "guitar bus");
429
430 let m_src = std::sync::Mutex::new(vec![1u32, 2, 3]);
431 let mut m_buf = Vec::new();
432 m_src.persist_write(&mut m_buf);
433 let m_dst = std::sync::Mutex::new(Vec::<u32>::new());
434 m_dst.persist_read(&mut StateCursor::new(&m_buf));
435 assert_eq!(*m_dst.lock().unwrap(), vec![1, 2, 3]);
436 }
437
438 #[test]
439 fn persist_field_atomic_cell_round_trip() {
440 let src = AtomicCell::new(0.75f32);
441 let mut buf = Vec::new();
442 src.persist_write(&mut buf);
443
444 let dst = AtomicCell::new(0.0f32);
445 dst.persist_read(&mut StateCursor::new(&buf));
446 assert_eq!(dst.load().to_bits(), 0.75f32.to_bits());
448 }
449
450 #[test]
451 fn persist_field_leaves_value_on_short_read() {
452 let dst = AtomicCell::new(42u32);
454 dst.persist_read(&mut StateCursor::new(&[0xFF, 0xFF]));
455 assert_eq!(dst.load(), 42);
456 }
457}