# synstructure [![Latest Version](https://img.shields.io/crates/v/synstructure.svg)](https://crates.io/crates/synstructure) [![Documentation](https://docs.rs/synstructure/badge.svg)](https://docs.rs/synstructure) [![Build Status](https://travis-ci.org/mystor/synstructure.svg?branch=master)](https://travis-ci.org/mystor/synstructure) [![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) > NOTE: What follows is an exerpt from the module level documentation. For full > details read the docs on [docs.rs](https://docs.rs/synstructure/) This crate provides helper types for matching against enum variants, and extracting bindings to each of the fields in the deriving Struct or Enum in a generic way. If you are writing a `#[derive]` which needs to perform some operation on every field, then you have come to the right place! # Example: `WalkFields` ### Trait Implementation ```rust pub trait WalkFields: std::any::Any { fn walk_fields(&self, walk: &mut FnMut(&WalkFields)); } impl WalkFields for i32 { fn walk_fields(&self, _walk: &mut FnMut(&WalkFields)) {} } ``` ### Custom Derive ```rust #[macro_use] extern crate synstructure; #[macro_use] extern crate quote; extern crate proc_macro2; fn walkfields_derive(s: synstructure::Structure) -> proc_macro2::TokenStream { let body = s.each(|bi| quote!{ walk(#bi) }); s.bound_impl(quote!(example_traits::WalkFields), quote!{ fn walk_fields(&self, walk: &mut FnMut(&example_traits::WalkFields)) { match *self { #body } } }) } decl_derive!([WalkFields] => walkfields_derive); /* * Test Case */ fn main() { test_derive! { walkfields_derive { enum A { B(i32, T), C(i32), } } expands to { #[allow(non_upper_case_globals)] const _DERIVE_example_traits_WalkFields_FOR_A: () = { extern crate example_traits; impl example_traits::WalkFields for A where T: example_traits::WalkFields { fn walk_fields(&self, walk: &mut FnMut(&example_traits::WalkFields)) { match *self { A::B(ref __binding_0, ref __binding_1,) => { { walk(__binding_0) } { walk(__binding_1) } } A::C(ref __binding_0,) => { { walk(__binding_0) } } } } } }; } } } ``` # Example: `Interest` ### Trait Implementation ```rust pub trait Interest { fn interesting(&self) -> bool; } impl Interest for i32 { fn interesting(&self) -> bool { *self > 0 } } ``` ### Custom Derive ```rust #[macro_use] extern crate synstructure; #[macro_use] extern crate quote; extern crate proc_macro2; fn interest_derive(mut s: synstructure::Structure) -> proc_macro2::TokenStream { let body = s.fold(false, |acc, bi| quote!{ #acc || example_traits::Interest::interesting(#bi) }); s.bound_impl(quote!(example_traits::Interest), quote!{ fn interesting(&self) -> bool { match *self { #body } } }) } decl_derive!([Interest] => interest_derive); /* * Test Case */ fn main() { test_derive!{ interest_derive { enum A { B(i32, T), C(i32), } } expands to { #[allow(non_upper_case_globals)] const _DERIVE_example_traits_Interest_FOR_A: () = { extern crate example_traits; impl example_traits::Interest for A where T: example_traits::Interest { fn interesting(&self) -> bool { match *self { A::B(ref __binding_0, ref __binding_1,) => { false || example_traits::Interest::interesting(__binding_0) || example_traits::Interest::interesting(__binding_1) } A::C(ref __binding_0,) => { false || example_traits::Interest::interesting(__binding_0) } } } } }; } } } ``` For more example usage, consider investigating the `abomonation_derive` crate, which makes use of this crate, and is fairly simple.