mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 02:09:05 +02:00 
			
		
		
		
	Signed-off-by: Nico Burns <nico@nicoburns.com> Differential Revision: https://phabricator.services.mozilla.com/D221815
		
			
				
	
	
		
			80 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			80 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
use darling::{FromDeriveInput, FromField};
 | 
						|
use proc_macro2::{Span, TokenStream};
 | 
						|
use quote::{quote, TokenStreamExt};
 | 
						|
use syn::{self, parse_quote, DeriveInput, Field, Ident, WherePredicate};
 | 
						|
use synstructure::{self, BindStyle, BindingInfo, VariantInfo};
 | 
						|
 | 
						|
pub(crate) fn parse_input_attrs<A>(input: &DeriveInput) -> A
 | 
						|
where
 | 
						|
    A: FromDeriveInput,
 | 
						|
{
 | 
						|
    match A::from_derive_input(input) {
 | 
						|
        Ok(attrs) => attrs,
 | 
						|
        Err(e) => panic!("failed to parse input attributes: {}", e),
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
pub(crate) fn parse_field_attrs<A>(field: &Field) -> A
 | 
						|
where
 | 
						|
    A: FromField,
 | 
						|
{
 | 
						|
    match A::from_field(field) {
 | 
						|
        Ok(attrs) => attrs,
 | 
						|
        Err(e) => panic!("failed to parse field attributes: {}", e),
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
pub(crate) fn add_predicate(where_clause: &mut Option<syn::WhereClause>, pred: WherePredicate) {
 | 
						|
    where_clause
 | 
						|
        .get_or_insert(parse_quote!(where))
 | 
						|
        .predicates
 | 
						|
        .push(pred);
 | 
						|
}
 | 
						|
 | 
						|
pub(crate) fn fmap2_match<F, G>(
 | 
						|
    input: &DeriveInput,
 | 
						|
    bind_style: BindStyle,
 | 
						|
    mut f: F,
 | 
						|
    mut g: G,
 | 
						|
) -> TokenStream
 | 
						|
where
 | 
						|
    F: FnMut(&BindingInfo) -> TokenStream,
 | 
						|
    G: FnMut(&BindingInfo) -> Option<TokenStream>,
 | 
						|
{
 | 
						|
    let mut s = synstructure::Structure::new(input);
 | 
						|
    s.variants_mut().iter_mut().for_each(|v| {
 | 
						|
        v.bind_with(|_| bind_style);
 | 
						|
    });
 | 
						|
    s.each_variant(|variant| {
 | 
						|
        let (mapped, mapped_fields) = value(variant, "mapped");
 | 
						|
        let fields_pairs = variant.bindings().iter().zip(mapped_fields.iter());
 | 
						|
        let mut computations = quote!();
 | 
						|
        computations.append_all(fields_pairs.map(|(field, mapped_field)| {
 | 
						|
            let expr = f(field);
 | 
						|
            quote! { let #mapped_field = #expr; }
 | 
						|
        }));
 | 
						|
        computations.append_all(
 | 
						|
            mapped_fields
 | 
						|
                .iter()
 | 
						|
                .map(|mapped_field| match g(mapped_field) {
 | 
						|
                    Some(expr) => quote! { let #mapped_field = #expr; },
 | 
						|
                    None => quote!(),
 | 
						|
                }),
 | 
						|
        );
 | 
						|
        computations.append_all(mapped);
 | 
						|
        Some(computations)
 | 
						|
    })
 | 
						|
}
 | 
						|
 | 
						|
fn value<'a>(variant: &'a VariantInfo, prefix: &str) -> (TokenStream, Vec<BindingInfo<'a>>) {
 | 
						|
    let mut v = variant.clone();
 | 
						|
    v.bindings_mut().iter_mut().for_each(|b| {
 | 
						|
        b.binding = Ident::new(&format!("{}_{}", b.binding, prefix), Span::call_site())
 | 
						|
    });
 | 
						|
    v.bind_with(|_| BindStyle::Move);
 | 
						|
    (v.pat(), v.bindings().to_vec())
 | 
						|
}
 |