1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use super::mathml;
use super::xml;
use std::collections::HashMap;

/*
struct Prefix {
    prefix: String,
}
impl Prefix {
    fn new(prefix: String) -> Prefix {
        Prefix { prefix }
    }
}
*/
// https://www.w3.org/TR/xml-names/
// The xmlns prefix is bound to  http://www.w3.org/2000/xmlns/

#[derive(Debug, PartialEq, Eq)]
pub struct Namespace {
    pub prefix: &'static str,
    pub uri: &'static str,
}
/*
impl PartialEq for Namespace {
    fn eq(&self, other: &Namespace) -> bool {
        self.uri == other.uri
    }
}
impl Eq for Namespace {}
 */
const XMLNS_NAMESPACE_PREFIX: &str = "xmlns";
const XMLNS_NAMESPACE: Namespace = Namespace {
    prefix: XMLNS_NAMESPACE_PREFIX,
    uri: "http://www.w3.org/2000/xmlns/",
};

const XHTML_NAMESPACE_PREFIX: &str = "xhtml";
const XHTML_NAMESPACE: Namespace = Namespace {
    prefix: XHTML_NAMESPACE_PREFIX,
    uri: "http://www.w3.org/1999/xhtml",
};

const SVG_NAMESPACE_PREFIX: &str = "svg";
const SVG_NAMESPACE: Namespace = Namespace {
    prefix: SVG_NAMESPACE_PREFIX,
    uri: "http://www.w3.org/2000/svg",
};

const U_NAMESPACE_PREFIX: &str = "u";
const U_NAMESPACE: Namespace = Namespace {
    prefix: U_NAMESPACE_PREFIX,
    uri: "http://danieljrmay.com/U",
};

pub struct NamespaceRegistry {
    custom_namespaces: HashMap<&'static str, Namespace>,
}
impl NamespaceRegistry {
    pub fn new() -> NamespaceRegistry {
        NamespaceRegistry {
            custom_namespaces: HashMap::new(),
        }
    }

    pub fn get(&self, prefix: &str) -> Option<&Namespace> {
        match prefix.as_ref() {
            XMLNS_NAMESPACE_PREFIX => Some(&XMLNS_NAMESPACE),
            xml::NAMESPACE_PREFIX => Some(&xml::NAMESPACE),
            XHTML_NAMESPACE_PREFIX => Some(&XHTML_NAMESPACE),
            mathml::NAMESPACE_PREFIX => Some(&mathml::NAMESPACE),
            SVG_NAMESPACE_PREFIX => Some(&SVG_NAMESPACE),
            U_NAMESPACE_PREFIX => Some(&U_NAMESPACE),
            _ => self.custom_namespaces.get(prefix),
        }
    }

    pub fn add(&mut self, prefix: &'static str, uri: &'static str) {
        if self.custom_namespaces.contains_key(prefix) {
            panic!("Namespace prefix already exists.");
        }

        for v in self.custom_namespaces.values() {
            if v.uri == uri {
                panic!("Namespace uri already exists.");
            }
        }

        let namespace = Namespace {
            prefix: prefix,
            uri: uri,
        };
        self.custom_namespaces.insert(prefix, namespace);
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn predefined_namspaces() {
        let nsr: NamespaceRegistry = NamespaceRegistry::new();

        let xml_ns = nsr.get("xml").unwrap();
        assert_eq!(xml_ns.prefix, "xml");
        assert_eq!(xml_ns.uri, "http://www.w3.org/XML/1998/namespace");

        let xhtml_ns = nsr.get("xhtml").unwrap();
        assert_eq!(xhtml_ns.prefix, "xhtml");
        assert_eq!(xhtml_ns.uri, "http://www.w3.org/1999/xhtml");

        let mathml_ns = nsr.get("mathml").unwrap();
        assert_eq!(mathml_ns.prefix, "mathml");
        assert_eq!(mathml_ns.uri, "http://www.w3.org/1998/Math/MathML");

        let svg_ns = nsr.get("svg").unwrap();
        assert_eq!(svg_ns.prefix, "svg");
        assert_eq!(svg_ns.uri, "http://www.w3.org/2000/svg");

        let u_ns = nsr.get("u").unwrap();
        assert_eq!(u_ns.prefix, "u");
        assert_eq!(u_ns.uri, "http://danieljrmay.com/U");
    }
}