diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs index 05c462636e0..a2b681dc262 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, OneOrMoreSeparated, CommaSeparator, ParseError, StyleParseError}; +use style_traits::{Comma, OneOrMoreSeparated, ParseError, StyleParseError, ToCss}; use values::CustomIdent; /// Parse the prelude of an @counter-style rule @@ -553,7 +553,7 @@ pub struct AdditiveTuple { } impl OneOrMoreSeparated for AdditiveTuple { - type S = CommaSeparator; + type S = Comma; } impl Parse for AdditiveTuple { diff --git a/components/style/font_face.rs b/components/style/font_face.rs index 2c2f5882f11..5737d4ee60c 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -22,7 +22,7 @@ use properties::longhands::font_language_override; use selectors::parser::SelectorParseError; use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard}; use std::fmt; -use style_traits::{ToCss, OneOrMoreSeparated, CommaSeparator, ParseError, StyleParseError}; +use style_traits::{Comma, OneOrMoreSeparated, ParseError, StyleParseError, ToCss}; use values::specified::url::SpecifiedUrl; /// A source for a font-face rule. @@ -37,7 +37,7 @@ pub enum Source { } impl OneOrMoreSeparated for Source { - type S = CommaSeparator; + type S = Comma; } /// A `UrlSource` represents a font-face source that has been specified with a diff --git a/components/style/parser.rs b/components/style/parser.rs index 86e7b6d4199..d1121533170 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::{OneOrMoreSeparated, IsCommaSeparator, ParseError, ParsingMode}; +use style_traits::{OneOrMoreSeparated, ParseError, ParsingMode, Separator}; #[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,12 +161,14 @@ pub trait Parse : Sized { -> Result>; } -impl Parse for Vec where T: Parse + OneOrMoreSeparated, - ::S: IsCommaSeparator +impl Parse for Vec +where + T: Parse + OneOrMoreSeparated, + ::S: Separator, { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - input.parse_comma_separated(|input| T::parse(context, input)) + ::S::parse(input, |i| T::parse(context, i)) } } diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index da3d6dc5212..1a5ad79afea 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::{OneOrMoreSeparated, CommaSeparator, ToCss, ParseError, StyleParseError}; +use style_traits::{Comma, OneOrMoreSeparated, ParseError, StyleParseError, ToCss}; use super::CustomIdent; use values::specified::url::SpecifiedUrl; @@ -125,7 +125,7 @@ pub struct FontSettingTag { } impl OneOrMoreSeparated for FontSettingTag { - type S = CommaSeparator; + type S = Comma; } impl ToCss for FontSettingTag { diff --git a/components/style_traits/lib.rs b/components/style_traits/lib.rs index f3f9b1e8d03..feebf80bfdc 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, OneOrMoreSeparated, CommaSeparator, SpaceSeparator, IsCommaSeparator}; +pub use values::{Comma, OneOrMoreSeparated, Separator, Space, ToCss}; 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 5f8760ea58b..5ae48def781 100644 --- a/components/style_traits/values.rs +++ b/components/style_traits/values.rs @@ -5,7 +5,7 @@ //! Helper types and traits for the handling of CSS values. use app_units::Au; -use cssparser::{UnicodeRange, serialize_string}; +use cssparser::{ParseError, Parser, UnicodeRange, serialize_string}; use std::fmt::{self, Write}; /// Serialises a value according to its CSS representation. @@ -184,38 +184,69 @@ where /// 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; +pub struct Comma; /// 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; +pub struct Space; /// 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; + + /// Parses a sequence of values separated by this separator. + /// + /// The given closure is called repeatedly for each item in the sequence. + /// + /// Successful results are accumulated in a vector. + /// + /// This method returns `Err(_)` the first time a closure does or if + /// the separators aren't correct. + fn parse<'i, 't, F, T, E>( + parser: &mut Parser<'i, 't>, + parse_one: F, + ) -> Result, ParseError<'i, E>> + where + F: for<'tt> FnMut(&mut Parser<'i, 'tt>) -> Result>; } -impl Separator for CommaSeparator { +impl Separator for Comma { fn separator() -> &'static str { ", " } -} -impl Separator for SpaceSeparator { - fn separator() -> &'static str { - " " + fn parse<'i, 't, F, T, E>( + input: &mut Parser<'i, 't>, + parse_one: F, + ) -> Result, ParseError<'i, E>> + where + F: for<'tt> FnMut(&mut Parser<'i, 'tt>) -> Result> + { + input.parse_comma_separated(parse_one) } } -/// 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 Separator for Space { + fn separator() -> &'static str { + " " + } -impl IsCommaSeparator for CommaSeparator {} + fn parse<'i, 't, F, T, E>( + input: &mut Parser<'i, 't>, + mut parse_one: F, + ) -> Result, ParseError<'i, E>> + where + F: for<'tt> FnMut(&mut Parser<'i, 'tt>) -> Result> + { + let mut results = vec![parse_one(input)?]; + while let Ok(item) = input.try(&mut parse_one) { + results.push(item); + } + Ok(results) + } +} /// Marker trait on T to automatically implement ToCss for Vec when T's are /// separated by some delimiter `delim`. @@ -225,7 +256,7 @@ pub trait OneOrMoreSeparated { } impl OneOrMoreSeparated for UnicodeRange { - type S = CommaSeparator; + type S = Comma; } impl ToCss for Vec where T: ToCss + OneOrMoreSeparated {