util.rs (2596B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 4 5 use darling::{FromDeriveInput, FromField}; 6 use proc_macro2::{Span, TokenStream}; 7 use quote::{quote, TokenStreamExt}; 8 use syn::{self, parse_quote, DeriveInput, Field, Ident, WherePredicate}; 9 use synstructure::{self, BindStyle, BindingInfo, VariantInfo}; 10 11 pub(crate) fn parse_input_attrs<A>(input: &DeriveInput) -> A 12 where 13 A: FromDeriveInput, 14 { 15 match A::from_derive_input(input) { 16 Ok(attrs) => attrs, 17 Err(e) => panic!("failed to parse input attributes: {}", e), 18 } 19 } 20 21 pub(crate) fn parse_field_attrs<A>(field: &Field) -> A 22 where 23 A: FromField, 24 { 25 match A::from_field(field) { 26 Ok(attrs) => attrs, 27 Err(e) => panic!("failed to parse field attributes: {}", e), 28 } 29 } 30 31 pub(crate) fn add_predicate(where_clause: &mut Option<syn::WhereClause>, pred: WherePredicate) { 32 where_clause 33 .get_or_insert(parse_quote!(where)) 34 .predicates 35 .push(pred); 36 } 37 38 pub(crate) fn fmap2_match<F, G>( 39 input: &DeriveInput, 40 bind_style: BindStyle, 41 mut f: F, 42 mut g: G, 43 ) -> TokenStream 44 where 45 F: FnMut(&BindingInfo) -> TokenStream, 46 G: FnMut(&BindingInfo) -> Option<TokenStream>, 47 { 48 let mut s = synstructure::Structure::new(input); 49 s.variants_mut().iter_mut().for_each(|v| { 50 v.bind_with(|_| bind_style); 51 }); 52 s.each_variant(|variant| { 53 let (mapped, mapped_fields) = value(variant, "mapped"); 54 let fields_pairs = variant.bindings().iter().zip(mapped_fields.iter()); 55 let mut computations = quote!(); 56 computations.append_all(fields_pairs.map(|(field, mapped_field)| { 57 let expr = f(field); 58 quote! { let #mapped_field = #expr; } 59 })); 60 computations.append_all( 61 mapped_fields 62 .iter() 63 .map(|mapped_field| match g(mapped_field) { 64 Some(expr) => quote! { let #mapped_field = #expr; }, 65 None => quote!(), 66 }), 67 ); 68 computations.append_all(mapped); 69 Some(computations) 70 }) 71 } 72 73 fn value<'a>(variant: &'a VariantInfo, prefix: &str) -> (TokenStream, Vec<BindingInfo<'a>>) { 74 let mut v = variant.clone(); 75 v.bindings_mut().iter_mut().for_each(|b| { 76 b.binding = Ident::new(&format!("{}_{}", b.binding, prefix), Span::call_site()) 77 }); 78 v.bind_with(|_| BindStyle::Move); 79 (v.pat(), v.bindings().to_vec()) 80 }