Generate a PHF of SVG attribute names

We will map SVG attribute names to enum values using a Perfect Hash
Function, instead of doing string comparisons and hash table lookups
everywhere.

At build time, we generate the PHF mapping.  We do this with
phf_codegen (in the build.rs script) instead of phf_macros, as the
latter cannot be used on Rust stable yet.
parent 4bb8914a
......@@ -64,7 +64,9 @@ librsvg_@RSVG_API_MAJOR_VERSION@_la_SOURCES = \
RUST_SOURCES = \
rust/Cargo.toml \
rust/build.rs \
rust/src/aspect_ratio.rs \
rust/src/attributes.rs \
rust/src/bbox.rs \
rust/src/chars.rs \
rust/src/clip_path.rs \
......
......@@ -220,7 +220,7 @@ version = "0.7.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
......@@ -248,11 +248,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand"
version = "0.3.20"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
......@@ -287,6 +298,8 @@ dependencies = [
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"pango 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pango-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
......@@ -355,6 +368,25 @@ name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
......@@ -387,7 +419,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
"checksum procedural-masquerade 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dc1bcafee1590f81acb329ae45ec627b318123f085153913620316ae9a144b2a"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1"
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa"
"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e"
"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
......@@ -400,3 +433,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
......@@ -2,6 +2,10 @@
name = "rsvg_internals"
version = "0.0.1"
authors = ["Federico Mena Quintero <federico@gnome.org>"]
build = "build.rs"
[build-dependencies]
phf_codegen = "0.7.21"
[dependencies]
libc = "0.2"
......@@ -12,6 +16,7 @@ pango = "0.3.0"
pango-sys = "0.5.0"
cssparser = "0.23"
lazy_static = "1.0.0"
phf = "0.7.21"
[dependencies.cairo-sys-rs]
version = "0.5.0"
......
extern crate phf_codegen;
use std::env;
use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::Path;
fn main() {
generate_phf_of_svg_attributes();
}
/// Creates a perfect hash function (PHF) to map SVG attribute names to enum values.
fn generate_phf_of_svg_attributes() {
// (attribute name, Rust enum value, C enum value suffix
let attribute_defs = [
( "alternate", "Alternate", "ALTERNATE" ),
( "amplitude", "Amplitude", "AMPLITUDE" ),
( "azimuth", "Azimuth", "AZIMUTH" ),
( "baseFrequency", "BaseFrequency", "BASE_FREQUENCY" ),
( "baseline-shift", "BaselineShift", "BASELINE_SHIFT" ),
( "bias", "Bias", "BIAS" ),
( "class", "Class", "CLASS" ),
( "clip-path", "ClipPath", "CLIP_PATH" ),
( "clip-rule", "ClipRule", "CLIP_RULE" ),
( "color", "Color", "COLOR" ),
( "comp-op", "CompOp", "COMP_OP" ),
( "diffuseConstant", "DiffuseConstant", "DIFFUSE_CONSTANT" ),
( "direction", "Direction", "DIRECTION" ),
( "display", "Display", "DISPLAY" ),
( "divisor", "Divisor", "DIVISOR" ),
( "dx", "Dx", "DX" ),
( "dy", "Dy", "DY" ),
( "edgeMode", "EdgeMode", "EDGE_MODE" ),
( "elevation", "Elevation", "ELEVATION" ),
( "enable-background", "EnableBackground", "ENABLE_BACKGROUND" ),
( "encoding", "Encoding", "ENCODING" ),
( "exponent", "Exponent", "EXPONENT" ),
( "fill", "Fill", "FILL" ),
( "fill-opacity", "FillOpacity", "FILL_OPACITY" ),
( "fill-rule", "FillRule", "FILL_RULE" ),
( "filter", "Filter", "FILTER" ),
( "filterUnits", "FilterUnits", "FILTERUNITS" ),
( "flood-color", "FloodColor", "FLOOD_COLOR" ),
( "flood-opacity", "FloodOpacity", "FLOOD_OPACITY" ),
( "font-family", "FontFamily", "FONT_FAMILY" ),
( "font-size", "FontSize", "FONT_SIZE" ),
( "font-stretch", "FontStretch", "FONT_STRETCH" ),
( "font-style", "FontStyle", "FONT_STYLE" ),
( "font-variant", "FontVariant", "FONT_VARIANT" ),
( "font-weight", "FontWeight", "FONT_WEIGHT" ),
( "height", "Height", "HEIGHT" ),
( "href", "Href", "HREF" ),
( "id", "Id", "ID" ),
( "in", "In", "IN" ),
( "in2", "In2", "IN2" ),
( "intercept", "Intercept", "INTERCEPT" ),
( "k1", "K1", "K1" ),
( "k2", "K2", "K2" ),
( "k3", "K3", "K3" ),
( "k4", "K4", "K4" ),
( "kernelMatrix", "KernelMatrix", "KERNEL_MATRIX" ),
( "kernelUnitLength", "KernelUnitLength", "KERNEL_UNIT_LENGTH" ),
( "letter-spacing", "LetterSpacing", "LETTER_SPACING" ),
( "lighting-color", "LightingColor", "LIGHTING_COLOR" ),
( "limitingConeAngle", "LimitingConeAngle", "LIMITING_CONE_ANGLE" ),
( "marker", "Marker", "MARKER" ),
( "marker-end", "MarkerEnd", "MARKER_END" ),
( "marker-mid", "MarkerMid", "MARKER_MID" ),
( "marker-start", "MarkerStart", "MARKER_START" ),
( "mask", "Mask", "MASK" ),
( "mode", "Mode", "MODE" ),
( "numOctaves", "NumOctaves", "NUM_OCTAVES" ),
( "offset", "Offset", "OFFSET" ),
( "opacity", "Opacity", "OPACITY" ),
( "operator", "Operator", "OPERATOR" ),
( "order", "Order", "ORDER" ),
( "overflow", "Overflow", "OVERFLOW" ),
( "parse", "Parse", "PARSE" ),
( "pointsAtX", "PointsAtX", "POINTS_AT_X" ),
( "pointsAtY", "PointsAtY", "POINTS_AT_Y" ),
( "pointsAtZ", "PointsAtZ", "POINTS_AT_Z" ),
( "preserveAlpha", "PreserveAlpha", "PRESERVE_ALPHA" ),
( "primitiveUnits", "PrimitiveUnits", "PRIMITIVE_UNITS" ),
( "radius", "Radius", "RADIUS" ),
( "requiredExtensions", "RequiredExtensions", "REQUIRED_EXTENSIONS" ),
( "requiredFeatures", "RequiredFeatures", "REQUIRED_FEATURES" ),
( "result", "Result", "RESULT" ),
( "scale", "Scale", "SCALE" ),
( "seed", "Seed", "SEED" ),
( "shape-rendering", "ShapeRendering", "SHAPE_RENDERING" ),
( "slope", "Slope", "SLOPE" ),
( "specularConstant", "SpecularConstant", "SPECULAR_CONSTANT" ),
( "specularExponent", "SpecularExponent", "SPECULAR_EXPONENT" ),
( "stdDeviation", "StdDeviation", "STD_DEVIATION" ),
( "stitchTiles", "StitchTiles", "STITCH_TILES" ),
( "stop-color", "StopColor", "STOP_COLOR" ),
( "stop-opacity", "StopOpacity", "STOP_OPACITY" ),
( "stroke", "Stroke", "STROKE" ),
( "stroke-dasharray", "StrokeDasharray", "STROKE_DASHARRAY" ),
( "stroke-dashoffset", "StrokeDashoffset", "STROKE_DASHOFFSET" ),
( "stroke-linecap", "StrokeLinecap", "STROKE_LINECAP" ),
( "stroke-linejoin", "StrokeLinejoin", "STROKE_LINEJOIN" ),
( "stroke-miterlimit", "StrokeMiterlimit", "STROKE_MITERLIMIT" ),
( "stroke-opacity", "StrokeOpacity", "STROKE_OPACITY" ),
( "stroke-width", "StrokeWidth", "STROKE_WIDTH" ),
( "style", "Style", "STYLE" ),
( "surfaceScale", "SurfaceScale", "SURFACE_SCALE" ),
( "systemLanguage", "SystemLanguage", "SYSTEM_LANGUAGE" ),
( "tableValues", "TableValues", "TABLE_VALUES" ),
( "targetX", "TargetX", "TARGET_X" ),
( "targetY", "TargetY", "TARGET_Y" ),
( "text-anchor", "TextAnchor", "TEXT_ANCHOR" ),
( "text-decoration", "TextDecoration", "TEXT_DECORATION" ),
( "text-rendering", "TextRendering", "TEXT_RENDERING" ),
( "transform", "Transform", "TRANSFORM" ),
( "type", "Type", "TYPE" ),
( "unicode-bidi", "UnicodeBidi", "UNICODE_BIDI" ),
( "values", "Values", "VALUES" ),
( "visibility", "Visibility", "VISIBILITY" ),
( "width", "Width", "WIDTH" ),
( "writing-mode", "WritingMode", "WRITING_MODE" ),
( "x", "X", "X" ),
( "xChannelSelector", "XChannelSelector", "X_CHANNEL_SELECTOR" ),
( "xlink:href", "XlinkHref", "XLINK_HREF" ),
( "xml:lang", "XmlLang", "XML_LANG" ),
( "xml:space", "XmlSpace", "XML_SPACE" ),
( "y", "Y", "Y" ),
( "yChannelSelector", "YChannelSelector", "Y_CHANNEL_SELECTOR" ),
( "z", "Z", "Z" ),
];
let path = Path::new(&env::var("OUT_DIR").unwrap()).join("attributes-codegen.rs");
let mut file = BufWriter::new(File::create(&path).unwrap());
writeln!(&mut file, "#[repr(C)]").unwrap();
writeln!(&mut file, "#[derive(Debug, Clone, Copy, PartialEq)]").unwrap();
writeln!(&mut file, "pub enum Attribute {{").unwrap();
for &(_, rust, _) in attribute_defs.iter() {
writeln!(&mut file, " {},", rust).unwrap();
}
writeln!(&mut file, "}}").unwrap();
writeln!(&mut file, "static ATTRIBUTES: phf::Map<&'static str, Attribute> = ").unwrap();
let mut map = phf_codegen::Map::new();
map.phf_path("phf");
for &(name, rust, _) in attribute_defs.iter() {
let rust = ["Attribute::", rust].concat();
map.entry(name, &rust);
}
map.build(&mut file).unwrap();
writeln!(&mut file, ";").unwrap();
}
extern crate phf;
use std::str::FromStr;
include!(concat!(env!("OUT_DIR"), "/attributes-codegen.rs"));
impl FromStr for Attribute {
type Err = ();
fn from_str(s: &str) -> Result<Attribute, ()> {
ATTRIBUTES.get(s).cloned().ok_or(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_attributes() {
assert_eq!(Attribute::from_str("width"), Ok(Attribute::Width));
}
#[test]
fn unknown_attribute_yields_error() {
assert_eq!(Attribute::from_str("foobar"), Err(()));
}
}
......@@ -173,6 +173,7 @@ pub use viewbox::{
mod coord_units;
mod aspect_ratio;
mod attributes;
mod bbox;
mod chars;
mod clip_path;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment