No bug - Revendor rust dependencies

This commit is contained in:
Servo VCS Sync 2017-06-16 14:55:25 +00:00
parent 58442c5f01
commit 3a02645a7b
15 changed files with 475 additions and 205 deletions

View File

@ -1 +1 @@
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"0b944a5f5edfe3dca4796907e63f537a0e919630df66dca7945d51ba4e3c8051",".travis.yml":"f1fb4b65964c81bc1240544267ea334f554ca38ae7a74d57066f4d47d2b5d568","Cargo.toml":"1d93aa78c4ee8b63f15e58ce6f1de3992aac298668d947b665b31fde703a03ca","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"9afe084d70a5d9396674a2624012d6ac749df35f81e322d2d75b042bf208f523","build.rs":"950bcc47a196f07f99f59637c28cc65e02a885130011f90a2b2608248b4724a2","build/match_byte.rs":"89e8b941af74df2c204abf808672d3ff278bdec75abc918c41a843260b924677","docs/.nojekyll":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/big-data-url.css":"04a8f6197ea1181123bca48bd1ebd016268e1da40f01b8f21055814e44bf62b8","src/color.rs":"016815fb48102b41f6d74305f78a31c529b3a406e41b3607762cb7fc6f4e9ef0","src/css-parsing-tests/An+B.json":"d24559c1dad55d3da9d1fca29383edefdfc6046988435d6388a9bc0f28850257","src/css-parsing-tests/LICENSE":"5f9019a92f4aa8917aadc8e035aa673c2c1bf08d5ca2e535a0564106599f44eb","src/css-parsing-tests/README.rst":"775c5f957dd1d46d3ce954aaad219c821d2b64b4a9fb93c42e9737a11131ca44","src/css-parsing-tests/color3.json":"814179b0a6a9d3a935e635f485f1eaec9880129c5a0d09c0cda4efcea69649fb","src/css-parsing-tests/color3_hsl.json":"61c3b7d8d5ae02f94769d64458e0dd29e4c22c5068e5ea44040d14b88f9616b0","src/css-parsing-tests/color3_keywords.json":"95609bf9fe762c316878a30f371fa375a2e51c21a6fda24fa188a95cd9118f5c","src/css-parsing-tests/component_value_list.json":"516f9495fe089fa669321660bc431d7884839da8fb73e45edcbcd98625cb09dc","src/css-parsing-tests/declaration_list.json":"0b85cc3f19e945f838432acbfb9edb003abea13debc4ea27bcdcef25d117eac5","src/css-parsing-tests/make_color3_hsl.py":"3df7dd908ee719f78fd097ab24622f75edd10fcb67514230c172cbfc842c8ab7","src/css-parsing-tests/make_color3_keywords.py":"66bccab3f1dea18698fcfd854be79b1fd1cd724dd487e25b1f057b522163aad2","src/css-parsing-tests/one_component_value.json":"8798017709002e14cf11e203c9d716f82d308ce6ba0f6e64ee4eea331b8485c6","src/css-parsing-tests/one_declaration.json":"a34c9da56edfff9e2e21615f059e141b0e878e90f794dc8fa58d65b47cd193ed","src/css-parsing-tests/one_rule.json":"88f7b1b6049be88e1e2827673b75fc9261986b216e8ee6bf09621fecbe274e3c","src/css-parsing-tests/rule_list.json":"97c45e80fb83abef149a4016c5625a74f053e7ad70a2ce5a95c02fce1c195686","src/css-parsing-tests/stylesheet.json":"05f1e10fc486bfbda2c059c313a74ff78c0063c0768b99737cab41969c0c87ce","src/css-parsing-tests/stylesheet_bytes.json":"890fd856a596e61f82cf7ed77920ffe95df89209fdb5ee0afe0b26bdfdb80a42","src/css-parsing-tests/urange.json":"62720b143ddf52508baad42921473dd69519aad6c1cd49f37f3f264dc29e1c13","src/from_bytes.rs":"331fe63af2123ae3675b61928a69461b5ac77799fff3ce9978c55cf2c558f4ff","src/lib.rs":"d619e424e665f0c73a6ff5e556f877fe937dc33b2c40ba37762da5f4741c755c","src/macros.rs":"adb9773c157890381556ea83d7942dcc676f99eea71abbb6afeffee1e3f28960","src/nth.rs":"105c7f4295ce8f86a41a3e28a51b98626fdbe34b5b412889796668dcdb02e1a2","src/parser.rs":"2a392ce783121f454c19f8d0c32994e2469db2486f72917310b9cd0e37d41f63","src/rules_and_declarations.rs":"6f270f19e1083a2d7c599b84ca8e9d352fc5ba2f94ac05b406090663ed4b6ea5","src/serializer.rs":"13bf417e747b742576402543e25d7bdf65aa5dd6971455eb9d355169d2182f89","src/tests.rs":"01695d16370ecf9c657f44c0dd87af7b0ec9c0ee6f4c6ab980fc7ac0b7f0f9b0","src/tokenizer.rs":"8bf7665995801bcc37c113637759371cce426f687c508a9b8aab0b49a17cd7da","src/unicode_range.rs":"30c05ad535e3c35d70d698eb0e0f4a73b16dcdd058ac31546857098979cece06"},"package":"dd54cdee668d71d20e9f8b9676e2e969968d186ab20a101af59c28398393a2b0"}
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"0b944a5f5edfe3dca4796907e63f537a0e919630df66dca7945d51ba4e3c8051",".travis.yml":"f1fb4b65964c81bc1240544267ea334f554ca38ae7a74d57066f4d47d2b5d568","Cargo.toml":"50b7d2c3be314d0890f52f5e3b93dc53c58801934ec05e2c7baeab4df3378d52","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"9afe084d70a5d9396674a2624012d6ac749df35f81e322d2d75b042bf208f523","build.rs":"950bcc47a196f07f99f59637c28cc65e02a885130011f90a2b2608248b4724a2","build/match_byte.rs":"89e8b941af74df2c204abf808672d3ff278bdec75abc918c41a843260b924677","docs/.nojekyll":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/big-data-url.css":"04a8f6197ea1181123bca48bd1ebd016268e1da40f01b8f21055814e44bf62b8","src/color.rs":"89f69097660fddf48141e221e59ab4cc5c3f53f5407c0f043b032b4796bb2668","src/compact_cow_str.rs":"7f5abdae953febe5a833604e6868d6f60518f1b4ece8de6a8aa8d521f21b8daa","src/css-parsing-tests/An+B.json":"d24559c1dad55d3da9d1fca29383edefdfc6046988435d6388a9bc0f28850257","src/css-parsing-tests/LICENSE":"5f9019a92f4aa8917aadc8e035aa673c2c1bf08d5ca2e535a0564106599f44eb","src/css-parsing-tests/README.rst":"775c5f957dd1d46d3ce954aaad219c821d2b64b4a9fb93c42e9737a11131ca44","src/css-parsing-tests/color3.json":"814179b0a6a9d3a935e635f485f1eaec9880129c5a0d09c0cda4efcea69649fb","src/css-parsing-tests/color3_hsl.json":"61c3b7d8d5ae02f94769d64458e0dd29e4c22c5068e5ea44040d14b88f9616b0","src/css-parsing-tests/color3_keywords.json":"95609bf9fe762c316878a30f371fa375a2e51c21a6fda24fa188a95cd9118f5c","src/css-parsing-tests/component_value_list.json":"516f9495fe089fa669321660bc431d7884839da8fb73e45edcbcd98625cb09dc","src/css-parsing-tests/declaration_list.json":"0b85cc3f19e945f838432acbfb9edb003abea13debc4ea27bcdcef25d117eac5","src/css-parsing-tests/make_color3_hsl.py":"3df7dd908ee719f78fd097ab24622f75edd10fcb67514230c172cbfc842c8ab7","src/css-parsing-tests/make_color3_keywords.py":"66bccab3f1dea18698fcfd854be79b1fd1cd724dd487e25b1f057b522163aad2","src/css-parsing-tests/one_component_value.json":"8798017709002e14cf11e203c9d716f82d308ce6ba0f6e64ee4eea331b8485c6","src/css-parsing-tests/one_declaration.json":"a34c9da56edfff9e2e21615f059e141b0e878e90f794dc8fa58d65b47cd193ed","src/css-parsing-tests/one_rule.json":"88f7b1b6049be88e1e2827673b75fc9261986b216e8ee6bf09621fecbe274e3c","src/css-parsing-tests/rule_list.json":"97c45e80fb83abef149a4016c5625a74f053e7ad70a2ce5a95c02fce1c195686","src/css-parsing-tests/stylesheet.json":"05f1e10fc486bfbda2c059c313a74ff78c0063c0768b99737cab41969c0c87ce","src/css-parsing-tests/stylesheet_bytes.json":"890fd856a596e61f82cf7ed77920ffe95df89209fdb5ee0afe0b26bdfdb80a42","src/css-parsing-tests/urange.json":"62720b143ddf52508baad42921473dd69519aad6c1cd49f37f3f264dc29e1c13","src/from_bytes.rs":"331fe63af2123ae3675b61928a69461b5ac77799fff3ce9978c55cf2c558f4ff","src/lib.rs":"a612f377e1b8a4bf1830c4a1da5b4d52296e965fc59ef2d8f915a49fd8db3a37","src/macros.rs":"adb9773c157890381556ea83d7942dcc676f99eea71abbb6afeffee1e3f28960","src/nth.rs":"7da645b4fcb492dda7e771897482ddb373a114e0ba4b66e1b23d655098e4653a","src/parser.rs":"51d2a55eca22cc8e7324b413016fd5ebe3e79b5e26f0ada2f8efaf981213a132","src/rules_and_declarations.rs":"81e1af778ccc580e42162d2e374dc9cac6a40d1164c55e8996c688caec59700f","src/serializer.rs":"99651bf65670ba478b918240a94362ef2f6e656a24e5e120802ec477321888fb","src/size_of_tests.rs":"fdcc0a12e274cc86b057e607e099b9b3f6af842d0edf9b65e40c0fcdd76fbf17","src/tests.rs":"621bcb4b14afccc6fcda11d91e90dd68d4b5016a532593a6cedc8c8fe39be4fd","src/tokenizer.rs":"f63aa6b443ca710122e54c223925dfd21573ad560fa30dcf531b4619933b3af7","src/unicode_range.rs":"efd937ab97ab6a38e2cfe2e89a44e259c33d111ee73ba4a6c4388b8517607d2d"},"package":"3c711c0c610b1e5fc2bf96e325b2d9f85839a8e71f6279a77c194af5dcafa502"}

View File

@ -1,7 +1,7 @@
[package]
name = "cssparser"
version = "0.15.0"
version = "0.16.0"
authors = [ "Simon Sapin <simon.sapin@exyr.org>" ]
description = "Rust implementation of CSS Syntax Level 3"

View File

@ -6,7 +6,6 @@ use std::fmt;
use std::f32::consts::PI;
use super::{Token, Parser, ToCss, ParseError, BasicParseError};
use tokenizer::NumericValue;
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
@ -430,11 +429,11 @@ fn parse_color_function<'i, 't>(name: &str, arguments: &mut Parser<'i, 't>) -> R
};
let token = try!(arguments.next());
match token {
Token::Number(NumericValue { value: v, .. }) => {
Token::Number { value: v, .. } => {
clamp_unit_f32(v)
}
Token::Percentage(ref v) => {
clamp_unit_f32(v.unit_value)
Token::Percentage { unit_value: v, .. } => {
clamp_unit_f32(v)
}
t => {
return Err(BasicParseError::UnexpectedToken(t))
@ -459,10 +458,10 @@ fn parse_rgb_components_rgb<'i, 't>(arguments: &mut Parser<'i, 't>) -> Result<(u
// Either integers or percentages, but all the same type.
// https://drafts.csswg.org/css-color/#rgb-functions
match try!(arguments.next()) {
Token::Number(NumericValue { value: v, .. }) => {
Token::Number { value: v, .. } => {
red = clamp_floor_256_f32(v);
green = clamp_floor_256_f32(match try!(arguments.next()) {
Token::Number(NumericValue { value: v, .. }) => v,
Token::Number { value: v, .. } => v,
Token::Comma => {
uses_commas = true;
try!(arguments.expect_number())
@ -474,10 +473,10 @@ fn parse_rgb_components_rgb<'i, 't>(arguments: &mut Parser<'i, 't>) -> Result<(u
}
blue = clamp_floor_256_f32(try!(arguments.expect_number()));
}
Token::Percentage(ref v) => {
red = clamp_unit_f32(v.unit_value);
Token::Percentage { unit_value, .. } => {
red = clamp_unit_f32(unit_value);
green = clamp_unit_f32(match try!(arguments.next()) {
Token::Percentage(ref v) => v.unit_value,
Token::Percentage { unit_value, .. } => unit_value,
Token::Comma => {
uses_commas = true;
try!(arguments.expect_percentage())
@ -501,8 +500,8 @@ fn parse_rgb_components_hsl<'i, 't>(arguments: &mut Parser<'i, 't>) -> Result<(u
// https://drafts.csswg.org/css-values/#angles
let token = try!(arguments.next());
let hue_degrees = match token {
Token::Number(NumericValue { value: v, .. }) => Ok(v),
Token::Dimension(NumericValue { value: v, .. }, ref unit) => {
Token::Number { value: v, .. } => Ok(v),
Token::Dimension { value: v, ref unit, .. } => {
match_ignore_ascii_case! { &*unit,
"deg" => Ok(v),
"grad" => Ok(v * 360. / 400.),
@ -521,7 +520,7 @@ fn parse_rgb_components_hsl<'i, 't>(arguments: &mut Parser<'i, 't>) -> Result<(u
// Saturation and lightness are clamped to 0% ... 100%
// https://drafts.csswg.org/css-color/#the-hsl-notation
let saturation = match try!(arguments.next()) {
Token::Percentage(ref v) => v.unit_value,
Token::Percentage { unit_value, .. } => unit_value,
Token::Comma => {
uses_commas = true;
try!(arguments.expect_percentage())

View File

@ -0,0 +1,246 @@
/* 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/. */
use std::borrow::{Borrow, Cow};
use std::cmp;
use std::fmt;
use std::hash;
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::slice;
use std::str;
// All bits set except the highest
const MAX_LEN: usize = !0 >> 1;
// Only the highest bit
const OWNED_TAG: usize = MAX_LEN + 1;
/// Like `Cow<'a, str>`, but with smaller `std::mem::size_of`. (Two words instead of four.)
pub struct CompactCowStr<'a> {
// `tagged_len` is a tag in its highest bit, and the string length in the rest of the bits.
//
// * If the tag is 1, the memory pointed to by `ptr` is owned
// and the lifetime parameter is irrelevant.
// `ptr` and `len` are the components of a `Box<str>`.
//
// * If the tag is 0, the memory is borrowed.
// `ptr` and `len` are the components of a `&'a str`.
// FIXME: https://github.com/rust-lang/rust/issues/27730 use NonZero or Shared
ptr: *const u8,
tagged_len: usize,
phantom: PhantomData<&'a str>,
}
impl<'a> From<&'a str> for CompactCowStr<'a> {
#[inline]
fn from(s: &'a str) -> Self {
let len = s.len();
assert!(len <= MAX_LEN);
CompactCowStr {
ptr: s.as_ptr(),
tagged_len: len,
phantom: PhantomData,
}
}
}
impl<'a> From<Box<str>> for CompactCowStr<'a> {
#[inline]
fn from(s: Box<str>) -> Self {
let ptr = s.as_ptr();
let len = s.len();
assert!(len <= MAX_LEN);
mem::forget(s);
CompactCowStr {
ptr: ptr,
tagged_len: len | OWNED_TAG,
phantom: PhantomData,
}
}
}
impl<'a> CompactCowStr<'a> {
/// Whether this string refers to borrowed memory
/// (as opposed to owned, which would be freed when `CompactCowStr` goes out of scope).
#[inline]
pub fn is_borrowed(&self) -> bool {
(self.tagged_len & OWNED_TAG) == 0
}
/// The length of this string
#[inline]
pub fn len(&self) -> usize {
self.tagged_len & !OWNED_TAG
}
// Intentionally private since it is easy to use incorrectly.
#[inline]
fn as_raw_str(&self) -> *const str {
unsafe {
str::from_utf8_unchecked(slice::from_raw_parts(self.ptr, self.len()))
}
}
/// If this string is borrowed, return a slice with the original lifetime,
/// not borrowing `self`.
///
/// (`Deref` is implemented unconditionally, but returns a slice with a shorter lifetime.)
#[inline]
pub fn as_str(&self) -> Option<&'a str> {
if self.is_borrowed() {
Some(unsafe { &*self.as_raw_str() })
} else {
None
}
}
/// Convert into `String`, re-using the memory allocation if it was already owned.
#[inline]
pub fn into_owned(self) -> String {
unsafe {
let raw = self.as_raw_str();
let is_borrowed = self.is_borrowed();
mem::forget(self);
if is_borrowed {
String::from(&*raw)
} else {
Box::from_raw(raw as *mut str).into_string()
}
}
}
}
impl<'a> Clone for CompactCowStr<'a> {
#[inline]
fn clone(&self) -> Self {
if self.is_borrowed() {
CompactCowStr { ..*self }
} else {
Self::from(String::from(&**self).into_boxed_str())
}
}
}
impl<'a> Drop for CompactCowStr<'a> {
#[inline]
fn drop(&mut self) {
if !self.is_borrowed() {
unsafe {
Box::from_raw(self.as_raw_str() as *mut str);
}
}
}
}
impl<'a> Deref for CompactCowStr<'a> {
type Target = str;
#[inline]
fn deref(&self) -> &str {
unsafe {
&*self.as_raw_str()
}
}
}
impl<'a> From<CompactCowStr<'a>> for Cow<'a, str> {
#[inline]
fn from(cow: CompactCowStr<'a>) -> Self {
unsafe {
let raw = cow.as_raw_str();
let is_borrowed = cow.is_borrowed();
mem::forget(cow);
if is_borrowed {
Cow::Borrowed(&*raw)
} else {
Cow::Owned(Box::from_raw(raw as *mut str).into_string())
}
}
}
}
impl<'a> From<String> for CompactCowStr<'a> {
#[inline]
fn from(s: String) -> Self {
Self::from(s.into_boxed_str())
}
}
impl<'a> From<Cow<'a, str>> for CompactCowStr<'a> {
#[inline]
fn from(s: Cow<'a, str>) -> Self {
match s {
Cow::Borrowed(s) => Self::from(s),
Cow::Owned(s) => Self::from(s),
}
}
}
impl<'a> AsRef<str> for CompactCowStr<'a> {
#[inline]
fn as_ref(&self) -> &str {
self
}
}
impl<'a> Borrow<str> for CompactCowStr<'a> {
#[inline]
fn borrow(&self) -> &str {
self
}
}
impl<'a> Default for CompactCowStr<'a> {
#[inline]
fn default() -> Self {
Self::from("")
}
}
impl<'a> hash::Hash for CompactCowStr<'a> {
#[inline]
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
str::hash(self, hasher)
}
}
impl<'a, T: AsRef<str>> PartialEq<T> for CompactCowStr<'a> {
#[inline]
fn eq(&self, other: &T) -> bool {
str::eq(self, other.as_ref())
}
}
impl<'a, T: AsRef<str>> PartialOrd<T> for CompactCowStr<'a> {
#[inline]
fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
str::partial_cmp(self, other.as_ref())
}
}
impl<'a> Eq for CompactCowStr<'a> {}
impl<'a> Ord for CompactCowStr<'a> {
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering {
str::cmp(self, other)
}
}
impl<'a> fmt::Display for CompactCowStr<'a> {
#[inline]
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
str::fmt(self, formatter)
}
}
impl<'a> fmt::Debug for CompactCowStr<'a> {
#[inline]
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
str::fmt(self, formatter)
}
}

View File

@ -80,7 +80,7 @@ fn parse_border_spacing(_context: &ParserContext, input: &mut Parser)
pub use cssparser_macros::*;
pub use tokenizer::{Token, NumericValue, PercentageValue, SourceLocation};
pub use tokenizer::{Token, SourceLocation};
pub use rules_and_declarations::{parse_important};
pub use rules_and_declarations::{DeclarationParser, DeclarationListParser, parse_one_declaration};
pub use rules_and_declarations::{RuleListParser, parse_one_rule};
@ -91,6 +91,7 @@ pub use nth::parse_nth;
pub use serializer::{ToCss, CssStringWriter, serialize_identifier, serialize_string, TokenSerializationType};
pub use parser::{Parser, Delimiter, Delimiters, SourcePosition, ParseError, BasicParseError, ParserInput};
pub use unicode_range::UnicodeRange;
pub use compact_cow_str::CompactCowStr;
// For macros
#[doc(hidden)] pub use macros::_internal__to_lowercase;
@ -116,6 +117,7 @@ mod color;
mod nth;
mod serializer;
mod unicode_range;
mod compact_cow_str;
#[cfg(test)]
mod tests;
#[cfg(test)] mod tests;
#[cfg(test)] mod size_of_tests;

View File

@ -14,26 +14,17 @@ use super::{Token, Parser, BasicParseError};
pub fn parse_nth<'i, 't>(input: &mut Parser<'i, 't>) -> Result<(i32, i32), BasicParseError<'i>> {
let token = try!(input.next());
match token {
Token::Number(ref value) => {
match value.int_value {
Some(v) => Ok((0, v as i32)),
None => Err(()),
}
Token::Number { int_value: Some(b), .. } => {
Ok((0, b))
}
Token::Dimension(value, ref unit) => {
match value.int_value {
Some(v) => {
let a = v as i32;
match_ignore_ascii_case! {
&unit,
"n" => Ok(try!(parse_b(input, a))),
"n-" => Ok(try!(parse_signless_b(input, a, -1))),
_ => {
parse_n_dash_digits(&*unit).map(|val| (a, val))
}
}
Token::Dimension { int_value: Some(a), ref unit, .. } => {
match_ignore_ascii_case! {
&unit,
"n" => Ok(try!(parse_b(input, a))),
"n-" => Ok(try!(parse_signless_b(input, a, -1))),
_ => {
parse_n_dash_digits(&*unit).map(|val| (a, val))
}
None => Err(()),
}
}
Token::Ident(ref value) => {
@ -72,12 +63,7 @@ fn parse_b<'i, 't>(input: &mut Parser<'i, 't>, a: i32) -> Result<(i32, i32), Bas
match token {
Ok(Token::Delim('+')) => Ok(try!(parse_signless_b(input, a, 1))),
Ok(Token::Delim('-')) => Ok(try!(parse_signless_b(input, a, -1))),
Ok(Token::Number(ref value)) if value.has_sign => {
match value.int_value {
Some(v) => Ok((a, v as i32)),
None => Err(()),
}
}
Ok(Token::Number { has_sign: true, int_value: Some(b), .. }) => Ok((a, b)),
_ => {
input.reset(start_position);
Ok((a, 0))
@ -88,12 +74,7 @@ fn parse_b<'i, 't>(input: &mut Parser<'i, 't>, a: i32) -> Result<(i32, i32), Bas
fn parse_signless_b<'i, 't>(input: &mut Parser<'i, 't>, a: i32, b_sign: i32) -> Result<(i32, i32), BasicParseError<'i>> {
let token = try!(input.next());
match token {
Token::Number(ref value) if !value.has_sign => {
match value.int_value {
Some(v) => Ok((a, b_sign * v as i32)),
None => Err(()),
}
}
Token::Number { has_sign: false, int_value: Some(b), .. } => Ok((a, b_sign * b)),
_ => Err(())
}.map_err(|()| BasicParseError::UnexpectedToken(token))
}

View File

@ -2,11 +2,11 @@
* 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/. */
use compact_cow_str::CompactCowStr;
use std::ops::Range;
use std::ascii::AsciiExt;
use std::ops::BitOr;
use std::borrow::Cow;
use tokenizer::{self, Token, NumericValue, PercentageValue, Tokenizer, SourceLocation};
use tokenizer::{self, Token, Tokenizer, SourceLocation};
/// A capture of the internal state of a `Parser` (including the position within the input),
@ -440,7 +440,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
/// Parse a <ident-token> and return the unescaped value.
#[inline]
pub fn expect_ident(&mut self) -> Result<Cow<'i, str>, BasicParseError<'i>> {
pub fn expect_ident(&mut self) -> Result<CompactCowStr<'i>, BasicParseError<'i>> {
match try!(self.next()) {
Token::Ident(value) => Ok(value),
t => Err(BasicParseError::UnexpectedToken(t))
@ -458,7 +458,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
/// Parse a <string-token> and return the unescaped value.
#[inline]
pub fn expect_string(&mut self) -> Result<Cow<'i, str>, BasicParseError<'i>> {
pub fn expect_string(&mut self) -> Result<CompactCowStr<'i>, BasicParseError<'i>> {
match try!(self.next()) {
Token::QuotedString(value) => Ok(value),
t => Err(BasicParseError::UnexpectedToken(t))
@ -467,7 +467,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
/// Parse either a <ident-token> or a <string-token>, and return the unescaped value.
#[inline]
pub fn expect_ident_or_string(&mut self) -> Result<Cow<'i, str>, BasicParseError<'i>> {
pub fn expect_ident_or_string(&mut self) -> Result<CompactCowStr<'i>, BasicParseError<'i>> {
match try!(self.next()) {
Token::Ident(value) => Ok(value),
Token::QuotedString(value) => Ok(value),
@ -477,7 +477,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
/// Parse a <url-token> and return the unescaped value.
#[inline]
pub fn expect_url(&mut self) -> Result<Cow<'i, str>, BasicParseError<'i>> {
pub fn expect_url(&mut self) -> Result<CompactCowStr<'i>, BasicParseError<'i>> {
match try!(self.next()) {
Token::UnquotedUrl(value) => Ok(value),
Token::Function(ref name) if name.eq_ignore_ascii_case("url") => {
@ -491,7 +491,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
/// Parse either a <url-token> or a <string-token>, and return the unescaped value.
#[inline]
pub fn expect_url_or_string(&mut self) -> Result<Cow<'i, str>, BasicParseError<'i>> {
pub fn expect_url_or_string(&mut self) -> Result<CompactCowStr<'i>, BasicParseError<'i>> {
match try!(self.next()) {
Token::UnquotedUrl(value) => Ok(value),
Token::QuotedString(value) => Ok(value),
@ -507,7 +507,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
#[inline]
pub fn expect_number(&mut self) -> Result<f32, BasicParseError<'i>> {
match try!(self.next()) {
Token::Number(NumericValue { value, .. }) => Ok(value),
Token::Number { value, .. } => Ok(value),
t => Err(BasicParseError::UnexpectedToken(t))
}
}
@ -517,7 +517,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
pub fn expect_integer(&mut self) -> Result<i32, BasicParseError<'i>> {
let token = try!(self.next());
match token {
Token::Number(NumericValue { int_value: Some(int_value), .. }) => {
Token::Number { int_value: Some(int_value), .. } => {
Ok(int_value)
}
t => Err(BasicParseError::UnexpectedToken(t))
@ -529,7 +529,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
#[inline]
pub fn expect_percentage(&mut self) -> Result<f32, BasicParseError<'i>> {
match try!(self.next()) {
Token::Percentage(PercentageValue { unit_value, .. }) => Ok(unit_value),
Token::Percentage { unit_value, .. } => Ok(unit_value),
t => Err(BasicParseError::UnexpectedToken(t))
}
}
@ -607,7 +607,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
///
/// If the result is `Ok`, you can then call the `Parser::parse_nested_block` method.
#[inline]
pub fn expect_function(&mut self) -> Result<Cow<'i, str>, BasicParseError<'i>> {
pub fn expect_function(&mut self) -> Result<CompactCowStr<'i>, BasicParseError<'i>> {
match try!(self.next()) {
Token::Function(name) => Ok(name),
t => Err(BasicParseError::UnexpectedToken(t))

View File

@ -4,10 +4,10 @@
// https://drafts.csswg.org/css-syntax/#parsing
use compact_cow_str::CompactCowStr;
use parser::{parse_until_before, parse_until_after, parse_nested_block};
use std::ascii::AsciiExt;
use std::ops::Range;
use std::borrow::Cow;
use super::{Token, Parser, Delimiter, SourcePosition, ParseError, BasicParseError};
@ -72,7 +72,7 @@ pub trait DeclarationParser<'i> {
/// If `!important` can be used in a given context,
/// `input.try(parse_important).is_ok()` should be used at the end
/// of the implementation of this method and the result should be part of the return value.
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>)
-> Result<Self::Declaration, ParseError<'i, Self::Error>>;
}
@ -112,7 +112,7 @@ pub trait AtRuleParser<'i> {
/// The given `input` is a "delimited" parser
/// that ends wherever the prelude should end.
/// (Before the next semicolon, the next `{`, or the end of the current block.)
fn parse_prelude<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
fn parse_prelude<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>)
-> Result<AtRuleType<Self::Prelude, Self::AtRule>, ParseError<'i, Self::Error>> {
let _ = name;
let _ = input;
@ -407,7 +407,7 @@ pub struct PreciseParseError<'i, E: 'i> {
pub span: Range<SourcePosition>,
}
fn parse_at_rule<'i: 't, 't, P, E>(start_position: SourcePosition, name: Cow<'i, str>,
fn parse_at_rule<'i: 't, 't, P, E>(start_position: SourcePosition, name: CompactCowStr<'i>,
input: &mut Parser<'i, 't>, parser: &mut P)
-> Result<<P as AtRuleParser<'i>>::AtRule, PreciseParseError<'i, E>>
where P: AtRuleParser<'i, Error = E> {

View File

@ -5,7 +5,7 @@
use std::ascii::AsciiExt;
use std::fmt::{self, Write};
use super::{Token, NumericValue, PercentageValue};
use super::Token;
/// Trait for things the can serialize themselves in CSS syntax.
@ -43,20 +43,21 @@ pub trait ToCss {
#[inline]
fn write_numeric<W>(value: NumericValue, dest: &mut W) -> fmt::Result where W: fmt::Write {
fn write_numeric<W>(value: f32, int_value: Option<i32>, has_sign: bool, dest: &mut W)
-> fmt::Result where W: fmt::Write {
// `value.value >= 0` is true for negative 0.
if value.has_sign && value.value.is_sign_positive() {
if has_sign && value.is_sign_positive() {
try!(dest.write_str("+"));
}
if value.value == 0.0 && value.value.is_sign_negative() {
if value == 0.0 && value.is_sign_negative() {
// Negative zero. Work around #20596.
try!(dest.write_str("-0"))
} else {
try!(write!(dest, "{}", value.value))
try!(write!(dest, "{}", value))
}
if value.int_value.is_none() && value.value.fract() == 0. {
if int_value.is_none() && value.fract() == 0. {
try!(dest.write_str(".0"));
}
Ok(())
@ -87,18 +88,15 @@ impl<'a> ToCss for Token<'a> {
},
Token::Delim(value) => try!(write!(dest, "{}", value)),
Token::Number(value) => try!(write_numeric(value, dest)),
Token::Percentage(PercentageValue { unit_value, int_value, has_sign }) => {
let value = NumericValue {
value: unit_value * 100.,
int_value: int_value,
has_sign: has_sign,
};
try!(write_numeric(value, dest));
Token::Number { value, int_value, has_sign } => {
try!(write_numeric(value, int_value, has_sign, dest))
}
Token::Percentage { unit_value, int_value, has_sign } => {
try!(write_numeric(unit_value * 100., int_value, has_sign, dest));
try!(dest.write_str("%"));
},
Token::Dimension(value, ref unit) => {
try!(write_numeric(value, dest));
Token::Dimension { value, int_value, has_sign, ref unit } => {
try!(write_numeric(value, int_value, has_sign, dest));
// Disambiguate with scientific notation.
let unit = &**unit;
if unit == "e" || unit == "E" || unit.starts_with("e-") || unit.starts_with("E-") {
@ -389,9 +387,9 @@ impl<'a> Token<'a> {
Token::Delim('|') => DelimBar,
Token::Delim('/') => DelimSlash,
Token::Delim('*') => DelimAsterisk,
Token::Number(_) => Number,
Token::Percentage(_) => Percentage,
Token::Dimension(..) => Dimension,
Token::Number { .. } => Number,
Token::Percentage { .. } => Percentage,
Token::Dimension { .. } => Dimension,
Token::WhiteSpace(_) => WhiteSpace,
Token::Comment(_) => DelimSlash,
Token::DashMatch => DashMatch,

View File

@ -0,0 +1,37 @@
/* 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/. */
use compact_cow_str::CompactCowStr;
use std::borrow::Cow;
use tokenizer::Token;
#[macro_export]
macro_rules! size_of_test {
($testname: ident, $t: ty, $expected_size: expr) => {
#[test]
fn $testname() {
let new = ::std::mem::size_of::<$t>();
let old = $expected_size;
if new < old {
panic!(
"Your changes have decreased the stack size of {} from {} to {}. \
Good work! Please update the expected size in {}.",
stringify!($t), old, new, file!()
)
} else if new > old {
panic!(
"Your changes have increased the stack size of {} from {} to {}. \
Please consider choosing a design which avoids this increase. \
If you feel that the increase is necessary, update the size in {}.",
stringify!($t), old, new, file!()
)
}
}
}
}
// These assume 64-bit
size_of_test!(token, Token, 32);
size_of_test!(std_cow_str, Cow<'static, str>, 32);
size_of_test!(compact_cow_str, CompactCowStr, 16);

View File

@ -6,18 +6,17 @@
extern crate test;
use encoding_rs;
use std::borrow::Cow::{self, Borrowed};
use rustc_serialize::json::{self, Json, ToJson};
#[cfg(feature = "bench")]
use self::test::Bencher;
use super::{Parser, Delimiter, Token, NumericValue, PercentageValue, SourceLocation, ParseError,
use super::{Parser, Delimiter, Token, SourceLocation, ParseError,
DeclarationListParser, DeclarationParser, RuleListParser, BasicParseError,
AtRuleType, AtRuleParser, QualifiedRuleParser, ParserInput,
parse_one_declaration, parse_one_rule, parse_important,
stylesheet_encoding, EncodingSupport,
TokenSerializationType,
TokenSerializationType, CompactCowStr,
Color, RGBA, parse_nth, UnicodeRange, ToCss};
macro_rules! JArray {
@ -290,12 +289,12 @@ fn unquoted_url_escaping() {
)\
");
let mut input = ParserInput::new(&serialized);
assert_eq!(Parser::new(&mut input).next(), Ok(token))
assert_eq!(Parser::new(&mut input).next(), Ok(token));
}
#[test]
fn test_expect_url() {
fn parse<'a>(s: &mut ParserInput<'a>) -> Result<Cow<'a, str>, BasicParseError<'a>> {
fn parse<'a>(s: &mut ParserInput<'a>) -> Result<CompactCowStr<'a>, BasicParseError<'a>> {
Parser::new(s).expect_url()
}
let mut input = ParserInput::new("url()");
@ -453,15 +452,15 @@ fn line_numbers() {
let mut input = ParserInput::new("foo bar\nbaz\r\n\n\"a\\\r\nb\"");
let mut input = Parser::new(&mut input);
assert_eq!(input.current_source_location(), SourceLocation { line: 1, column: 1 });
assert_eq!(input.next_including_whitespace(), Ok(Token::Ident(Borrowed("foo"))));
assert_eq!(input.next_including_whitespace(), Ok(Token::Ident("foo".into())));
assert_eq!(input.current_source_location(), SourceLocation { line: 1, column: 4 });
assert_eq!(input.next_including_whitespace(), Ok(Token::WhiteSpace(" ")));
assert_eq!(input.current_source_location(), SourceLocation { line: 1, column: 5 });
assert_eq!(input.next_including_whitespace(), Ok(Token::Ident(Borrowed("bar"))));
assert_eq!(input.next_including_whitespace(), Ok(Token::Ident("bar".into())));
assert_eq!(input.current_source_location(), SourceLocation { line: 1, column: 8 });
assert_eq!(input.next_including_whitespace(), Ok(Token::WhiteSpace("\n")));
assert_eq!(input.current_source_location(), SourceLocation { line: 2, column: 1 });
assert_eq!(input.next_including_whitespace(), Ok(Token::Ident(Borrowed("baz"))));
assert_eq!(input.next_including_whitespace(), Ok(Token::Ident("baz".into())));
assert_eq!(input.current_source_location(), SourceLocation { line: 2, column: 4 });
let position = input.position();
@ -470,7 +469,7 @@ fn line_numbers() {
assert_eq!(input.source_location(position), SourceLocation { line: 2, column: 4 });
assert_eq!(input.next_including_whitespace(), Ok(Token::QuotedString(Borrowed("ab"))));
assert_eq!(input.next_including_whitespace(), Ok(Token::QuotedString("ab".into())));
assert_eq!(input.current_source_location(), SourceLocation { line: 5, column: 3 });
assert!(input.next_including_whitespace().is_err());
}
@ -679,7 +678,7 @@ impl<'i> DeclarationParser<'i> for JsonParser {
type Declaration = Json;
type Error = ();
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>)
-> Result<Json, ParseError<'i, ()>> {
let mut value = vec![];
let mut important = false;
@ -720,7 +719,7 @@ impl<'i> AtRuleParser<'i> for JsonParser {
type AtRule = Json;
type Error = ();
fn parse_prelude<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
fn parse_prelude<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>)
-> Result<AtRuleType<Vec<Json>, Json>, ParseError<'i, ()>> {
Ok(AtRuleType::OptionalBlock(vec![
"at-rule".to_json(),
@ -769,11 +768,15 @@ fn component_values_to_json(input: &mut Parser) -> Vec<Json> {
}
fn one_component_value_to_json(token: Token, input: &mut Parser) -> Json {
fn numeric(value: NumericValue) -> Vec<json::Json> {
fn numeric(value: f32, int_value: Option<i32>, has_sign: bool) -> Vec<json::Json> {
vec![
Token::Number(value).to_css_string().to_json(),
match value.int_value { Some(i) => i.to_json(), None => value.value.to_json() },
match value.int_value { Some(_) => "integer", None => "number" }.to_json()
Token::Number {
value: value,
int_value: int_value,
has_sign: has_sign,
}.to_css_string().to_json(),
match int_value { Some(i) => i.to_json(), None => value.to_json() },
match int_value { Some(_) => "integer", None => "number" }.to_json()
]
}
@ -794,23 +797,19 @@ fn one_component_value_to_json(token: Token, input: &mut Parser) -> Json {
Token::Delim('\\') => "\\".to_json(),
Token::Delim(value) => value.to_string().to_json(),
Token::Number(value) => Json::Array({
Token::Number { value, int_value, has_sign } => Json::Array({
let mut v = vec!["number".to_json()];
v.extend(numeric(value));
v.extend(numeric(value, int_value, has_sign));
v
}),
Token::Percentage(PercentageValue { unit_value, int_value, has_sign }) => Json::Array({
Token::Percentage { unit_value, int_value, has_sign } => Json::Array({
let mut v = vec!["percentage".to_json()];
v.extend(numeric(NumericValue {
value: unit_value * 100.,
int_value: int_value,
has_sign: has_sign,
}));
v.extend(numeric(unit_value * 100., int_value, has_sign));
v
}),
Token::Dimension(value, unit) => Json::Array({
Token::Dimension { value, int_value, has_sign, unit } => Json::Array({
let mut v = vec!["dimension".to_json()];
v.extend(numeric(value));
v.extend(numeric(value, int_value, has_sign));
v.push(unit.to_json());
v
}),

View File

@ -8,59 +8,93 @@ use std::ops::Range;
use std::cell::Cell;
use std::char;
use std::ascii::AsciiExt;
use std::borrow::{Cow, ToOwned};
use std::borrow::Cow::{Owned, Borrowed};
use std::i32;
use compact_cow_str::CompactCowStr;
use self::Token::*;
/// One of the pieces the CSS input is broken into.
///
/// Some components use `CowString` in order to borrow from the original input string
/// Some components use `Cow` in order to borrow from the original input string
/// and avoid allocating/copying when possible.
#[derive(PartialEq, Debug, Clone)]
pub enum Token<'a> {
/// A [`<ident-token>`](https://drafts.csswg.org/css-syntax/#ident-token-diagram)
Ident(Cow<'a, str>),
Ident(CompactCowStr<'a>),
/// A [`<at-keyword-token>`](https://drafts.csswg.org/css-syntax/#at-keyword-token-diagram)
///
/// The value does not include the `@` marker.
AtKeyword(Cow<'a, str>),
AtKeyword(CompactCowStr<'a>),
/// A [`<hash-token>`](https://drafts.csswg.org/css-syntax/#hash-token-diagram) with the type flag set to "unrestricted"
///
/// The value does not include the `#` marker.
Hash(Cow<'a, str>),
Hash(CompactCowStr<'a>),
/// A [`<hash-token>`](https://drafts.csswg.org/css-syntax/#hash-token-diagram) with the type flag set to "id"
///
/// The value does not include the `#` marker.
IDHash(Cow<'a, str>), // Hash that is a valid ID selector.
IDHash(CompactCowStr<'a>), // Hash that is a valid ID selector.
/// A [`<string-token>`](https://drafts.csswg.org/css-syntax/#string-token-diagram)
///
/// The value does not include the quotes.
QuotedString(Cow<'a, str>),
QuotedString(CompactCowStr<'a>),
/// A [`<url-token>`](https://drafts.csswg.org/css-syntax/#url-token-diagram) or `url( <string-token> )` function
///
/// The value does not include the `url(` `)` markers or the quotes.
UnquotedUrl(Cow<'a, str>),
UnquotedUrl(CompactCowStr<'a>),
/// A `<delim-token>`
Delim(char),
/// A [`<number-token>`](https://drafts.csswg.org/css-syntax/#number-token-diagram)
Number(NumericValue),
Number {
/// Whether the number had a `+` or `-` sign.
///
/// This is used is some cases like the <An+B> micro syntax. (See the `parse_nth` function.)
has_sign: bool,
/// The value as a float
value: f32,
/// If the origin source did not include a fractional part, the value as an integer.
int_value: Option<i32>,
},
/// A [`<percentage-token>`](https://drafts.csswg.org/css-syntax/#percentage-token-diagram)
Percentage(PercentageValue),
Percentage {
/// Whether the number had a `+` or `-` sign.
has_sign: bool,
/// The value as a float, divided by 100 so that the nominal range is 0.0 to 1.0.
unit_value: f32,
/// If the origin source did not include a fractional part, the value as an integer.
/// It is **not** divided by 100.
int_value: Option<i32>,
},
/// A [`<dimension-token>`](https://drafts.csswg.org/css-syntax/#dimension-token-diagram)
Dimension(NumericValue, Cow<'a, str>),
Dimension {
/// Whether the number had a `+` or `-` sign.
///
/// This is used is some cases like the <An+B> micro syntax. (See the `parse_nth` function.)
has_sign: bool,
/// The value as a float
value: f32,
/// If the origin source did not include a fractional part, the value as an integer.
int_value: Option<i32>,
/// The unit, e.g. "px" in `12px`
unit: CompactCowStr<'a>
},
/// A [`<whitespace-token>`](https://drafts.csswg.org/css-syntax/#whitespace-token-diagram)
WhiteSpace(&'a str),
@ -109,7 +143,7 @@ pub enum Token<'a> {
/// A [`<function-token>`](https://drafts.csswg.org/css-syntax/#function-token-diagram)
///
/// The value (name) does not include the `(` marker.
Function(Cow<'a, str>),
Function(CompactCowStr<'a>),
/// A `<(-token>`
ParenthesisBlock,
@ -166,36 +200,6 @@ impl<'a> Token<'a> {
}
/// The numeric value of `Number` and `Dimension` tokens.
#[derive(PartialEq, Debug, Copy, Clone)]
pub struct NumericValue {
/// The value as a float
pub value: f32,
/// If the origin source did not include a fractional part, the value as an integer.
pub int_value: Option<i32>,
/// Whether the number had a `+` or `-` sign.
///
/// This is used is some cases like the <An+B> micro syntax. (See the `parse_nth` function.)
pub has_sign: bool,
}
/// The numeric value of `Percentage` tokens.
#[derive(PartialEq, Debug, Copy, Clone)]
pub struct PercentageValue {
/// The value as a float, divided by 100 so that the nominal range is 0.0 to 1.0.
pub unit_value: f32,
/// If the origin source did not include a fractional part, the value as an integer. It is **not** divided by 100.
pub int_value: Option<i32>,
/// Whether the number had a `+` or `-` sign.
pub has_sign: bool,
}
#[derive(Clone)]
pub struct Tokenizer<'a> {
input: &'a str,
@ -559,28 +563,28 @@ fn consume_string<'a>(tokenizer: &mut Tokenizer<'a>, single_quote: bool) -> Toke
/// Return `Err(())` on syntax error (ie. unescaped newline)
fn consume_quoted_string<'a>(tokenizer: &mut Tokenizer<'a>, single_quote: bool)
-> Result<Cow<'a, str>, ()> {
-> Result<CompactCowStr<'a>, ()> {
tokenizer.advance(1); // Skip the initial quote
// start_pos is at code point boundary, after " or '
let start_pos = tokenizer.position();
let mut string_bytes;
loop {
if tokenizer.is_eof() {
return Ok(Borrowed(tokenizer.slice_from(start_pos)))
return Ok(tokenizer.slice_from(start_pos).into())
}
match_byte! { tokenizer.next_byte_unchecked(),
b'"' => {
if !single_quote {
let value = tokenizer.slice_from(start_pos);
tokenizer.advance(1);
return Ok(Borrowed(value))
return Ok(value.into())
}
}
b'\'' => {
if single_quote {
let value = tokenizer.slice_from(start_pos);
tokenizer.advance(1);
return Ok(Borrowed(value))
return Ok(value.into())
}
}
b'\\' | b'\0' => {
@ -644,10 +648,10 @@ fn consume_quoted_string<'a>(tokenizer: &mut Tokenizer<'a>, single_quote: bool)
string_bytes.push(b);
}
Ok(Owned(
Ok(
// string_bytes is well-formed UTF-8, see other comments.
unsafe { from_utf8_release_unchecked(string_bytes) }
))
unsafe { from_utf8_release_unchecked(string_bytes) }.into()
)
}
@ -688,13 +692,13 @@ fn consume_ident_like<'a>(tokenizer: &mut Tokenizer<'a>) -> Token<'a> {
}
}
fn consume_name<'a>(tokenizer: &mut Tokenizer<'a>) -> Cow<'a, str> {
fn consume_name<'a>(tokenizer: &mut Tokenizer<'a>) -> CompactCowStr<'a> {
// start_pos is the end of the previous token, therefore at a code point boundary
let start_pos = tokenizer.position();
let mut value_bytes;
loop {
if tokenizer.is_eof() {
return Borrowed(tokenizer.slice_from(start_pos))
return tokenizer.slice_from(start_pos).into()
}
match_byte! { tokenizer.next_byte_unchecked(),
b'a'...b'z' | b'A'...b'Z' | b'0'...b'9' | b'_' | b'-' => { tokenizer.advance(1) },
@ -709,7 +713,7 @@ fn consume_name<'a>(tokenizer: &mut Tokenizer<'a>) -> Cow<'a, str> {
}
b => {
if b.is_ascii() {
return Borrowed(tokenizer.slice_from(start_pos));
return tokenizer.slice_from(start_pos).into();
}
tokenizer.advance(1);
}
@ -744,10 +748,8 @@ fn consume_name<'a>(tokenizer: &mut Tokenizer<'a>) -> Cow<'a, str> {
}
}
}
Owned(
// string_bytes is well-formed UTF-8, see other comments.
unsafe { from_utf8_release_unchecked(value_bytes) }
)
// string_bytes is well-formed UTF-8, see other comments.
unsafe { from_utf8_release_unchecked(value_bytes) }.into()
}
fn byte_to_hex_digit(b: u8) -> Option<u32> {
@ -858,30 +860,35 @@ fn consume_numeric<'a>(tokenizer: &mut Tokenizer<'a>) -> Token<'a> {
if !tokenizer.is_eof() && tokenizer.next_byte_unchecked() == b'%' {
tokenizer.advance(1);
return Percentage(PercentageValue {
return Percentage {
unit_value: (value / 100.) as f32,
int_value: int_value,
has_sign: has_sign,
})
}
}
let value = NumericValue {
value: value as f32,
int_value: int_value,
has_sign: has_sign,
};
let value = value as f32;
if is_ident_start(tokenizer) {
let name = consume_name(tokenizer);
let unit = consume_name(tokenizer);
if tokenizer.viewport_percentages == SeenStatus::LookingForThem {
if name.eq_ignore_ascii_case("vh") ||
name.eq_ignore_ascii_case("vw") ||
name.eq_ignore_ascii_case("vmin") ||
name.eq_ignore_ascii_case("vmax") {
if unit.eq_ignore_ascii_case("vh") ||
unit.eq_ignore_ascii_case("vw") ||
unit.eq_ignore_ascii_case("vmin") ||
unit.eq_ignore_ascii_case("vmax") {
tokenizer.viewport_percentages = SeenStatus::SeenAtLeastOne;
}
}
Dimension(value, name)
Dimension {
value: value,
int_value: int_value,
has_sign: has_sign,
unit: unit,
}
} else {
Number(value)
Number {
value: value,
int_value: int_value,
has_sign: has_sign,
}
}
}
@ -903,7 +910,7 @@ fn consume_unquoted_url<'a>(tokenizer: &mut Tokenizer<'a>) -> Result<Token<'a>,
b'"' | b'\'' => { return Err(()) }, // Do not advance
b')' => {
tokenizer.advance(offset + 1);
return Ok(UnquotedUrl(Borrowed("")));
return Ok(UnquotedUrl("".into()));
}
_ => {
tokenizer.advance(offset);
@ -914,7 +921,7 @@ fn consume_unquoted_url<'a>(tokenizer: &mut Tokenizer<'a>) -> Result<Token<'a>,
}
}
tokenizer.position = tokenizer.input.len();
return Ok(UnquotedUrl(Borrowed("")));
return Ok(UnquotedUrl("".into()));
fn consume_unquoted_url_internal<'a>(tokenizer: &mut Tokenizer<'a>) -> Token<'a> {
// This function is only called with start_pos at a code point boundary.
@ -922,18 +929,18 @@ fn consume_unquoted_url<'a>(tokenizer: &mut Tokenizer<'a>) -> Result<Token<'a>,
let mut string_bytes: Vec<u8>;
loop {
if tokenizer.is_eof() {
return UnquotedUrl(Borrowed(tokenizer.slice_from(start_pos)))
return UnquotedUrl(tokenizer.slice_from(start_pos).into())
}
match_byte! { tokenizer.next_byte_unchecked(),
b' ' | b'\t' | b'\n' | b'\r' | b'\x0C' => {
let value = tokenizer.slice_from(start_pos);
tokenizer.advance(1);
return consume_url_end(tokenizer, Borrowed(value))
return consume_url_end(tokenizer, value.into())
}
b')' => {
let value = tokenizer.slice_from(start_pos);
tokenizer.advance(1);
return UnquotedUrl(Borrowed(value))
return UnquotedUrl(value.into())
}
b'\x01'...b'\x08' | b'\x0B' | b'\x0E'...b'\x1F' | b'\x7F' // non-printable
| b'"' | b'\'' | b'(' => {
@ -957,10 +964,11 @@ fn consume_unquoted_url<'a>(tokenizer: &mut Tokenizer<'a>) -> Result<Token<'a>,
while !tokenizer.is_eof() {
match_byte! { tokenizer.consume_byte(),
b' ' | b'\t' | b'\n' | b'\r' | b'\x0C' => {
return consume_url_end(tokenizer, Owned(
return consume_url_end(
tokenizer,
// string_bytes is well-formed UTF-8, see other comments.
unsafe { from_utf8_release_unchecked(string_bytes) }
))
unsafe { from_utf8_release_unchecked(string_bytes) }.into()
)
}
b')' => {
break;
@ -985,13 +993,13 @@ fn consume_unquoted_url<'a>(tokenizer: &mut Tokenizer<'a>) -> Result<Token<'a>,
b => { string_bytes.push(b) }
}
}
UnquotedUrl(Owned(
UnquotedUrl(
// string_bytes is well-formed UTF-8, see other comments.
unsafe { from_utf8_release_unchecked(string_bytes) }
))
unsafe { from_utf8_release_unchecked(string_bytes) }.into()
)
}
fn consume_url_end<'a>(tokenizer: &mut Tokenizer<'a>, string: Cow<'a, str>) -> Token<'a> {
fn consume_url_end<'a>(tokenizer: &mut Tokenizer<'a>, string: CompactCowStr<'a>) -> Token<'a> {
while !tokenizer.is_eof() {
match_byte! { tokenizer.consume_byte(),
b' ' | b'\t' | b'\n' | b'\r' | b'\x0C' => {},

View File

@ -64,15 +64,15 @@ fn parse_tokens<'i, 't>(input: &mut Parser<'i, 't>) -> Result<(), BasicParseErro
}
parse_question_marks(input)
}
Token::Dimension(..) => {
Token::Dimension { .. } => {
parse_question_marks(input)
}
Token::Number(_) => {
Token::Number { .. } => {
let after_number = input.position();
match input.next_including_whitespace() {
Ok(Token::Delim('?')) => parse_question_marks(input),
Ok(Token::Dimension(..)) => {}
Ok(Token::Number(_)) => {}
Ok(Token::Dimension { .. }) => {}
Ok(Token::Number { .. }) => {}
_ => input.reset(after_number)
}
}

View File

@ -238,7 +238,7 @@ dependencies = [
[[package]]
name = "cssparser"
version = "0.15.0"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -392,7 +392,7 @@ name = "geckoservo"
version = "0.0.1"
dependencies = [
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -831,7 +831,7 @@ name = "selectors"
version = "0.19.0"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -928,7 +928,7 @@ dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -973,7 +973,7 @@ version = "0.0.1"
dependencies = [
"app_units 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.19.0",
]
@ -1279,7 +1279,7 @@ dependencies = [
"checksum core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41115a6aa5d3e1e5ef98148373f25971d1fad53818553f216495f9e67e90a624"
"checksum core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ead017dcf77f503dc991f6b52de6084eeea60a94b0a652baa9bf88654a28e83f"
"checksum core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9719616a10f717628e074744f8c55df7b450f7a34d29c196d14f4498aad05d"
"checksum cssparser 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd54cdee668d71d20e9f8b9676e2e969968d186ab20a101af59c28398393a2b0"
"checksum cssparser 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c711c0c610b1e5fc2bf96e325b2d9f85839a8e71f6279a77c194af5dcafa502"
"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
"checksum dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74114b6b49d6731835da7a28a3642651451e315f7f9b9d04e907e65a45681796"
"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"

View File

@ -236,7 +236,7 @@ dependencies = [
[[package]]
name = "cssparser"
version = "0.15.0"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -390,7 +390,7 @@ name = "geckoservo"
version = "0.0.1"
dependencies = [
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -818,7 +818,7 @@ name = "selectors"
version = "0.19.0"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -915,7 +915,7 @@ dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -960,7 +960,7 @@ version = "0.0.1"
dependencies = [
"app_units 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.19.0",
]
@ -1266,7 +1266,7 @@ dependencies = [
"checksum core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41115a6aa5d3e1e5ef98148373f25971d1fad53818553f216495f9e67e90a624"
"checksum core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ead017dcf77f503dc991f6b52de6084eeea60a94b0a652baa9bf88654a28e83f"
"checksum core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9719616a10f717628e074744f8c55df7b450f7a34d29c196d14f4498aad05d"
"checksum cssparser 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd54cdee668d71d20e9f8b9676e2e969968d186ab20a101af59c28398393a2b0"
"checksum cssparser 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c711c0c610b1e5fc2bf96e325b2d9f85839a8e71f6279a77c194af5dcafa502"
"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
"checksum dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74114b6b49d6731835da7a28a3642651451e315f7f9b9d04e907e65a45681796"
"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"