Skip to main content

morphir_core/naming/
qname.rs

1use crate::naming::{name::Name, path::Path};
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4
5/// QName represents a Qualified Name (Path + Name).
6#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
7#[serde(try_from = "String", into = "String")]
8pub struct QName {
9    pub module_path: Path,
10    pub local_name: Name,
11}
12
13impl QName {
14    pub fn new(module_path: Path, local_name: Name) -> Self {
15        Self {
16            module_path,
17            local_name,
18        }
19    }
20
21    pub fn parse(s: &str) -> Option<Self> {
22        let parts: Vec<&str> = s.split(':').collect();
23        if parts.len() != 2 {
24            return None;
25        }
26        let path_str = parts[0];
27        let name_str = parts[1];
28        // The empty string does not name anything, so `a:` is not a qualified name.
29        if name_str.is_empty() {
30            return None;
31        }
32        Some(Self::new(Path::new(path_str), Name::from(name_str)))
33    }
34}
35
36impl std::fmt::Display for QName {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        write!(f, "{}:{}", self.module_path, self.local_name)
39    }
40}
41
42impl From<QName> for String {
43    fn from(qname: QName) -> String {
44        qname.to_string()
45    }
46}
47
48impl TryFrom<String> for QName {
49    type Error = String;
50    fn try_from(s: String) -> Result<Self, Self::Error> {
51        QName::parse(&s).ok_or_else(|| format!("Invalid QName string: {}", s))
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[test]
60    fn test_qname_parsing() {
61        let q = QName::parse("foo/bar:Baz").unwrap();
62        assert_eq!(q.module_path.to_string(), "foo/bar");
63        assert_eq!(q.local_name.to_kebab_case(), "baz");
64    }
65
66    #[test]
67    fn test_qname_roundtrip() {
68        let q = QName::parse("mypkg/mymod:MyFunc").unwrap();
69        let s = q.to_string();
70        assert_eq!(s, "mypkg/mymod:my-func");
71    }
72}