1use std::borrow::Cow;
2
3use crate::id::{NameId, NamespaceId, PrefixId};
4use crate::xotdata::Xot;
5use crate::{Error, Node};
6
7use super::owned::OwnedName;
8
9pub trait NameStrInfo {
11 fn local_name(&self) -> &str;
13
14 fn namespace(&self) -> &str;
18
19 fn prefix(&self) -> &str;
21
22 fn full_name(&self) -> Cow<str> {
24 let prefix = self.prefix();
25 if !prefix.is_empty() {
26 Cow::Owned(format!("{}:{}", prefix, self.local_name()))
27 } else {
28 Cow::Borrowed(self.local_name())
29 }
30 }
31}
32
33#[derive(Debug, Clone)]
44pub struct RefName<'a> {
45 xot: &'a Xot,
47 name_id: NameId,
50 prefix_id: PrefixId,
52}
53
54impl std::hash::Hash for RefName<'_> {
55 #[inline]
56 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
57 self.name_id.hash(state);
58 }
59}
60
61impl PartialEq for RefName<'_> {
62 #[inline]
63 fn eq(&self, other: &Self) -> bool {
64 self.name_id == other.name_id
65 }
66}
67
68impl Eq for RefName<'_> {}
69
70impl<'a> NameStrInfo for RefName<'a> {
71 #[inline]
72 fn local_name(&self) -> &'a str {
73 self.xot.local_name_str(self.name_id)
74 }
75
76 #[inline]
77 fn namespace(&self) -> &'a str {
78 self.xot.namespace_str(self.namespace_id())
79 }
80
81 #[inline]
82 fn prefix(&self) -> &'a str {
83 let prefix_id = self.prefix_id();
84 self.xot.prefix_str(prefix_id)
85 }
86}
87
88impl<'a> RefName<'a> {
89 pub(crate) fn new(xot: &'a Xot, name_id: NameId, prefix_id: PrefixId) -> Self {
90 Self {
91 xot,
92 name_id,
93 prefix_id,
94 }
95 }
96
97 #[inline]
99 pub fn name_id(&self) -> NameId {
100 self.name_id
101 }
102
103 #[inline]
105 pub fn namespace_id(&self) -> NamespaceId {
106 self.xot.namespace_for_name(self.name_id)
107 }
108
109 #[inline]
111 pub fn prefix_id(&self) -> PrefixId {
112 self.prefix_id
113 }
114
115 pub(crate) fn from_node(xot: &'a Xot, node: Node, name_id: NameId) -> Result<Self, Error> {
116 let namespace_id = xot.namespace_for_name(name_id);
117 let prefix_id = if namespace_id != xot.no_namespace() {
118 xot.prefix_for_namespace(node, namespace_id)
119 .ok_or_else(|| Error::MissingPrefix(xot.namespace_str(namespace_id).to_string()))?
120 } else {
121 xot.empty_prefix()
122 };
123 Ok(Self::new(xot, name_id, prefix_id))
124 }
125
126 pub fn to_owned(&self) -> OwnedName {
131 OwnedName::new(
132 self.local_name().to_string(),
133 self.namespace().to_string(),
134 self.prefix().to_string(),
135 )
136 }
137
138 pub fn has_unprefixed_namespace(&self) -> bool {
140 self.namespace_id() != self.xot.no_namespace()
141 && self.xot.empty_prefix() == self.prefix_id()
142 }
143}
144
145impl<'a> From<RefName<'a>> for NameId {
146 #[inline]
147 fn from(name: RefName<'a>) -> Self {
148 name.name_id
149 }
150}