README.md
1# synstructure
2
3[![Latest Version](https://img.shields.io/crates/v/synstructure.svg)](https://crates.io/crates/synstructure)
4[![Documentation](https://docs.rs/synstructure/badge.svg)](https://docs.rs/synstructure)
5[![Build Status](https://travis-ci.org/mystor/synstructure.svg?branch=master)](https://travis-ci.org/mystor/synstructure)
6[![Rustc Version 1.31+](https://img.shields.io/badge/rustc-1.31+-lightgray.svg)](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 #[allow(non_upper_case_globals)]
63 const _DERIVE_example_traits_WalkFields_FOR_A: () = {
64 extern crate example_traits;
65 impl<T> example_traits::WalkFields for A<T>
66 where T: example_traits::WalkFields
67 {
68 fn walk_fields(&self, walk: &mut FnMut(&example_traits::WalkFields)) {
69 match *self {
70 A::B(ref __binding_0, ref __binding_1,) => {
71 { walk(__binding_0) }
72 { walk(__binding_1) }
73 }
74 A::C(ref __binding_0,) => {
75 { walk(__binding_0) }
76 }
77 }
78 }
79 }
80 };
81 }
82 }
83}
84```
85
86# Example: `Interest`
87### Trait Implementation
88```rust
89pub trait Interest {
90 fn interesting(&self) -> bool;
91}
92impl Interest for i32 {
93 fn interesting(&self) -> bool { *self > 0 }
94}
95```
96
97### Custom Derive
98```rust
99#[macro_use]
100extern crate synstructure;
101#[macro_use]
102extern crate quote;
103extern crate proc_macro2;
104
105fn interest_derive(mut s: synstructure::Structure) -> proc_macro2::TokenStream {
106 let body = s.fold(false, |acc, bi| quote!{
107 #acc || example_traits::Interest::interesting(#bi)
108 });
109
110 s.bound_impl(quote!(example_traits::Interest), quote!{
111 fn interesting(&self) -> bool {
112 match *self {
113 #body
114 }
115 }
116 })
117}
118decl_derive!([Interest] => interest_derive);
119
120/*
121 * Test Case
122 */
123fn main() {
124 test_derive!{
125 interest_derive {
126 enum A<T> {
127 B(i32, T),
128 C(i32),
129 }
130 }
131 expands to {
132 #[allow(non_upper_case_globals)]
133 const _DERIVE_example_traits_Interest_FOR_A: () = {
134 extern crate example_traits;
135 impl<T> example_traits::Interest for A<T>
136 where T: example_traits::Interest
137 {
138 fn interesting(&self) -> bool {
139 match *self {
140 A::B(ref __binding_0, ref __binding_1,) => {
141 false ||
142 example_traits::Interest::interesting(__binding_0) ||
143 example_traits::Interest::interesting(__binding_1)
144 }
145 A::C(ref __binding_0,) => {
146 false ||
147 example_traits::Interest::interesting(__binding_0)
148 }
149 }
150 }
151 }
152 };
153 }
154 }
155}
156```
157
158For more example usage, consider investigating the `abomonation_derive` crate,
159which makes use of this crate, and is fairly simple.
160