aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/values/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/style/values/mod.rs')
-rw-r--r--components/style/values/mod.rs105
1 files changed, 104 insertions, 1 deletions
diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs
index 46d7b304d0b..485b46c82a2 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,102 @@ impl<T> HasViewportPercentage for T where T: NoViewportPercentage {
}
}
+use self::computed::ComputedValueAsSpecified;
+
+macro_rules! define_keyword_type {
+ ($name: ident, $css: expr) => {
+ #[derive(Clone, PartialEq, Copy)]
+ #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+ pub struct $name;
+
+ impl ::style_traits::ToCss for $name {
+ fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result where W: ::std::fmt::Write {
+ write!(dest, $css)
+ }
+ }
+
+ impl fmt::Debug for $name {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, $css)
+ }
+ }
+
+ impl Parse for $name {
+ fn parse(input: &mut ::cssparser::Parser) -> Result<$name, ()> {
+ input.expect_ident_matching($css).map(|_| $name)
+ }
+ }
+
+ impl ComputedValueAsSpecified for $name {}
+ impl NoViewportPercentage for $name {}
+ };
+}
+
+define_keyword_type!(None_, "none");
+define_keyword_type!(Auto, "auto");
+define_keyword_type!(Normal, "normal");
+
+#[derive(Clone, PartialEq, Copy)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub enum Either<A, B> {
+ First(A),
+ Second(B),
+}
+
+impl<A: Debug, B: Debug> Debug for Either<A, B> {
+ 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<A: ToCss, B: ToCss> ToCss for Either<A, B> {
+ fn to_css<W>(&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<A: HasViewportPercentage, B: HasViewportPercentage> HasViewportPercentage for Either<A, B> {
+ 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<A: Parse, B: Parse> Parse for Either<A, B> {
+ fn parse(input: &mut Parser) -> Result<Either<A, B>, ()> {
+ 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<A: ToComputedValue, B: ToComputedValue> ToComputedValue for Either<A, B> {
+ type ComputedValue = Either<A::ComputedValue, B::ComputedValue>;
+
+ 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)),
+ }
+ }
+}