/* 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 crate::animate::{AnimationFieldAttrs, AnimationInputAttrs, AnimationVariantAttrs}; use derive_common::cg; use proc_macro2::TokenStream; use quote::TokenStreamExt; use syn; use synstructure; pub fn derive(mut input: syn::DeriveInput) -> TokenStream { let animation_input_attrs = cg::parse_input_attrs::(&input); let no_bound = animation_input_attrs.no_bound.unwrap_or_default(); let mut where_clause = input.generics.where_clause.take(); for param in input.generics.type_params() { if !no_bound.iter().any(|name| name.is_ident(¶m.ident)) { cg::add_predicate( &mut where_clause, parse_quote!(#param: crate::values::animated::ToAnimatedZero), ); } } let to_body = synstructure::Structure::new(&input).each_variant(|variant| { let attrs = cg::parse_variant_attrs_from_ast::(&variant.ast()); if attrs.error { return Some(quote! { Err(()) }); } let (mapped, mapped_bindings) = cg::value(variant, "mapped"); let bindings_pairs = variant.bindings().iter().zip(mapped_bindings); let mut computations = quote!(); computations.append_all(bindings_pairs.map(|(binding, mapped_binding)| { let field_attrs = cg::parse_field_attrs::(&binding.ast()); if field_attrs.constant { quote! { let #mapped_binding = std::clone::Clone::clone(#binding); } } else { quote! { let #mapped_binding = crate::values::animated::ToAnimatedZero::to_animated_zero(#binding)?; } } })); computations.append_all(quote! { Ok(#mapped) }); Some(computations) }); input.generics.where_clause = where_clause; let name = &input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); quote! { impl #impl_generics crate::values::animated::ToAnimatedZero for #name #ty_generics #where_clause { #[allow(unused_variables)] #[inline] fn to_animated_zero(&self) -> Result { match *self { #to_body } } } } }