diff --git a/Cargo.lock b/Cargo.lock index d7e98579172..8a79b8eda44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2610,6 +2610,8 @@ dependencies = [ "ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", "quickersort 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 5a1b854ca4d..95778b61c88 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -40,6 +40,7 @@ num-traits = "0.1.32" ordered-float = "0.2.2" owning_ref = "0.2.2" parking_lot = "0.3.3" +phf = "0.7.20" quickersort = "2.0.0" rand = "0.3" rayon = "0.5" @@ -64,4 +65,5 @@ version = "1.0" kernel32-sys = "0.2" [build-dependencies] +phf_codegen = "0.7.20" walkdir = "0.1" diff --git a/components/style/build.rs b/components/style/build.rs index b8d46348b94..8d68fe45ce6 100644 --- a/components/style/build.rs +++ b/components/style/build.rs @@ -3,8 +3,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ extern crate walkdir; +extern crate phf_codegen; use std::env; +use std::fs::File; +use std::io::{BufWriter, BufReader, BufRead, Write}; use std::path::Path; use std::process::{Command, exit}; use walkdir::WalkDir; @@ -61,4 +64,21 @@ fn main() { if !status.success() { exit(1) } + + let path = Path::new(&env::var("OUT_DIR").unwrap()).join("static_ids.rs"); + let static_ids = Path::new(&env::var("OUT_DIR").unwrap()).join("static_ids.txt"); + let mut file = BufWriter::new(File::create(&path).unwrap()); + let static_ids = BufReader::new(File::open(&static_ids).unwrap()); + + write!(&mut file, "static STATIC_IDS: ::phf::Map<&'static str, StaticId> = ").unwrap(); + let mut map = phf_codegen::Map::new(); + for result in static_ids.lines() { + let line = result.unwrap(); + let mut split = line.split('\t'); + let key = split.next().unwrap().to_owned(); + let value = split.next().unwrap(); + map.entry(key, value); + } + map.build(&mut file).unwrap(); + write!(&mut file, ";\n").unwrap(); } diff --git a/components/style/lib.rs b/components/style/lib.rs index 0955a651105..21873f03e13 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -71,6 +71,7 @@ extern crate num_traits; extern crate ordered_float; extern crate owning_ref; extern crate parking_lot; +extern crate phf; extern crate quickersort; extern crate rayon; extern crate rustc_serialize; diff --git a/components/style/properties/build.py b/components/style/properties/build.py index 4e61f456541..c20cac95cb4 100644 --- a/components/style/properties/build.py +++ b/components/style/properties/build.py @@ -33,6 +33,7 @@ def main(): rust = render(template, product=product, data=properties, __file__=template) if output == "style-crate": write(os.environ["OUT_DIR"], "properties.rs", rust) + write(os.environ["OUT_DIR"], "static_ids.txt", static_ids(properties)) if product == "gecko": template = os.path.join(BASE, "gecko.mako.rs") rust = render(template, data=properties) @@ -69,6 +70,15 @@ def write(directory, filename, content): open(os.path.join(directory, filename), "wb").write(content) +def static_ids(properties): + return '\n'.join( + "%s\tStaticId::%s(%sId::%s)" % (p.name, kind, kind, p.camel_case) + for kind, props in [("Longhand", properties.longhands), + ("Shorthand", properties.shorthands)] + for p in props + ) + + def write_html(properties): properties = dict( (p.name, { diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index a14da5262a5..3aa08eaafac 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -391,16 +391,6 @@ pub enum LonghandId { } impl LonghandId { - pub fn from_ascii_lowercase_name(name: &str) -> Result { - // FIXME: use rust-phf? - match name { - % for property in data.longhands: - "${property.name}" => Ok(LonghandId::${property.camel_case}), - % endfor - _ => Err(()) - } - } - pub fn name(&self) -> &'static str { match *self { % for property in data.longhands: @@ -425,16 +415,6 @@ impl ToCss for ShorthandId { } impl ShorthandId { - pub fn from_ascii_lowercase_name(name: &str) -> Result { - // FIXME: use rust-phf? - match name { - % for property in data.shorthands: - "${property.name}" => Ok(ShorthandId::${property.camel_case}), - % endfor - _ => Err(()) - } - } - pub fn name(&self) -> &'static str { match *self { % for property in data.shorthands: @@ -629,19 +609,26 @@ impl ToCss for PropertyId { } } +// FIXME(https://github.com/rust-lang/rust/issues/33156): remove this enum and use PropertyId +// when stable Rust allows destructors in statics. +enum StaticId { + Longhand(LonghandId), + Shorthand(ShorthandId), +} +include!(concat!(env!("OUT_DIR"), "/static_ids.rs")); + impl PropertyId { /// Returns Err(()) for unknown non-custom properties pub fn parse(s: Cow) -> Result { if let Ok(name) = ::custom_properties::parse_name(&s) { return Ok(PropertyId::Custom(::custom_properties::Name::from(name))) } + let lower_case = ::str::cow_into_ascii_lowercase(s); - if let Ok(id) = LonghandId::from_ascii_lowercase_name(&lower_case) { - Ok(PropertyId::Longhand(id)) - } else if let Ok(id) = ShorthandId::from_ascii_lowercase_name(&lower_case) { - Ok(PropertyId::Shorthand(id)) - } else { - Err(()) + match STATIC_IDS.get(&*lower_case) { + Some(&StaticId::Longhand(id)) => Ok(PropertyId::Longhand(id)), + Some(&StaticId::Shorthand(id)) => Ok(PropertyId::Shorthand(id)), + None => Err(()), } } diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index bdb0cc4539e..95392a8fb26 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -49,8 +49,7 @@ use style::gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI}; use style::parallel; use style::parser::{ParserContext, ParserContextExtraData}; use style::properties::{CascadeFlags, ComputedValues, Importance, PropertyDeclaration}; -use style::properties::{PropertyDeclarationParseResult, PropertyDeclarationBlock}; -use style::properties::{PropertyId, LonghandId, ShorthandId}; +use style::properties::{PropertyDeclarationParseResult, PropertyDeclarationBlock, PropertyId}; use style::properties::{apply_declarations, parse_one_declaration}; use style::restyle_hints::RestyleHint; use style::selector_parser::PseudoElementCascadeType; @@ -643,14 +642,7 @@ fn get_property_id_from_atom(atom: *mut nsIAtom, is_custom: bool) -> PropertyId if !is_custom { // FIXME: can we do this mapping without going through a UTF-8 string? // Maybe even from nsCSSPropertyID directly? - let s = atom.to_string(); - if let Ok(id) = LonghandId::from_ascii_lowercase_name(&s) { - PropertyId::Longhand(id) - } else if let Ok(id) = ShorthandId::from_ascii_lowercase_name(&s) { - PropertyId::Shorthand(id) - } else { - panic!("got unknown property name {:?} from Gecko", s) - } + PropertyId::parse(atom.to_string().into()).expect("got unknown property name from Gecko") } else { PropertyId::Custom(atom) }