зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1830369 - [css-nesting] Update cssparser to allow parsing qualified rules along with declarations. r=tlouw,supply-chain-reviewers
No implementation just yet (the default QualifiedRuleParser implementation just rejects stuff), but this is plumbing that I'd rather get reviewed separately. Differential Revision: https://phabricator.services.mozilla.com/D176686
This commit is contained in:
Родитель
9acd8521cd
Коммит
8d2220d803
|
@ -105,9 +105,9 @@ git = "https://github.com/mozilla/uniffi-rs.git"
|
|||
rev = "bc7ff8977bf38d0fdd1a458810b14f434d4dc4de"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/servo/rust-cssparser?rev=45bc47e2bcb846f1efb5aea156be5fe7d18624bf"]
|
||||
[source."git+https://github.com/servo/rust-cssparser?rev=3e1bd05139cb7174ace395d498ca7128feb8f69d"]
|
||||
git = "https://github.com/servo/rust-cssparser"
|
||||
rev = "45bc47e2bcb846f1efb5aea156be5fe7d18624bf"
|
||||
rev = "3e1bd05139cb7174ace395d498ca7128feb8f69d"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
|
||||
|
|
|
@ -1016,8 +1016,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cssparser"
|
||||
version = "0.30.0"
|
||||
source = "git+https://github.com/servo/rust-cssparser?rev=45bc47e2bcb846f1efb5aea156be5fe7d18624bf#45bc47e2bcb846f1efb5aea156be5fe7d18624bf"
|
||||
version = "0.31.0"
|
||||
source = "git+https://github.com/servo/rust-cssparser?rev=3e1bd05139cb7174ace395d498ca7128feb8f69d#3e1bd05139cb7174ace395d498ca7128feb8f69d"
|
||||
dependencies = [
|
||||
"cssparser-macros",
|
||||
"dtoa-short",
|
||||
|
@ -1032,7 +1032,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cssparser-macros"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/servo/rust-cssparser?rev=45bc47e2bcb846f1efb5aea156be5fe7d18624bf#45bc47e2bcb846f1efb5aea156be5fe7d18624bf"
|
||||
source = "git+https://github.com/servo/rust-cssparser?rev=3e1bd05139cb7174ace395d498ca7128feb8f69d#3e1bd05139cb7174ace395d498ca7128feb8f69d"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
|
|
|
@ -163,7 +163,7 @@ midir = { git = "https://github.com/mozilla/midir.git", rev = "519e651241e867af3
|
|||
# warp 0.3.3 + https://github.com/seanmonstar/warp/pull/1007
|
||||
warp = { git = "https://github.com/glandium/warp", rev = "4af45fae95bc98b0eba1ef0db17e1dac471bb23d" }
|
||||
|
||||
cssparser = { git = "https://github.com/servo/rust-cssparser", rev = "45bc47e2bcb846f1efb5aea156be5fe7d18624bf" }
|
||||
cssparser = { git = "https://github.com/servo/rust-cssparser", rev = "3e1bd05139cb7174ace395d498ca7128feb8f69d" }
|
||||
|
||||
# application-services overrides to make updating them all simpler.
|
||||
interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "86c84c217036c12283d19368867323a66bf35883" }
|
||||
|
|
|
@ -31,7 +31,7 @@ accountable-refcell = { version = "0.2.0", optional = true }
|
|||
app_units = "0.7"
|
||||
content-security-policy = { version = "0.4.0", features = ["serde"], optional = true }
|
||||
crossbeam-channel = { version = "0.4", optional = true }
|
||||
cssparser = "0.30"
|
||||
cssparser = "0.31"
|
||||
dom = { path = "../../../dom/base/rust" }
|
||||
euclid = "0.22"
|
||||
hyper = { version = "0.12", optional = true }
|
||||
|
|
|
@ -20,7 +20,7 @@ bench = []
|
|||
[dependencies]
|
||||
bitflags = "1.0"
|
||||
matches = "0.1"
|
||||
cssparser = "0.30"
|
||||
cssparser = "0.31"
|
||||
derive_more = { version = "0.99", default-features = false, features = ["add", "add_assign"] }
|
||||
fxhash = "0.2"
|
||||
log = "0.4"
|
||||
|
|
|
@ -32,7 +32,7 @@ arrayvec = "0.7"
|
|||
atomic_refcell = "0.1"
|
||||
bitflags = "1.0"
|
||||
byteorder = "1.0"
|
||||
cssparser = "0.30"
|
||||
cssparser = "0.31"
|
||||
derive_more = { version = "0.99", default-features = false, features = ["add", "add_assign", "deref", "from"] }
|
||||
dom = { path = "../../../dom/base/rust" }
|
||||
new_debug_unreachable = "1.0"
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::str::CssStringWriter;
|
|||
use crate::values::specified::Integer;
|
||||
use crate::values::CustomIdent;
|
||||
use crate::Atom;
|
||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser};
|
||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, QualifiedRuleParser};
|
||||
use cssparser::{CowRcStr, Parser, SourceLocation, Token};
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use std::fmt::{self, Write};
|
||||
|
@ -153,6 +153,12 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for CounterStyleRuleParser<'a, 'b> {
|
|||
type Error = StyleParseErrorKind<'i>;
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for CounterStyleRuleParser<'a, 'b> {
|
||||
type Prelude = ();
|
||||
type QualifiedRule = ();
|
||||
type Error = StyleParseErrorKind<'i>;
|
||||
}
|
||||
|
||||
macro_rules! checker {
|
||||
($self:ident._($value:ident)) => {};
|
||||
($self:ident. $checker:ident($value:ident)) => {
|
||||
|
|
|
@ -14,18 +14,20 @@ use crate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
|||
use crate::str::CssStringWriter;
|
||||
use crate::values::computed::font::{FamilyName, FontStretch};
|
||||
use crate::values::generics::font::FontStyle as GenericFontStyle;
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::values::specified::font::{FontFeatureSettings, FontVariationSettings};
|
||||
use crate::values::specified::font::SpecifiedFontStyle;
|
||||
use crate::values::specified::font::{
|
||||
AbsoluteFontWeight, FontStretch as SpecifiedFontStretch, MetricsOverride,
|
||||
};
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::values::specified::font::{FontFeatureSettings, FontVariationSettings};
|
||||
use crate::values::specified::url::SpecifiedUrl;
|
||||
use crate::values::specified::{Angle, NonNegativePercentage};
|
||||
#[cfg(feature = "gecko")]
|
||||
use cssparser::UnicodeRange;
|
||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
|
||||
use cssparser::{CowRcStr, SourceLocation};
|
||||
use cssparser::{
|
||||
AtRuleParser, CowRcStr, DeclarationListParser, DeclarationParser, Parser, QualifiedRuleParser,
|
||||
SourceLocation,
|
||||
};
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{CssWriter, ParseError};
|
||||
|
@ -541,6 +543,12 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for FontFaceRuleParser<'a, 'b> {
|
|||
type Error = StyleParseErrorKind<'i>;
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for FontFaceRuleParser<'a, 'b> {
|
||||
type Prelude = ();
|
||||
type QualifiedRule = ();
|
||||
type Error = StyleParseErrorKind<'i>;
|
||||
}
|
||||
|
||||
impl Parse for Source {
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
|
|
|
@ -18,10 +18,12 @@ use crate::selector_map::PrecomputedHashSet;
|
|||
use crate::selector_parser::SelectorImpl;
|
||||
use crate::shared_lock::Locked;
|
||||
use crate::str::{CssString, CssStringWriter};
|
||||
use crate::stylesheets::{CssRuleType, Origin, UrlExtraData, layer_rule::LayerOrder};
|
||||
use crate::stylesheets::{layer_rule::LayerOrder, CssRuleType, Origin, UrlExtraData};
|
||||
use crate::values::computed::Context;
|
||||
use cssparser::{parse_important, CowRcStr, DeclarationListParser, ParserInput};
|
||||
use cssparser::{AtRuleParser, DeclarationParser, Delimiter, ParseErrorKind, Parser};
|
||||
use cssparser::{
|
||||
parse_important, AtRuleParser, CowRcStr, DeclarationListParser, DeclarationParser, Delimiter,
|
||||
ParseErrorKind, Parser, ParserInput, QualifiedRuleParser,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use selectors::SelectorList;
|
||||
use smallbitvec::{self, SmallBitVec};
|
||||
|
@ -915,10 +917,7 @@ impl PropertyDeclarationBlock {
|
|||
&self,
|
||||
context: &Context,
|
||||
) -> Option<Arc<crate::custom_properties::CustomPropertiesMap>> {
|
||||
self.cascade_custom_properties(
|
||||
context.style().custom_properties(),
|
||||
context.device(),
|
||||
)
|
||||
self.cascade_custom_properties(context.style().custom_properties(), context.device())
|
||||
}
|
||||
|
||||
/// Returns a custom properties map which is the result of cascading custom
|
||||
|
@ -933,7 +932,13 @@ impl PropertyDeclarationBlock {
|
|||
|
||||
for declaration in self.normal_declaration_iter() {
|
||||
if let PropertyDeclaration::Custom(ref declaration) = *declaration {
|
||||
builder.cascade(declaration, CascadePriority::new(CascadeLevel::same_tree_author_normal(), LayerOrder::root()));
|
||||
builder.cascade(
|
||||
declaration,
|
||||
CascadePriority::new(
|
||||
CascadeLevel::same_tree_author_normal(),
|
||||
LayerOrder::root(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1097,12 +1102,11 @@ impl PropertyDeclarationBlock {
|
|||
// 3.4.7:
|
||||
// Let value be the result of invoking serialize a CSS value
|
||||
// of current longhands.
|
||||
let appendable_value = match shorthand
|
||||
.get_shorthand_appendable_value(¤t_longhands)
|
||||
{
|
||||
None => continue,
|
||||
Some(appendable_value) => appendable_value,
|
||||
};
|
||||
let appendable_value =
|
||||
match shorthand.get_shorthand_appendable_value(¤t_longhands) {
|
||||
None => continue,
|
||||
Some(appendable_value) => appendable_value,
|
||||
};
|
||||
|
||||
// We avoid re-serializing if we're already an
|
||||
// AppendableValue::Css.
|
||||
|
@ -1125,7 +1129,9 @@ impl PropertyDeclarationBlock {
|
|||
AppendableValue::Css({
|
||||
// Safety: serialization only generates valid utf-8.
|
||||
#[cfg(feature = "gecko")]
|
||||
unsafe { v.as_str_unchecked() }
|
||||
unsafe {
|
||||
v.as_str_unchecked()
|
||||
}
|
||||
#[cfg(feature = "servo")]
|
||||
&v
|
||||
})
|
||||
|
@ -1356,6 +1362,13 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
|||
type Error = StyleParseErrorKind<'i>;
|
||||
}
|
||||
|
||||
/// Default methods reject all rules.
|
||||
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
||||
type Prelude = ();
|
||||
type QualifiedRule = Importance;
|
||||
type Error = StyleParseErrorKind<'i>;
|
||||
}
|
||||
|
||||
/// Based on NonMozillaVendorIdentifier from Gecko's CSS parser.
|
||||
fn is_non_mozilla_vendor_identifier(name: &str) -> bool {
|
||||
(name.starts_with("-") && !name.starts_with("-moz-")) || name.starts_with("_")
|
||||
|
|
|
@ -18,9 +18,10 @@ use crate::stylesheets::CssRuleType;
|
|||
use crate::values::computed::font::FamilyName;
|
||||
use crate::values::serialize_atom_identifier;
|
||||
use crate::Atom;
|
||||
use cssparser::{AtRuleParser, BasicParseErrorKind, CowRcStr};
|
||||
use cssparser::{DeclarationListParser, DeclarationParser, Parser};
|
||||
use cssparser::{ParserState, QualifiedRuleParser, RuleListParser, SourceLocation, Token};
|
||||
use cssparser::{
|
||||
AtRuleParser, BasicParseErrorKind, CowRcStr, DeclarationListParser, DeclarationParser, Parser,
|
||||
ParserState, QualifiedRuleParser, RuleListParser, SourceLocation, Token,
|
||||
};
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||
|
||||
|
@ -193,6 +194,12 @@ impl<'a, 'b, 'i, T> AtRuleParser<'i> for FFVDeclarationsParser<'a, 'b, T> {
|
|||
type Error = StyleParseErrorKind<'i>;
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'i, T> QualifiedRuleParser<'i> for FFVDeclarationsParser<'a, 'b, T> {
|
||||
type Prelude = ();
|
||||
type QualifiedRule = ();
|
||||
type Error = StyleParseErrorKind<'i>;
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'i, T> DeclarationParser<'i> for FFVDeclarationsParser<'a, 'b, T>
|
||||
where
|
||||
T: Parse,
|
||||
|
|
|
@ -636,6 +636,12 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for KeyframeDeclarationParser<'a, 'b> {
|
|||
type Error = StyleParseErrorKind<'i>;
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for KeyframeDeclarationParser<'a, 'b> {
|
||||
type Prelude = ();
|
||||
type QualifiedRule = ();
|
||||
type Error = StyleParseErrorKind<'i>;
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'i> DeclarationParser<'i> for KeyframeDeclarationParser<'a, 'b> {
|
||||
type Declaration = ();
|
||||
type Error = StyleParseErrorKind<'i>;
|
||||
|
|
|
@ -24,8 +24,10 @@ use crate::values::generics::NonNegative;
|
|||
use crate::values::specified::{self, NoCalcLength};
|
||||
use crate::values::specified::{NonNegativeLengthPercentageOrAuto, ViewportPercentageLength};
|
||||
use app_units::Au;
|
||||
use cssparser::CowRcStr;
|
||||
use cssparser::{parse_important, AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
|
||||
use cssparser::{
|
||||
parse_important, AtRuleParser, CowRcStr, DeclarationListParser, DeclarationParser, Parser,
|
||||
QualifiedRuleParser,
|
||||
};
|
||||
use euclid::Size2D;
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use std::borrow::Cow;
|
||||
|
@ -245,6 +247,12 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for ViewportRuleParser<'a, 'b> {
|
|||
type Error = StyleParseErrorKind<'i>;
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for ViewportRuleParser<'a, 'b> {
|
||||
type Prelude = ();
|
||||
type QualifiedRule = Vec<ViewportDescriptorDeclaration>;
|
||||
type Error = StyleParseErrorKind<'i>;
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'i> DeclarationParser<'i> for ViewportRuleParser<'a, 'b> {
|
||||
type Declaration = Vec<ViewportDescriptorDeclaration>;
|
||||
type Error = StyleParseErrorKind<'i>;
|
||||
|
|
|
@ -16,7 +16,7 @@ gecko = []
|
|||
[dependencies]
|
||||
app_units = "0.7"
|
||||
bitflags = "1.0"
|
||||
cssparser = "0.30"
|
||||
cssparser = "0.31"
|
||||
euclid = "0.22"
|
||||
lazy_static = "1"
|
||||
malloc_size_of = { path = "../malloc_size_of" }
|
||||
|
|
|
@ -14,7 +14,7 @@ servo = ["cssparser/serde", "string_cache"]
|
|||
gecko = []
|
||||
|
||||
[dependencies]
|
||||
cssparser = "0.30"
|
||||
cssparser = "0.31"
|
||||
servo_arc = { path = "../servo_arc" }
|
||||
smallbitvec = "2.1.1"
|
||||
smallvec = "1.0"
|
||||
|
|
|
@ -15,7 +15,7 @@ gecko_refcount_logging = ["style/gecko_refcount_logging", "servo_arc/gecko_refco
|
|||
[dependencies]
|
||||
atomic_refcell = "0.1"
|
||||
bincode = "1.0"
|
||||
cssparser = "0.30"
|
||||
cssparser = "0.31"
|
||||
cstr = "0.2"
|
||||
dom = { path = "../../../dom/base/rust" }
|
||||
gecko-profiler = { path = "../../../tools/profiler/rust-api" }
|
||||
|
|
|
@ -12,7 +12,7 @@ doctest = false
|
|||
[dependencies]
|
||||
byteorder = "1.0"
|
||||
app_units = "0.7"
|
||||
cssparser = "0.30"
|
||||
cssparser = "0.31"
|
||||
euclid = "0.22"
|
||||
html5ever = "0.22"
|
||||
parking_lot = "0.10"
|
||||
|
|
|
@ -600,27 +600,11 @@ to a match expression.
|
|||
"""
|
||||
|
||||
[[audits.cssparser-macros]]
|
||||
who = "Tiaan Louw <tlouw@mozilla.com>"
|
||||
who = "Emilio Cobos Álvarez <emilio@crisal.io>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.6.0 -> 0.6.0@git:45bc47e2bcb846f1efb5aea156be5fe7d18624bf"
|
||||
notes = "Latest version of changes to the cssparser pulled from master branch."
|
||||
|
||||
[[audits.cssparser-macros]]
|
||||
who = "Tiaan Louw <tlouw@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.6.0 -> 0.6.0@git:722b30d2f1634714befab967ecae627813fa4cf0"
|
||||
delta = "0.6.0 -> 0.6.0@git:3e1bd05139cb7174ace395d498ca7128feb8f69d"
|
||||
notes = "We are pulling this package from a non crates.io source until the changes are published. No changes were made to the code."
|
||||
|
||||
[[audits.cssparser-macros]]
|
||||
who = "Tiaan Louw <tlouw@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.6.0 -> 0.6.0@git:b196a164dcbb317016d4aa6c58c13147e6045ebb"
|
||||
|
||||
[[audits.cssparser-macros]]
|
||||
who = "Tiaan Louw <tlouw@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.6.0 -> 0.6.0@git:d3670a89bae26ba3a8db4758eb7976616113987d"
|
||||
|
||||
[[audits.cstr]]
|
||||
who = "Emilio Cobos Álvarez <emilio@crisal.io>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".github/workflows/main.yml":"d66f2aac0764ebb09540737931fe2b9311e7033a2bf9a116c072cae6bec5e187","Cargo.toml":"50e9595b9b5243dab2200c2006ea9aed05e68118a9109e3320bda3d3bd82924b","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"53a6805edd80f642473514cb93f1f4197e17a911d66a2dfcefc3dc5e82bac206","build.rs":"b30f35bfbd713943822a19ce6ebe5c99017f603cb001ed37354020549aec71fc","build/match_byte.rs":"f57faf0597cb7b3e32999c5fb1215a43a5603121588c67d5031f720362171e1c","docs/.nojekyll":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/color.rs":"788898ddc0dec90fc972091642f37ab769fc818199293b8dc1c59c21ad0d3d00","src/cow_rc_str.rs":"89b5dff5cf80eef3fcff0c11799e54a978d02d8b8963a621fbb999d35e7c03a3","src/from_bytes.rs":"b1cf15c4e975523fef46b575598737a39f3c63e5ce0b2bfd6ec627c69c6ea54a","src/lib.rs":"9a6b8657291eb142cd33972eaba1afd8fb2432b96b061687238278fecc3e0de1","src/macros.rs":"0d4c3d27a22677d9eb3616d7f7af604dc3de2932ca04fd1c036102884cd6f079","src/nth.rs":"2fc26915f0a36cb22ac45dd9a7ecbdc64c327b2ec135370258ec3db9f9985460","src/parser.rs":"f9985187ede4361a29b3bf22d248903343d58e5cf369a9b5e046961356a4faf9","src/rules_and_declarations.rs":"d826f82f8c179fc13756b92336556e3ee40a273314ef774f95af71e687745f2a","src/serializer.rs":"3a0155521676deea9a6327c2ed00af6d5dabb29a97e2341d0f565f8c2b66d0a3","src/size_of_tests.rs":"da0cbcaa304f7800e9122e2bce0a11d42a70b9012e646a723cb23ee74a6b858c","src/tests.rs":"9847bd8a60bda34259d2900e2b2d217e4c4a0e7dc6e410c61eee3b0e805b9a7e","src/tokenizer.rs":"71600903284f1d68a7da6b69c938b31f9d641f8d981c7adfd06a3c8b783541f2","src/unicode_range.rs":"20d96f06fbb73921e308cc340c9fe065e27f19843005689fb259007a6a372bcc"},"package":null}
|
||||
{"files":{".github/workflows/main.yml":"73c57dbb2c5471de2fcba828e356d09931ae89176f3bb695029b169dbb3f696f","Cargo.toml":"ad9de3a9ca008259eb361bc7150e70ca2a20e1a6af6d85d89288a4a1371b7f32","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"53a6805edd80f642473514cb93f1f4197e17a911d66a2dfcefc3dc5e82bac206","build.rs":"b30f35bfbd713943822a19ce6ebe5c99017f603cb001ed37354020549aec71fc","build/match_byte.rs":"f57faf0597cb7b3e32999c5fb1215a43a5603121588c67d5031f720362171e1c","docs/.nojekyll":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/color.rs":"df7d97636896df02b7ba56abf6f74f121d8320615f9e6ef6d43e6f272d3600cb","src/cow_rc_str.rs":"22d6829ab54c51486af4bacf5f184a6c95c15febdbbd5630a98b995ed0ee3e55","src/from_bytes.rs":"b1cf15c4e975523fef46b575598737a39f3c63e5ce0b2bfd6ec627c69c6ea54a","src/lib.rs":"445e7b09b906014cffa0330a34ac7fcb011288cf370549d24883c8570219140f","src/macros.rs":"4462d7063e10e892ae9542074374422ca38bcffc0638f8a87343b049fef5504f","src/nth.rs":"2fc26915f0a36cb22ac45dd9a7ecbdc64c327b2ec135370258ec3db9f9985460","src/parser.rs":"c47a34d302dc458cb84a7ec9377cc94eb613d2365efa414b783f130d77dd6fe6","src/rules_and_declarations.rs":"011d0411106762b4241928907bab225d4c1a1191c220ed852ec228c1a38b8578","src/serializer.rs":"3a0155521676deea9a6327c2ed00af6d5dabb29a97e2341d0f565f8c2b66d0a3","src/size_of_tests.rs":"da0cbcaa304f7800e9122e2bce0a11d42a70b9012e646a723cb23ee74a6b858c","src/tests.rs":"58dba29c73a59fb45a0fe1810cfee1d018aa427dcd6bae8cc5d8f17d5230fba8","src/tokenizer.rs":"6fd5b9f3a89a87bf9334cc4765ad76e080ab6aaec73d996f052558480a3f007a","src/unicode_range.rs":"20d96f06fbb73921e308cc340c9fe065e27f19843005689fb259007a6a372bcc"},"package":null}
|
|
@ -16,7 +16,7 @@ jobs:
|
|||
- nightly
|
||||
- beta
|
||||
- stable
|
||||
- 1.56.0
|
||||
- 1.63.0
|
||||
features:
|
||||
-
|
||||
- --features dummy_match_byte
|
||||
|
@ -35,10 +35,6 @@ jobs:
|
|||
toolchain: ${{ matrix.toolchain }}
|
||||
override: true
|
||||
|
||||
- name: Downgrade phf to a version compatible with the MSRV
|
||||
run: cargo update --package phf --precise 0.10.1
|
||||
if: matrix.toolchain == '1.40.0'
|
||||
|
||||
- name: Cargo build
|
||||
run: cargo build ${{ matrix.features }}
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
|
||||
[package]
|
||||
edition = "2018"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.63"
|
||||
name = "cssparser"
|
||||
version = "0.30.0"
|
||||
version = "0.31.0"
|
||||
authors = ["Simon Sapin <simon.sapin@exyr.org>"]
|
||||
build = "build.rs"
|
||||
exclude = [
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
* 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/. */
|
||||
|
||||
// Allow text like <color> in docs.
|
||||
#![allow(rustdoc::invalid_html_tags)]
|
||||
|
||||
use std::f32::consts::PI;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
@ -23,7 +26,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-color-4/#serializing-alpha-values
|
||||
/// <https://drafts.csswg.org/css-color-4/#serializing-alpha-values>
|
||||
#[inline]
|
||||
fn serialize_alpha(
|
||||
dest: &mut impl fmt::Write,
|
||||
|
@ -53,14 +56,13 @@ fn serialize_alpha(
|
|||
|
||||
// Guaratees hue in [0..360)
|
||||
fn normalize_hue(hue: f32) -> f32 {
|
||||
// https://drafts.csswg.org/css-values/#angles
|
||||
// <https://drafts.csswg.org/css-values/#angles>
|
||||
// Subtract an integer before rounding, to avoid some rounding errors:
|
||||
hue - 360.0 * (hue / 360.0).floor()
|
||||
}
|
||||
|
||||
/// A color with red, green, blue, and alpha components, in a byte each.
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct RGBA {
|
||||
/// The red component.
|
||||
pub red: Option<u8>,
|
||||
|
@ -150,6 +152,7 @@ impl ToCss for RGBA {
|
|||
}
|
||||
}
|
||||
|
||||
/// Color specified by hue, saturation and lightness components.
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub struct Hsl {
|
||||
/// The hue component.
|
||||
|
@ -163,6 +166,7 @@ pub struct Hsl {
|
|||
}
|
||||
|
||||
impl Hsl {
|
||||
/// Construct a new HSL color from it's components.
|
||||
pub fn new(
|
||||
hue: Option<f32>,
|
||||
saturation: Option<f32>,
|
||||
|
@ -215,6 +219,7 @@ impl<'de> Deserialize<'de> for Hsl {
|
|||
}
|
||||
}
|
||||
|
||||
/// Color specified by hue, whiteness and blackness components.
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub struct Hwb {
|
||||
/// The hue component.
|
||||
|
@ -228,6 +233,7 @@ pub struct Hwb {
|
|||
}
|
||||
|
||||
impl Hwb {
|
||||
/// Construct a new HWB color from it's components.
|
||||
pub fn new(
|
||||
hue: Option<f32>,
|
||||
whiteness: Option<f32>,
|
||||
|
@ -285,7 +291,6 @@ impl<'de> Deserialize<'de> for Hwb {
|
|||
|
||||
/// Color specified by lightness, a- and b-axis components.
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct Lab {
|
||||
/// The lightness component.
|
||||
pub lightness: Option<f32>,
|
||||
|
@ -299,7 +304,6 @@ pub struct Lab {
|
|||
|
||||
/// Color specified by lightness, a- and b-axis components.
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct Oklab {
|
||||
/// The lightness component.
|
||||
pub lightness: Option<f32>,
|
||||
|
@ -378,7 +382,6 @@ impl_lab_like!(Oklab, "oklab");
|
|||
|
||||
/// Color specified by lightness, chroma and hue components.
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct Lch {
|
||||
/// The lightness component.
|
||||
pub lightness: Option<f32>,
|
||||
|
@ -392,7 +395,6 @@ pub struct Lch {
|
|||
|
||||
/// Color specified by lightness, chroma and hue components.
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct Oklch {
|
||||
/// The lightness component.
|
||||
pub lightness: Option<f32>,
|
||||
|
@ -467,24 +469,24 @@ impl_lch_like!(Lch, "lch");
|
|||
impl_lch_like!(Oklch, "oklch");
|
||||
|
||||
/// A Predefined color space specified in:
|
||||
/// https://drafts.csswg.org/css-color-4/#predefined
|
||||
/// <https://drafts.csswg.org/css-color-4/#predefined>
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub enum PredefinedColorSpace {
|
||||
/// https://drafts.csswg.org/css-color-4/#predefined-sRGB
|
||||
/// <https://drafts.csswg.org/css-color-4/#predefined-sRGB>
|
||||
Srgb,
|
||||
/// https://drafts.csswg.org/css-color-4/#predefined-sRGB-linear
|
||||
/// <https://drafts.csswg.org/css-color-4/#predefined-sRGB-linear>
|
||||
SrgbLinear,
|
||||
/// https://drafts.csswg.org/css-color-4/#predefined-display-p3
|
||||
/// <https://drafts.csswg.org/css-color-4/#predefined-display-p3>
|
||||
DisplayP3,
|
||||
/// https://drafts.csswg.org/css-color-4/#predefined-a98-rgb
|
||||
/// <https://drafts.csswg.org/css-color-4/#predefined-a98-rgb>
|
||||
A98Rgb,
|
||||
/// https://drafts.csswg.org/css-color-4/#predefined-prophoto-rgb
|
||||
/// <https://drafts.csswg.org/css-color-4/#predefined-prophoto-rgb>
|
||||
ProphotoRgb,
|
||||
/// https://drafts.csswg.org/css-color-4/#predefined-rec2020
|
||||
/// <https://drafts.csswg.org/css-color-4/#predefined-rec2020>
|
||||
Rec2020,
|
||||
/// https://drafts.csswg.org/css-color-4/#predefined-xyz
|
||||
/// <https://drafts.csswg.org/css-color-4/#predefined-xyz>
|
||||
XyzD50,
|
||||
/// https://drafts.csswg.org/css-color-4/#predefined-xyz
|
||||
/// <https://drafts.csswg.org/css-color-4/#predefined-xyz>
|
||||
XyzD65,
|
||||
}
|
||||
|
||||
|
@ -533,7 +535,7 @@ impl ToCss for PredefinedColorSpace {
|
|||
}
|
||||
|
||||
/// A color specified by the color() function.
|
||||
/// https://drafts.csswg.org/css-color-4/#color-function
|
||||
/// <https://drafts.csswg.org/css-color-4/#color-function>
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub struct ColorFunction {
|
||||
/// The color space for this color.
|
||||
|
@ -588,8 +590,13 @@ impl ToCss for ColorFunction {
|
|||
}
|
||||
}
|
||||
|
||||
/// A <color> value.
|
||||
/// https://drafts.csswg.org/css-color-4/#color-type
|
||||
/// Describes one of the value <color> values according to the CSS
|
||||
/// specification.
|
||||
///
|
||||
/// Most components are `Option<_>`, so when the value is `None`, that component
|
||||
/// serializes to the "none" keyword.
|
||||
///
|
||||
/// <https://drafts.csswg.org/css-color-4/#color-type>
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub enum Color {
|
||||
/// The 'currentcolor' keyword.
|
||||
|
@ -715,12 +722,14 @@ pub trait ColorParser<'i> {
|
|||
Token::Dimension {
|
||||
value: v, ref unit, ..
|
||||
} => {
|
||||
let degrees = match_ignore_ascii_case! { &*unit,
|
||||
let degrees = match_ignore_ascii_case! { unit,
|
||||
"deg" => v,
|
||||
"grad" => v * 360. / 400.,
|
||||
"rad" => v * 360. / (2. * PI),
|
||||
"turn" => v * 360.,
|
||||
_ => return Err(location.new_unexpected_token_error(Token::Ident(unit.clone()))),
|
||||
_ => {
|
||||
return Err(location.new_unexpected_token_error(Token::Ident(unit.clone())))
|
||||
}
|
||||
};
|
||||
|
||||
AngleOrNumber::Angle { degrees }
|
||||
|
@ -773,7 +782,7 @@ impl Color {
|
|||
/// Parse a <color> value, per CSS Color Module Level 3.
|
||||
///
|
||||
/// FIXME(#2) Deprecated CSS2 System Colors are not supported yet.
|
||||
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Color, ParseError<'i, ()>> {
|
||||
pub fn parse<'i>(input: &mut Parser<'i, '_>) -> Result<Color, ParseError<'i, ()>> {
|
||||
parse_color_with(&DefaultColorParser, input)
|
||||
}
|
||||
}
|
||||
|
@ -842,7 +851,7 @@ pub trait FromParsedColor {
|
|||
|
||||
/// Parse a color hash, without the leading '#' character.
|
||||
#[inline]
|
||||
pub fn parse_hash_color<'i, 't, O>(value: &[u8]) -> Result<O, ()>
|
||||
pub fn parse_hash_color<'i, O>(value: &[u8]) -> Result<O, ()>
|
||||
where
|
||||
O: FromParsedColor,
|
||||
{
|
||||
|
@ -875,8 +884,8 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
/// Parse a CSS color with the specified [`ColorComponentParser`] and return a
|
||||
/// new color value on success.
|
||||
/// Parse a CSS color using the specified [`ColorParser`] and return a new color
|
||||
/// value on success.
|
||||
pub fn parse_color_with<'i, 't, P>(
|
||||
color_parser: &P,
|
||||
input: &mut Parser<'i, 't>,
|
||||
|
@ -888,11 +897,11 @@ where
|
|||
let token = input.next()?;
|
||||
match *token {
|
||||
Token::Hash(ref value) | Token::IDHash(ref value) => parse_hash_color(value.as_bytes()),
|
||||
Token::Ident(ref value) => parse_color_keyword(&*value),
|
||||
Token::Ident(ref value) => parse_color_keyword(value),
|
||||
Token::Function(ref name) => {
|
||||
let name = name.clone();
|
||||
return input.parse_nested_block(|arguments| {
|
||||
parse_color_function(color_parser, &*name, arguments)
|
||||
parse_color_function(color_parser, &name, arguments)
|
||||
});
|
||||
}
|
||||
_ => Err(()),
|
||||
|
@ -1173,12 +1182,12 @@ fn clamp_unit_f32(val: f32) -> u8 {
|
|||
// Chrome does something similar for the alpha value, but not
|
||||
// the rgb values.
|
||||
//
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1340484
|
||||
// See <https://bugzilla.mozilla.org/show_bug.cgi?id=1340484>
|
||||
//
|
||||
// Clamping to 256 and rounding after would let 1.0 map to 256, and
|
||||
// `256.0_f32 as u8` is undefined behavior:
|
||||
//
|
||||
// https://github.com/rust-lang/rust/issues/10184
|
||||
// <https://github.com/rust-lang/rust/issues/10184>
|
||||
clamp_floor_256_f32(val * 255.)
|
||||
}
|
||||
|
||||
|
@ -1347,7 +1356,7 @@ where
|
|||
|
||||
/// Parses hsl syntax.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-color/#the-hsl-notation
|
||||
/// <https://drafts.csswg.org/css-color/#the-hsl-notation>
|
||||
#[inline]
|
||||
fn parse_hsl<'i, 't, P>(
|
||||
color_parser: &P,
|
||||
|
@ -1386,7 +1395,7 @@ where
|
|||
|
||||
/// Parses hwb syntax.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-color/#the-hbw-notation
|
||||
/// <https://drafts.csswg.org/css-color/#the-hbw-notation>
|
||||
#[inline]
|
||||
fn parse_hwb<'i, 't, P>(
|
||||
color_parser: &P,
|
||||
|
@ -1410,7 +1419,7 @@ where
|
|||
Ok(P::Output::from_hwb(hue, whiteness, blackness, alpha))
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-color-4/#hwb-to-rgb
|
||||
/// <https://drafts.csswg.org/css-color-4/#hwb-to-rgb>
|
||||
#[inline]
|
||||
pub fn hwb_to_rgb(h: f32, w: f32, b: f32) -> (f32, f32, f32) {
|
||||
if w + b >= 1.0 {
|
||||
|
@ -1427,11 +1436,11 @@ pub fn hwb_to_rgb(h: f32, w: f32, b: f32) -> (f32, f32, f32) {
|
|||
(red, green, blue)
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-color/#hsl-color
|
||||
/// <https://drafts.csswg.org/css-color/#hsl-color>
|
||||
/// except with h pre-multiplied by 3, to avoid some rounding errors.
|
||||
#[inline]
|
||||
pub fn hsl_to_rgb(hue: f32, saturation: f32, lightness: f32) -> (f32, f32, f32) {
|
||||
debug_assert!(hue >= 0.0 && hue <= 1.0);
|
||||
debug_assert!((0.0..=1.0).contains(&hue));
|
||||
|
||||
fn hue_to_rgb(m1: f32, m2: f32, mut h3: f32) -> f32 {
|
||||
if h3 < 0. {
|
||||
|
@ -1463,13 +1472,16 @@ pub fn hsl_to_rgb(hue: f32, saturation: f32, lightness: f32) -> (f32, f32, f32)
|
|||
(red, green, blue)
|
||||
}
|
||||
|
||||
type IntoColorFn<Output> =
|
||||
fn(l: Option<f32>, a: Option<f32>, b: Option<f32>, alpha: Option<f32>) -> Output;
|
||||
|
||||
#[inline]
|
||||
fn parse_lab_like<'i, 't, P>(
|
||||
color_parser: &P,
|
||||
arguments: &mut Parser<'i, 't>,
|
||||
lightness_range: f32,
|
||||
a_b_range: f32,
|
||||
into_color: fn(l: Option<f32>, a: Option<f32>, b: Option<f32>, alpha: Option<f32>) -> P::Output,
|
||||
into_color: IntoColorFn<P::Output>,
|
||||
) -> Result<P::Output, ParseError<'i, P::Error>>
|
||||
where
|
||||
P: ColorParser<'i>,
|
||||
|
@ -1495,7 +1507,7 @@ fn parse_lch_like<'i, 't, P>(
|
|||
arguments: &mut Parser<'i, 't>,
|
||||
lightness_range: f32,
|
||||
chroma_range: f32,
|
||||
into_color: fn(l: Option<f32>, c: Option<f32>, h: Option<f32>, alpha: Option<f32>) -> P::Output,
|
||||
into_color: IntoColorFn<P::Output>,
|
||||
) -> Result<P::Output, ParseError<'i, P::Error>>
|
||||
where
|
||||
P: ColorParser<'i>,
|
||||
|
@ -1553,6 +1565,9 @@ where
|
|||
))
|
||||
}
|
||||
|
||||
type ComponentParseResult<'i, R1, R2, R3, Error> =
|
||||
Result<(Option<R1>, Option<R2>, Option<R3>, Option<f32>), ParseError<'i, Error>>;
|
||||
|
||||
/// Parse the color components and alpha with the modern [color-4] syntax.
|
||||
pub fn parse_components<'i, 't, P, F1, F2, F3, R1, R2, R3>(
|
||||
color_parser: &P,
|
||||
|
@ -1560,7 +1575,7 @@ pub fn parse_components<'i, 't, P, F1, F2, F3, R1, R2, R3>(
|
|||
f1: F1,
|
||||
f2: F2,
|
||||
f3: F3,
|
||||
) -> Result<(Option<R1>, Option<R2>, Option<R3>, Option<f32>), ParseError<'i, P::Error>>
|
||||
) -> ComponentParseResult<'i, R1, R2, R3, P::Error>
|
||||
where
|
||||
P: ColorParser<'i>,
|
||||
F1: FnOnce(&P, &mut Parser<'i, 't>) -> Result<R1, ParseError<'i, P::Error>>,
|
||||
|
|
|
@ -12,7 +12,6 @@ use std::ops::Deref;
|
|||
use std::rc::Rc;
|
||||
use std::slice;
|
||||
use std::str;
|
||||
use std::usize;
|
||||
|
||||
/// A string that is either shared (heap-allocated and reference-counted) or borrowed.
|
||||
///
|
||||
|
|
|
@ -69,8 +69,8 @@ fn parse_border_spacing(_context: &ParserContext, input: &mut Parser)
|
|||
|
||||
pub use crate::color::{
|
||||
hsl_to_rgb, hwb_to_rgb, parse_color_keyword, parse_color_with, parse_hash_color, AngleOrNumber,
|
||||
Color, ColorFunction, ColorParser, FromParsedColor, Lab, Lch, NumberOrPercentage, Oklab, Oklch,
|
||||
PredefinedColorSpace, RGBA,
|
||||
Color, ColorFunction, ColorParser, FromParsedColor, Hsl, Hwb, Lab, Lch, NumberOrPercentage,
|
||||
Oklab, Oklch, PredefinedColorSpace, RGBA,
|
||||
};
|
||||
pub use crate::cow_rc_str::CowRcStr;
|
||||
pub use crate::from_bytes::{stylesheet_encoding, EncodingSupport};
|
||||
|
|
|
@ -12,11 +12,9 @@ use std::mem::MaybeUninit;
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// #[macro_use] extern crate cssparser;
|
||||
///
|
||||
/// # fn main() {} // Make doctest not wrap everything in its own main
|
||||
/// # fn dummy(function_name: &String) { let _ =
|
||||
/// match_ignore_ascii_case! { &function_name,
|
||||
/// cssparser::match_ignore_ascii_case! { &function_name,
|
||||
/// "rgb" => parse_rgb(..),
|
||||
/// # #[cfg(not(something))]
|
||||
/// "rgba" => parse_rgba(..),
|
||||
|
@ -51,7 +49,7 @@ macro_rules! match_ignore_ascii_case {
|
|||
$( $( $pattern )+ )+
|
||||
}
|
||||
}
|
||||
_cssparser_internal_to_lowercase!($input, cssparser_internal::MAX_LENGTH => lowercase);
|
||||
$crate::_cssparser_internal_to_lowercase!($input, cssparser_internal::MAX_LENGTH => lowercase);
|
||||
// "A" is a short string that we know is different for every string pattern,
|
||||
// since we’ve verified that none of them include ASCII upper case letters.
|
||||
match lowercase.unwrap_or("A") {
|
||||
|
@ -74,12 +72,10 @@ macro_rules! match_ignore_ascii_case {
|
|||
/// ## Example:
|
||||
///
|
||||
/// ```rust
|
||||
/// #[macro_use] extern crate cssparser;
|
||||
///
|
||||
/// # fn main() {} // Make doctest not wrap everything in its own main
|
||||
///
|
||||
/// fn color_rgb(input: &str) -> Option<(u8, u8, u8)> {
|
||||
/// ascii_case_insensitive_phf_map! {
|
||||
/// cssparser::ascii_case_insensitive_phf_map! {
|
||||
/// keyword -> (u8, u8, u8) = {
|
||||
/// "red" => (255, 0, 0),
|
||||
/// "green" => (0, 255, 0),
|
||||
|
@ -108,7 +104,7 @@ macro_rules! ascii_case_insensitive_phf_map {
|
|||
$key => $value,
|
||||
)*
|
||||
};
|
||||
_cssparser_internal_to_lowercase!(input, _cssparser_internal::MAX_LENGTH => lowercase);
|
||||
$crate::_cssparser_internal_to_lowercase!(input, _cssparser_internal::MAX_LENGTH => lowercase);
|
||||
lowercase.and_then(|s| MAP.get(s))
|
||||
}
|
||||
}
|
||||
|
@ -156,22 +152,21 @@ pub fn _cssparser_internal_to_lowercase<'a>(
|
|||
input: &'a str,
|
||||
first_uppercase: usize,
|
||||
) -> &'a str {
|
||||
unsafe {
|
||||
// This cast doesn't change the pointer's validity
|
||||
// since `u8` has the same layout as `MaybeUninit<u8>`:
|
||||
let input_bytes = &*(input.as_bytes() as *const [u8] as *const [MaybeUninit<u8>]);
|
||||
// This cast doesn't change the pointer's validity
|
||||
// since `u8` has the same layout as `MaybeUninit<u8>`:
|
||||
let input_bytes =
|
||||
unsafe { &*(input.as_bytes() as *const [u8] as *const [MaybeUninit<u8>]) };
|
||||
|
||||
buffer.copy_from_slice(&*input_bytes);
|
||||
buffer.copy_from_slice(&*input_bytes);
|
||||
|
||||
// Same as above re layout, plus these bytes have been initialized:
|
||||
let buffer = &mut *(buffer as *mut [MaybeUninit<u8>] as *mut [u8]);
|
||||
// Same as above re layout, plus these bytes have been initialized:
|
||||
let buffer = unsafe { &mut *(buffer as *mut [MaybeUninit<u8>] as *mut [u8]) };
|
||||
|
||||
buffer[first_uppercase..].make_ascii_lowercase();
|
||||
// `buffer` was initialized to a copy of `input`
|
||||
// (which is `&str` so well-formed UTF-8)
|
||||
// then ASCII-lowercased (which preserves UTF-8 well-formedness):
|
||||
::std::str::from_utf8_unchecked(buffer)
|
||||
}
|
||||
buffer[first_uppercase..].make_ascii_lowercase();
|
||||
// `buffer` was initialized to a copy of `input`
|
||||
// (which is `&str` so well-formed UTF-8)
|
||||
// then ASCII-lowercased (which preserves UTF-8 well-formedness):
|
||||
unsafe { ::std::str::from_utf8_unchecked(buffer) }
|
||||
}
|
||||
|
||||
Some(
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
use crate::cow_rc_str::CowRcStr;
|
||||
use crate::tokenizer::{SourceLocation, SourcePosition, Token, Tokenizer};
|
||||
use smallvec::SmallVec;
|
||||
use std::fmt;
|
||||
use std::ops::BitOr;
|
||||
use std::ops::Range;
|
||||
|
||||
|
@ -53,6 +54,24 @@ pub enum BasicParseErrorKind<'i> {
|
|||
QualifiedRuleInvalid,
|
||||
}
|
||||
|
||||
impl<'i> fmt::Display for BasicParseErrorKind<'i> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
BasicParseErrorKind::UnexpectedToken(token) => {
|
||||
write!(f, "unexpected token: {:?}", token)
|
||||
}
|
||||
BasicParseErrorKind::EndOfInput => write!(f, "unexpected end of input"),
|
||||
BasicParseErrorKind::AtRuleInvalid(rule) => {
|
||||
write!(f, "invalid @ rule encountered: '@{}'", rule)
|
||||
}
|
||||
BasicParseErrorKind::AtRuleBodyInvalid => write!(f, "invalid @ rule body encountered"),
|
||||
BasicParseErrorKind::QualifiedRuleInvalid => {
|
||||
write!(f, "invalid qualified rule encountered")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The fundamental parsing errors that can be triggered by built-in parsing routines.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct BasicParseError<'i> {
|
||||
|
@ -123,6 +142,15 @@ impl<'i, T> ParseErrorKind<'i, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'i, E: fmt::Display> fmt::Display for ParseErrorKind<'i, E> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
ParseErrorKind::Basic(ref basic) => basic.fmt(f),
|
||||
ParseErrorKind::Custom(ref custom) => custom.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extensible parse errors that can be encountered by client parsing implementations.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct ParseError<'i, E> {
|
||||
|
@ -137,7 +165,7 @@ impl<'i, T> ParseError<'i, T> {
|
|||
pub fn basic(self) -> BasicParseError<'i> {
|
||||
match self.kind {
|
||||
ParseErrorKind::Basic(kind) => BasicParseError {
|
||||
kind: kind,
|
||||
kind,
|
||||
location: self.location,
|
||||
},
|
||||
ParseErrorKind::Custom(_) => panic!("Not a basic parse error"),
|
||||
|
@ -156,6 +184,14 @@ impl<'i, T> ParseError<'i, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'i, E: fmt::Display> fmt::Display for ParseError<'i, E> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.kind.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'i, E: fmt::Display + fmt::Debug> std::error::Error for ParseError<'i, E> {}
|
||||
|
||||
/// The owned input for a parser.
|
||||
pub struct ParserInput<'i> {
|
||||
tokenizer: Tokenizer<'i>,
|
||||
|
@ -396,7 +432,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
|
|||
#[inline]
|
||||
pub fn new_basic_error(&self, kind: BasicParseErrorKind<'i>) -> BasicParseError<'i> {
|
||||
BasicParseError {
|
||||
kind: kind,
|
||||
kind,
|
||||
location: self.current_source_location(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,13 @@ pub trait DeclarationParser<'i> {
|
|||
name: CowRcStr<'i>,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self::Declaration, ParseError<'i, Self::Error>>;
|
||||
|
||||
/// Whether to try to parse qualified rules along with declarations. See
|
||||
/// <https://github.com/w3c/csswg-drafts/issues/7961> for the current state of the discussion.
|
||||
/// This is a low effort opt-in to be able to experiment with it, but it's likely to be needed
|
||||
/// when nesting is less experimental as well (e.g., you probably don't want to allow nesting
|
||||
/// in a style attribute anyways).
|
||||
fn enable_nesting(&self) -> bool { false }
|
||||
}
|
||||
|
||||
/// A trait to provide various parsing of at-rules.
|
||||
|
@ -140,14 +147,14 @@ pub trait AtRuleParser<'i> {
|
|||
|
||||
/// A trait to provide various parsing of qualified rules.
|
||||
///
|
||||
/// For example, there could be different implementations
|
||||
/// for top-level qualified rules (i.e. style rules with Selectors as prelude)
|
||||
/// and for qualified rules inside `@keyframes` (keyframe rules with keyframe selectors as prelude).
|
||||
/// For example, there could be different implementations for top-level qualified rules (i.e. style
|
||||
/// rules with Selectors as prelude) and for qualified rules inside `@keyframes` (keyframe rules
|
||||
/// with keyframe selectors as prelude).
|
||||
///
|
||||
/// Default implementations that reject all qualified rules are provided,
|
||||
/// so that `impl QualifiedRuleParser<(), ()> for ... {}` can be used
|
||||
/// for example for using `RuleListParser` to parse a rule list with only at-rules
|
||||
/// (such as inside `@font-feature-values`).
|
||||
/// Default implementations that reject all qualified rules are provided, so that
|
||||
/// `impl QualifiedRuleParser<(), ()> for ... {}` can be used for example for using
|
||||
/// `RuleListParser` to parse a rule list with only at-rules (such as inside
|
||||
/// `@font-feature-values`).
|
||||
pub trait QualifiedRuleParser<'i> {
|
||||
/// The intermediate representation of a qualified rule prelude.
|
||||
type Prelude;
|
||||
|
@ -223,10 +230,7 @@ where
|
|||
/// since `<DeclarationListParser as Iterator>::next` can return either.
|
||||
/// It could be a custom enum.
|
||||
pub fn new(input: &'a mut Parser<'i, 't>, parser: P) -> Self {
|
||||
DeclarationListParser {
|
||||
input: input,
|
||||
parser: parser,
|
||||
}
|
||||
DeclarationListParser { input, parser }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,7 +238,9 @@ where
|
|||
/// or `Err(())` for an invalid one.
|
||||
impl<'i, 't, 'a, I, P, E: 'i> Iterator for DeclarationListParser<'i, 't, 'a, P>
|
||||
where
|
||||
P: DeclarationParser<'i, Declaration = I, Error = E> + AtRuleParser<'i, AtRule = I, Error = E>,
|
||||
P: DeclarationParser<'i, Declaration = I, Error = E>
|
||||
+ AtRuleParser<'i, AtRule = I, Error = E>
|
||||
+ QualifiedRuleParser<'i, QualifiedRule = I, Error = E>,
|
||||
{
|
||||
type Item = Result<I, (ParseError<'i, E>, &'i str)>;
|
||||
|
||||
|
@ -247,15 +253,19 @@ where
|
|||
}
|
||||
Ok(&Token::Ident(ref name)) => {
|
||||
let name = name.clone();
|
||||
let result = {
|
||||
let mut result = {
|
||||
let parser = &mut self.parser;
|
||||
// FIXME: https://github.com/servo/rust-cssparser/issues/254
|
||||
let callback = |input: &mut Parser<'i, '_>| {
|
||||
parse_until_after(self.input, Delimiter::Semicolon, |input| {
|
||||
input.expect_colon()?;
|
||||
parser.parse_value(name, input)
|
||||
};
|
||||
parse_until_after(self.input, Delimiter::Semicolon, callback)
|
||||
})
|
||||
};
|
||||
|
||||
if result.is_err() && self.parser.enable_nesting() {
|
||||
self.input.reset(&start);
|
||||
result = parse_qualified_rule(&start, self.input, &mut self.parser);
|
||||
}
|
||||
|
||||
return Some(result.map_err(|e| (e, self.input.slice_from(start.position()))));
|
||||
}
|
||||
Ok(&Token::AtKeyword(ref name)) => {
|
||||
|
@ -263,10 +273,17 @@ where
|
|||
return Some(parse_at_rule(&start, name, self.input, &mut self.parser));
|
||||
}
|
||||
Ok(token) => {
|
||||
let token = token.clone();
|
||||
let result = self.input.parse_until_after(Delimiter::Semicolon, |_| {
|
||||
Err(start.source_location().new_unexpected_token_error(token))
|
||||
});
|
||||
let result = if self.parser.enable_nesting() {
|
||||
self.input.reset(&start);
|
||||
// XXX do we need to, if we fail, consume only until the next semicolon,
|
||||
// rather than until the next `{`?
|
||||
parse_qualified_rule(&start, self.input, &mut self.parser)
|
||||
} else {
|
||||
let token = token.clone();
|
||||
self.input.parse_until_after(Delimiter::Semicolon, |_| {
|
||||
Err(start.source_location().new_unexpected_token_error(token))
|
||||
})
|
||||
};
|
||||
return Some(result.map_err(|e| (e, self.input.slice_from(start.position()))));
|
||||
}
|
||||
Err(..) => return None,
|
||||
|
@ -304,8 +321,8 @@ where
|
|||
/// It could be a custom enum.
|
||||
pub fn new_for_stylesheet(input: &'a mut Parser<'i, 't>, parser: P) -> Self {
|
||||
RuleListParser {
|
||||
input: input,
|
||||
parser: parser,
|
||||
input,
|
||||
parser,
|
||||
is_stylesheet: true,
|
||||
any_rule_so_far: false,
|
||||
}
|
||||
|
@ -319,8 +336,8 @@ where
|
|||
/// (This is to deal with legacy workarounds for `<style>` HTML element parsing.)
|
||||
pub fn new_for_nested_rule(input: &'a mut Parser<'i, 't>, parser: P) -> Self {
|
||||
RuleListParser {
|
||||
input: input,
|
||||
parser: parser,
|
||||
input,
|
||||
parser,
|
||||
is_stylesheet: false,
|
||||
any_rule_so_far: false,
|
||||
}
|
||||
|
@ -372,7 +389,7 @@ where
|
|||
}
|
||||
} else {
|
||||
self.any_rule_so_far = true;
|
||||
let result = parse_qualified_rule(self.input, &mut self.parser);
|
||||
let result = parse_qualified_rule(&start, self.input, &mut self.parser);
|
||||
return Some(result.map_err(|e| (e, self.input.slice_from(start.position()))));
|
||||
}
|
||||
}
|
||||
|
@ -424,7 +441,7 @@ where
|
|||
if let Some(name) = at_keyword {
|
||||
parse_at_rule(&start, name, input, parser).map_err(|e| e.0)
|
||||
} else {
|
||||
parse_qualified_rule(input, parser)
|
||||
parse_qualified_rule(&start, input, parser)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -439,26 +456,20 @@ where
|
|||
P: AtRuleParser<'i, Error = E>,
|
||||
{
|
||||
let delimiters = Delimiter::Semicolon | Delimiter::CurlyBracketBlock;
|
||||
// FIXME: https://github.com/servo/rust-cssparser/issues/254
|
||||
let callback = |input: &mut Parser<'i, '_>| parser.parse_prelude(name, input);
|
||||
let result = parse_until_before(input, delimiters, callback);
|
||||
let result = parse_until_before(input, delimiters, |input| parser.parse_prelude(name, input));
|
||||
match result {
|
||||
Ok(prelude) => {
|
||||
let result = match input.next() {
|
||||
Ok(&Token::Semicolon) | Err(_) => {
|
||||
parser.rule_without_block(prelude, start)
|
||||
.map_err(|()| input.new_unexpected_token_error(Token::Semicolon))
|
||||
},
|
||||
Ok(&Token::Semicolon) | Err(_) => parser
|
||||
.rule_without_block(prelude, start)
|
||||
.map_err(|()| input.new_unexpected_token_error(Token::Semicolon)),
|
||||
Ok(&Token::CurlyBracketBlock) => {
|
||||
// FIXME: https://github.com/servo/rust-cssparser/issues/254
|
||||
let callback =
|
||||
|input: &mut Parser<'i, '_>| parser.parse_block(prelude, start, input);
|
||||
parse_nested_block(input, callback)
|
||||
},
|
||||
parse_nested_block(input, |input| parser.parse_block(prelude, start, input))
|
||||
}
|
||||
Ok(_) => unreachable!(),
|
||||
};
|
||||
result.map_err(|e| (e, input.slice_from(start.position())))
|
||||
},
|
||||
}
|
||||
Err(error) => {
|
||||
let end_position = input.position();
|
||||
match input.next() {
|
||||
|
@ -466,28 +477,26 @@ where
|
|||
_ => unreachable!(),
|
||||
};
|
||||
Err((error, input.slice(start.position()..end_position)))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_qualified_rule<'i, 't, P, E>(
|
||||
start: &ParserState,
|
||||
input: &mut Parser<'i, 't>,
|
||||
parser: &mut P,
|
||||
) -> Result<<P as QualifiedRuleParser<'i>>::QualifiedRule, ParseError<'i, E>>
|
||||
where
|
||||
P: QualifiedRuleParser<'i, Error = E>,
|
||||
{
|
||||
let start = input.state();
|
||||
// FIXME: https://github.com/servo/rust-cssparser/issues/254
|
||||
let callback = |input: &mut Parser<'i, '_>| parser.parse_prelude(input);
|
||||
let prelude = parse_until_before(input, Delimiter::CurlyBracketBlock, callback);
|
||||
let prelude = parse_until_before(input, Delimiter::CurlyBracketBlock, |input| {
|
||||
parser.parse_prelude(input)
|
||||
});
|
||||
match *input.next()? {
|
||||
Token::CurlyBracketBlock => {
|
||||
// Do this here so that we consume the `{` even if the prelude is `Err`.
|
||||
let prelude = prelude?;
|
||||
// FIXME: https://github.com/servo/rust-cssparser/issues/254
|
||||
let callback = |input: &mut Parser<'i, '_>| parser.parse_block(prelude, &start, input);
|
||||
parse_nested_block(input, callback)
|
||||
parse_nested_block(input, |input| parser.parse_block(prelude, &start, input))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
|
|
@ -703,7 +703,6 @@ fn line_numbers() {
|
|||
|
||||
#[test]
|
||||
fn overflow() {
|
||||
use std::f32;
|
||||
use std::iter::repeat;
|
||||
|
||||
let css = r"
|
||||
|
@ -1487,7 +1486,7 @@ fn utf16_columns() {
|
|||
#[test]
|
||||
fn servo_define_css_keyword_enum() {
|
||||
macro_rules! define_css_keyword_enum {
|
||||
(pub enum $name:ident { $($variant:ident = $css:expr,)+ }) => {
|
||||
(pub enum $name:ident { $($variant:ident = $css:pat,)+ }) => {
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum $name {
|
||||
$($variant),+
|
||||
|
|
|
@ -8,7 +8,6 @@ use self::Token::*;
|
|||
use crate::cow_rc_str::CowRcStr;
|
||||
use crate::parser::ParserState;
|
||||
use std::char;
|
||||
use std::i32;
|
||||
use std::ops::Range;
|
||||
|
||||
/// One of the pieces the CSS input is broken into.
|
||||
|
|
Загрузка…
Ссылка в новой задаче