Support #[animation(error)] in more cases

The trait ToAnimatedZero now supports it, and it now applies to things with generics,
avoiding the trait bounds for field types of the variant on which it applies.
This commit is contained in:
Anthony Ramine 2017-08-25 22:40:24 +02:00
parent dc827c14e1
commit af560a8fab
4 changed files with 31 additions and 90 deletions

View file

@ -48,9 +48,10 @@ use values::animated::effects::TextShadowList as AnimatedTextShadowList;
use values::computed::{Angle, BorderCornerRadius, CalcLengthOrPercentage};
use values::computed::{ClipRect, Context, ComputedUrl, ComputedValueAsSpecified};
use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
use values::computed::{LengthOrPercentageOrNone, MaxLength, MozLength, NonNegativeAu};
use values::computed::{LengthOrPercentageOrNone, MaxLength, NonNegativeAu};
use values::computed::{NonNegativeNumber, Number, NumberOrPercentage, Percentage};
use values::computed::{PositiveIntegerOrAuto, ToComputedValue};
#[cfg(feature = "gecko")] use values::computed::MozLength;
use values::computed::length::{NonNegativeLengthOrAuto, NonNegativeLengthOrNormal};
use values::computed::length::NonNegativeLengthOrPercentage;
use values::distance::{ComputeSquaredDistance, SquaredDistance};
@ -939,54 +940,6 @@ impl ToAnimatedZero for LengthOrPercentageOrNone {
}
}
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
impl Animate for MozLength {
#[inline]
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
match (self, other) {
(
&MozLength::LengthOrPercentageOrAuto(ref this),
&MozLength::LengthOrPercentageOrAuto(ref other),
) => {
Ok(MozLength::LengthOrPercentageOrAuto(
this.animate(other, procedure)?,
))
}
_ => Err(()),
}
}
}
impl ToAnimatedZero for MozLength {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
match *self {
MozLength::LengthOrPercentageOrAuto(ref length) => {
Ok(MozLength::LengthOrPercentageOrAuto(length.to_animated_zero()?))
},
_ => Err(())
}
}
}
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
impl Animate for MaxLength {
#[inline]
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
match (self, other) {
(
&MaxLength::LengthOrPercentageOrNone(ref this),
&MaxLength::LengthOrPercentageOrNone(ref other),
) => {
Ok(MaxLength::LengthOrPercentageOrNone(
this.animate(other, procedure)?,
))
},
_ => Err(()),
}
}
}
impl ToAnimatedZero for MaxLength {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }

View file

@ -695,28 +695,14 @@ pub type NonNegativeLengthOrNumber = Either<NonNegativeLength, NonNegativeNumber
/// See values/specified/length.rs for more details.
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Debug, PartialEq, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq)]
#[derive(ToAnimatedZero, ToCss)]
pub enum MozLength {
LengthOrPercentageOrAuto(LengthOrPercentageOrAuto),
#[animation(error)]
ExtremumLength(ExtremumLength),
}
impl ComputeSquaredDistance for MozLength {
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
match (self, other) {
(&MozLength::LengthOrPercentageOrAuto(ref this), &MozLength::LengthOrPercentageOrAuto(ref other)) => {
this.compute_squared_distance(other)
},
_ => {
// FIXME(nox): Should this return `Ok(SquaredDistance::Value(1.))`
// when `self` and `other` are the same extremum value?
Err(())
},
}
}
}
impl MozLength {
/// Returns the `auto` value.
pub fn auto() -> Self {
@ -755,28 +741,13 @@ impl ToComputedValue for specified::MozLength {
/// See values/specified/length.rs for more details.
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Debug, PartialEq, ToCss)]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToCss)]
pub enum MaxLength {
LengthOrPercentageOrNone(LengthOrPercentageOrNone),
#[animation(error)]
ExtremumLength(ExtremumLength),
}
impl ComputeSquaredDistance for MaxLength {
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
match (self, other) {
(&MaxLength::LengthOrPercentageOrNone(ref this), &MaxLength::LengthOrPercentageOrNone(ref other)) => {
this.compute_squared_distance(other)
},
_ => {
// FIXME(nox): Should this return `Ok(SquaredDistance::Value(1.))`
// when `self` and `other` are the same extremum value?
Err(())
},
}
}
}
impl MaxLength {
/// Returns the `none` value.
pub fn none() -> Self {

View file

@ -43,7 +43,7 @@ pub fn derive_to_animated_value(stream: TokenStream) -> TokenStream {
to_animated_value::derive(input).to_string().parse().unwrap()
}
#[proc_macro_derive(ToAnimatedZero)]
#[proc_macro_derive(ToAnimatedZero, attributes(animation))]
pub fn derive_to_animated_zero(stream: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&stream.to_string()).unwrap();
to_animated_zero::derive(input).to_string().parse().unwrap()

View file

@ -2,10 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use animate::AnimateAttrs;
use cg;
use quote;
use syn;
use synstructure::BindStyle;
use synstructure::{self, BindStyle};
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
let name = &input.ident;
@ -13,9 +14,25 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
let (impl_generics, ty_generics, mut where_clause) =
cg::trait_parts(&input, trait_path);
let to_body = cg::fmap_match(&input, BindStyle::Ref, |binding| {
where_clause.add_trait_bound(binding.field.ty.clone());
quote! { ::values::animated::ToAnimatedZero::to_animated_zero(#binding)? }
let bind_opts = BindStyle::Ref.into();
let to_body = synstructure::each_variant(&input, &bind_opts, |bindings, variant| {
let attrs = cg::parse_variant_attrs::<AnimateAttrs>(variant);
if attrs.error {
return Some(quote! { Err(()) });
}
let name = cg::variant_ctor(&input, variant);
let (mapped, mapped_bindings) = cg::value(&name, variant, "mapped");
let bindings_pairs = bindings.into_iter().zip(mapped_bindings);
let mut computations = quote!();
computations.append_all(bindings_pairs.map(|(binding, mapped_binding)| {
where_clause.add_trait_bound(binding.field.ty.clone());
quote! {
let #mapped_binding =
::values::animated::ToAnimatedZero::to_animated_zero(#binding)?;
}
}));
computations.append(quote! { Ok(#mapped) });
Some(computations)
});
quote! {
@ -23,9 +40,9 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
#[allow(unused_variables)]
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(match *self {
match *self {
#to_body
})
}
}
}
}