Bug 1457332: Derive ToCss for Counters. r?xidorn draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Sun, 29 Apr 2018 05:12:57 +0200
changeset 789548 f7b102dab993904a1d12e53409ff2d6eaf23f833
parent 789547 08c7837160c874d75f8d5c720e00cf9fe91ebacc
push id108276
push userbmo:emilio@crisal.io
push dateSun, 29 Apr 2018 03:14:00 +0000
reviewersxidorn
bugs1457332
milestone61.0a1
Bug 1457332: Derive ToCss for Counters. r?xidorn MozReview-Commit-ID: 1jOglcqt1Dd
servo/components/style/properties/gecko.mako.rs
servo/components/style/values/generics/counters.rs
servo/components/style/values/specified/counters.rs
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -5692,19 +5692,19 @@ clip-path
 
     % for counter_property in ["Increment", "Reset"]:
         pub fn set_counter_${counter_property.lower()}(
             &mut self,
             v: longhands::counter_${counter_property.lower()}::computed_value::T
         ) {
             unsafe {
                 bindings::Gecko_ClearAndResizeCounter${counter_property}s(&mut self.gecko, v.len() as u32);
-                for (i, &(ref name, value)) in v.iter().enumerate() {
-                    self.gecko.m${counter_property}s[i].mCounter.assign(name.0.as_slice());
-                    self.gecko.m${counter_property}s[i].mValue = value;
+                for (i, ref pair) in v.iter().enumerate() {
+                    self.gecko.m${counter_property}s[i].mCounter.assign(pair.name.0.as_slice());
+                    self.gecko.m${counter_property}s[i].mValue = pair.delta;
                 }
             }
         }
 
         pub fn copy_counter_${counter_property.lower()}_from(&mut self, other: &Self) {
             unsafe {
                 bindings::Gecko_CopyCounter${counter_property}sFrom(&mut self.gecko, &other.gecko)
             }
@@ -5712,22 +5712,26 @@ clip-path
 
         pub fn reset_counter_${counter_property.lower()}(&mut self, other: &Self) {
             self.copy_counter_${counter_property.lower()}_from(other)
         }
 
         pub fn clone_counter_${counter_property.lower()}(
             &self
         ) -> longhands::counter_${counter_property.lower()}::computed_value::T {
+            use values::generics::counters::CounterPair;
             use values::CustomIdent;
             use gecko_string_cache::Atom;
 
             longhands::counter_${counter_property.lower()}::computed_value::T::new(
                 self.gecko.m${counter_property}s.iter().map(|ref gecko_counter| {
-                    (CustomIdent(Atom::from(gecko_counter.mCounter.to_string())), gecko_counter.mValue)
+                    CounterPair {
+                        name: CustomIdent(Atom::from(gecko_counter.mCounter.to_string())),
+                        delta: gecko_counter.mValue,
+                    }
                 }).collect()
             )
         }
     % endfor
 </%self:impl_trait>
 
 <%self:impl_trait style_struct_name="UI" skip_longhands="-moz-force-broken-image-icon">
     ${impl_simple_type_with_conversion("_moz_force_broken_image_icon", "mForceBrokenImageIcon")}
--- a/servo/components/style/values/generics/counters.rs
+++ b/servo/components/style/values/generics/counters.rs
@@ -1,96 +1,76 @@
 /* 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 http://mozilla.org/MPL/2.0/. */
 
 //! Generic types for counters-related CSS values.
 
-use std::fmt;
-use std::fmt::Write;
 use std::ops::Deref;
-use style_traits::{CssWriter, ToCss};
 use values::CustomIdent;
 
+/// A name / value pair for counters.
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
+         ToComputedValue, ToCss)]
+pub struct CounterPair<Integer> {
+    /// The name of the counter.
+    pub name: CustomIdent,
+    /// The value of the counter / increment / etc.
+    pub delta: Integer,
+}
+
 /// A generic value for the `counter-increment` property.
 #[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo,
          ToComputedValue, ToCss)]
 pub struct CounterIncrement<I>(Counters<I>);
 
 impl<I> CounterIncrement<I> {
     /// Returns a new value for `counter-increment`.
     #[inline]
-    pub fn new(counters: Vec<(CustomIdent, I)>) -> Self {
+    pub fn new(counters: Vec<CounterPair<I>>) -> Self {
         CounterIncrement(Counters(counters.into_boxed_slice()))
     }
 }
 
 impl<I> Deref for CounterIncrement<I> {
-    type Target = [(CustomIdent, I)];
+    type Target = [CounterPair<I>];
 
     #[inline]
     fn deref(&self) -> &Self::Target {
         &(self.0).0
     }
 }
 
 /// A generic value for the `counter-reset` property.
 #[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo,
          ToComputedValue, ToCss)]
 pub struct CounterReset<I>(Counters<I>);
 
 impl<I> CounterReset<I> {
     /// Returns a new value for `counter-reset`.
     #[inline]
-    pub fn new(counters: Vec<(CustomIdent, I)>) -> Self {
+    pub fn new(counters: Vec<CounterPair<I>>) -> Self {
         CounterReset(Counters(counters.into_boxed_slice()))
     }
 }
 
 impl<I> Deref for CounterReset<I> {
-    type Target = [(CustomIdent, I)];
+    type Target = [CounterPair<I>];
 
     #[inline]
     fn deref(&self) -> &Self::Target {
         &(self.0).0
     }
 }
 
 /// A generic value for lists of counters.
 ///
 /// Keyword `none` is represented by an empty vector.
 #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
-         ToComputedValue)]
-pub struct Counters<I>(#[css(if_empty = "none")] Box<[(CustomIdent, I)]>);
+         ToComputedValue, ToCss)]
+pub struct Counters<I>(#[css(iterable, if_empty = "none")] Box<[CounterPair<I>]>);
 
 impl<I> Default for Counters<I> {
     #[inline]
     fn default() -> Self {
         Counters(vec![].into_boxed_slice())
     }
 }
-
-impl<I> ToCss for Counters<I>
-where
-    I: ToCss,
-{
-    #[inline]
-    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
-    where
-        W: fmt::Write,
-    {
-        if self.0.is_empty() {
-            return dest.write_str("none");
-        }
-
-        let mut first = true;
-        for &(ref name, ref value) in &*self.0 {
-            if !first {
-                dest.write_str(" ")?;
-            }
-            first = false;
-            name.to_css(dest)?;
-            dest.write_str(" ")?;
-            value.to_css(dest)?;
-        }
-        Ok(())
-    }
-}
--- a/servo/components/style/values/specified/counters.rs
+++ b/servo/components/style/values/specified/counters.rs
@@ -7,16 +7,17 @@
 #[cfg(feature = "servo")]
 use computed_values::list_style_type::T as ListStyleType;
 use cssparser::{Parser, Token};
 use parser::{Parse, ParserContext};
 use style_traits::{ParseError, StyleParseErrorKind};
 use values::CustomIdent;
 #[cfg(feature = "gecko")]
 use values::generics::CounterStyleOrNone;
+use values::generics::counters::CounterPair;
 use values::generics::counters::CounterIncrement as GenericCounterIncrement;
 use values::generics::counters::CounterReset as GenericCounterReset;
 #[cfg(feature = "gecko")]
 use values::specified::Attr;
 use values::specified::Integer;
 #[cfg(feature = "gecko")]
 use values::specified::url::SpecifiedImageUrl;
 
@@ -43,37 +44,37 @@ impl Parse for CounterReset {
         Ok(Self::new(parse_counters(context, input, 0)?))
     }
 }
 
 fn parse_counters<'i, 't>(
     context: &ParserContext,
     input: &mut Parser<'i, 't>,
     default_value: i32,
-) -> Result<Vec<(CustomIdent, Integer)>, ParseError<'i>> {
+) -> Result<Vec<CounterPair<Integer>>, ParseError<'i>> {
     if input
         .try(|input| input.expect_ident_matching("none"))
         .is_ok()
     {
         return Ok(vec![]);
     }
 
     let mut counters = Vec::new();
     loop {
         let location = input.current_source_location();
-        let counter_name = match input.next() {
+        let name = match input.next() {
             Ok(&Token::Ident(ref ident)) => CustomIdent::from_ident(location, ident, &["none"])?,
             Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
             Err(_) => break,
         };
 
-        let counter_delta = input
+        let delta = input
             .try(|input| Integer::parse(context, input))
             .unwrap_or(Integer::new(default_value));
-        counters.push((counter_name, counter_delta))
+        counters.push(CounterPair { name, delta });
     }
 
     if !counters.is_empty() {
         Ok(counters)
     } else {
         Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
     }
 }