1use crate::{Error, Xot};
2
3use super::CreateName;
4use super::{reference::NameStrInfo, RefName};
5
6#[derive(Debug, Clone)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20pub struct OwnedName {
21 local_name_str: String,
24 namespace_str: String,
26 prefix_str: String,
28}
29
30impl std::hash::Hash for OwnedName {
31 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
32 self.local_name_str.hash(state);
33 self.namespace_str.hash(state);
34 }
35}
36
37impl PartialEq for OwnedName {
38 fn eq(&self, other: &Self) -> bool {
39 self.local_name_str == other.local_name_str && self.namespace_str == other.namespace_str
40 }
41}
42
43impl Eq for OwnedName {}
44
45impl NameStrInfo for OwnedName {
46 fn local_name(&self) -> &str {
47 &self.local_name_str
48 }
49
50 fn namespace(&self) -> &str {
51 &self.namespace_str
52 }
53
54 fn prefix(&self) -> &str {
55 &self.prefix_str
56 }
57}
58
59impl OwnedName {
60 pub fn new(local_name: String, namespace: String, prefix: String) -> Self {
62 Self {
63 local_name_str: local_name,
64 namespace_str: namespace,
65 prefix_str: prefix,
66 }
67 }
68
69 pub fn name(local_name: &str) -> Self {
71 Self {
72 local_name_str: local_name.to_string(),
73 namespace_str: String::new(),
74 prefix_str: String::new(),
75 }
76 }
77
78 pub fn namespaced(
80 local_name: String,
81 namespace: String,
82 prefix_lookup: impl Fn(&str) -> Option<String>,
83 ) -> Result<Self, Error> {
84 let prefix =
85 prefix_lookup(&namespace).ok_or_else(|| Error::MissingPrefix(namespace.clone()))?;
86 Ok(Self {
87 local_name_str: local_name,
88 namespace_str: namespace,
89 prefix_str: prefix,
90 })
91 }
92
93 pub fn prefixed(
95 prefix: &str,
96 local_name: &str,
97 lookup_namespace: impl Fn(&str) -> Option<String>,
98 ) -> Result<Self, Error> {
99 let namespace =
100 lookup_namespace(prefix).ok_or_else(|| Error::UnknownPrefix(prefix.to_string()))?;
101 Ok(Self {
102 local_name_str: local_name.to_string(),
103 namespace_str: namespace,
104 prefix_str: prefix.to_string(),
105 })
106 }
107
108 pub fn parse_full_name(
112 full_name: &str,
113 lookup_namespace: impl Fn(&str) -> Option<String>,
114 ) -> Result<Self, Error> {
115 let (prefix, local_name) = parse_full_name(full_name);
116 Self::prefixed(prefix, local_name, lookup_namespace)
117 }
118
119 pub fn with_suffix(self) -> Self {
123 let mut local_name = self.local_name_str;
124 local_name.push('*');
125 Self {
126 local_name_str: local_name,
127 namespace_str: self.namespace_str,
128 prefix_str: self.prefix_str,
129 }
130 }
131
132 pub fn with_default_namespace(self, namespace: &str) -> Self {
137 if !self.prefix_str.is_empty() || !self.namespace_str.is_empty() {
138 return self;
139 }
140 Self {
141 local_name_str: self.local_name_str,
142 namespace_str: namespace.to_string(),
143 prefix_str: self.prefix_str,
144 }
145 }
146
147 pub fn in_default_namespace(&self) -> bool {
149 !self.namespace_str.is_empty() && self.prefix_str.is_empty()
150 }
151
152 pub fn to_ref<'a>(&self, xot: &'a mut Xot) -> RefName<'a> {
154 let prefix_id = xot.add_prefix(&self.prefix_str);
155 let namespace_id = xot.add_namespace(&self.namespace_str);
156 let name_id = xot.add_name_ns(&self.local_name_str, namespace_id);
157 RefName::new(xot, name_id, prefix_id)
158 }
159
160 pub fn maybe_to_ref<'a>(&self, xot: &'a Xot) -> Option<RefName<'a>> {
173 let prefix_id = xot.prefix(&self.prefix_str).unwrap_or(xot.empty_prefix());
174 let namespace_id = xot.namespace(&self.namespace_str)?;
175 let name_id = xot.name_ns(&self.local_name_str, namespace_id)?;
176 Some(RefName::new(xot, name_id, prefix_id))
177 }
178
179 pub fn to_create(&self, xot: &mut Xot) -> CreateName {
183 let namespace_id = xot.add_namespace(&self.namespace_str);
184 let name_id = xot.add_name_ns(&self.local_name_str, namespace_id);
185 CreateName::new(name_id)
186 }
187}
188
189pub(crate) fn parse_full_name(full_name: &str) -> (&str, &str) {
191 match full_name.find(':') {
192 Some(pos) => {
193 let (prefix, local_name) = full_name.split_at(pos);
194 (prefix, &local_name[1..])
195 }
196 None => ("", full_name),
197 }
198}