diff options
author | Marge Bot <marge-bot@gnome.org> | 2023-04-25 23:30:10 +0000 |
---|---|---|
committer | Marge Bot <marge-bot@gnome.org> | 2023-04-25 23:30:10 +0000 |
commit | 30567b3eac0148e3e95f5dd011ff76bda5000a99 (patch) | |
tree | 7d5c56dc2b20f91ccc77aee4dad07830e7eb429a /rsvg/src/iri.rs | |
parent | d597831ff93b09cc41ce4768a833bc6407c95184 (diff) | |
parent | 7608c94036d7a44296a7e135f42e84aed20afeb7 (diff) | |
download | librsvg-30567b3eac0148e3e95f5dd011ff76bda5000a99.tar.gz |
Merge branch 'wip/sophie-h/workspace' into 'main'
meta: Move lib and bins into separate crates
Closes #950
See merge request GNOME/librsvg!822
Diffstat (limited to 'rsvg/src/iri.rs')
-rw-r--r-- | rsvg/src/iri.rs | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/rsvg/src/iri.rs b/rsvg/src/iri.rs new file mode 100644 index 00000000..e3272fe6 --- /dev/null +++ b/rsvg/src/iri.rs @@ -0,0 +1,90 @@ +//! CSS funciri values. + +use cssparser::Parser; + +use crate::document::NodeId; +use crate::error::*; +use crate::parsers::Parse; + +/// Used where style properties take a funciri or "none" +/// +/// This is not to be used for values which don't come from properties. +/// For example, the `xlink:href` attribute in the `<image>` element +/// does not take a funciri value (which looks like `url(...)`), but rather +/// it takes a plain URL. +#[derive(Debug, Clone, PartialEq)] +pub enum Iri { + None, + Resource(Box<NodeId>), +} + +impl Iri { + /// Returns the contents of an `IRI::Resource`, or `None` + pub fn get(&self) -> Option<&NodeId> { + match *self { + Iri::None => None, + Iri::Resource(ref f) => Some(f), + } + } +} + +impl Parse for Iri { + fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Iri, ParseError<'i>> { + if parser + .try_parse(|i| i.expect_ident_matching("none")) + .is_ok() + { + Ok(Iri::None) + } else { + let loc = parser.current_source_location(); + let url = parser.expect_url()?; + let node_id = + NodeId::parse(&url).map_err(|e| loc.new_custom_error(ValueErrorKind::from(e)))?; + + Ok(Iri::Resource(Box::new(node_id))) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parses_none() { + assert_eq!(Iri::parse_str("none").unwrap(), Iri::None); + } + + #[test] + fn parses_url() { + assert_eq!( + Iri::parse_str("url(#bar)").unwrap(), + Iri::Resource(Box::new(NodeId::Internal("bar".to_string()))) + ); + + assert_eq!( + Iri::parse_str("url(foo#bar)").unwrap(), + Iri::Resource(Box::new(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(Box::new(NodeId::Internal("bar".to_string()))) + ); + assert_eq!( + Iri::parse_str("url(foo#bar").unwrap(), + Iri::Resource(Box::new(NodeId::External( + "foo".to_string(), + "bar".to_string() + ))) + ); + + assert!(Iri::parse_str("").is_err()); + assert!(Iri::parse_str("foo").is_err()); + assert!(Iri::parse_str("url(foo)bar").is_err()); + } +} |