From f36a573d2dbb9c09b1ee396b8b6c7ba04f552c0a Mon Sep 17 00:00:00 2001 From: Ravi Shankar Date: Wed, 2 Nov 2016 19:46:33 +0530 Subject: [PATCH] Add an Either type for sharing specified and computed CSS types --- components/style/values/mod.rs | 70 +++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index 46d7b304d0b..f817a8f01eb 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -6,7 +6,11 @@ //! //! [values]: https://drafts.csswg.org/css-values/ -pub use cssparser::RGBA; +pub use cssparser::{RGBA, Parser}; + +use parser::Parse; +use std::fmt::{self, Debug}; +use style_traits::ToCss; macro_rules! define_numbered_css_keyword_enum { ($name: ident: $( $css: expr => $variant: ident = $value: expr ),+,) => { @@ -59,3 +63,67 @@ impl HasViewportPercentage for T where T: NoViewportPercentage { } } +#[derive(Clone, PartialEq, Copy)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub enum Either { + First(A), + Second(B), +} + +impl Debug for Either { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Either::First(ref v) => v.fmt(f), + Either::Second(ref v) => v.fmt(f), + } + } +} + +impl ToCss for Either { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match *self { + Either::First(ref v) => v.to_css(dest), + Either::Second(ref v) => v.to_css(dest), + } + } +} + +impl HasViewportPercentage for Either { + fn has_viewport_percentage(&self) -> bool { + match *self { + Either::First(ref v) => v.has_viewport_percentage(), + Either::Second(ref v) => v.has_viewport_percentage(), + } + } +} + +impl Parse for Either { + fn parse(input: &mut Parser) -> Result, ()> { + if let Ok(v) = input.try(|i| A::parse(i)) { + Ok(Either::First(v)) + } else { + B::parse(input).map(Either::Second) + } + } +} + +use self::computed::{Context, ToComputedValue}; + +impl ToComputedValue for Either { + type ComputedValue = Either; + + fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { + match *self { + Either::First(ref a) => Either::First(a.to_computed_value(context)), + Either::Second(ref a) => Either::Second(a.to_computed_value(context)), + } + } + + #[inline] + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + match *computed { + Either::First(ref a) => Either::First(ToComputedValue::from_computed_value(a)), + Either::Second(ref a) => Either::Second(ToComputedValue::from_computed_value(a)), + } + } +}