From 26179b3660f9583ec6859d8e49e676861546d4ec Mon Sep 17 00:00:00 2001 From: Jonathan Chan Date: Mon, 19 Jun 2017 15:35:58 -0700 Subject: [PATCH] style: Have OneOrMoreSeparated replace OneOrMoreCommaSeparated. A future patch series has some values that should be separated by spaces. This allows us to re-use the code for serialization, but the types do get a little clunky. The separator is now indicated with an associated type. --- components/style/counter_style/mod.rs | 6 ++- components/style/font_face.rs | 6 ++- components/style/parser.rs | 6 ++- components/style/values/generics/mod.rs | 6 ++- components/style_traits/lib.rs | 2 +- components/style_traits/values.rs | 52 ++++++++++++++++++++++--- 6 files changed, 64 insertions(+), 14 deletions(-) diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs index cfe35bccf05e..05c462636e0b 100644 --- a/components/style/counter_style/mod.rs +++ b/components/style/counter_style/mod.rs @@ -19,7 +19,7 @@ use std::ascii::AsciiExt; use std::borrow::Cow; use std::fmt; use std::ops::Range; -use style_traits::{ToCss, OneOrMoreCommaSeparated, ParseError, StyleParseError}; +use style_traits::{ToCss, OneOrMoreSeparated, CommaSeparator, ParseError, StyleParseError}; use values::CustomIdent; /// Parse the prelude of an @counter-style rule @@ -552,7 +552,9 @@ pub struct AdditiveTuple { pub symbol: Symbol, } -impl OneOrMoreCommaSeparated for AdditiveTuple {} +impl OneOrMoreSeparated for AdditiveTuple { + type S = CommaSeparator; +} impl Parse for AdditiveTuple { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { diff --git a/components/style/font_face.rs b/components/style/font_face.rs index 662b0c733cee..e8801b5a1254 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -20,7 +20,7 @@ use parser::{ParserContext, log_css_error, Parse}; use selectors::parser::SelectorParseError; use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard}; use std::fmt; -use style_traits::{ToCss, OneOrMoreCommaSeparated, ParseError, StyleParseError}; +use style_traits::{ToCss, OneOrMoreSeparated, CommaSeparator, ParseError, StyleParseError}; use values::specified::url::SpecifiedUrl; /// A source for a font-face rule. @@ -34,7 +34,9 @@ pub enum Source { Local(FamilyName), } -impl OneOrMoreCommaSeparated for Source {} +impl OneOrMoreSeparated for Source { + type S = CommaSeparator; +} /// A `UrlSource` represents a font-face source that has been specified with a /// `url()` function. diff --git a/components/style/parser.rs b/components/style/parser.rs index 0145c128eca3..86e7b6d41993 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -7,7 +7,7 @@ use context::QuirksMode; use cssparser::{Parser, SourcePosition, UnicodeRange}; use error_reporting::{ParseErrorReporter, ContextualParseError}; -use style_traits::{OneOrMoreCommaSeparated, ParseError, ParsingMode}; +use style_traits::{OneOrMoreSeparated, IsCommaSeparator, ParseError, ParsingMode}; #[cfg(feature = "gecko")] use style_traits::{PARSING_MODE_DEFAULT, PARSING_MODE_ALLOW_UNITLESS_LENGTH, PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES}; use stylesheets::{CssRuleType, Origin, UrlExtraData, Namespaces}; @@ -161,7 +161,9 @@ pub trait Parse : Sized { -> Result>; } -impl Parse for Vec where T: Parse + OneOrMoreCommaSeparated { +impl Parse for Vec where T: Parse + OneOrMoreSeparated, + ::S: IsCommaSeparator +{ fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { input.parse_comma_separated(|input| T::parse(context, input)) diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 81cebbffb811..f42dc875260a 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -9,7 +9,7 @@ use counter_style::{Symbols, parse_counter_style_name}; use cssparser::Parser; use parser::{Parse, ParserContext}; use std::fmt; -use style_traits::{OneOrMoreCommaSeparated, ToCss, ParseError, StyleParseError}; +use style_traits::{OneOrMoreSeparated, CommaSeparator, ToCss, ParseError, StyleParseError}; use super::CustomIdent; use values::specified::url::SpecifiedUrl; @@ -123,7 +123,9 @@ pub struct FontSettingTag { pub value: T, } -impl OneOrMoreCommaSeparated for FontSettingTag {} +impl OneOrMoreSeparated for FontSettingTag { + type S = CommaSeparator; +} impl ToCss for FontSettingTag { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { diff --git a/components/style_traits/lib.rs b/components/style_traits/lib.rs index a9934e5b56f8..f3f9b1e8d037 100644 --- a/components/style_traits/lib.rs +++ b/components/style_traits/lib.rs @@ -71,7 +71,7 @@ pub mod values; #[macro_use] pub mod viewport; -pub use values::{ToCss, OneOrMoreCommaSeparated}; +pub use values::{ToCss, OneOrMoreSeparated, CommaSeparator, SpaceSeparator, IsCommaSeparator}; pub use viewport::HasViewportPercentage; /// The error type for all CSS parsing routines. diff --git a/components/style_traits/values.rs b/components/style_traits/values.rs index 3a587ac81f93..8f17edf4cafd 100644 --- a/components/style_traits/values.rs +++ b/components/style_traits/values.rs @@ -55,17 +55,59 @@ impl ToCss for String { } } -/// Marker trait to automatically implement ToCss for Vec. -pub trait OneOrMoreCommaSeparated {} +/// Type used as the associated type in the `OneOrMoreSeparated` trait on a +/// type to indicate that a serialized list of elements of this type is +/// separated by commas. +pub struct CommaSeparator; + +/// Type used as the associated type in the `OneOrMoreSeparated` trait on a +/// type to indicate that a serialized list of elements of this type is +/// separated by spaces. +pub struct SpaceSeparator; + +/// A trait satisfied by the types corresponding to separators. +pub trait Separator { + /// The separator string that the satisfying separator type corresponds to. + fn separator() -> &'static str; +} + +impl Separator for CommaSeparator { + fn separator() -> &'static str { + ", " + } +} + +impl Separator for SpaceSeparator { + fn separator() -> &'static str { + " " + } +} + +/// Trait that indicates that satisfying separator types are comma separators. +/// This seems kind of redundant, but we aren't able to express type equality +/// constraints yet. +/// https://github.com/rust-lang/rust/issues/20041 +pub trait IsCommaSeparator {} + +impl IsCommaSeparator for CommaSeparator {} -impl OneOrMoreCommaSeparated for UnicodeRange {} +/// Marker trait on T to automatically implement ToCss for Vec when T's are +/// separated by some delimiter `delim`. +pub trait OneOrMoreSeparated { + /// Associated type indicating which separator is used. + type S: Separator; +} + +impl OneOrMoreSeparated for UnicodeRange { + type S = CommaSeparator; +} -impl ToCss for Vec where T: ToCss + OneOrMoreCommaSeparated { +impl ToCss for Vec where T: ToCss + OneOrMoreSeparated { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { let mut iter = self.iter(); iter.next().unwrap().to_css(dest)?; for item in iter { - dest.write_str(", ")?; + dest.write_str(::S::separator())?; item.to_css(dest)?; } Ok(())