[librsvg: 8/10] Replace Fragment with NodeId




commit 42a15e6b912ec35fbfb184e3dcf8701b8d626d34
Author: Paolo Borelli <pborelli gnome org>
Date:   Sat Dec 12 19:07:47 2020 +0100

    Replace Fragment with NodeId
    
    I find NodeId clearer as a type name, since fragment makes sense
    only as part of an Url. Also turn it into an enum, so that we
    do not need to manually check if an external uri is present.

 src/css.rs           |   8 ++--
 src/document.rs      | 121 ++++++++++++++++++++++++++-------------------------
 src/drawing_ctx.rs   |  24 +++++-----
 src/error.rs         |  18 ++++----
 src/filter.rs        |  10 ++---
 src/filters/image.rs |  12 ++---
 src/gradient.rs      |  14 +++---
 src/handle.rs        |  28 ++++++------
 src/iri.rs           |  20 ++++-----
 src/marker.rs        |   4 +-
 src/paint_server.rs  |  20 ++++-----
 src/pattern.rs       |  14 +++---
 src/structure.rs     |   6 +--
 src/text.rs          |   6 +--
 14 files changed, 154 insertions(+), 151 deletions(-)
---
diff --git a/src/css.rs b/src/css.rs
index 11e2d65b..4158d68a 100644
--- a/src/css.rs
+++ b/src/css.rs
@@ -826,10 +826,10 @@ mod tests {
 "#,
         );
 
-        let a = document.lookup_node(None, "a").unwrap();
-        let b = document.lookup_node(None, "b").unwrap();
-        let c = document.lookup_node(None, "c").unwrap();
-        let d = document.lookup_node(None, "d").unwrap();
+        let a = document.lookup_internal_node("a").unwrap();
+        let b = document.lookup_internal_node("b").unwrap();
+        let c = document.lookup_internal_node("c").unwrap();
+        let d = document.lookup_internal_node("d").unwrap();
 
         // Node types
         assert!(is_element_of_type!(a, Svg));
diff --git a/src/document.rs b/src/document.rs
index 0fe7725e..fdb6214b 100644
--- a/src/document.rs
+++ b/src/document.rs
@@ -12,7 +12,7 @@ use std::rc::Rc;
 
 use crate::attributes::Attributes;
 use crate::css::{self, Origin, Stylesheet};
-use crate::error::{AcquireError, AllowedUrlError, FragmentError, LoadingError};
+use crate::error::{AcquireError, AllowedUrlError, LoadingError, NodeIdError};
 use crate::handle::LoadOptions;
 use crate::io::{self, BinaryData};
 use crate::limits;
@@ -30,6 +30,42 @@ static UA_STYLESHEETS: Lazy<Vec<Stylesheet>> = Lazy::new(|| {
     .unwrap()]
 });
 
+/// Identifier of a node
+#[derive(Debug, PartialEq, Clone)]
+pub enum NodeId {
+    /// element id
+    Internal(String),
+    /// url, element id
+    External(String, String),
+}
+
+impl NodeId {
+    pub fn parse(href: &str) -> Result<NodeId, NodeIdError> {
+        let (url, id) = match href.rfind('#') {
+            None => (Some(href), None),
+            Some(p) if p == 0 => (None, Some(&href[1..])),
+            Some(p) => (Some(&href[..p]), Some(&href[(p + 1)..])),
+        };
+
+        match (url, id) {
+            (None, Some(id)) if !id.is_empty() => Ok(NodeId::Internal(String::from(id))),
+            (Some(url), Some(id)) if !id.is_empty() => {
+                Ok(NodeId::External(String::from(url), String::from(id)))
+            }
+            _ => Err(NodeIdError::NodeIdRequired),
+        }
+    }
+}
+
+impl fmt::Display for NodeId {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            NodeId::Internal(id) => write!(f, "#{}", id),
+            NodeId::External(url, id) => write!(f, "{}#{}", url, id),
+        }
+    }
+}
+
 /// A loaded SVG file and its derived data.
 pub struct Document {
     /// Tree of nodes; the root is guaranteed to be an `<svg>` element.
@@ -75,23 +111,28 @@ impl Document {
     }
 
     /// Looks up a node in this document or one of its resources by its `id` attribute.
-    pub fn lookup_node(&self, url: Option<&str>, id: &str) -> Option<Node> {
-        match url {
-            Some(u) => self
+    pub fn lookup_node(&self, node_id: &NodeId) -> Option<Node> {
+        match node_id {
+            NodeId::Internal(id) => self.lookup_internal_node(id),
+            NodeId::External(url, id) => self
                 .externs
                 .borrow_mut()
-                .lookup(&self.load_options, u, id)
+                .lookup(&self.load_options, url, id)
                 .ok(),
-            _ => self.ids.get(id).map(|n| (*n).clone()),
         }
     }
 
+    /// Looks up a node in this document by its `id` attribute.
+    pub fn lookup_internal_node(&self, id: &str) -> Option<Node> {
+        self.ids.get(id).map(|n| (*n).clone())
+    }
+
     /// Loads an image by URL, or returns a pre-loaded one.
-    pub fn lookup_image(&self, href: &str) -> Result<SharedImageSurface, LoadingError> {
+    pub fn lookup_image(&self, url: &str) -> Result<SharedImageSurface, LoadingError> {
         let aurl = self
             .load_options
             .url_resolver
-            .resolve_href(href)
+            .resolve_href(url)
             .map_err(|_| LoadingError::BadUrl)?;
 
         self.images.borrow_mut().lookup(&self.load_options, &aurl)
@@ -124,7 +165,7 @@ impl Resources {
         id: &str,
     ) -> Result<Node, LoadingError> {
         self.get_extern_document(load_options, url)
-            .and_then(|doc| doc.lookup_node(None, id).ok_or(LoadingError::BadUrl))
+            .and_then(|doc| doc.lookup_internal_node(id).ok_or(LoadingError::BadUrl))
     }
 
     fn get_extern_document(
@@ -252,46 +293,6 @@ fn image_loading_error_from_cairo(status: cairo::Status, aurl: &AllowedUrl) -> L
     }
 }
 
-/// Optional URI, mandatory fragment id
-#[derive(Debug, PartialEq, Clone)]
-pub struct Fragment(Option<String>, String);
-
-impl Fragment {
-    // Outside of testing, we don't want code creating Fragments by hand;
-    // they are obtained by parsing a href string.
-    #[cfg(test)]
-    pub fn new(uri: Option<String>, fragment: String) -> Fragment {
-        Fragment(uri, fragment)
-    }
-
-    pub fn parse(href: &str) -> Result<Fragment, FragmentError> {
-        let (uri, fragment) = match href.rfind('#') {
-            None => (Some(href), None),
-            Some(p) if p == 0 => (None, Some(&href[1..])),
-            Some(p) => (Some(&href[..p]), Some(&href[(p + 1)..])),
-        };
-
-        match (uri, fragment) {
-            (u, Some(f)) if !f.is_empty() => Ok(Fragment(u.map(String::from), String::from(f))),
-            _ => Err(FragmentError::FragmentRequired),
-        }
-    }
-
-    pub fn uri(&self) -> Option<&str> {
-        self.0.as_deref()
-    }
-
-    pub fn fragment(&self) -> &str {
-        &self.1
-    }
-}
-
-impl fmt::Display for Fragment {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}#{}", self.uri().unwrap_or(""), self.fragment())
-    }
-}
-
 pub struct AcquiredNode {
     stack: Option<Rc<RefCell<NodeStack>>>,
     node: Node,
@@ -343,7 +344,7 @@ impl<'i> AcquiredNodes<'i> {
 
     /// Acquires a node.
     /// Nodes acquired by this function must be released in reverse acquiring order.
-    pub fn acquire(&mut self, fragment: &Fragment) -> Result<AcquiredNode, AcquireError> {
+    pub fn acquire(&mut self, node_id: &NodeId) -> Result<AcquiredNode, AcquireError> {
         self.num_elements_acquired += 1;
 
         // This is a mitigation for SVG files that try to instance a huge number of
@@ -362,11 +363,11 @@ impl<'i> AcquiredNodes<'i> {
         //   - Now that all files are loaded, resolve URL references
         let node = self
             .document
-            .lookup_node(fragment.uri(), fragment.fragment())
-            .ok_or_else(|| AcquireError::LinkNotFound(fragment.clone()))?;
+            .lookup_node(node_id)
+            .ok_or_else(|| AcquireError::LinkNotFound(node_id.clone()))?;
 
         if !node.is_element() {
-            return Err(AcquireError::InvalidLinkType(fragment.clone()));
+            return Err(AcquireError::InvalidLinkType(node_id.clone()));
         }
 
         if node.borrow_element().is_accessed_by_reference() {
@@ -548,20 +549,20 @@ mod tests {
     use super::*;
 
     #[test]
-    fn parses_fragment() {
+    fn parses_node_id() {
         assert_eq!(
-            Fragment::parse("#foo").unwrap(),
-            Fragment::new(None, "foo".to_string())
+            NodeId::parse("#foo").unwrap(),
+            NodeId::Internal("foo".to_string())
         );
 
         assert_eq!(
-            Fragment::parse("uri#foo").unwrap(),
-            Fragment::new(Some("uri".to_string()), "foo".to_string())
+            NodeId::parse("uri#foo").unwrap(),
+            NodeId::External("uri".to_string(), "foo".to_string())
         );
 
         assert!(matches!(
-            Fragment::parse("uri"),
-            Err(FragmentError::FragmentRequired)
+            NodeId::parse("uri"),
+            Err(NodeIdError::NodeIdRequired)
         ));
     }
 }
diff --git a/src/drawing_ctx.rs b/src/drawing_ctx.rs
index 58b35618..40481bca 100644
--- a/src/drawing_ctx.rs
+++ b/src/drawing_ctx.rs
@@ -13,7 +13,7 @@ use crate::aspect_ratio::AspectRatio;
 use crate::bbox::BoundingBox;
 use crate::coord_units::CoordUnits;
 use crate::dasharray::Dasharray;
-use crate::document::{AcquiredNodes, Fragment};
+use crate::document::{AcquiredNodes, NodeId};
 use crate::dpi::Dpi;
 use crate::element::Element;
 use crate::error::{AcquireError, ImplementationLimit, RenderingError};
@@ -665,8 +665,8 @@ impl DrawingCtx {
 
                     // Mask
 
-                    if let Some(fragment) = mask {
-                        if let Ok(acquired) = acquired_nodes.acquire(fragment) {
+                    if let Some(node_id) = mask {
+                        if let Ok(acquired) = acquired_nodes.acquire(node_id) {
                             let mask_node = acquired.get();
 
                             match *mask_node.borrow_element() {
@@ -692,7 +692,7 @@ impl DrawingCtx {
                                     rsvg_log!(
                                         "element {} references \"{}\" which is not a mask",
                                         node,
-                                        fragment
+                                        node_id
                                     );
                                 }
                             }
@@ -700,7 +700,7 @@ impl DrawingCtx {
                             rsvg_log!(
                                 "element {} references nonexistent mask \"{}\"",
                                 node,
-                                fragment
+                                node_id
                             );
                         }
                     } else {
@@ -885,7 +885,7 @@ impl DrawingCtx {
     fn run_filter(
         &mut self,
         acquired_nodes: &mut AcquiredNodes<'_>,
-        filter_uri: &Fragment,
+        filter_uri: &NodeId,
         node: &Node,
         values: &ComputedValues,
         child_surface: SharedImageSurface,
@@ -1609,7 +1609,7 @@ impl DrawingCtx {
         node: &Node,
         acquired_nodes: &mut AcquiredNodes<'_>,
         cascaded: &CascadedValues<'_>,
-        link: Option<&Fragment>,
+        link: Option<&NodeId>,
         clipping: bool,
     ) -> Result<BoundingBox, RenderingError> {
         // <use> is an element that is used directly, unlike
@@ -1650,8 +1650,8 @@ impl DrawingCtx {
 
             Err(AcquireError::InvalidLinkType(_)) => unreachable!(),
 
-            Err(AcquireError::LinkNotFound(fragment)) => {
-                rsvg_log!("element {} references nonexistent \"{}\"", node, fragment);
+            Err(AcquireError::LinkNotFound(node_id)) => {
+                rsvg_log!("element {} references nonexistent \"{}\"", node, node_id);
                 return Ok(self.empty_bbox());
             }
         };
@@ -1769,12 +1769,12 @@ impl CompositingAffines {
 // Returns (clip_in_user_space, clip_in_object_space), both Option<Node>
 fn get_clip_in_user_and_object_space(
     acquired_nodes: &mut AcquiredNodes<'_>,
-    clip_uri: Option<&Fragment>,
+    clip_uri: Option<&NodeId>,
 ) -> (Option<Node>, Option<Node>) {
     clip_uri
-        .and_then(|fragment| {
+        .and_then(|node_id| {
             acquired_nodes
-                .acquire(fragment)
+                .acquire(node_id)
                 .ok()
                 .filter(|a| is_element_of_type!(*a.get(), ClipPath))
         })
diff --git a/src/error.rs b/src/error.rs
index 53688825..22632fce 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -6,7 +6,7 @@ use std::fmt;
 use cssparser::{BasicParseError, BasicParseErrorKind, ParseErrorKind, ToCss};
 use markup5ever::QualName;
 
-use crate::document::Fragment;
+use crate::document::NodeId;
 use crate::io::IoError;
 use crate::limits;
 use crate::node::Node;
@@ -170,8 +170,8 @@ impl From<cairo::Status> for RenderingError {
 }
 
 pub enum AcquireError {
-    LinkNotFound(Fragment),
-    InvalidLinkType(Fragment),
+    LinkNotFound(NodeId),
+    InvalidLinkType(NodeId),
     CircularReference(Node),
     MaxReferencesExceeded,
 }
@@ -322,16 +322,16 @@ impl fmt::Display for AllowedUrlError {
     }
 }
 
-/// Errors returned when creating a `Fragment` out of a string
+/// Errors returned when creating a `NodeId` out of a string
 #[derive(Debug, Clone)]
-pub enum FragmentError {
-    FragmentRequired,
+pub enum NodeIdError {
+    NodeIdRequired,
 }
 
-impl From<FragmentError> for ValueErrorKind {
-    fn from(e: FragmentError) -> ValueErrorKind {
+impl From<NodeIdError> for ValueErrorKind {
+    fn from(e: NodeIdError) -> ValueErrorKind {
         match e {
-            FragmentError::FragmentRequired => {
+            NodeIdError::NodeIdRequired => {
                 ValueErrorKind::value_error("fragment identifier required")
             }
         }
diff --git a/src/filter.rs b/src/filter.rs
index 5fa3cbb1..a6f4fc8c 100644
--- a/src/filter.rs
+++ b/src/filter.rs
@@ -6,7 +6,7 @@ use std::slice::Iter;
 
 use crate::attributes::Attributes;
 use crate::coord_units::CoordUnits;
-use crate::document::{AcquiredNodes, Fragment};
+use crate::document::{AcquiredNodes, NodeId};
 use crate::drawing_ctx::ViewParams;
 use crate::element::{Draw, Element, ElementResult, SetAttributes};
 use crate::error::ValueErrorKind;
@@ -151,7 +151,7 @@ impl Draw for Filter {}
 
 #[derive(Debug, Clone, PartialEq)]
 pub enum FilterValue {
-    URL(Fragment),
+    URL(NodeId),
 }
 #[derive(Debug, Clone, PartialEq)]
 pub struct FilterValueList(Vec<FilterValue>);
@@ -238,11 +238,11 @@ mod tests {
 
     #[test]
     fn parses_filter_value_list() {
-        let f1 = Fragment::new(Some("foo.svg".to_string()), "bar".to_string());
-        let f2 = Fragment::new(Some("test.svg".to_string()), "baz".to_string());
+        let n1 = NodeId::External("foo.svg".to_string(), "bar".to_string());
+        let n2 = NodeId::External("test.svg".to_string(), "baz".to_string());
         assert_eq!(
             FilterValueList::parse_str("url(foo.svg#bar) url(test.svg#baz)").unwrap(),
-            FilterValueList(vec![FilterValue::URL(f1), FilterValue::URL(f2)])
+            FilterValueList(vec![FilterValue::URL(n1), FilterValue::URL(n2)])
         );
     }
 
diff --git a/src/filters/image.rs b/src/filters/image.rs
index 40a46453..5d6e040b 100644
--- a/src/filters/image.rs
+++ b/src/filters/image.rs
@@ -2,7 +2,7 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
 
 use crate::aspect_ratio::AspectRatio;
 use crate::attributes::Attributes;
-use crate::document::{AcquiredNodes, Fragment};
+use crate::document::{AcquiredNodes, NodeId};
 use crate::drawing_ctx::DrawingCtx;
 use crate::element::{ElementResult, SetAttributes};
 use crate::href::{is_href, set_href};
@@ -42,10 +42,10 @@ impl FeImage {
         acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
         bounds: Rect,
-        fragment: &Fragment,
+        node_id: &NodeId,
     ) -> Result<SharedImageSurface, FilterError> {
         let acquired_drawable = acquired_nodes
-            .acquire(fragment)
+            .acquire(node_id)
             .map_err(|_| FilterError::InvalidInput)?;
         let drawable = acquired_drawable.get();
 
@@ -131,9 +131,9 @@ impl FilterEffect for FeImage {
 
         let href = self.href.as_ref().ok_or(FilterError::InvalidInput)?;
 
-        let surface = if let Ok(fragment) = Fragment::parse(href) {
-            // if there is a fragment, render as a node
-            self.render_node(ctx, acquired_nodes, draw_ctx, bounds, &fragment)
+        let surface = if let Ok(node_id) = NodeId::parse(href) {
+            // if href has a fragment specified, render as a node
+            self.render_node(ctx, acquired_nodes, draw_ctx, bounds, &node_id)
         } else {
             // if there is no fragment, render as an image
             let unclipped_bounds = bounds_builder.into_rect_without_clipping(draw_ctx);
diff --git a/src/gradient.rs b/src/gradient.rs
index a83c9e1e..69298c05 100644
--- a/src/gradient.rs
+++ b/src/gradient.rs
@@ -9,7 +9,7 @@ use std::cell::RefCell;
 use crate::attributes::Attributes;
 use crate::bbox::BoundingBox;
 use crate::coord_units::CoordUnits;
-use crate::document::{AcquiredNodes, Fragment, NodeStack};
+use crate::document::{AcquiredNodes, NodeId, NodeStack};
 use crate::drawing_ctx::DrawingCtx;
 use crate::element::{Draw, Element, ElementResult, SetAttributes};
 use crate::error::*;
@@ -309,7 +309,7 @@ struct Common {
     transform: Option<Transform>,
     spread: Option<SpreadMethod>,
 
-    fallback: Option<Fragment>,
+    fallback: Option<NodeId>,
 
     resolved: RefCell<Option<ResolvedGradient>>,
 }
@@ -513,7 +513,7 @@ impl UnresolvedGradient {
 /// resolved gradient yet.
 struct Unresolved {
     gradient: UnresolvedGradient,
-    fallback: Option<Fragment>,
+    fallback: Option<NodeId>,
 }
 
 impl LinearGradient {
@@ -553,7 +553,7 @@ impl SetAttributes for Common {
                     set_href(
                         a,
                         &mut self.fallback,
-                        Fragment::parse(value).attribute(attr.clone())?,
+                        NodeId::parse(value).attribute(attr.clone())?,
                     );
                 }
                 _ => (),
@@ -623,8 +623,8 @@ macro_rules! impl_gradient {
                 let mut stack = NodeStack::new();
 
                 while !gradient.is_resolved() {
-                    if let Some(fragment) = fallback {
-                        let acquired = acquired_nodes.acquire(&fragment)?;
+                    if let Some(node_id) = fallback {
+                        let acquired = acquired_nodes.acquire(&node_id)?;
                         let acquired_node = acquired.get();
 
                         if stack.contains(acquired_node) {
@@ -634,7 +634,7 @@ macro_rules! impl_gradient {
                         let unresolved = match *acquired_node.borrow_element() {
                             Element::$gradient_type(ref g) => g.get_unresolved(&acquired_node),
                             Element::$other_type(ref g) => g.get_unresolved(&acquired_node),
-                            _ => return Err(AcquireError::InvalidLinkType(fragment.clone())),
+                            _ => return Err(AcquireError::InvalidLinkType(node_id.clone())),
                         };
 
                         gradient = gradient.resolve_from_fallback(&unresolved.gradient);
diff --git a/src/handle.rs b/src/handle.rs
index a44e3960..0d13da26 100644
--- a/src/handle.rs
+++ b/src/handle.rs
@@ -4,7 +4,7 @@
 
 use crate::bbox::BoundingBox;
 use crate::css::{Origin, Stylesheet};
-use crate::document::{AcquiredNodes, Document, Fragment};
+use crate::document::{AcquiredNodes, Document, NodeId};
 use crate::dpi::Dpi;
 use crate::drawing_ctx::{draw_tree, DrawingMode, ViewParams};
 use crate::error::{DefsLookupErrorKind, LoadingError, RenderingError};
@@ -192,7 +192,7 @@ impl Handle {
     }
 
     fn lookup_node(&self, id: &str) -> Result<Node, DefsLookupErrorKind> {
-        let fragment = Fragment::parse(&id).map_err(|_| DefsLookupErrorKind::InvalidId)?;
+        let node_id = NodeId::parse(&id).map_err(|_| DefsLookupErrorKind::InvalidId)?;
 
         // The public APIs to get geometries of individual elements, or to render
         // them, should only allow referencing elements within the main handle's
@@ -202,18 +202,20 @@ impl Handle {
         // resources that the main SVG actually references.  In the future we may
         // relax this requirement to allow lookups within that set, but not to
         // other random files.
-        if fragment.uri().is_some() {
-            rsvg_log!(
-                "the public API is not allowed to look up external references: {}",
-                fragment
-            );
-
-            return Err(DefsLookupErrorKind::CannotLookupExternalReferences);
+        match node_id {
+            NodeId::Internal(id) => self
+                .document
+                .lookup_internal_node(&id)
+                .ok_or(DefsLookupErrorKind::NotFound),
+            NodeId::External(_, _) => {
+                rsvg_log!(
+                    "the public API is not allowed to look up external references: {}",
+                    node_id
+                );
+
+                Err(DefsLookupErrorKind::CannotLookupExternalReferences)
+            }
         }
-
-        self.document
-            .lookup_node(None, fragment.fragment())
-            .ok_or(DefsLookupErrorKind::NotFound)
     }
 
     pub fn render_document(
diff --git a/src/iri.rs b/src/iri.rs
index 2a88f931..e73a3fd5 100644
--- a/src/iri.rs
+++ b/src/iri.rs
@@ -2,7 +2,7 @@
 
 use cssparser::Parser;
 
-use crate::document::Fragment;
+use crate::document::NodeId;
 use crate::error::*;
 use crate::parsers::Parse;
 
@@ -15,7 +15,7 @@ use crate::parsers::Parse;
 #[derive(Debug, Clone, PartialEq)]
 pub enum IRI {
     None,
-    Resource(Fragment),
+    Resource(NodeId),
 }
 
 impl Default for IRI {
@@ -26,7 +26,7 @@ impl Default for IRI {
 
 impl IRI {
     /// Returns the contents of an `IRI::Resource`, or `None`
-    pub fn get(&self) -> Option<&Fragment> {
+    pub fn get(&self) -> Option<&NodeId> {
         match *self {
             IRI::None => None,
             IRI::Resource(ref f) => Some(f),
@@ -44,10 +44,10 @@ impl Parse for IRI {
         } else {
             let loc = parser.current_source_location();
             let url = parser.expect_url()?;
-            let fragment =
-                Fragment::parse(&url).map_err(|e| loc.new_custom_error(ValueErrorKind::from(e)))?;
+            let node_id =
+                NodeId::parse(&url).map_err(|e| loc.new_custom_error(ValueErrorKind::from(e)))?;
 
-            Ok(IRI::Resource(fragment))
+            Ok(IRI::Resource(node_id))
         }
     }
 }
@@ -65,22 +65,22 @@ mod tests {
     fn parses_url() {
         assert_eq!(
             IRI::parse_str("url(#bar)").unwrap(),
-            IRI::Resource(Fragment::new(None, "bar".to_string()))
+            IRI::Resource(NodeId::Internal("bar".to_string()))
         );
 
         assert_eq!(
             IRI::parse_str("url(foo#bar)").unwrap(),
-            IRI::Resource(Fragment::new(Some("foo".to_string()), "bar".to_string()))
+            IRI::Resource(NodeId::External("foo".to_string(), "bar".to_string()))
         );
 
         // be permissive if the closing ) is missing
         assert_eq!(
             IRI::parse_str("url(#bar").unwrap(),
-            IRI::Resource(Fragment::new(None, "bar".to_string()))
+            IRI::Resource(NodeId::Internal("bar".to_string()))
         );
         assert_eq!(
             IRI::parse_str("url(foo#bar").unwrap(),
-            IRI::Resource(Fragment::new(Some("foo".to_string()), "bar".to_string()))
+            IRI::Resource(NodeId::External("foo".to_string(), "bar".to_string()))
         );
 
         assert!(IRI::parse_str("").is_err());
diff --git a/src/marker.rs b/src/marker.rs
index 7f639594..349528c7 100644
--- a/src/marker.rs
+++ b/src/marker.rs
@@ -10,7 +10,7 @@ use crate::angle::Angle;
 use crate::aspect_ratio::*;
 use crate::attributes::Attributes;
 use crate::bbox::BoundingBox;
-use crate::document::{AcquiredNodes, Fragment};
+use crate::document::{AcquiredNodes, NodeId};
 use crate::drawing_ctx::DrawingCtx;
 use crate::element::{Draw, Element, ElementResult, SetAttributes};
 use crate::error::*;
@@ -556,7 +556,7 @@ enum MarkerType {
 fn emit_marker_by_name(
     draw_ctx: &mut DrawingCtx,
     acquired_nodes: &mut AcquiredNodes<'_>,
-    name: &Fragment,
+    name: &NodeId,
     xpos: f64,
     ypos: f64,
     computed_angle: Angle,
diff --git a/src/paint_server.rs b/src/paint_server.rs
index 6f88424e..83c17364 100644
--- a/src/paint_server.rs
+++ b/src/paint_server.rs
@@ -3,11 +3,11 @@
 use cssparser::Parser;
 
 use crate::bbox::BoundingBox;
-use crate::document::{AcquiredNodes, Fragment};
+use crate::document::{AcquiredNodes, NodeId};
 use crate::drawing_ctx::DrawingCtx;
 use crate::element::Element;
 use crate::error::{
-    AcquireError, FragmentError, ImplementationLimit, ParseError, RenderingError, ValueErrorKind,
+    AcquireError, ImplementationLimit, NodeIdError, ParseError, RenderingError, ValueErrorKind,
 };
 use crate::gradient::{ResolvedGradient, UserSpaceGradient};
 use crate::node::NodeBorrow;
@@ -19,7 +19,7 @@ use crate::properties::ComputedValues;
 pub enum PaintServer {
     None,
     Iri {
-        iri: Fragment,
+        iri: NodeId,
         alternate: Option<cssparser::Color>,
     },
     SolidColor(cssparser::Color),
@@ -63,8 +63,8 @@ impl Parse for PaintServer {
             };
 
             Ok(PaintServer::Iri {
-                iri: Fragment::parse(&url)
-                    .map_err(|e: FragmentError| -> ValueErrorKind { e.into() })
+                iri: NodeId::parse(&url)
+                    .map_err(|e: NodeIdError| -> ValueErrorKind { e.into() })
                     .map_err(|e| loc.new_custom_error(e))?,
                 alternate,
             })
@@ -203,7 +203,7 @@ mod tests {
         assert_eq!(
             PaintServer::parse_str("url(#link)").unwrap(),
             PaintServer::Iri {
-                iri: Fragment::new(None, "link".to_string()),
+                iri: NodeId::Internal("link".to_string()),
                 alternate: None,
             }
         );
@@ -211,7 +211,7 @@ mod tests {
         assert_eq!(
             PaintServer::parse_str("url(foo#link) none").unwrap(),
             PaintServer::Iri {
-                iri: Fragment::new(Some("foo".to_string()), "link".to_string()),
+                iri: NodeId::External("foo".to_string(), "link".to_string()),
                 alternate: None,
             }
         );
@@ -219,7 +219,7 @@ mod tests {
         assert_eq!(
             PaintServer::parse_str("url(#link) #ff8040").unwrap(),
             PaintServer::Iri {
-                iri: Fragment::new(None, "link".to_string()),
+                iri: NodeId::Internal("link".to_string()),
                 alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
                     255, 128, 64, 255
                 ))),
@@ -229,7 +229,7 @@ mod tests {
         assert_eq!(
             PaintServer::parse_str("url(#link) rgb(255, 128, 64, 0.5)").unwrap(),
             PaintServer::Iri {
-                iri: Fragment::new(None, "link".to_string()),
+                iri: NodeId::Internal("link".to_string()),
                 alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
                     255, 128, 64, 128
                 ))),
@@ -239,7 +239,7 @@ mod tests {
         assert_eq!(
             PaintServer::parse_str("url(#link) currentColor").unwrap(),
             PaintServer::Iri {
-                iri: Fragment::new(None, "link".to_string()),
+                iri: NodeId::Internal("link".to_string()),
                 alternate: Some(cssparser::Color::CurrentColor),
             }
         );
diff --git a/src/pattern.rs b/src/pattern.rs
index 2c818e48..66533e1e 100644
--- a/src/pattern.rs
+++ b/src/pattern.rs
@@ -7,7 +7,7 @@ use crate::aspect_ratio::*;
 use crate::attributes::Attributes;
 use crate::bbox::BoundingBox;
 use crate::coord_units::CoordUnits;
-use crate::document::{AcquiredNodes, Fragment, NodeStack};
+use crate::document::{AcquiredNodes, NodeId, NodeStack};
 use crate::drawing_ctx::DrawingCtx;
 use crate::element::{Draw, Element, ElementResult, SetAttributes};
 use crate::error::*;
@@ -47,7 +47,7 @@ struct Common {
 /// resolved pattern yet.
 struct Unresolved {
     pattern: UnresolvedPattern,
-    fallback: Option<Fragment>,
+    fallback: Option<NodeId>,
 }
 
 /// Keeps track of which Pattern provided a non-empty set of children during pattern resolution
@@ -118,7 +118,7 @@ pub struct UserSpacePattern {
 #[derive(Default)]
 pub struct Pattern {
     common: Common,
-    fallback: Option<Fragment>,
+    fallback: Option<NodeId>,
     resolved: RefCell<Option<ResolvedPattern>>,
 }
 
@@ -141,7 +141,7 @@ impl SetAttributes for Pattern {
                     set_href(
                         a,
                         &mut self.fallback,
-                        Fragment::parse(value).attribute(attr.clone())?,
+                        NodeId::parse(value).attribute(attr.clone())?,
                     );
                 }
                 expanded_name!("", "x") => self.common.x = Some(attr.parse(value)?),
@@ -387,8 +387,8 @@ impl Pattern {
         let mut stack = NodeStack::new();
 
         while !pattern.is_resolved() {
-            if let Some(ref fragment) = fallback {
-                match acquired_nodes.acquire(&fragment) {
+            if let Some(ref node_id) = fallback {
+                match acquired_nodes.acquire(&node_id) {
                     Ok(acquired) => {
                         let acquired_node = acquired.get();
 
@@ -404,7 +404,7 @@ impl Pattern {
 
                                 stack.push(acquired_node);
                             }
-                            _ => return Err(AcquireError::InvalidLinkType(fragment.clone())),
+                            _ => return Err(AcquireError::InvalidLinkType(node_id.clone())),
                         }
                     }
 
diff --git a/src/structure.rs b/src/structure.rs
index 2d6a1761..8219f1a4 100644
--- a/src/structure.rs
+++ b/src/structure.rs
@@ -6,7 +6,7 @@ use crate::aspect_ratio::*;
 use crate::attributes::Attributes;
 use crate::bbox::BoundingBox;
 use crate::coord_units::CoordUnits;
-use crate::document::{AcquiredNodes, Fragment};
+use crate::document::{AcquiredNodes, NodeId};
 use crate::drawing_ctx::{ClipMode, DrawingCtx, ViewParams};
 use crate::element::{Draw, ElementResult, SetAttributes};
 use crate::error::*;
@@ -250,7 +250,7 @@ impl Draw for Svg {
 
 #[derive(Default)]
 pub struct Use {
-    link: Option<Fragment>,
+    link: Option<NodeId>,
     x: Length<Horizontal>,
     y: Length<Vertical>,
     w: Option<Length<Horizontal>>,
@@ -287,7 +287,7 @@ impl SetAttributes for Use {
                 ref a if is_href(a) => set_href(
                     a,
                     &mut self.link,
-                    Fragment::parse(value).attribute(attr.clone())?,
+                    NodeId::parse(value).attribute(attr.clone())?,
                 ),
 
                 expanded_name!("", "x") => self.x = attr.parse(value)?,
diff --git a/src/text.rs b/src/text.rs
index c1ca2d67..ee1ad0d4 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -5,7 +5,7 @@ use std::cell::RefCell;
 
 use crate::attributes::Attributes;
 use crate::bbox::BoundingBox;
-use crate::document::{AcquiredNodes, Fragment};
+use crate::document::{AcquiredNodes, NodeId};
 use crate::drawing_ctx::DrawingCtx;
 use crate::element::{Draw, Element, ElementResult, SetAttributes};
 use crate::error::*;
@@ -527,7 +527,7 @@ impl Draw for Text {
 
 #[derive(Default)]
 pub struct TRef {
-    link: Option<Fragment>,
+    link: Option<NodeId>,
 }
 
 impl TRef {
@@ -584,7 +584,7 @@ impl SetAttributes for TRef {
             // Unlike other elements which use `href` in SVG2 versus `xlink:href` in SVG1.1,
             // the <tref> element got removed in SVG2.  So, here we still use a match
             // against the full namespaced version of the attribute.
-            .and_then(|(attr, value)| Fragment::parse(value).attribute(attr).ok());
+            .and_then(|(attr, value)| NodeId::parse(value).attribute(attr).ok());
 
         Ok(())
     }


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