use alloc::collections::{btree_map, BTreeMap};
use alloc::string::String;
use core::borrow::Borrow;
use core::fmt;
use core::hash::Hash;
use core::iter::FromIterator;
use crate::{Namespace, NcName};
#[derive(Clone, Default)]
pub struct XmlMap<V> {
inner: BTreeMap<Namespace<'static>, BTreeMap<NcName, V>>,
}
pub type AttrMap = XmlMap<String>;
impl<V> XmlMap<V> {
#[inline(always)]
pub fn new() -> Self {
Self {
inner: BTreeMap::new(),
}
}
#[inline(always)]
pub fn clear(&mut self) {
self.inner.clear()
}
#[inline(always)]
pub fn get<'a, NS: Ord + Hash + Eq + ?Sized, N: Ord + Hash + Eq + ?Sized>(
&'a self,
namespace: &NS,
name: &N,
) -> Option<&'a V>
where
Namespace<'static>: Borrow<NS>,
NcName: Borrow<N>,
{
self.inner.get(namespace).and_then(|inner| inner.get(name))
}
#[inline(always)]
pub fn contains_key<NS: Ord + Hash + Eq + ?Sized, N: Ord + Hash + Eq + ?Sized>(
&self,
namespace: &NS,
name: &N,
) -> bool
where
Namespace<'static>: Borrow<NS>,
NcName: Borrow<N>,
{
self.inner
.get(namespace)
.map(|inner| inner.contains_key(name))
.unwrap_or(false)
}
pub fn get_mut<'a, NS: Ord + Hash + Eq + ?Sized, N: Ord + Hash + Eq + ?Sized>(
&'a mut self,
namespace: &NS,
name: &N,
) -> Option<&'a mut V>
where
Namespace<'static>: Borrow<NS>,
NcName: Borrow<N>,
{
self.inner
.get_mut(namespace)
.and_then(|inner| inner.get_mut(name))
}
pub fn insert(&mut self, namespace: Namespace<'static>, name: NcName, value: V) -> Option<V> {
match self.inner.entry(namespace) {
btree_map::Entry::Occupied(mut o) => o.get_mut().insert(name, value),
btree_map::Entry::Vacant(v) => v.insert(BTreeMap::new()).insert(name, value),
}
}
#[inline(always)]
pub fn remove<NS: Ord + Hash + Eq + ?Sized, N: Ord + Hash + Eq + ?Sized>(
&mut self,
namespace: &NS,
name: &N,
) -> Option<V>
where
Namespace<'static>: Borrow<NS>,
NcName: Borrow<N>,
{
match self.inner.get_mut(namespace) {
None => None,
Some(inner) => {
let result = inner.remove(name);
if inner.is_empty() {
self.inner.remove(namespace);
}
result
}
}
}
#[inline(always)]
pub fn retain<F: FnMut(&Namespace, &NcName, &mut V) -> bool>(&mut self, mut f: F) {
self.inner.retain(|ns, inner| {
inner.retain(|name, value| f(ns, name, value));
!inner.is_empty()
})
}
#[inline(always)]
pub fn into_names(self) -> IntoNames<V> {
IntoNames::new(self.inner.into_iter())
}
#[inline(always)]
pub fn into_values(self) -> IntoValues<V> {
IntoValues::new(self.inner.into_values())
}
#[inline(always)]
pub fn iter(&self) -> Iter<'_, V> {
self.into_iter()
}
#[inline(always)]
pub fn iter_mut(&mut self) -> IterMut<'_, V> {
self.into_iter()
}
#[inline(always)]
pub fn names(&self) -> Names<'_, V> {
Names::new(self.inner.iter())
}
#[inline(always)]
pub fn values(&self) -> Values<'_, V> {
Values::new(self.inner.values())
}
#[inline(always)]
pub fn values_mut(&mut self) -> ValuesMut<'_, V> {
ValuesMut::new(self.inner.values_mut())
}
#[inline(always)]
pub fn len(&self) -> usize {
self.inner.values().map(|x| x.len()).sum::<usize>()
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty() || self.inner.values().all(|x| x.is_empty())
}
pub fn entry(&mut self, namespace: Namespace<'static>, name: NcName) -> Entry<'_, V> {
match self.inner.entry(namespace) {
btree_map::Entry::Vacant(entry) => {
Entry::Vacant(VacantEntry(VacantInner::OuterVacant { entry, name }))
}
btree_map::Entry::Occupied(entry) => {
let namespace = entry.key().clone();
match entry.into_mut().entry(name) {
btree_map::Entry::Vacant(entry) => {
Entry::Vacant(VacantEntry(VacantInner::InnerVacant { namespace, entry }))
}
btree_map::Entry::Occupied(entry) => {
Entry::Occupied(OccupiedEntry { namespace, entry })
}
}
}
}
}
}
impl<V: fmt::Debug> fmt::Debug for XmlMap<V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()
}
}
impl<V: PartialEq> PartialEq for XmlMap<V> {
fn eq(&self, other: &XmlMap<V>) -> bool {
if self.len() != other.len() {
return false;
}
for (lhs, rhs) in self.iter().zip(other.iter()) {
if lhs != rhs {
return false;
}
}
true
}
}
impl<V: Eq> Eq for XmlMap<V> {}
pub struct OccupiedEntry<'a, V> {
namespace: Namespace<'static>,
entry: btree_map::OccupiedEntry<'a, NcName, V>,
}
impl<'a, V> OccupiedEntry<'a, V> {
#[inline(always)]
pub fn get(&self) -> &V {
self.entry.get()
}
#[inline(always)]
pub fn get_mut(&mut self) -> &mut V {
self.entry.get_mut()
}
#[inline(always)]
pub fn insert(&mut self, value: V) -> V {
self.entry.insert(value)
}
#[inline(always)]
pub fn into_mut(self) -> &'a mut V {
self.entry.into_mut()
}
#[inline(always)]
pub fn key(&self) -> (&Namespace<'static>, &NcName) {
(&self.namespace, self.entry.key())
}
#[inline(always)]
pub fn remove(self) -> V {
self.entry.remove()
}
#[inline(always)]
pub fn remove_entry(self) -> ((Namespace<'static>, NcName), V) {
let (name, value) = self.entry.remove_entry();
((self.namespace, name), value)
}
}
enum VacantInner<'a, V> {
OuterVacant {
entry: btree_map::VacantEntry<'a, Namespace<'static>, BTreeMap<NcName, V>>,
name: NcName,
},
InnerVacant {
namespace: Namespace<'static>,
entry: btree_map::VacantEntry<'a, NcName, V>,
},
}
pub struct VacantEntry<'a, V>(VacantInner<'a, V>);
impl<'a, V> VacantEntry<'a, V> {
pub fn key(&self) -> (&Namespace<'static>, &NcName) {
match self.0 {
VacantInner::OuterVacant {
ref entry,
ref name,
} => (entry.key(), name),
VacantInner::InnerVacant {
ref namespace,
ref entry,
} => (namespace, entry.key()),
}
}
pub fn into_key(self) -> (Namespace<'static>, NcName) {
match self.0 {
VacantInner::OuterVacant { entry, name } => (entry.into_key(), name),
VacantInner::InnerVacant { namespace, entry } => (namespace, entry.into_key()),
}
}
pub fn insert(self, value: V) -> &'a mut V {
match self.0 {
VacantInner::OuterVacant { entry, name } => {
let map = entry.insert(BTreeMap::new());
match map.entry(name) {
btree_map::Entry::Vacant(v) => v.insert(value),
_ => unreachable!(),
}
}
VacantInner::InnerVacant { entry, .. } => entry.insert(value),
}
}
}
pub enum Entry<'a, V> {
Vacant(VacantEntry<'a, V>),
Occupied(OccupiedEntry<'a, V>),
}
pub struct IntoIter<V> {
outer: btree_map::IntoIter<Namespace<'static>, BTreeMap<NcName, V>>,
inner: Option<(Namespace<'static>, btree_map::IntoIter<NcName, V>)>,
}
impl<V> IntoIter<V> {
fn new(mut outer: btree_map::IntoIter<Namespace<'static>, BTreeMap<NcName, V>>) -> Self {
let inner = Self::fix_inner(outer.next());
Self { outer, inner }
}
fn fix_inner(
inner: Option<(Namespace<'static>, BTreeMap<NcName, V>)>,
) -> Option<(Namespace<'static>, btree_map::IntoIter<NcName, V>)> {
match inner {
Some((ns, map)) => Some((ns, map.into_iter())),
None => None,
}
}
}
impl<V> Iterator for IntoIter<V> {
type Item = ((Namespace<'static>, NcName), V);
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some((namespace, inner)) = self.inner.as_mut() {
if let Some((name, value)) = inner.next() {
return Some(((namespace.clone(), name), value));
}
self.inner = Self::fix_inner(self.outer.next());
} else {
return None;
}
}
}
}
impl<V> IntoIterator for XmlMap<V> {
type IntoIter = IntoIter<V>;
type Item = ((Namespace<'static>, NcName), V);
fn into_iter(self) -> Self::IntoIter {
IntoIter::new(self.inner.into_iter())
}
}
pub struct Iter<'a, V> {
outer: btree_map::Iter<'a, Namespace<'static>, BTreeMap<NcName, V>>,
inner: Option<(&'a Namespace<'static>, btree_map::Iter<'a, NcName, V>)>,
}
impl<'a, V> Iter<'a, V> {
fn new(mut outer: btree_map::Iter<'a, Namespace<'static>, BTreeMap<NcName, V>>) -> Self {
let inner = outer.next().map(|(ns, inner)| (ns, inner.iter()));
Self { outer, inner }
}
}
impl<'a, V> Iterator for Iter<'a, V> {
type Item = ((&'a Namespace<'static>, &'a NcName), &'a V);
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some((namespace, inner)) = self.inner.as_mut() {
if let Some((name, value)) = inner.next() {
return Some(((namespace, name), value));
}
self.inner = self.outer.next().map(|(ns, inner)| (ns, inner.iter()));
} else {
return None;
}
}
}
}
impl<'a, V> IntoIterator for &'a XmlMap<V> {
type IntoIter = Iter<'a, V>;
type Item = ((&'a Namespace<'static>, &'a NcName), &'a V);
fn into_iter(self) -> Self::IntoIter {
Iter::new(self.inner.iter())
}
}
pub struct IterMut<'a, V> {
outer: btree_map::IterMut<'a, Namespace<'static>, BTreeMap<NcName, V>>,
inner: Option<(&'a Namespace<'static>, btree_map::IterMut<'a, NcName, V>)>,
}
impl<'a, V> IterMut<'a, V> {
fn new(mut outer: btree_map::IterMut<'a, Namespace<'static>, BTreeMap<NcName, V>>) -> Self {
let inner = outer.next().map(|(ns, inner)| (ns, inner.iter_mut()));
Self { outer, inner }
}
}
impl<'a, V> Iterator for IterMut<'a, V> {
type Item = ((&'a Namespace<'static>, &'a NcName), &'a mut V);
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some((namespace, inner)) = self.inner.as_mut() {
if let Some((name, value)) = inner.next() {
return Some(((namespace, name), value));
}
self.inner = self.outer.next().map(|(ns, inner)| (ns, inner.iter_mut()));
} else {
return None;
}
}
}
}
impl<'a, V> IntoIterator for &'a mut XmlMap<V> {
type IntoIter = IterMut<'a, V>;
type Item = ((&'a Namespace<'static>, &'a NcName), &'a mut V);
fn into_iter(self) -> Self::IntoIter {
IterMut::new(self.inner.iter_mut())
}
}
pub struct Names<'a, V> {
outer: btree_map::Iter<'a, Namespace<'static>, BTreeMap<NcName, V>>,
inner: Option<(&'a Namespace<'static>, btree_map::Keys<'a, NcName, V>)>,
}
impl<'a, V> Names<'a, V> {
fn new(mut outer: btree_map::Iter<'a, Namespace<'static>, BTreeMap<NcName, V>>) -> Self {
let inner = outer.next().map(|(ns, inner)| (ns, inner.keys()));
Self { outer, inner }
}
}
impl<'a, V> Iterator for Names<'a, V> {
type Item = (&'a Namespace<'static>, &'a NcName);
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some((namespace, inner)) = self.inner.as_mut() {
if let Some(name) = inner.next() {
return Some((namespace, name));
}
self.inner = self.outer.next().map(|(ns, inner)| (ns, inner.keys()));
} else {
return None;
}
}
}
}
pub struct Values<'a, V> {
outer: btree_map::Values<'a, Namespace<'static>, BTreeMap<NcName, V>>,
inner: Option<btree_map::Values<'a, NcName, V>>,
}
impl<'a, V> Values<'a, V> {
fn new(mut outer: btree_map::Values<'a, Namespace<'static>, BTreeMap<NcName, V>>) -> Self {
let inner = outer.next().map(|inner| inner.values());
Self { outer, inner }
}
}
impl<'a, V> Iterator for Values<'a, V> {
type Item = &'a V;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(inner) = self.inner.as_mut() {
if let Some(value) = inner.next() {
return Some(value);
}
self.inner = self.outer.next().map(|inner| inner.values());
} else {
return None;
}
}
}
}
pub struct ValuesMut<'a, V> {
outer: btree_map::ValuesMut<'a, Namespace<'static>, BTreeMap<NcName, V>>,
inner: Option<btree_map::ValuesMut<'a, NcName, V>>,
}
impl<'a, V> ValuesMut<'a, V> {
fn new(mut outer: btree_map::ValuesMut<'a, Namespace<'static>, BTreeMap<NcName, V>>) -> Self {
let inner = outer.next().map(|inner| inner.values_mut());
Self { outer, inner }
}
}
impl<'a, V> Iterator for ValuesMut<'a, V> {
type Item = &'a mut V;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(inner) = self.inner.as_mut() {
if let Some(value) = inner.next() {
return Some(value);
}
self.inner = self.outer.next().map(|inner| inner.values_mut());
} else {
return None;
}
}
}
}
pub struct IntoNames<V> {
outer: btree_map::IntoIter<Namespace<'static>, BTreeMap<NcName, V>>,
inner: Option<(Namespace<'static>, btree_map::IntoKeys<NcName, V>)>,
}
impl<V> IntoNames<V> {
fn new(mut outer: btree_map::IntoIter<Namespace<'static>, BTreeMap<NcName, V>>) -> Self {
let inner = Self::fix_inner(outer.next());
Self { outer, inner }
}
fn fix_inner(
inner: Option<(Namespace<'static>, BTreeMap<NcName, V>)>,
) -> Option<(Namespace<'static>, btree_map::IntoKeys<NcName, V>)> {
match inner {
Some((ns, map)) => Some((ns, map.into_keys())),
None => None,
}
}
}
impl<V> Iterator for IntoNames<V> {
type Item = (Namespace<'static>, NcName);
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some((namespace, inner)) = self.inner.as_mut() {
if let Some(name) = inner.next() {
return Some((namespace.clone(), name));
}
self.inner = Self::fix_inner(self.outer.next());
} else {
return None;
}
}
}
}
pub struct IntoValues<V> {
outer: btree_map::IntoValues<Namespace<'static>, BTreeMap<NcName, V>>,
inner: Option<btree_map::IntoValues<NcName, V>>,
}
impl<V> IntoValues<V> {
fn new(mut outer: btree_map::IntoValues<Namespace<'static>, BTreeMap<NcName, V>>) -> Self {
let inner = outer.next().map(|inner| inner.into_values());
Self { outer, inner }
}
}
impl<V> Iterator for IntoValues<V> {
type Item = V;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(inner) = self.inner.as_mut() {
if let Some(value) = inner.next() {
return Some(value);
}
self.inner = self.outer.next().map(|inner| inner.into_values());
} else {
return None;
}
}
}
}
impl<V> FromIterator<(Namespace<'static>, NcName, V)> for XmlMap<V> {
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = (Namespace<'static>, NcName, V)>,
{
let mut result = Self::new();
result.extend(iter);
result
}
}
impl<V> Extend<(Namespace<'static>, NcName, V)> for XmlMap<V> {
fn extend<T>(&mut self, iter: T)
where
T: IntoIterator<Item = (Namespace<'static>, NcName, V)>,
{
for (ns, name, v) in iter {
self.insert(ns, name, v);
}
}
}
impl<V> FromIterator<((Namespace<'static>, NcName), V)> for XmlMap<V> {
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = ((Namespace<'static>, NcName), V)>,
{
let mut result = Self::new();
result.extend(iter);
result
}
}
impl<V> Extend<((Namespace<'static>, NcName), V)> for XmlMap<V> {
fn extend<T>(&mut self, iter: T)
where
T: IntoIterator<Item = ((Namespace<'static>, NcName), V)>,
{
for ((ns, name), v) in iter {
self.insert(ns, name, v);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn xml_map_get_does_not_borrow_namespace_or_name() {
fn foo<'a>(map: &'a AttrMap, ns: Namespace<'static>, name: NcName) -> Option<&'a String> {
map.get(&ns, &name)
}
let map = AttrMap::new();
foo(&map, Namespace::NONE, NcName::try_from("foo").unwrap());
}
#[test]
fn xml_map_get_mut_does_not_borrow_namespace_or_name() {
fn foo<'a>(
map: &'a mut AttrMap,
ns: Namespace<'static>,
name: NcName,
) -> Option<&'a mut String> {
map.get_mut(&ns, &name)
}
let mut map = AttrMap::new();
foo(&mut map, Namespace::NONE, NcName::try_from("foo").unwrap());
}
}