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.
parent 38797bce
......@@ -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());
}
}
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