[librsvg: 26/48] defs::Reference - encapsulate the micro-parser for uri#fragment_id
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 26/48] defs::Reference - encapsulate the micro-parser for uri#fragment_id
- Date: Sat, 17 Nov 2018 10:22:12 +0000 (UTC)
commit 09a38917ff5a7e292238928c74be57b7fa5d039b
Author: Federico Mena Quintero <federico gnome org>
Date: Mon Sep 10 13:34:01 2018 -0500
defs::Reference - encapsulate the micro-parser for uri#fragment_id
We have an implicit way of doing that in Defs.lookup(); we'll move
that little bit of logic to a separate function.
rsvg_internals/src/defs.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
---
diff --git a/rsvg_internals/src/defs.rs b/rsvg_internals/src/defs.rs
index 1fbd4bd7..f0589320 100644
--- a/rsvg_internals/src/defs.rs
+++ b/rsvg_internals/src/defs.rs
@@ -61,6 +61,39 @@ impl Defs {
}
}
+/// Represents a possibly non-canonical URI with an optional fragment identifier
+///
+/// Sometimes in SVG element references (e.g. the `href` in the `<feImage>` element) we
+/// must decide between referencing an external file, or using a plain fragment identifier
+/// like `href="#foo"` as a reference to an SVG element in the same file as the one being
+/// processes. This enum makes that distinction.
+#[derive(Debug, PartialEq)]
+pub enum Reference<'a> {
+ PlainUri(&'a str),
+ FragmentId(&'a str),
+ UriWithFragmentId(&'a str, &'a str),
+}
+
+impl<'a> Reference<'a> {
+ pub fn parse(s: &str) -> Result<Reference, ()> {
+ let (uri, fragment) = match s.rfind('#') {
+ None => (Some(s), None),
+ Some(p) if p == 0 => (None, Some(&s[1..])),
+ Some(p) => (Some(&s[..p]), Some(&s[(p + 1)..])),
+ };
+
+ match (uri, fragment) {
+ (None, Some(f)) if f.len() == 0 => Err(()),
+ (None, Some(f)) => Ok(Reference::FragmentId(f)),
+ (Some(u), _) if u.len() == 0 => Err(()),
+ (Some(u), None) => Ok(Reference::PlainUri(u)),
+ (Some(_u), Some(f)) if f.len() == 0 => Err(()),
+ (Some(u), Some(f)) => Ok(Reference::UriWithFragmentId(u, f)),
+ (_, _) => Err(()),
+ }
+ }
+}
+
#[no_mangle]
pub extern "C" fn rsvg_defs_new(handle: *const RsvgHandle) -> *mut RsvgDefs {
Box::into_raw(Box::new(Defs::new(handle))) as *mut RsvgDefs
@@ -92,3 +125,28 @@ pub extern "C" fn rsvg_defs_lookup(
None => ptr::null(),
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn reference_kinds() {
+ assert_eq!(Reference::parse("uri"), Ok(Reference::PlainUri("uri")));
+ assert_eq!(
+ Reference::parse("#fragment"),
+ Ok(Reference::FragmentId("fragment"))
+ );
+ assert_eq!(
+ Reference::parse("uri#fragment"),
+ Ok(Reference::UriWithFragmentId("uri", "fragment"))
+ );
+ }
+
+ #[test]
+ fn reference_errors() {
+ assert!(Reference::parse("").is_err());
+ assert!(Reference::parse("#").is_err());
+ assert!(Reference::parse("uri#").is_err());
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]