• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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            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