Skip to main content

rsvg/
iri.rs

1//! CSS funciri values.
2
3use cssparser::Parser;
4
5use crate::document::NodeId;
6use crate::error::*;
7use crate::parsers::Parse;
8
9/// Used where style properties take a funciri or "none"
10///
11/// This is not to be used for values which don't come from properties.
12/// For example, the `xlink:href` attribute in the `<image>` element
13/// does not take a funciri value (which looks like `url(...)`), but rather
14/// it takes a plain URL.
15#[derive(Debug, Clone, PartialEq)]
16pub enum Iri {
17    None,
18    Resource(Box<NodeId>),
19}
20
21impl Iri {
22    /// Returns the contents of an `IRI::Resource`, or `None`
23    pub fn get(&self) -> Option<&NodeId> {
24        match *self {
25            Iri::None => None,
26            Iri::Resource(ref f) => Some(f),
27        }
28    }
29}
30
31impl Parse for Iri {
32    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Iri, ParseError<'i>> {
33        if parser
34            .try_parse(|i| i.expect_ident_matching("none"))
35            .is_ok()
36        {
37            Ok(Iri::None)
38        } else {
39            let loc = parser.current_source_location();
40            let url = parser.expect_url()?;
41            let node_id =
42                NodeId::parse(&url).map_err(|e| loc.new_custom_error(ValueErrorKind::from(e)))?;
43
44            Ok(Iri::Resource(Box::new(node_id)))
45        }
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn parses_none() {
55        assert_eq!(Iri::parse_str("none").unwrap(), Iri::None);
56    }
57
58    #[test]
59    fn parses_url() {
60        assert_eq!(
61            Iri::parse_str("url(#bar)").unwrap(),
62            Iri::Resource(Box::new(NodeId::Internal("bar".to_string())))
63        );
64
65        assert_eq!(
66            Iri::parse_str("url(foo#bar)").unwrap(),
67            Iri::Resource(Box::new(NodeId::External(
68                "foo".to_string(),
69                "bar".to_string()
70            )))
71        );
72
73        // be permissive if the closing ) is missing
74        assert_eq!(
75            Iri::parse_str("url(#bar").unwrap(),
76            Iri::Resource(Box::new(NodeId::Internal("bar".to_string())))
77        );
78        assert_eq!(
79            Iri::parse_str("url(foo#bar").unwrap(),
80            Iri::Resource(Box::new(NodeId::External(
81                "foo".to_string(),
82                "bar".to_string()
83            )))
84        );
85
86        assert!(Iri::parse_str("").is_err());
87        assert!(Iri::parse_str("foo").is_err());
88        assert!(Iri::parse_str("url(foo)bar").is_err());
89    }
90}