From d9278e3f6a884a681fcb37e960f96aa4cf6f3582 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 11 Aug 2014 20:06:17 +0100 Subject: [PATCH] Use Result/Err(()) instead of Option/None to indicate a CSS parse error. --- src/components/style/font_face.rs | 2 +- src/components/style/parsing_utils.rs | 21 +- .../style/properties/common_types.rs | 70 ++-- src/components/style/properties/mod.rs.mako | 332 +++++++++--------- src/components/style/selectors.rs | 8 +- src/support/css/rust-cssparser | 2 +- 6 files changed, 223 insertions(+), 212 deletions(-) diff --git a/src/components/style/font_face.rs b/src/components/style/font_face.rs index 228c5d459ae..43a5cc65dca 100644 --- a/src/components/style/font_face.rs +++ b/src/components/style/font_face.rs @@ -61,7 +61,7 @@ pub fn parse_font_face_rule(rule: AtRule, parent_rules: &mut Vec, base_ "font-family" => { // FIXME(#2802): Share code with the font-family parser. match one_component_value(value.as_slice()) { - Some(&String(ref string_value)) => { + Ok(&String(ref string_value)) => { maybe_family = Some(string_value.clone()); }, _ => { diff --git a/src/components/style/parsing_utils.rs b/src/components/style/parsing_utils.rs index df355629971..fef2506bfe2 100644 --- a/src/components/style/parsing_utils.rs +++ b/src/components/style/parsing_utils.rs @@ -7,15 +7,18 @@ use std::ascii::StrAsciiExt; use cssparser::ast::{ComponentValue, Ident, SkipWhitespaceIterable}; -pub fn one_component_value<'a>(input: &'a [ComponentValue]) -> Option<&'a ComponentValue> { +pub fn one_component_value<'a>(input: &'a [ComponentValue]) -> Result<&'a ComponentValue, ()> { let mut iter = input.skip_whitespace(); - iter.next().filtered(|_| iter.next().is_none()) -} - - -pub fn get_ident_lower(component_value: &ComponentValue) -> Option { - match component_value { - &Ident(ref value) => Some(value.as_slice().to_ascii_lower()), - _ => None, + match iter.next() { + Some(value) => if iter.next().is_none() { Ok(value) } else { Err(()) }, + None => Err(()) + } +} + + +pub fn get_ident_lower(component_value: &ComponentValue) -> Result { + match component_value { + &Ident(ref value) => Ok(value.as_slice().to_ascii_lower()), + _ => Err(()), } } diff --git a/src/components/style/properties/common_types.rs b/src/components/style/properties/common_types.rs index 6672daa1894..fc30a4036fe 100644 --- a/src/components/style/properties/common_types.rs +++ b/src/components/style/properties/common_types.rs @@ -40,32 +40,32 @@ pub mod specified { static AU_PER_PC: CSSFloat = AU_PER_PT * 12.; impl Length { #[inline] - fn parse_internal(input: &ComponentValue, negative_ok: bool) -> Option { + fn parse_internal(input: &ComponentValue, negative_ok: bool) -> Result { match input { &Dimension(ref value, ref unit) if negative_ok || value.value >= 0. => Length::parse_dimension(value.value, unit.as_slice()), - &Number(ref value) if value.value == 0. => Some(Au_(Au(0))), - _ => None + &Number(ref value) if value.value == 0. => Ok(Au_(Au(0))), + _ => Err(()) } } #[allow(dead_code)] - pub fn parse(input: &ComponentValue) -> Option { + pub fn parse(input: &ComponentValue) -> Result { Length::parse_internal(input, /* negative_ok = */ true) } - pub fn parse_non_negative(input: &ComponentValue) -> Option { + pub fn parse_non_negative(input: &ComponentValue) -> Result { Length::parse_internal(input, /* negative_ok = */ false) } - pub fn parse_dimension(value: CSSFloat, unit: &str) -> Option { + pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result { match unit.to_ascii_lower().as_slice() { - "px" => Some(Length::from_px(value)), - "in" => Some(Au_(Au((value * AU_PER_IN) as i32))), - "cm" => Some(Au_(Au((value * AU_PER_CM) as i32))), - "mm" => Some(Au_(Au((value * AU_PER_MM) as i32))), - "pt" => Some(Au_(Au((value * AU_PER_PT) as i32))), - "pc" => Some(Au_(Au((value * AU_PER_PC) as i32))), - "em" => Some(Em(value)), - "ex" => Some(Ex(value)), - _ => None + "px" => Ok(Length::from_px(value)), + "in" => Ok(Au_(Au((value * AU_PER_IN) as i32))), + "cm" => Ok(Au_(Au((value * AU_PER_CM) as i32))), + "mm" => Ok(Au_(Au((value * AU_PER_MM) as i32))), + "pt" => Ok(Au_(Au((value * AU_PER_PT) as i32))), + "pc" => Ok(Au_(Au((value * AU_PER_PC) as i32))), + "em" => Ok(Em(value)), + "ex" => Ok(Ex(value)), + _ => Err(()) } } #[inline] @@ -81,23 +81,23 @@ pub mod specified { } impl LengthOrPercentage { fn parse_internal(input: &ComponentValue, negative_ok: bool) - -> Option { + -> Result { match input { &Dimension(ref value, ref unit) if negative_ok || value.value >= 0. => Length::parse_dimension(value.value, unit.as_slice()).map(LP_Length), &ast::Percentage(ref value) if negative_ok || value.value >= 0. - => Some(LP_Percentage(value.value / 100.)), - &Number(ref value) if value.value == 0. => Some(LP_Length(Au_(Au(0)))), - _ => None + => Ok(LP_Percentage(value.value / 100.)), + &Number(ref value) if value.value == 0. => Ok(LP_Length(Au_(Au(0)))), + _ => Err(()) } } #[allow(dead_code)] #[inline] - pub fn parse(input: &ComponentValue) -> Option { + pub fn parse(input: &ComponentValue) -> Result { LengthOrPercentage::parse_internal(input, /* negative_ok = */ true) } #[inline] - pub fn parse_non_negative(input: &ComponentValue) -> Option { + pub fn parse_non_negative(input: &ComponentValue) -> Result { LengthOrPercentage::parse_internal(input, /* negative_ok = */ false) } } @@ -110,23 +110,23 @@ pub mod specified { } impl LengthOrPercentageOrAuto { fn parse_internal(input: &ComponentValue, negative_ok: bool) - -> Option { + -> Result { match input { &Dimension(ref value, ref unit) if negative_ok || value.value >= 0. => Length::parse_dimension(value.value, unit.as_slice()).map(LPA_Length), &ast::Percentage(ref value) if negative_ok || value.value >= 0. - => Some(LPA_Percentage(value.value / 100.)), - &Number(ref value) if value.value == 0. => Some(LPA_Length(Au_(Au(0)))), - &Ident(ref value) if value.as_slice().eq_ignore_ascii_case("auto") => Some(LPA_Auto), - _ => None + => Ok(LPA_Percentage(value.value / 100.)), + &Number(ref value) if value.value == 0. => Ok(LPA_Length(Au_(Au(0)))), + &Ident(ref value) if value.as_slice().eq_ignore_ascii_case("auto") => Ok(LPA_Auto), + _ => Err(()) } } #[inline] - pub fn parse(input: &ComponentValue) -> Option { + pub fn parse(input: &ComponentValue) -> Result { LengthOrPercentageOrAuto::parse_internal(input, /* negative_ok = */ true) } #[inline] - pub fn parse_non_negative(input: &ComponentValue) -> Option { + pub fn parse_non_negative(input: &ComponentValue) -> Result { LengthOrPercentageOrAuto::parse_internal(input, /* negative_ok = */ false) } } @@ -139,24 +139,24 @@ pub mod specified { } impl LengthOrPercentageOrNone { fn parse_internal(input: &ComponentValue, negative_ok: bool) - -> Option { + -> Result { match input { &Dimension(ref value, ref unit) if negative_ok || value.value >= 0. => Length::parse_dimension(value.value, unit.as_slice()).map(LPN_Length), &ast::Percentage(ref value) if negative_ok || value.value >= 0. - => Some(LPN_Percentage(value.value / 100.)), - &Number(ref value) if value.value == 0. => Some(LPN_Length(Au_(Au(0)))), - &Ident(ref value) if value.as_slice().eq_ignore_ascii_case("none") => Some(LPN_None), - _ => None + => Ok(LPN_Percentage(value.value / 100.)), + &Number(ref value) if value.value == 0. => Ok(LPN_Length(Au_(Au(0)))), + &Ident(ref value) if value.as_slice().eq_ignore_ascii_case("none") => Ok(LPN_None), + _ => Err(()) } } #[allow(dead_code)] #[inline] - pub fn parse(input: &ComponentValue) -> Option { + pub fn parse(input: &ComponentValue) -> Result { LengthOrPercentageOrNone::parse_internal(input, /* negative_ok = */ true) } #[inline] - pub fn parse_non_negative(input: &ComponentValue) -> Option { + pub fn parse_non_negative(input: &ComponentValue) -> Result { LengthOrPercentageOrNone::parse_internal(input, /* negative_ok = */ false) } } diff --git a/src/components/style/properties/mod.rs.mako b/src/components/style/properties/mod.rs.mako index 5dc6a22012d..7abc1005202 100644 --- a/src/components/style/properties/mod.rs.mako +++ b/src/components/style/properties/mod.rs.mako @@ -118,12 +118,13 @@ pub mod longhands { ${caller.body()} % if derived_from is None: pub fn parse_declared(input: &[ComponentValue], base_url: &Url) - -> Option> { + -> Result, ()> { match CSSWideKeyword::parse(input) { - Some(Some(keyword)) => Some(CSSWideKeyword(keyword)), - Some(None) => Some(CSSWideKeyword(${ - "Inherit" if THIS_STYLE_STRUCT.inherited else "Initial"})), - None => parse_specified(input, base_url), + Ok(InheritKeyword) => Ok(Inherit), + Ok(InitialKeyword) => Ok(Initial), + Ok(UnsetKeyword) => Ok(${ + "Inherit" if THIS_STYLE_STRUCT.inherited else "Initial"}), + Err(()) => parse_specified(input, base_url), } } % endif @@ -136,7 +137,7 @@ pub mod longhands { ${caller.body()} % if derived_from is None: pub fn parse_specified(_input: &[ComponentValue], _base_url: &Url) - -> Option> { + -> Result, ()> { parse(_input, _base_url).map(super::SpecifiedValue) } % endif @@ -147,7 +148,7 @@ pub mod longhands { <%self:longhand name="${name}" derived_from="${derived_from}" experimental="${experimental}"> ${caller.body()} - pub fn parse(input: &[ComponentValue], base_url: &Url) -> Option { + pub fn parse(input: &[ComponentValue], base_url: &Url) -> Result { one_component_value(input).and_then(|c| from_component_value(c, base_url)) } @@ -170,13 +171,13 @@ pub mod longhands { ${to_rust_ident(values.split()[0])} } pub fn from_component_value(v: &ComponentValue, _base_url: &Url) - -> Option { + -> Result { get_ident_lower(v).and_then(|keyword| { match keyword.as_slice() { % for value in values.split(): - "${value}" => Some(${to_rust_ident(value)}), + "${value}" => Ok(${to_rust_ident(value)}), % endfor - _ => None, + _ => Err(()), } }) } @@ -201,7 +202,7 @@ pub mod longhands { } #[inline] pub fn get_initial_value() -> computed_value::T { ${initial_value} } #[inline] pub fn from_component_value(v: &ComponentValue, _base_url: &Url) - -> Option { + -> Result { specified::${type}::${parse_method}(v) } @@ -244,14 +245,14 @@ pub mod longhands { % endfor pub fn parse_border_width(component_value: &ComponentValue, _base_url: &Url) - -> Option { + -> Result { match component_value { &Ident(ref value) => { match value.as_slice().to_ascii_lower().as_slice() { - "thin" => Some(specified::Length::from_px(1.)), - "medium" => Some(specified::Length::from_px(3.)), - "thick" => Some(specified::Length::from_px(5.)), - _ => None + "thin" => Ok(specified::Length::from_px(1.)), + "medium" => Ok(specified::Length::from_px(3.)), + "thick" => Ok(specified::Length::from_px(5.)), + _ => Err(()) } }, _ => specified::Length::parse_non_negative(component_value) @@ -267,7 +268,7 @@ pub mod longhands { #[inline] pub fn get_initial_value() -> computed_value::T { Au::from_px(3) // medium } - pub fn parse(input: &[ComponentValue], base_url: &Url) -> Option { + pub fn parse(input: &[ComponentValue], base_url: &Url) -> Result { one_component_value(input).and_then(|c| parse_border_width(c, base_url)) } #[inline] @@ -346,7 +347,7 @@ pub mod longhands { pub fn get_initial_value() -> computed_value::T { computed::LPA_Auto } #[inline] pub fn from_component_value(v: &ComponentValue, _base_url: &Url) - -> Option { + -> Result { specified::LengthOrPercentageOrAuto::parse_non_negative(v) } pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) @@ -387,18 +388,18 @@ pub mod longhands { } /// normal | | | pub fn from_component_value(input: &ComponentValue, _base_url: &Url) - -> Option { + -> Result { match input { &ast::Number(ref value) if value.value >= 0. - => Some(SpecifiedNumber(value.value)), + => Ok(SpecifiedNumber(value.value)), &ast::Percentage(ref value) if value.value >= 0. - => Some(SpecifiedLength(specified::Em(value.value / 100.))), + => Ok(SpecifiedLength(specified::Em(value.value / 100.))), &Dimension(ref value, ref unit) if value.value >= 0. => specified::Length::parse_dimension(value.value, unit.as_slice()) .map(SpecifiedLength), &Ident(ref value) if value.as_slice().eq_ignore_ascii_case("normal") - => Some(SpecifiedNormal), - _ => None, + => Ok(SpecifiedNormal), + _ => Err(()), } } pub mod computed_value { @@ -474,14 +475,14 @@ pub mod longhands { /// baseline | sub | super | top | text-top | middle | bottom | text-bottom /// | | pub fn from_component_value(input: &ComponentValue, _base_url: &Url) - -> Option { + -> Result { match input { &Ident(ref value) => { match value.as_slice().to_ascii_lower().as_slice() { % for keyword in vertical_align_keywords: - "${keyword}" => Some(Specified_${to_rust_ident(keyword)}), + "${keyword}" => Ok(Specified_${to_rust_ident(keyword)}), % endfor - _ => None, + _ => Err(()), } }, _ => specified::LengthOrPercentage::parse_non_negative(input) @@ -552,12 +553,12 @@ pub mod longhands { // normal | none | [ ]+ // TODO: , , attr(), open-quote, close-quote, no-open-quote, no-close-quote - pub fn parse(input: &[ComponentValue], _base_url: &Url) -> Option { + pub fn parse(input: &[ComponentValue], _base_url: &Url) -> Result { match one_component_value(input) { - Some(&Ident(ref keyword)) => { + Ok(&Ident(ref keyword)) => { match keyword.as_slice().to_ascii_lower().as_slice() { - "normal" => return Some(normal), - "none" => return Some(none), + "normal" => return Ok(normal), + "none" => return Ok(none), _ => () } }, @@ -568,10 +569,10 @@ pub mod longhands { match component_value { &String(ref value) => content.push(StringContent(value.clone())), - _ => return None // invalid/unsupported value + _ => return Err(()) // invalid/unsupported value } } - Some(Content(content)) + Ok(Content(content)) } // CSS 2.1, Section 13 - Paged media @@ -593,14 +594,16 @@ pub mod longhands { #[inline] pub fn get_initial_value() -> SpecifiedValue { None } - pub fn from_component_value(component_value: &ComponentValue, base_url: &Url) -> Option { + pub fn from_component_value(component_value: &ComponentValue, base_url: &Url) + -> Result { match component_value { &ast::URL(ref url) => { let image_url = parse_url(url.as_slice(), base_url); - Some(Some(image_url)) + Ok(Some(image_url)) }, - &ast::Ident(ref value) if value.as_slice().eq_ignore_ascii_case("none") => Some(None), - _ => None, + &ast::Ident(ref value) if value.as_slice().eq_ignore_ascii_case("none") + => Ok(None), + _ => Err(()), } } @@ -643,36 +646,29 @@ pub mod longhands { // FIXME(#1997, pcwalton): Support complete CSS2 syntax. pub fn parse_horizontal_and_vertical(horiz: &ComponentValue, vert: &ComponentValue) - -> Option { - let horiz = match specified::LengthOrPercentage::parse_non_negative(horiz) { - None => return None, - Some(value) => value, - }; + -> Result { + let horiz = try!(specified::LengthOrPercentage::parse_non_negative(horiz)); + let vert = try!(specified::LengthOrPercentage::parse_non_negative(vert)); - let vert = match specified::LengthOrPercentage::parse_non_negative(vert) { - None => return None, - Some(value) => value, - }; - - Some(SpecifiedValue { + Ok(SpecifiedValue { horizontal: horiz, vertical: vert, }) } - pub fn parse(input: &[ComponentValue], _: &Url) -> Option { + pub fn parse(input: &[ComponentValue], _: &Url) -> Result { let mut input_iter = input.skip_whitespace(); let horizontal = input_iter.next(); let vertical = input_iter.next(); if input_iter.next().is_some() { - return None + return Err(()) } match (horizontal, vertical) { (Some(horizontal), Some(vertical)) => { parse_horizontal_and_vertical(horizontal, vertical) } - _ => None + _ => Err(()) } } @@ -693,11 +689,11 @@ pub mod longhands { RGBA { red: 0., green: 0., blue: 0., alpha: 1. } /* black */ } pub fn parse_specified(input: &[ComponentValue], _base_url: &Url) - -> Option> { + -> Result, ()> { match one_component_value(input).and_then(Color::parse) { - Some(RGBA(rgba)) => Some(SpecifiedValue(rgba)), - Some(CurrentColor) => Some(CSSWideKeyword(Inherit)), - None => None, + Ok(RGBA(rgba)) => Ok(SpecifiedValue(rgba)), + Ok(CurrentColor) => Ok(Inherit), + Err(()) => Err(()), } } @@ -726,10 +722,10 @@ pub mod longhands { /// # /// = | [ + ] /// TODO: - pub fn parse(input: &[ComponentValue], _base_url: &Url) -> Option { + pub fn parse(input: &[ComponentValue], _base_url: &Url) -> Result { from_iter(input.skip_whitespace()) } - pub fn from_iter<'a>(mut iter: SkipWhitespaceIterator<'a>) -> Option { + pub fn from_iter<'a>(mut iter: SkipWhitespaceIterator<'a>) -> Result { let mut result = vec!(); macro_rules! add( ($value: expr, $b: expr) => { @@ -738,7 +734,7 @@ pub mod longhands { match iter.next() { Some(&Comma) => (), None => $b, - _ => return None, + _ => return Err(()), } } } @@ -767,16 +763,16 @@ pub mod longhands { result.push(FamilyName(idents.connect(" "))); break 'outer }, - _ => return None, + _ => return Err(()), } } } } } - _ => return None, + _ => return Err(()), } } - Some(result) + Ok(result) } @@ -795,30 +791,30 @@ pub mod longhands { } /// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 pub fn from_component_value(input: &ComponentValue, _base_url: &Url) - -> Option { + -> Result { match input { &Ident(ref value) => { match value.as_slice().to_ascii_lower().as_slice() { - "bold" => Some(SpecifiedWeight700), - "normal" => Some(SpecifiedWeight400), - "bolder" => Some(Bolder), - "lighter" => Some(Lighter), - _ => None, + "bold" => Ok(SpecifiedWeight700), + "normal" => Ok(SpecifiedWeight400), + "bolder" => Ok(Bolder), + "lighter" => Ok(Lighter), + _ => Err(()), } }, &Number(ref value) => match value.int_value { - Some(100) => Some(SpecifiedWeight100), - Some(200) => Some(SpecifiedWeight200), - Some(300) => Some(SpecifiedWeight300), - Some(400) => Some(SpecifiedWeight400), - Some(500) => Some(SpecifiedWeight500), - Some(600) => Some(SpecifiedWeight600), - Some(700) => Some(SpecifiedWeight700), - Some(800) => Some(SpecifiedWeight800), - Some(900) => Some(SpecifiedWeight900), - _ => None, + Some(100) => Ok(SpecifiedWeight100), + Some(200) => Ok(SpecifiedWeight200), + Some(300) => Ok(SpecifiedWeight300), + Some(400) => Ok(SpecifiedWeight400), + Some(500) => Ok(SpecifiedWeight500), + Some(600) => Ok(SpecifiedWeight600), + Some(700) => Ok(SpecifiedWeight700), + Some(800) => Ok(SpecifiedWeight800), + Some(900) => Ok(SpecifiedWeight900), + _ => Err(()), }, - _ => None + _ => Err(()) } } pub mod computed_value { @@ -890,7 +886,7 @@ pub mod longhands { /// | /// TODO: support and pub fn from_component_value(input: &ComponentValue, _base_url: &Url) - -> Option { + -> Result { specified::LengthOrPercentage::parse_non_negative(input).map(|value| { match value { specified::LP_Length(value) => value, @@ -927,7 +923,7 @@ pub mod longhands { none } /// none | [ underline || overline || line-through || blink ] - pub fn parse(input: &[ComponentValue], _base_url: &Url) -> Option { + pub fn parse(input: &[ComponentValue], _base_url: &Url) -> Result { let mut result = SpecifiedValue { underline: false, overline: false, line_through: false, }; @@ -935,22 +931,22 @@ pub mod longhands { let mut empty = true; for component_value in input.skip_whitespace() { match get_ident_lower(component_value) { - None => return None, - Some(keyword) => match keyword.as_slice() { - "underline" => if result.underline { return None } + Err(()) => return Err(()), + Ok(keyword) => match keyword.as_slice() { + "underline" => if result.underline { return Err(()) } else { empty = false; result.underline = true }, - "overline" => if result.overline { return None } + "overline" => if result.overline { return Err(()) } else { empty = false; result.overline = true }, - "line-through" => if result.line_through { return None } + "line-through" => if result.line_through { return Err(()) } else { empty = false; result.line_through = true }, - "blink" => if blink { return None } + "blink" => if blink { return Err(()) } else { empty = false; blink = true }, - "none" => return if empty { Some(result) } else { None }, - _ => return None, + "none" => return if empty { Ok(result) } else { Err(()) }, + _ => return Err(()), } } } - if !empty { Some(result) } else { None } + if !empty { Ok(result) } else { Err(()) } } @@ -1070,7 +1066,7 @@ pub mod shorthands { pub ${sub_property.ident}: Option<${sub_property.ident}::SpecifiedValue>, % endfor } - pub fn parse(input: &[ComponentValue], base_url: &Url) -> Option { + pub fn parse(input: &[ComponentValue], base_url: &Url) -> Result { ${caller.body()} } } @@ -1080,7 +1076,7 @@ pub mod shorthands { <%self:shorthand name="${name}" sub_properties="${ ' '.join(sub_property_pattern % side for side in ['top', 'right', 'bottom', 'left'])}"> - let mut iter = input.skip_whitespace().map(|c| ${parser_function}(c, base_url)); + let mut iter = input.skip_whitespace().map(|c| ${parser_function}(c, base_url).ok()); // zero or more than four values is invalid. // one value sets them all // two values set (top, bottom) and (left, right) @@ -1092,13 +1088,13 @@ pub mod shorthands { let left = iter.next().unwrap_or(right); if top.is_some() && right.is_some() && bottom.is_some() && left.is_some() && iter.next().is_none() { - Some(Longhands { + Ok(Longhands { % for side in ["top", "right", "bottom", "left"]: ${to_rust_ident(sub_property_pattern % side)}: ${side}, % endfor }) } else { - None + Err(()) } @@ -1116,46 +1112,46 @@ pub mod shorthands { for component_value in input.skip_whitespace() { if color.is_none() { match background_color::from_component_value(component_value, base_url) { - Some(v) => { + Ok(v) => { color = Some(v); any = true; continue }, - None => () + Err(()) => () } } if image.is_none() { match background_image::from_component_value(component_value, base_url) { - Some(v) => { + Ok(v) => { image = Some(v); any = true; continue }, - None => (), + Err(()) => (), } } if repeat.is_none() { match background_repeat::from_component_value(component_value, base_url) { - Some(v) => { + Ok(v) => { repeat = Some(v); any = true; continue }, - None => () + Err(()) => () } } if attachment.is_none() { match background_attachment::from_component_value(component_value, base_url) { - Some(v) => { + Ok(v) => { attachment = Some(v); any = true; continue }, - None => () + Err(()) => () } } @@ -1165,17 +1161,17 @@ pub mod shorthands { match background_position::parse_horizontal_and_vertical( saved_component_value, component_value) { - Some(v) => { + Ok(v) => { position = Some(v); any = true; continue }, - None => (), + Err(()) => (), } } // If we get here, parsing failed. - return None + return Err(()) } None => { // Save the component value. @@ -1185,7 +1181,7 @@ pub mod shorthands { } if any && last_component_value.is_none() { - Some(Longhands { + Ok(Longhands { background_color: color, background_image: image, background_position: position, @@ -1193,14 +1189,14 @@ pub mod shorthands { background_attachment: attachment, }) } else { - None + Err(()) } ${four_sides_shorthand("margin", "margin-%s", "margin_top::from_component_value")} ${four_sides_shorthand("padding", "padding-%s", "padding_top::from_component_value")} - pub fn parse_color(value: &ComponentValue, _base_url: &Url) -> Option { + pub fn parse_color(value: &ComponentValue, _base_url: &Url) -> Result { specified::CSSColor::parse(value) } ${four_sides_shorthand("border-color", "border-%s-color", "parse_color")} @@ -1209,9 +1205,9 @@ pub mod shorthands { ${four_sides_shorthand("border-width", "border-%s-width", "parse_border_width")} pub fn parse_border(input: &[ComponentValue], base_url: &Url) - -> Option<(Option, + -> Result<(Option, Option, - Option)> { + Option), ()> { let mut color = None; let mut style = None; let mut width = None; @@ -1219,25 +1215,25 @@ pub mod shorthands { for component_value in input.skip_whitespace() { if color.is_none() { match specified::CSSColor::parse(component_value) { - Some(c) => { color = Some(c); any = true; continue }, - None => () + Ok(c) => { color = Some(c); any = true; continue }, + Err(()) => () } } if style.is_none() { match border_top_style::from_component_value(component_value, base_url) { - Some(s) => { style = Some(s); any = true; continue }, - None => () + Ok(s) => { style = Some(s); any = true; continue }, + Err(()) => () } } if width.is_none() { match parse_border_width(component_value, base_url) { - Some(w) => { width = Some(w); any = true; continue }, - None => () + Ok(w) => { width = Some(w); any = true; continue }, + Err(()) => () } } - return None + return Err(()) } - if any { Some((color, style, width)) } else { None } + if any { Ok((color, style, width)) } else { Err(()) } } @@ -1286,7 +1282,7 @@ pub mod shorthands { // font-style, font-weight and font-variant. // Leaves the values to None, 'normal' is the initial value for each of them. match get_ident_lower(component_value) { - Some(ref ident) if ident.as_slice().eq_ignore_ascii_case("normal") => { + Ok(ref ident) if ident.as_slice().eq_ignore_ascii_case("normal") => { nb_normals += 1; continue; } @@ -1294,25 +1290,25 @@ pub mod shorthands { } if style.is_none() { match font_style::from_component_value(component_value, base_url) { - Some(s) => { style = Some(s); continue }, - None => () + Ok(s) => { style = Some(s); continue }, + Err(()) => () } } if weight.is_none() { match font_weight::from_component_value(component_value, base_url) { - Some(w) => { weight = Some(w); continue }, - None => () + Ok(w) => { weight = Some(w); continue }, + Err(()) => () } } if variant.is_none() { match font_variant::from_component_value(component_value, base_url) { - Some(v) => { variant = Some(v); continue }, - None => () + Ok(v) => { variant = Some(v); continue }, + Err(()) => () } } match font_size::from_component_value(component_value, base_url) { - Some(s) => { size = Some(s); break }, - None => return None + Ok(s) => { size = Some(s); break }, + Err(()) => return Err(()) } } #[inline] @@ -1323,23 +1319,23 @@ pub mod shorthands { } } if size.is_none() || (count(&style) + count(&weight) + count(&variant) + nb_normals) > 3 { - return None + return Err(()) } let mut copied_iter = iter.clone(); match copied_iter.next() { Some(&Delim('/')) => { iter = copied_iter; line_height = match iter.next() { - Some(v) => line_height::from_component_value(v, base_url), - _ => return None, + Some(v) => line_height::from_component_value(v, base_url).ok(), + _ => return Err(()), }; - if line_height.is_none() { return None } + if line_height.is_none() { return Err(()) } } _ => () } - let family = font_family::from_iter(iter); - if family.is_none() { return None } - Some(Longhands { + let family = font_family::from_iter(iter).ok(); + if family.is_none() { return Err(()) } + Ok(Longhands { font_style: style, font_variant: variant, font_weight: weight, @@ -1459,20 +1455,20 @@ pub fn parse_property_declaration_list>(input: I, base_url: &U } -#[deriving(Clone)] pub enum CSSWideKeyword { - Initial, - Inherit, + InitialKeyword, + InheritKeyword, + UnsetKeyword, } impl CSSWideKeyword { - pub fn parse(input: &[ComponentValue]) -> Option> { + pub fn parse(input: &[ComponentValue]) -> Result { one_component_value(input).and_then(get_ident_lower).and_then(|keyword| { match keyword.as_slice() { - "initial" => Some(Some(Initial)), - "inherit" => Some(Some(Inherit)), - "unset" => Some(None), - _ => None + "initial" => Ok(InitialKeyword), + "inherit" => Ok(InheritKeyword), + "unset" => Ok(UnsetKeyword), + _ => Err(()) } }) } @@ -1482,7 +1478,11 @@ impl CSSWideKeyword { #[deriving(Clone)] pub enum DeclaredValue { SpecifiedValue(T), - CSSWideKeyword(CSSWideKeyword), + Initial, + Inherit, + // There is no Unset variant here. + // The 'unset' keyword is represented as either Initial or Inherit, + // depending on whether the property is inherited. } #[deriving(Clone)] @@ -1521,12 +1521,12 @@ impl PropertyDeclaration { return ValidOrIgnoredDeclaration } match longhands::${property.ident}::parse_declared(value, base_url) { - Some(value) => { + Ok(value) => { seen.set_${property.ident}(); result_list.push(${property.camel_case}Declaration(value)); ValidOrIgnoredDeclaration }, - None => InvalidValue, + Err(()) => InvalidValue, } }, % else: @@ -1540,45 +1540,53 @@ impl PropertyDeclaration { return ValidOrIgnoredDeclaration } match CSSWideKeyword::parse(value) { - Some(Some(keyword)) => { + Ok(InheritKeyword) => { % for sub_property in shorthand.sub_properties: if !seen.get_${sub_property.ident}() { seen.set_${sub_property.ident}(); - result_list.push(${sub_property.camel_case}Declaration( - CSSWideKeyword(keyword))); + result_list.push( + ${sub_property.camel_case}Declaration(Inherit)); } % endfor ValidOrIgnoredDeclaration }, - Some(None) => { + Ok(InitialKeyword) => { + % for sub_property in shorthand.sub_properties: + if !seen.get_${sub_property.ident}() { + seen.set_${sub_property.ident}(); + result_list.push( + ${sub_property.camel_case}Declaration(Initial)); + } + % endfor + ValidOrIgnoredDeclaration + }, + Ok(UnsetKeyword) => { % for sub_property in shorthand.sub_properties: if !seen.get_${sub_property.ident}() { seen.set_${sub_property.ident}(); result_list.push(${sub_property.camel_case}Declaration( - CSSWideKeyword( - ${"Inherit" if sub_property.style_struct.inherited else "Initial"} - ) + ${"Inherit" if sub_property.style_struct.inherited else "Initial"} )); } % endfor ValidOrIgnoredDeclaration }, - None => match shorthands::${shorthand.ident}::parse(value, base_url) { - Some(result) => { + Err(()) => match shorthands::${shorthand.ident}::parse(value, base_url) { + Ok(result) => { % for sub_property in shorthand.sub_properties: if !seen.get_${sub_property.ident}() { seen.set_${sub_property.ident}(); result_list.push(${sub_property.camel_case}Declaration( match result.${sub_property.ident} { Some(value) => SpecifiedValue(value), - None => CSSWideKeyword(Initial), + None => Initial, } )); } % endfor ValidOrIgnoredDeclaration }, - None => InvalidValue, + Err(()) => InvalidValue, } } }, @@ -1824,9 +1832,9 @@ fn cascade_with_cached_declarations(applicable_declarations: &[MatchedProperty], (*specified_value).clone(), context ), - CSSWideKeyword(Initial) + Initial => longhands::${property.ident}::get_initial_value(), - CSSWideKeyword(Inherit) => { + Inherit => { // This is a bit slow, but this is rare so it shouldn't // matter. // @@ -1934,8 +1942,8 @@ pub fn cascade(applicable_declarations: &[MatchedProperty], ($style_struct_getter: ident, $property: ident, $declared_value: expr) => { match *$declared_value { SpecifiedValue(specified_value) => specified_value, - CSSWideKeyword(Initial) => longhands::$property::get_initial_value(), - CSSWideKeyword(Inherit) => inherited_style.$style_struct_getter().$property.clone(), + Initial => longhands::$property::get_initial_value(), + Inherit => inherited_style.$style_struct_getter().$property.clone(), } }; ) @@ -1950,8 +1958,8 @@ pub fn cascade(applicable_declarations: &[MatchedProperty], context.font_size = match *value { SpecifiedValue(specified_value) => computed::compute_Au_with_font_size( specified_value, context.inherited_font_size), - CSSWideKeyword(Initial) => longhands::font_size::get_initial_value(), - CSSWideKeyword(Inherit) => context.inherited_font_size, + Initial => longhands::font_size::get_initial_value(), + Inherit => context.inherited_font_size, } } ColorDeclaration(ref value) => { @@ -2031,9 +2039,9 @@ pub fn cascade(applicable_declarations: &[MatchedProperty], (*specified_value).clone(), &context ), - CSSWideKeyword(Initial) + Initial => longhands::${property.ident}::get_initial_value(), - CSSWideKeyword(Inherit) => { + Inherit => { // This is a bit slow, but this is rare so it shouldn't // matter. // diff --git a/src/components/style/selectors.rs b/src/components/style/selectors.rs index 29fff94acf5..bf5b0e1aefa 100644 --- a/src/components/style/selectors.rs +++ b/src/components/style/selectors.rs @@ -504,10 +504,10 @@ fn parse_functional_pseudo_class(name: String, arguments: Vec, -> Option { match name.as_slice().to_ascii_lower().as_slice() { // "lang" => parse_lang(arguments), - "nth-child" => parse_nth(arguments.as_slice()).map(|(a, b)| NthChild(a, b)), - "nth-last-child" => parse_nth(arguments.as_slice()).map(|(a, b)| NthLastChild(a, b)), - "nth-of-type" => parse_nth(arguments.as_slice()).map(|(a, b)| NthOfType(a, b)), - "nth-last-of-type" => parse_nth(arguments.as_slice()).map(|(a, b)| NthLastOfType(a, b)), + "nth-child" => parse_nth(arguments.as_slice()).map(|(a, b)| NthChild(a, b)).ok(), + "nth-last-child" => parse_nth(arguments.as_slice()).map(|(a, b)| NthLastChild(a, b)).ok(), + "nth-of-type" => parse_nth(arguments.as_slice()).map(|(a, b)| NthOfType(a, b)).ok(), + "nth-last-of-type" => parse_nth(arguments.as_slice()).map(|(a, b)| NthLastOfType(a, b)).ok(), "not" => if inside_negation { None } else { parse_negation(arguments, namespaces) }, _ => None } diff --git a/src/support/css/rust-cssparser b/src/support/css/rust-cssparser index 918bae60d47..48e517b40c8 160000 --- a/src/support/css/rust-cssparser +++ b/src/support/css/rust-cssparser @@ -1 +1 @@ -Subproject commit 918bae60d4703e3db7f306b6c4a09de0670b9472 +Subproject commit 48e517b40c8aad55b5f2b7072d092102b48797bc