use crate::{Error, Xot};
use super::CreateName;
use super::{reference::NameStrInfo, RefName};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct OwnedName {
local_name_str: String,
namespace_str: String,
prefix_str: String,
}
impl std::hash::Hash for OwnedName {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.local_name_str.hash(state);
self.namespace_str.hash(state);
}
}
impl PartialEq for OwnedName {
fn eq(&self, other: &Self) -> bool {
self.local_name_str == other.local_name_str && self.namespace_str == other.namespace_str
}
}
impl Eq for OwnedName {}
impl NameStrInfo for OwnedName {
fn local_name(&self) -> &str {
&self.local_name_str
}
fn namespace(&self) -> &str {
&self.namespace_str
}
fn prefix(&self) -> &str {
&self.prefix_str
}
}
impl OwnedName {
pub fn new(local_name: String, namespace: String, prefix: String) -> Self {
Self {
local_name_str: local_name,
namespace_str: namespace,
prefix_str: prefix,
}
}
pub fn name(local_name: &str) -> Self {
Self {
local_name_str: local_name.to_string(),
namespace_str: String::new(),
prefix_str: String::new(),
}
}
pub fn namespaced(
local_name: String,
namespace: String,
prefix_lookup: impl Fn(&str) -> Option<String>,
) -> Result<Self, Error> {
let prefix =
prefix_lookup(&namespace).ok_or_else(|| Error::MissingPrefix(namespace.clone()))?;
Ok(Self {
local_name_str: local_name,
namespace_str: namespace,
prefix_str: prefix,
})
}
pub fn prefixed(
prefix: &str,
local_name: &str,
lookup_namespace: impl Fn(&str) -> Option<String>,
) -> Result<Self, Error> {
let namespace =
lookup_namespace(prefix).ok_or_else(|| Error::UnknownPrefix(prefix.to_string()))?;
Ok(Self {
local_name_str: local_name.to_string(),
namespace_str: namespace,
prefix_str: prefix.to_string(),
})
}
pub fn parse_full_name(
full_name: &str,
lookup_namespace: impl Fn(&str) -> Option<String>,
) -> Result<Self, Error> {
let (prefix, local_name) = parse_full_name(full_name);
Self::prefixed(prefix, local_name, lookup_namespace)
}
pub fn with_suffix(self) -> Self {
let mut local_name = self.local_name_str;
local_name.push('*');
Self {
local_name_str: local_name,
namespace_str: self.namespace_str,
prefix_str: self.prefix_str,
}
}
pub fn with_default_namespace(self, namespace: &str) -> Self {
if !self.prefix_str.is_empty() || !self.namespace_str.is_empty() {
return self;
}
Self {
local_name_str: self.local_name_str,
namespace_str: namespace.to_string(),
prefix_str: self.prefix_str,
}
}
pub fn in_default_namespace(&self) -> bool {
!self.namespace_str.is_empty() && self.prefix_str.is_empty()
}
pub fn to_ref<'a>(&self, xot: &'a mut Xot) -> RefName<'a> {
let prefix_id = xot.add_prefix(&self.prefix_str);
let namespace_id = xot.add_namespace(&self.namespace_str);
let name_id = xot.add_name_ns(&self.local_name_str, namespace_id);
RefName::new(xot, name_id, prefix_id)
}
pub fn maybe_to_ref<'a>(&self, xot: &'a Xot) -> Option<RefName<'a>> {
let prefix_id = xot.prefix(&self.prefix_str).unwrap_or(xot.empty_prefix());
let namespace_id = xot.namespace(&self.namespace_str)?;
let name_id = xot.name_ns(&self.local_name_str, namespace_id)?;
Some(RefName::new(xot, name_id, prefix_id))
}
pub fn to_create(&self, xot: &mut Xot) -> CreateName {
let namespace_id = xot.add_namespace(&self.namespace_str);
let name_id = xot.add_name_ns(&self.local_name_str, namespace_id);
CreateName::new(name_id)
}
}
pub(crate) fn parse_full_name(full_name: &str) -> (&str, &str) {
match full_name.find(':') {
Some(pos) => {
let (prefix, local_name) = full_name.split_at(pos);
(prefix, &local_name[1..])
}
None => ("", full_name),
}
}