truce_core/
custom_state.rs1pub struct StateCursor<'a> {
30 data: &'a [u8],
31 pos: usize,
32}
33
34impl<'a> StateCursor<'a> {
35 #[must_use]
36 pub fn new(data: &'a [u8]) -> Self {
37 Self { data, pos: 0 }
38 }
39
40 #[must_use]
41 pub fn remaining(&self) -> usize {
42 self.data.len().saturating_sub(self.pos)
43 }
44
45 pub fn read_bytes(&mut self, n: usize) -> Option<&'a [u8]> {
46 if self.pos + n > self.data.len() {
47 return None;
48 }
49 let slice = &self.data[self.pos..self.pos + n];
50 self.pos += n;
51 Some(slice)
52 }
53
54 pub fn skip_field(&mut self) -> bool {
63 if let Some(bytes) = self.read_bytes(4) {
65 let len = u32::from_le_bytes(
69 bytes
70 .try_into()
71 .expect("read_bytes(4) returned a slice of unexpected length"),
72 ) as usize;
73 if self.pos + len <= self.data.len() {
74 self.pos += len;
75 return true;
76 }
77 }
78 false
79 }
80}
81
82pub trait StateField: Sized {
86 fn write_field(&self, buf: &mut Vec<u8>);
87 fn read_field(cursor: &mut StateCursor) -> Option<Self>;
88}
89
90pub trait State: Sized + Default {
95 fn serialize(&self) -> Vec<u8>;
96 fn deserialize(data: &[u8]) -> Option<Self>;
97}
98
99macro_rules! impl_state_field_int {
104 ($($ty:ty),*) => {
105 $(
106 impl StateField for $ty {
107 fn write_field(&self, buf: &mut Vec<u8>) {
108 buf.extend_from_slice(&self.to_le_bytes());
109 }
110 fn read_field(cursor: &mut StateCursor) -> Option<Self> {
111 let bytes = cursor.read_bytes(std::mem::size_of::<Self>())?;
112 Some(Self::from_le_bytes(bytes.try_into().ok()?))
113 }
114 }
115 )*
116 };
117}
118
119impl_state_field_int!(u8, u16, u32, u64, i8, i16, i32, i64, f32, f64);
120
121impl StateField for bool {
122 fn write_field(&self, buf: &mut Vec<u8>) {
123 buf.push(u8::from(*self));
124 }
125 fn read_field(cursor: &mut StateCursor) -> Option<Self> {
126 let b = cursor.read_bytes(1)?;
127 Some(b[0] != 0)
128 }
129}
130
131impl StateField for String {
132 fn write_field(&self, buf: &mut Vec<u8>) {
133 let bytes = self.as_bytes();
134 crate::cast::len_u32(bytes.len()).write_field(buf);
135 buf.extend_from_slice(bytes);
136 }
137 fn read_field(cursor: &mut StateCursor) -> Option<Self> {
138 let len = u32::read_field(cursor)? as usize;
139 let bytes = cursor.read_bytes(len)?;
140 String::from_utf8(bytes.to_vec()).ok()
141 }
142}
143
144impl<T: StateField> StateField for Vec<T> {
145 fn write_field(&self, buf: &mut Vec<u8>) {
146 crate::cast::len_u32(self.len()).write_field(buf);
147 for item in self {
148 item.write_field(buf);
149 }
150 }
151 fn read_field(cursor: &mut StateCursor) -> Option<Self> {
152 let len = u32::read_field(cursor)? as usize;
153 let mut vec = Vec::with_capacity(len.min(1024));
154 for _ in 0..len {
155 vec.push(T::read_field(cursor)?);
156 }
157 Some(vec)
158 }
159}
160
161impl<T: StateField> StateField for Option<T> {
162 fn write_field(&self, buf: &mut Vec<u8>) {
163 match self {
164 Some(val) => {
165 1u8.write_field(buf);
166 val.write_field(buf);
167 }
168 None => {
169 0u8.write_field(buf);
170 }
171 }
172 }
173 fn read_field(cursor: &mut StateCursor) -> Option<Self> {
174 let tag = u8::read_field(cursor)?;
175 if tag == 0 {
176 Some(None)
177 } else {
178 Some(Some(T::read_field(cursor)?))
179 }
180 }
181}
182
183use crate::editor::PluginContext;
188use std::sync::Arc;
189
190pub struct StateBinding<T: State> {
214 cached: T,
215 get_state: Arc<dyn Fn() -> Vec<u8> + Send + Sync>,
216 set_state: Arc<dyn Fn(Vec<u8>) + Send + Sync>,
217}
218
219impl<T: State> StateBinding<T> {
220 #[must_use]
225 pub fn new<P: ?Sized>(context: &PluginContext<P>) -> Self {
226 let bridge_for_get = Arc::clone(context.bridge());
227 let bridge_for_set = Arc::clone(context.bridge());
228 let mut binding = Self {
229 cached: T::default(),
230 get_state: Arc::new(move || bridge_for_get.get_state()),
231 set_state: Arc::new(move |data| bridge_for_set.set_state(data)),
232 };
233 binding.sync();
234 binding
235 }
236
237 pub fn sync(&mut self) {
239 let data = (self.get_state)();
240 if !data.is_empty()
241 && let Some(s) = T::deserialize(&data)
242 {
243 self.cached = s;
244 }
245 }
246
247 pub fn get(&self) -> &T {
249 &self.cached
250 }
251
252 pub fn update(&mut self, f: impl FnOnce(&mut T)) {
254 f(&mut self.cached);
255 let data = self.cached.serialize();
256 (self.set_state)(data);
257 }
258}
259
260impl<T: State> Default for StateBinding<T> {
261 fn default() -> Self {
269 Self {
270 cached: T::default(),
271 get_state: Arc::new(Vec::new),
272 set_state: Arc::new(|_| {}),
273 }
274 }
275}
276
277#[cfg(test)]
282mod tests {
283 use super::*;
284
285 #[test]
286 fn primitives_round_trip() {
287 let mut buf = Vec::new();
288 42u32.write_field(&mut buf);
289 2.5f64.write_field(&mut buf);
290 true.write_field(&mut buf);
291
292 let mut cursor = StateCursor::new(&buf);
293 assert_eq!(u32::read_field(&mut cursor), Some(42));
294 assert_eq!(f64::read_field(&mut cursor), Some(2.5));
295 assert_eq!(bool::read_field(&mut cursor), Some(true));
296 }
297
298 #[test]
299 fn string_round_trip() {
300 let mut buf = Vec::new();
301 "hello world".to_string().write_field(&mut buf);
302
303 let mut cursor = StateCursor::new(&buf);
304 assert_eq!(
305 String::read_field(&mut cursor),
306 Some("hello world".to_string())
307 );
308 }
309
310 #[test]
311 fn vec_round_trip() {
312 let mut buf = Vec::new();
313 vec![1u32, 2, 3].write_field(&mut buf);
314
315 let mut cursor = StateCursor::new(&buf);
316 assert_eq!(Vec::<u32>::read_field(&mut cursor), Some(vec![1, 2, 3]));
317 }
318
319 #[test]
320 fn option_round_trip() {
321 let mut buf = Vec::new();
322 Some(42u32).write_field(&mut buf);
323 None::<u32>.write_field(&mut buf);
324
325 let mut cursor = StateCursor::new(&buf);
326 assert_eq!(Option::<u32>::read_field(&mut cursor), Some(Some(42)));
327 assert_eq!(Option::<u32>::read_field(&mut cursor), Some(None));
328 }
329
330 #[test]
331 fn nested_vec_string() {
332 let mut buf = Vec::new();
333 let v = vec!["foo".to_string(), "bar".to_string()];
334 v.write_field(&mut buf);
335
336 let mut cursor = StateCursor::new(&buf);
337 assert_eq!(Vec::<String>::read_field(&mut cursor), Some(v));
338 }
339}