tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }