typemap_meta/
lib.rs

1#![no_std]
2
3//! A simple compile-time derive macro to create type-to-value maps.
4//!
5//! This approach in contrast to crates such as [`typemap`](https://crates.io/crates/typemap/)
6//! or [`type-map`](https://crates.io/crates/type-map/) that perform run-time lookup.
7//! The static typing brings compile-time safety and faster execution at the expense
8//! of using a derive macro and generics.
9//!
10//! The crate is `no_std` compatible.
11//!
12//! # Example
13//! ```
14//! # use typemap_meta::*;
15//! #[derive(Typemap)]
16//! struct Test(i32, f32);
17//!
18//! let t = Test(1, 2.0);
19//! assert_eq!(*get!(t, i32), 1);
20//! assert_eq!(*get!(t, f32), 2.0);
21//! ```
22//!
23//! To get mutable references, add the `#[typemap_mut]` attribute on your struct, and
24//! use `get_mut!` instead of `get!`:
25//! ```
26//! # use typemap_meta::*;
27//! #[derive(Typemap)]
28//! #[typemap_mut]
29//! struct Test(i32, f32);
30//!
31//! let mut t = Test(1, 2.0);
32//! assert_eq!(*get!(t, i32), 1);
33//! assert_eq!(*get!(t, f32), 2.0);
34//!
35//! *get_mut!(t, i32) = 3;
36//! *get_mut!(t, f32) = 4.0;
37//!
38//! assert_eq!(*get!(t, i32), 3);
39//! assert_eq!(*get!(t, f32), 4.0);
40//! ```
41
42pub use typemap_meta_derive::*;
43
44/// Helper trait to get a specific type `T` from a tuple struct containing disjoint heterogeneous types
45pub trait Get<T> {
46    fn get(&self) -> &T;
47}
48
49/// Helper trait to mutably get a specific type `T` from a tuple struct containing disjoint heterogeneous types
50pub trait GetMut<T> {
51    fn get_mut(&mut self) -> &mut T;
52}
53
54/// Convenience macro to get a specific type `$t` from a tuple struct `$s` containing disjoint heterogeneous types
55///
56/// Passing a value is fine, as [`get`] will add a reference to `$t` before calling [`Get`].
57#[macro_export]
58macro_rules! get {
59    ($s:expr, $t:ty) => {
60        $crate::Get::<$t>::get(&$s)
61    };
62}
63
64/// Convenience macro to mutably get a specific type `$t` from a tuple struct `$s` containing disjoint heterogeneous types
65///
66/// Passing a value is fine, as [`get_mut`] will add a reference to `$t` before calling [`GetMut`].
67#[macro_export]
68macro_rules! get_mut {
69    ($s:expr, $t:ty) => {
70        $crate::GetMut::<$t>::get_mut(&mut $s)
71    };
72}
73
74#[cfg(test)]
75mod tests {
76    use crate::{get, Get, GetMut};
77
78    // without using the generation macro
79
80    #[test]
81    fn impl_get() {
82        struct Test(i32, f32);
83        impl Get<i32> for Test {
84            fn get(&self) -> &i32 {
85                &self.0
86            }
87        }
88        impl Get<f32> for Test {
89            fn get(&self) -> &f32 {
90                &self.1
91            }
92        }
93        let t = Test(1, 2.0);
94        assert_eq!(*get!(t, i32), 1);
95        assert_eq!(*get!(t, f32), 2.0);
96    }
97
98    #[test]
99    fn impl_get_mut() {
100        struct Test(i32, f32);
101        impl Get<i32> for Test {
102            fn get(&self) -> &i32 {
103                &self.0
104            }
105        }
106        impl Get<f32> for Test {
107            fn get(&self) -> &f32 {
108                &self.1
109            }
110        }
111
112        impl GetMut<i32> for Test {
113            fn get_mut(&mut self) -> &mut i32 {
114                &mut self.0
115            }
116        }
117        impl GetMut<f32> for Test {
118            fn get_mut(&mut self) -> &mut f32 {
119                &mut self.1
120            }
121        }
122
123        let t = Test(1, 2.0);
124        assert_eq!(*get!(t, i32), 1);
125        assert_eq!(*get!(t, f32), 2.0);
126
127        let mut t = t;
128
129        *get_mut!(t, i32) = 3;
130        *get_mut!(t, f32) = 4.0;
131        assert_eq!(*get!(t, i32), 3);
132        assert_eq!(*get!(t, f32), 4.0);
133    }
134
135    #[test]
136    fn impl_get_ref() {
137        struct Test<'a>(&'a i32, &'a f32);
138        impl<'a> Get<&'a i32> for Test<'a> {
139            fn get(&self) -> &&'a i32 {
140                &self.0
141            }
142        }
143        impl<'a> Get<&'a f32> for Test<'a> {
144            fn get(&self) -> &&'a f32 {
145                &self.1
146            }
147        }
148        let t = Test(&1, &2.0);
149        assert_eq!(**get!(t, &i32), 1);
150        assert_eq!(**get!(t, &f32), 2.0);
151    }
152
153    #[test]
154    fn impl_get_mut_ref() {
155        struct Test<'a>(&'a i32, &'a f32);
156        impl<'a> Get<&'a i32> for Test<'a> {
157            fn get(&self) -> &&'a i32 {
158                &self.0
159            }
160        }
161        impl<'a> Get<&'a f32> for Test<'a> {
162            fn get(&self) -> &&'a f32 {
163                &self.1
164            }
165        }
166
167        impl<'a> GetMut<&'a i32> for Test<'a> {
168            fn get_mut(&mut self) -> &mut &'a i32 {
169                &mut self.0
170            }
171        }
172        impl<'a> GetMut<&'a f32> for Test<'a> {
173            fn get_mut(&mut self) -> &mut &'a f32 {
174                &mut self.1
175            }
176        }
177        let t = Test(&1, &2.0);
178        assert_eq!(**get!(t, &i32), 1);
179        assert_eq!(**get!(t, &f32), 2.0);
180
181        let mut t = t;
182
183        *get_mut!(t, &i32) = &3;
184        *get_mut!(t, &f32) = &4.0;
185        assert_eq!(**get!(t, &i32), 3);
186        assert_eq!(**get!(t, &f32), 4.0);
187    }
188
189    // with using the generation macro
190
191    #[test]
192    fn derive_scalar() {
193        extern crate std;
194        use std::marker::PhantomData;
195        #[derive(Debug, PartialEq, Eq, Clone, Copy)]
196        struct A<T> {
197            _f: PhantomData<T>,
198        }
199        #[derive(crate::Typemap)]
200        struct Test(i32, f32, A<u32>);
201        let a = A { _f: PhantomData };
202        let t = Test(1, 2.0, a);
203        assert_eq!(*get!(t, i32), 1);
204        assert_eq!(*get!(t, f32), 2.0);
205        assert_eq!(*get!(t, A<u32>), a);
206    }
207
208    #[test]
209    fn derive_scalar_mut() {
210        extern crate std;
211        #[derive(Debug, PartialEq, Eq, Clone, Copy)]
212        struct A<T>(T);
213        #[derive(crate::Typemap)]
214        #[typemap_mut]
215        struct Test(i32, f32, A<u32>);
216        let a = A(3);
217        let t = Test(1, 2.0, a);
218        assert_eq!(*get!(t, i32), 1);
219        assert_eq!(*get!(t, f32), 2.0);
220        assert_eq!(*get!(t, A<u32>), a);
221
222        let mut t = t;
223        let b = A(6);
224
225        *get_mut!(t, i32) = 4;
226        *get_mut!(t, f32) = 5.0;
227        *get_mut!(t, A<u32>) = b;
228
229        assert_eq!(*get!(t, i32), 4);
230        assert_eq!(*get!(t, f32), 5.0);
231        assert_eq!(*get!(t, A<u32>), b);
232    }
233
234    #[test]
235    fn derive_struct() {
236        #[derive(Debug, PartialEq)]
237        struct A {}
238        #[derive(Debug, PartialEq)]
239        struct B {}
240        #[derive(crate::Typemap)]
241        struct Test(A, B);
242        let t = Test(A {}, B {});
243        assert_eq!(*get!(t, A), A {});
244    }
245
246    #[test]
247    fn derive_struct_mut() {
248        #[derive(Debug, PartialEq)]
249        struct A {
250            x: u32,
251        }
252        #[derive(Debug, PartialEq)]
253        struct B {}
254        #[derive(crate::Typemap)]
255        #[typemap_mut]
256        struct Test(A, B);
257        let t = Test(A { x: 1 }, B {});
258        assert_eq!(*get!(t, A), A { x: 1 });
259
260        let mut t = t;
261
262        get_mut!(t, A).x = 2;
263        assert_eq!(*get!(t, A), A { x: 2 });
264    }
265
266    #[test]
267    fn derive_ref() {
268        #[derive(Debug, PartialEq)]
269        struct A {}
270        #[derive(Debug, PartialEq)]
271        struct B {}
272        #[derive(crate::Typemap)]
273        struct Test<'l>(&'l A, &'l B, i32, f32);
274        let a = A {};
275        let b = B {};
276        let t = Test(&a, &b, 1, 2.0);
277        assert_eq!(**get!(t, &A), A {});
278        assert_eq!(**get!(t, &B), B {});
279        assert_eq!(*get!(t, i32), 1);
280        assert_eq!(*get!(t, f32), 2.0);
281    }
282
283    #[test]
284    fn derive_ref_mut() {
285        #[derive(Debug, PartialEq)]
286        struct A {
287            x: u32,
288        }
289        #[derive(Debug, PartialEq)]
290        struct B {}
291        #[derive(crate::Typemap)]
292        #[typemap_mut]
293        struct Test<'l>(&'l A, &'l B, i32, f32);
294        let a = A { x: 1 };
295        let b = B {};
296        let t = Test(&a, &b, 1, 2.0);
297        assert_eq!(**get!(t, &A), A { x: 1 });
298        assert_eq!(**get!(t, &B), B {});
299        assert_eq!(*get!(t, i32), 1);
300        assert_eq!(*get!(t, f32), 2.0);
301
302        let mut t = t;
303
304        *get_mut!(t, &A) = &A { x: 2 };
305        *get_mut!(t, &B) = &B {};
306        *get_mut!(t, i32) = 3;
307        *get_mut!(t, f32) = 4.0;
308        assert_eq!(**get!(t, &A), A { x: 2 });
309        assert_eq!(**get!(t, &B), B {});
310        assert_eq!(*get!(t, i32), 3);
311        assert_eq!(*get!(t, f32), 4.0);
312    }
313
314    #[test]
315    fn derive_box_trait() {
316        extern crate std;
317        use std::{boxed::Box, fmt::Debug};
318        // trait TA and struct A
319        trait TA {
320            fn value_a(&self) -> i32;
321        }
322        #[derive(Debug, PartialEq)]
323        struct A {
324            v: i32,
325        }
326        impl TA for A {
327            fn value_a(&self) -> i32 {
328                self.v
329            }
330        }
331        // trait TB and struct B
332        trait TB {
333            fn value_b(&self) -> f32;
334        }
335        #[derive(Debug, PartialEq)]
336        struct B {
337            v: f32,
338        }
339        impl TB for B {
340            fn value_b(&self) -> f32 {
341                self.v
342            }
343        }
344        // instance and asserts
345        #[derive(crate::Typemap)]
346        struct Test(Box<dyn TA>, Box<dyn TB>);
347        let t = Test(Box::new(A { v: 1 }), Box::new(B { v: 2.0 }));
348        assert_eq!(get!(t, Box<dyn TA>).value_a(), 1);
349        assert_eq!(get!(t, Box<dyn TB>).value_b(), 2.0);
350    }
351
352    #[test]
353    fn derive_box_trait_mut() {
354        extern crate std;
355        use std::{boxed::Box, fmt::Debug};
356        // trait TA and struct A
357        trait TA {
358            fn value_a(&self) -> i32;
359            fn set_a(&mut self, a: i32);
360        }
361        #[derive(Debug, PartialEq)]
362        struct A {
363            v: i32,
364        }
365        impl TA for A {
366            fn value_a(&self) -> i32 {
367                self.v
368            }
369            fn set_a(&mut self, a: i32) {
370                self.v = a;
371            }
372        }
373        // trait TB and struct B
374        trait TB {
375            fn value_b(&self) -> f32;
376            fn set_b(&mut self, b: f32);
377        }
378        #[derive(Debug, PartialEq)]
379        struct B {
380            v: f32,
381        }
382        impl TB for B {
383            fn value_b(&self) -> f32 {
384                self.v
385            }
386            fn set_b(&mut self, b: f32) {
387                self.v = b;
388            }
389        }
390        // instance and asserts
391        #[derive(crate::Typemap)]
392        #[typemap_mut]
393        struct Test(Box<dyn TA>, Box<dyn TB>);
394        let t = Test(Box::new(A { v: 1 }), Box::new(B { v: 2.0 }));
395        assert_eq!(get!(t, Box<dyn TA>).value_a(), 1);
396        assert_eq!(get!(t, Box<dyn TB>).value_b(), 2.0);
397
398        let mut t = t;
399        get_mut!(t, Box<dyn TA>).set_a(3);
400        get_mut!(t, Box<dyn TB>).set_b(4.0);
401        assert_eq!(get!(t, Box<dyn TA>).value_a(), 3);
402        assert_eq!(get!(t, Box<dyn TB>).value_b(), 4.0);
403    }
404
405    #[test]
406    fn derive_static_trait() {
407        extern crate std;
408        use std::fmt::Debug;
409        // trait TA and struct A
410        trait TA {
411            fn value_a(&self) -> i32;
412        }
413        #[derive(Debug, PartialEq)]
414        struct A {
415            v: i32,
416        }
417        impl TA for A {
418            fn value_a(&self) -> i32 {
419                self.v
420            }
421        }
422        // trait TB and struct B
423        trait TB {
424            fn value_b(&self) -> f32;
425        }
426        #[derive(Debug, PartialEq)]
427        struct B {
428            v: f32,
429        }
430        impl TB for B {
431            fn value_b(&self) -> f32 {
432                self.v
433            }
434        }
435        // instance and asserts
436        #[derive(crate::Typemap)]
437        struct Test(&'static dyn TA, &'static dyn TB);
438        let a: &'static dyn TA = &A { v: 1 };
439        let b: &'static dyn TB = &B { v: 2.0 };
440        let t = Test(a, b);
441        assert_eq!(get!(t, &'static dyn TA).value_a(), 1);
442        assert_eq!(get!(t, &'static dyn TB).value_b(), 2.0);
443    }
444
445    #[test]
446    fn derive_static_trait_mut() {
447        extern crate std;
448        use std::fmt::Debug;
449        // trait TA and struct A
450        trait TA {
451            fn value_a(&self) -> i32;
452        }
453        #[derive(Debug, PartialEq)]
454        struct A {
455            v: i32,
456        }
457        impl TA for A {
458            fn value_a(&self) -> i32 {
459                self.v
460            }
461        }
462        // trait TB and struct B
463        trait TB {
464            fn value_b(&self) -> f32;
465        }
466        #[derive(Debug, PartialEq)]
467        struct B {
468            v: f32,
469        }
470        impl TB for B {
471            fn value_b(&self) -> f32 {
472                self.v
473            }
474        }
475        // instance and asserts
476        #[derive(crate::Typemap)]
477        #[typemap_mut]
478        struct Test(&'static dyn TA, &'static dyn TB);
479        let a: &'static dyn TA = &A { v: 1 };
480        let b: &'static dyn TB = &B { v: 2.0 };
481        let t = Test(a, b);
482        assert_eq!(get!(t, &'static dyn TA).value_a(), 1);
483        assert_eq!(get!(t, &'static dyn TB).value_b(), 2.0);
484
485        let mut t = t;
486        let c: &'static dyn TA = &A { v: 3 };
487        let d: &'static dyn TB = &B { v: 4.0 };
488
489        *get_mut!(t, &'static dyn TA) = c;
490        *get_mut!(t, &'static dyn TB) = d;
491
492        assert_eq!(get!(t, &'static dyn TA).value_a(), 3);
493        assert_eq!(get!(t, &'static dyn TB).value_b(), 4.0);
494    }
495}