[librsvg/librsvg-2.48] (#582) - Parse XML processing instructions with xml5ever so we can build on Rust 1.39



commit b61c41f20daa5326b491ff4eff21711694298531
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Apr 1 17:17:00 2020 -0600

    (#582) - Parse XML processing instructions with xml5ever so we can build on Rust 1.39
    
    Apparently xml-rs is using #[cfg(doctest)], which was made stable since
    Rust 1.40.
    
    Fixes https://gitlab.gnome.org/GNOME/librsvg/-/issues/582

 Cargo.lock                | 31 ++++++++++++++---
 rsvg_internals/Cargo.toml |  2 +-
 rsvg_internals/src/lib.rs |  1 -
 rsvg_internals/src/xml.rs | 89 +++++++++++++++++++++++++++++++++++++----------
 4 files changed, 99 insertions(+), 24 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index f77caea5..fbbf318b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1088,6 +1088,11 @@ dependencies = [
  "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "redox_syscall"
+version = "0.1.56"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+
 [[package]]
 name = "regex"
 version = "1.3.6"
@@ -1147,7 +1152,7 @@ dependencies = [
  "regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "xml-rs 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "xml5ever 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1326,6 +1331,16 @@ dependencies = [
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "time"
+version = "0.1.42"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+dependencies = [
+ "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "tinytemplate"
 version = "1.0.3"
@@ -1424,9 +1439,15 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
-name = "xml-rs"
-version = "0.8.1"
+name = "xml5ever"
+version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
+dependencies = [
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "markup5ever 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [metadata]
 "checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = 
"8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
@@ -1550,6 +1571,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 "checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9"
 "checksum rctree 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"be9e29cb19c8fe84169fcb07f8f11e66bc9e6e0280efd4715c54818296f8a4a8"
 "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
+"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = 
"2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
 "checksum regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = 
"7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3"
 "checksum regex-automata 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = 
"ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
 "checksum regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = 
"7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
@@ -1575,6 +1597,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
 "checksum thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
 "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
+"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = 
"db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
 "checksum tinytemplate 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"57a3c6667d3e65eb1bc3aed6fd14011c6cbc3a0665218ab7f5daf040b9ec371a"
 "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = 
"49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
@@ -1589,4 +1612,4 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 "checksum winapi-util 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = 
"fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e"
 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-"checksum xml-rs 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"9afd061c1c7c8ef0a3d337fbf76fc8c098bd0dfefd4adaafef25a559352f2031"
+"checksum xml5ever 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"0b1b52e6e8614d4a58b8e70cf51ec0cc21b256ad8206708bcff8139b5bbd6a59"
diff --git a/rsvg_internals/Cargo.toml b/rsvg_internals/Cargo.toml
index 4cb4669b..fb9b451b 100644
--- a/rsvg_internals/Cargo.toml
+++ b/rsvg_internals/Cargo.toml
@@ -36,7 +36,7 @@ rctree = "0.3.3"
 regex = "1"
 selectors = "0.22.0"
 url = "2"
-xml-rs = "0.8.0"
+xml5ever = "0.16.1"
 
 [dev-dependencies]
 criterion = "0.2"
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 7f589e5c..e72566fe 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -38,7 +38,6 @@
 #![allow(clippy::not_unsafe_ptr_arg_deref)]
 #![allow(clippy::too_many_arguments)]
 #![warn(unused)]
-use ::xml as xml_rs;
 
 pub use crate::color::Color;
 
diff --git a/rsvg_internals/src/xml.rs b/rsvg_internals/src/xml.rs
index ad5456de..31872da1 100644
--- a/rsvg_internals/src/xml.rs
+++ b/rsvg_internals/src/xml.rs
@@ -4,12 +4,16 @@ use encoding::label::encoding_from_whatwg_label;
 use encoding::DecoderTrap;
 use libc;
 use markup5ever::{
-    expanded_name, local_name, namespace_url, ns, ExpandedName, LocalName, Namespace, QualName,
+    buffer_queue::BufferQueue, expanded_name, local_name, namespace_url, ns, ExpandedName,
+    LocalName, Namespace, QualName,
 };
 use std::cell::RefCell;
 use std::collections::HashMap;
 use std::rc::{Rc, Weak};
 use std::str;
+use std::string::ToString;
+use xml5ever::tendril::format_tendril;
+use xml5ever::tokenizer::{TagKind, Token, TokenSink, XmlTokenizer, XmlTokenizerOpts};
 
 use crate::allowed_url::AllowedUrl;
 use crate::document::{Document, DocumentBuilder};
@@ -21,7 +25,6 @@ use crate::property_bag::PropertyBag;
 use crate::style::{Style, StyleType};
 use crate::text::NodeChars;
 use crate::xml2_load::Xml2Parser;
-use crate::xml_rs::{reader::XmlEvent, ParserConfig};
 
 #[derive(Clone)]
 enum Context {
@@ -620,6 +623,36 @@ impl Drop for XmlState {
     }
 }
 
+/// Temporary holding space for data in an XML processing instruction
+#[derive(Default)]
+struct ProcessingInstructionData {
+    attributes: Vec<(String, String)>,
+    error: bool,
+}
+
+struct ProcessingInstructionSink(Rc<RefCell<ProcessingInstructionData>>);
+
+impl TokenSink for ProcessingInstructionSink {
+    fn process_token(&mut self, token: Token) {
+        let mut data = self.0.borrow_mut();
+
+        match token {
+            Token::TagToken(tag) if tag.kind == TagKind::EmptyTag => {
+                for a in &tag.attrs {
+                    let name = a.name.local.as_ref().to_string();
+                    let value = a.value.to_string();
+
+                    data.attributes.push((name, value));
+                }
+            }
+
+            Token::ParseError(_) => data.error = true,
+
+            _ => (),
+        }
+    }
+}
+
 // https://www.w3.org/TR/xml-stylesheet/
 //
 // The syntax for the xml-stylesheet processing instruction we support
@@ -631,26 +664,26 @@ impl Drop for XmlState {
 // ("xml-stylesheet"), so we'll create a mini-parser with a hackish
 // element just to extract the data as attributes.
 fn parse_xml_stylesheet_processing_instruction(data: &str) -> Result<Vec<(String, String)>, ()> {
-    let xml_str = format!("<rsvg-hack {} />\n", data);
+    let pi_data = Rc::new(RefCell::new(ProcessingInstructionData {
+        attributes: Vec::new(),
+        error: false,
+    }));
 
-    let mut buf = xml_str.as_bytes();
+    let mut queue = BufferQueue::new();
+    queue.push_back(format_tendril!("<rsvg-hack {} />", data));
 
-    let reader = ParserConfig::new().create_reader(&mut buf);
+    let sink = ProcessingInstructionSink(pi_data.clone());
 
-    for event in reader {
-        match event {
-            Ok(XmlEvent::StartElement { attributes, .. }) => {
-                return Ok(attributes
-                    .iter()
-                    .map(|att| (att.name.local_name.clone(), att.value.clone()))
-                    .collect());
-            }
-            Err(_) => return Err(()),
-            _ => (),
-        }
-    }
+    let mut tokenizer = XmlTokenizer::new(sink, XmlTokenizerOpts::default());
+    tokenizer.run(&mut queue);
 
-    unreachable!();
+    let pi_data = pi_data.borrow();
+
+    if pi_data.error {
+        return Err(());
+    } else {
+        return Ok(pi_data.attributes.clone());
+    }
 }
 
 pub fn xml_load_from_possibly_compressed_stream(
@@ -667,3 +700,23 @@ pub fn xml_load_from_possibly_compressed_stream(
 
     state.build_document(&stream, cancellable)
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn parses_processing_instruction_data() {
+        let mut r =
+            parse_xml_stylesheet_processing_instruction("foo=\"bar\" baz=\"beep\"").unwrap();
+        r.sort_by(|a, b| a.0.cmp(&b.0));
+
+        assert_eq!(
+            r,
+            vec![
+                ("baz".to_string(), "beep".to_string()),
+                ("foo".to_string(), "bar".to_string())
+            ]
+        );
+    }
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]