use std::borrow::{Borrow, Cow};
use std::collections::HashMap;
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::hash::{Hash, Hasher};
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use quick_xml::name::{Namespace, PrefixDeclaration};
use crate::misc::format_utf8_slice;
#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct Namespaces<'a>(pub HashMap<Key<'a>, Value<'a>>);
impl<'a> Namespaces<'a> {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn into_shared(self) -> NamespacesShared<'a> {
NamespacesShared::new(self)
}
}
impl<'a> Deref for Namespaces<'a> {
type Target = HashMap<Key<'a>, Value<'a>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Namespaces<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl Hash for Namespaces<'_> {
fn hash<H: Hasher>(&self, state: &mut H) {
let mut items = self.iter().collect::<Vec<_>>();
items.sort_by(|a, b| a.0.cmp(b.0));
for (k, v) in items {
k.hash(state);
v.hash(state);
}
}
}
impl<'a, K, V> FromIterator<(K, V)> for Namespaces<'a>
where
K: Into<Cow<'a, [u8]>>,
V: Into<Cow<'a, [u8]>>,
{
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
let mut namespaces = Namespaces::default();
for (k, v) in iter {
let key = Key(k.into());
let value = Value(v.into());
namespaces.insert(key, value);
}
namespaces
}
}
#[derive(Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub struct Key<'a>(pub Cow<'a, [u8]>);
impl Key<'_> {
#[must_use]
pub fn prefix_decl(&self) -> PrefixDeclaration<'_> {
if self.0.is_empty() {
PrefixDeclaration::Default
} else {
PrefixDeclaration::Named(&self.0)
}
}
}
impl From<Vec<u8>> for Key<'static> {
fn from(value: Vec<u8>) -> Self {
Self(Cow::Owned(value))
}
}
impl<'a> From<&'a [u8]> for Key<'a> {
fn from(value: &'a [u8]) -> Self {
Self(Cow::Borrowed(value))
}
}
impl<'a> From<Cow<'a, [u8]>> for Key<'a> {
fn from(value: Cow<'a, [u8]>) -> Self {
Self(value)
}
}
impl Deref for Key<'_> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Debug for Key<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "Key(\"")?;
format_utf8_slice(&self.0, f)?;
write!(f, "\")")?;
Ok(())
}
}
impl AsRef<[u8]> for Key<'_> {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl Borrow<[u8]> for Key<'_> {
fn borrow(&self) -> &[u8] {
&self.0
}
}
#[derive(Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub struct Value<'a>(pub Cow<'a, [u8]>);
impl Value<'_> {
#[inline]
#[must_use]
pub fn namespace(&self) -> Namespace<'_> {
Namespace(&self.0)
}
}
impl Debug for Value<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "Value(\"")?;
format_utf8_slice(&self.0, f)?;
write!(f, "\")")?;
Ok(())
}
}
impl Deref for Value<'_> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<[u8]> for Value<'_> {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl Borrow<[u8]> for Value<'_> {
fn borrow(&self) -> &[u8] {
&self.0
}
}
impl From<Vec<u8>> for Value<'static> {
fn from(value: Vec<u8>) -> Self {
Self(Cow::Owned(value))
}
}
impl<'a> From<&'a [u8]> for Value<'a> {
fn from(value: &'a [u8]) -> Self {
Self(Cow::Borrowed(value))
}
}
impl<'a> From<Cow<'a, [u8]>> for Value<'a> {
fn from(value: Cow<'a, [u8]>) -> Self {
Self(value)
}
}
#[derive(Default, Clone, Hash)]
pub struct NamespacesShared<'a>(pub Arc<Namespaces<'a>>);
impl<'a> NamespacesShared<'a> {
#[must_use]
pub fn new(namespaces: Namespaces<'a>) -> Self {
Self(Arc::new(namespaces))
}
#[must_use]
pub fn to_owned(&self) -> Namespaces<'a> {
(*self.0).clone()
}
#[must_use]
pub fn into_owned(self) -> Namespaces<'a> {
Arc::try_unwrap(self.0).unwrap_or_else(|x| (*x).clone())
}
}
impl<'a> Deref for NamespacesShared<'a> {
type Target = Namespaces<'a>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for NamespacesShared<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
Arc::make_mut(&mut self.0)
}
}
impl Debug for NamespacesShared<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
self.0.fmt(f)
}
}
impl Eq for NamespacesShared<'_> {}
impl PartialEq for NamespacesShared<'_> {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.0, &other.0) || self.0.eq(&other.0)
}
}