deltastruct/
lib.rs

1//! Create custom serializable changes to apply later
2//!
3//! Deltastruct is an attribute macro that generates definitions for
4//! serializable changes (called deltas) over structs recursively.
5//!
6//! For techinical reasons, the attribute macro must be applied to a `mod`
7//! definition containing a `struct` with the same name and an `impl` for
8//! it's change definitions. Function names are converted to camel case to
9//! appease the compiler.
10//!
11//! The generated deltas are always the type name followed by `Delta`. ie: `Foo` -> `FooDelta`, `i32` -> `i32Delta`.
12//!
13//! ```
14//! # use deltastruct::*;
15//! #[deltastruct]
16//! mod Vector3 {
17//!   #[derive(Clone, Copy)]
18//!   pub struct Vector3 {
19//!     pub x : f64,
20//!     pub y : f64,
21//!     pub z : f64,
22//!   }
23//!
24//!   impl Vector3 {
25//!     fn set(&mut self, other : Vector3) {
26//!       // Copy the given vec's components into our own.
27//!       self.x = other.x;
28//!       self.y = other.y;
29//!       self.z = other.z;
30//!     }
31//!
32//!     fn multiply_scalar(&mut self, n : f64) {
33//!       // Multiply each component by the given value
34//!       self.x *= n;
35//!       self.y *= n;
36//!       self.z *= n;
37//!     }
38//!
39//!     fn normalize(&mut self) {
40//!       // divide each component by the vector's magnitude
41//!       let magnitude = (
42//!           self.x.powf(2f64)
43//!         + self.y.powf(2f64)
44//!         + self.z.powf(2f64)
45//!       ).sqrt();
46//!       
47//!       self.x /= magnitude;
48//!       self.y /= magnitude;
49//!       self.z /= magnitude;
50//!     }
51//!   }
52//! }
53//!
54//! fn main() {
55//!   let mut v = Vector3 {
56//!     x: 3f64,
57//!     y: 6f64,
58//!     z: 6f64
59//!   };
60//!
61//!
62//!   let v_delta = Vector3Delta::MultiplyScalar(4f64);
63//!   v.apply(&v_delta);
64//!   v.apply(&v_delta);
65//!
66//!   assert_eq!(v.x, 48f64);
67//!
68//!
69//!   let v_delta = Vector3Delta::Normalize();
70//!   v.apply(&v_delta);
71//!
72//!   assert_eq!(v.z, 2f64/3f64);
73//!
74//!
75//!   let v_delta = Vector3Delta::X(f64Delta::Set(8f64));
76//!   v.apply(&v_delta);
77//!
78//!   assert_eq!(v.x, 8f64);
79//! }
80//!
81//! ```
82//!
83//!
84
85mod primitive_impls;
86pub use primitive_impls::*;
87
88/// An attribute macro applied to `mod`s. Will generate a Delta and it's `DeltaStruct<_>` implementation.
89///
90/// Applied to a `mod`. Expects the `mod` to have a `struct` with the same name
91/// and an implementation. Currently at least one field is expected in the `struct`
92/// definition and at least one method is expected in the implementation. This macro
93/// will generate an `enum` with the same name as the mod with `Delta` appended,
94/// and an implementation `impl DeltaStruct<FooDelta> for Foo`.
95///
96/// The delta will have a tuple variant for each method defined for the struct
97/// converted to camel case, and it's tuple will be of the same type as the
98/// argument list of it's respective method (without `&mut self`). It will also
99/// expose delta functions of it's fields.
100///
101/// ## Example:
102///
103/// ```
104/// # use deltastruct_proc::deltastruct;
105/// # use deltastruct::*;
106/// #[deltastruct]
107/// mod Foo {
108///   struct Foo {
109///     x : i32,
110///     y : i32
111///   }
112///
113///   impl Foo {
114///     fn swap(&mut self) {
115///       let tmp = self.x;
116///       self.x = self.y;
117///       self.y = tmp;
118///     }
119///     
120///     fn do_stuff(&mut self, n : f64) {
121///       self.x = (n * (self.x as f64)) as i32;
122///     }
123///   }
124/// }
125/// ```
126///
127/// will generate:
128/// ```
129/// # use deltastruct::DeltaStruct;
130/// # struct Foo;
131/// # #[allow(non_camel_case_types)] struct i32Delta;
132/// enum FooDelta {
133///   Swap(),
134///   DoStuff(f64),
135///   X(i32Delta),
136///   Y(i32Delta),
137/// }
138///
139/// impl DeltaStruct<FooDelta> for Foo {
140///   fn apply(&mut self, delta : &FooDelta) {
141///     /* ... */
142///   }
143/// }
144/// ```
145pub use deltastruct_proc::deltastruct;
146
147/// A trait derived for each tagged struct where `T` is it's generated delta.
148///
149/// ```
150/// # use deltastruct::*;
151/// #[deltastruct]
152/// mod Foo {
153///   struct Foo {
154///     bar : bool
155///   }
156///   impl Foo {
157///     fn foobar(&mut self) {}
158///   }
159/// }
160/// ```
161///
162/// will generate:
163/// ```
164/// # use deltastruct::*;
165/// # struct Foo;
166/// # struct FooDelta;
167/// impl DeltaStruct<FooDelta> for Foo {
168///   fn apply(&mut self, delta : &FooDelta) {
169///     /* ... */
170///   }
171/// }
172/// ```
173pub trait DeltaStruct<T> {
174  fn apply(&mut self, delta: &T);
175}
176
177#[cfg(test)]
178mod tests {
179  use super::*;
180
181  #[deltastruct]
182  mod Foo {
183    struct Foo {
184      x: i32,
185      y: i32,
186    }
187
188    impl Foo {
189      pub fn bar(&mut self, a: i64, b: i64) {
190        self.x = ((a * b) as i32) - self.y;
191      }
192
193      pub fn baz(&mut self, data: u32) {
194        self.x += data as i32;
195        self.y -= data as i32;
196      }
197    }
198  }
199
200  #[test]
201  fn self_func() {
202    let mut foo = Foo { x: 4, y: 7 };
203
204    let dfoo = FooDelta::Baz(5);
205    foo.apply(&dfoo);
206
207    assert_eq!(foo.x, 9);
208    assert_eq!(foo.y, 2);
209
210    foo.apply(&dfoo);
211
212    assert_eq!(foo.x, 14);
213    assert_eq!(foo.y, -3);
214
215    let dfoo = FooDelta::Bar(3, 4);
216    foo.apply(&dfoo);
217
218    assert_eq!(foo.x, 15);
219    assert_eq!(foo.y, -3);
220  }
221
222  #[test]
223  fn field_func() {
224    let mut foo = Foo { x: 3, y: 6 };
225
226    let dfoo = FooDelta::X(i32Delta::Set(1));
227    foo.apply(&dfoo);
228
229    assert_eq!(foo.x, 1);
230    assert_eq!(foo.y, 6);
231
232    let dfoo = FooDelta::Y(i32Delta::Set(-20));
233    foo.apply(&dfoo);
234
235    assert_eq!(foo.x, 1);
236    assert_eq!(foo.y, -20);
237  }
238
239  #[test]
240  fn delta_derives() {
241    #[deltastruct(derive(Clone))]
242    mod Testbug {
243      struct Testbug {
244        meh: u8,
245      }
246
247      impl Testbug {
248        fn bar(&mut self) {}
249      }
250    }
251
252    let testbugdelta = TestbugDelta::Bar();
253    testbugdelta.clone();
254  }
255}