README.md
1# synstructure
2
3[](https://crates.io/crates/synstructure)
4[](https://docs.rs/synstructure)
5[](https://travis-ci.org/mystor/synstructure)
6[](https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html)
7
8> NOTE: What follows is an exerpt from the module level documentation. For full
9> details read the docs on [docs.rs](https://docs.rs/synstructure/)
10
11This crate provides helper types for matching against enum variants, and
12extracting bindings to each of the fields in the deriving Struct or Enum in
13a generic way.
14
15If you are writing a `#[derive]` which needs to perform some operation on
16every field, then you have come to the right place!
17
18# Example: `WalkFields`
19### Trait Implementation
20```rust
21pub trait WalkFields: std::any::Any {
22 fn walk_fields(&self, walk: &mut FnMut(&WalkFields));
23}
24impl WalkFields for i32 {
25 fn walk_fields(&self, _walk: &mut FnMut(&WalkFields)) {}
26}
27```
28
29### Custom Derive
30```rust
31#[macro_use]
32extern crate synstructure;
33#[macro_use]
34extern crate quote;
35extern crate proc_macro2;
36
37fn walkfields_derive(s: synstructure::Structure) -> proc_macro2::TokenStream {
38 let body = s.each(|bi| quote!{
39 walk(#bi)
40 });
41
42 s.bound_impl(quote!(example_traits::WalkFields), quote!{
43 fn walk_fields(&self, walk: &mut FnMut(&example_traits::WalkFields)) {
44 match *self { #body }
45 }
46 })
47}
48decl_derive!([WalkFields] => walkfields_derive);
49
50/*
51 * Test Case
52 */
53fn main() {
54 test_derive! {
55 walkfields_derive {
56 enum A<T> {
57 B(i32, T),
58 C(i32),
59 }
60 }
61 expands to {
62 const _: () = {
63 extern crate example_traits;
64 impl<T> example_traits::WalkFields for A<T>
65 where T: example_traits::WalkFields
66 {
67 fn walk_fields(&self, walk: &mut FnMut(&example_traits::WalkFields)) {
68 match *self {
69 A::B(ref __binding_0, ref __binding_1,) => {
70 { walk(__binding_0) }
71 { walk(__binding_1) }
72 }
73 A::C(ref __binding_0,) => {
74 { walk(__binding_0) }
75 }
76 }
77 }
78 }
79 };
80 }
81 }
82}
83```
84
85# Example: `Interest`
86### Trait Implementation
87```rust
88pub trait Interest {
89 fn interesting(&self) -> bool;
90}
91impl Interest for i32 {
92 fn interesting(&self) -> bool { *self > 0 }
93}
94```
95
96### Custom Derive
97```rust
98#[macro_use]
99extern crate synstructure;
100#[macro_use]
101extern crate quote;
102extern crate proc_macro2;
103
104fn interest_derive(mut s: synstructure::Structure) -> proc_macro2::TokenStream {
105 let body = s.fold(false, |acc, bi| quote!{
106 #acc || example_traits::Interest::interesting(#bi)
107 });
108
109 s.bound_impl(quote!(example_traits::Interest), quote!{
110 fn interesting(&self) -> bool {
111 match *self {
112 #body
113 }
114 }
115 })
116}
117decl_derive!([Interest] => interest_derive);
118
119/*
120 * Test Case
121 */
122fn main() {
123 test_derive!{
124 interest_derive {
125 enum A<T> {
126 B(i32, T),
127 C(i32),
128 }
129 }
130 expands to {
131 const _: () = {
132 extern crate example_traits;
133 impl<T> example_traits::Interest for A<T>
134 where T: example_traits::Interest
135 {
136 fn interesting(&self) -> bool {
137 match *self {
138 A::B(ref __binding_0, ref __binding_1,) => {
139 false ||
140 example_traits::Interest::interesting(__binding_0) ||
141 example_traits::Interest::interesting(__binding_1)
142 }
143 A::C(ref __binding_0,) => {
144 false ||
145 example_traits::Interest::interesting(__binding_0)
146 }
147 }
148 }
149 }
150 };
151 }
152 }
153}
154```
155
156For more example usage, consider investigating the `abomonation_derive` crate,
157which makes use of this crate, and is fairly simple.
158