1
//! CSS funciri values.
2

            
3
use cssparser::Parser;
4

            
5
use crate::document::NodeId;
6
use crate::error::*;
7
use 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
30514866
#[derive(Debug, Clone, PartialEq)]
16
pub enum Iri {
17
    None,
18
1906
    Resource(Box<NodeId>),
19
}
20

            
21
impl Iri {
22
    /// Returns the contents of an `IRI::Resource`, or `None`
23
4012242
    pub fn get(&self) -> Option<&NodeId> {
24
4012242
        match *self {
25
4012002
            Iri::None => None,
26
240
            Iri::Resource(ref f) => Some(f),
27
        }
28
4012242
    }
29
}
30

            
31
impl Parse for Iri {
32
2045
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Iri, ParseError<'i>> {
33
2045
        if parser
34
2045
            .try_parse(|i| i.expect_ident_matching("none"))
35
2045
            .is_ok()
36
        {
37
1802
            Ok(Iri::None)
38
        } else {
39
243
            let loc = parser.current_source_location();
40
243
            let url = parser.expect_url()?;
41
            let node_id =
42
242
                NodeId::parse(&url).map_err(|e| loc.new_custom_error(ValueErrorKind::from(e)))?;
43

            
44
240
            Ok(Iri::Resource(Box::new(node_id)))
45
241
        }
46
2045
    }
47
}
48

            
49
#[cfg(test)]
50
mod tests {
51
    use super::*;
52

            
53
    #[test]
54
2
    fn parses_none() {
55
2
        assert_eq!(Iri::parse_str("none").unwrap(), Iri::None);
56
2
    }
57

            
58
    #[test]
59
2
    fn parses_url() {
60
2
        assert_eq!(
61
1
            Iri::parse_str("url(#bar)").unwrap(),
62
1
            Iri::Resource(Box::new(NodeId::Internal("bar".to_string())))
63
        );
64

            
65
2
        assert_eq!(
66
1
            Iri::parse_str("url(foo#bar)").unwrap(),
67
1
            Iri::Resource(Box::new(NodeId::External(
68
1
                "foo".to_string(),
69
1
                "bar".to_string()
70
            )))
71
        );
72

            
73
        // be permissive if the closing ) is missing
74
2
        assert_eq!(
75
1
            Iri::parse_str("url(#bar").unwrap(),
76
1
            Iri::Resource(Box::new(NodeId::Internal("bar".to_string())))
77
        );
78
2
        assert_eq!(
79
1
            Iri::parse_str("url(foo#bar").unwrap(),
80
1
            Iri::Resource(Box::new(NodeId::External(
81
1
                "foo".to_string(),
82
1
                "bar".to_string()
83
            )))
84
        );
85

            
86
1
        assert!(Iri::parse_str("").is_err());
87
1
        assert!(Iri::parse_str("foo").is_err());
88
1
        assert!(Iri::parse_str("url(foo)bar").is_err());
89
2
    }
90
}