use core::hash::{BuildHasher, Hash};
use core::ops::{Index, IndexMut};
#[cfg(feature = "std")]
use std::collections::hash_map::RandomState;
use indexmap::{Equivalent, IndexMap};
use itertools::zip_eq;
#[cfg(feature = "std")]
#[derive(Clone, Debug)]
pub struct OrderedHashMap<Key, Value, BH = RandomState>(IndexMap<Key, Value, BH>);
#[cfg(not(feature = "std"))]
#[derive(Clone, Debug)]
pub struct OrderedHashMap<Key, Value, BH = hashbrown::hash_map::DefaultHashBuilder>(
IndexMap<Key, Value, BH>,
);
impl<Key, Value, BH: Default> Default for OrderedHashMap<Key, Value, BH> {
#[cfg(feature = "std")]
fn default() -> Self {
Self(Default::default())
}
#[cfg(not(feature = "std"))]
fn default() -> Self {
Self(IndexMap::with_hasher(Default::default()))
}
}
impl<Key, Value, BH> OrderedHashMap<Key, Value, BH> {
pub fn iter(&self) -> indexmap::map::Iter<'_, Key, Value> {
self.0.iter()
}
pub fn iter_mut(&mut self) -> indexmap::map::IterMut<'_, Key, Value> {
self.0.iter_mut()
}
pub fn keys(&self) -> indexmap::map::Keys<'_, Key, Value> {
self.0.keys()
}
pub fn into_keys(self) -> indexmap::map::IntoKeys<Key, Value> {
self.0.into_keys()
}
pub fn values(&self) -> indexmap::map::Values<'_, Key, Value> {
self.0.values()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn clear(&mut self) {
self.0.clear()
}
pub fn shift_remove_index(&mut self, index: usize) -> Option<(Key, Value)> {
self.0.shift_remove_index(index)
}
}
impl<Key: Eq + Hash, Value, BH: BuildHasher> OrderedHashMap<Key, Value, BH> {
pub fn get<Q: ?Sized + Hash + Equivalent<Key>>(&self, key: &Q) -> Option<&Value> {
self.0.get(key)
}
pub fn get_mut<Q: ?Sized + Hash + Equivalent<Key>>(&mut self, key: &Q) -> Option<&mut Value> {
self.0.get_mut(key)
}
pub fn entry(&mut self, key: Key) -> Entry<'_, Key, Value> {
self.0.entry(key)
}
pub fn insert(&mut self, key: Key, value: Value) -> Option<Value> {
self.0.insert(key, value)
}
pub fn extend<I: IntoIterator<Item = (Key, Value)>>(&mut self, iter: I) {
self.0.extend(iter)
}
pub fn contains_key<Q: ?Sized + Hash + Equivalent<Key>>(&self, key: &Q) -> bool {
self.0.contains_key(key)
}
pub fn shift_remove<Q: ?Sized + Hash + Equivalent<Key>>(&mut self, key: &Q) -> Option<Value> {
self.0.shift_remove(key)
}
pub fn swap_remove<Q: ?Sized + Hash + Equivalent<Key>>(&mut self, key: &Q) -> Option<Value> {
self.0.swap_remove(key)
}
pub fn retain(&mut self, keep: impl FnMut(&Key, &mut Value) -> bool) {
self.0.retain(keep);
}
pub fn eq_unordered(&self, other: &Self) -> bool
where
Value: Eq,
{
if self.0.len() != other.0.len() {
return false;
};
self.0.iter().all(|(k, v)| other.0.get(k) == Some(v))
}
}
pub type Entry<'a, Key, Value> = indexmap::map::Entry<'a, Key, Value>;
impl<Key, Value, BH> IntoIterator for OrderedHashMap<Key, Value, BH> {
type Item = (Key, Value);
type IntoIter = indexmap::map::IntoIter<Key, Value>;
fn into_iter(self) -> Self::IntoIter {
let OrderedHashMap(inner) = self;
inner.into_iter()
}
}
impl<Key, Value, Q: ?Sized, BH> Index<&Q> for OrderedHashMap<Key, Value, BH>
where
Q: Hash + Equivalent<Key>,
Key: Hash + Eq,
BH: BuildHasher,
{
type Output = Value;
fn index(&self, index: &Q) -> &Self::Output {
self.0.index(index)
}
}
impl<Key, Value, Q: ?Sized, BH> IndexMut<&Q> for OrderedHashMap<Key, Value, BH>
where
Q: Hash + Equivalent<Key>,
Key: Hash + Eq,
BH: BuildHasher,
{
fn index_mut(&mut self, index: &Q) -> &mut Value {
self.0.index_mut(index)
}
}
impl<Key: Eq, Value: Eq, BH> PartialEq for OrderedHashMap<Key, Value, BH> {
fn eq(&self, other: &Self) -> bool {
if self.0.len() != other.0.len() {
return false;
};
zip_eq(self.0.iter(), other.0.iter()).all(|(a, b)| a == b)
}
}
impl<Key: Hash + Eq, Value: Eq, BH: BuildHasher> Eq for OrderedHashMap<Key, Value, BH> {}
impl<Key: Hash + Eq, Value, BH: BuildHasher + Default> FromIterator<(Key, Value)>
for OrderedHashMap<Key, Value, BH>
{
fn from_iter<T: IntoIterator<Item = (Key, Value)>>(iter: T) -> Self {
Self(iter.into_iter().collect())
}
}
impl<Key: Hash + Eq, Value, BH: BuildHasher + Default, const N: usize> From<[(Key, Value); N]>
for OrderedHashMap<Key, Value, BH>
{
fn from(init_map: [(Key, Value); N]) -> Self {
Self(IndexMap::from_iter(init_map))
}
}
#[cfg(feature = "serde")]
mod impl_serde {
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use itertools::Itertools;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::*;
impl<K: Hash + Eq + Serialize, V: Serialize, BH: BuildHasher> Serialize
for OrderedHashMap<K, V, BH>
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}
impl<'de, K: Hash + Eq + Deserialize<'de>, V: Deserialize<'de>, BH: BuildHasher + Default>
Deserialize<'de> for OrderedHashMap<K, V, BH>
{
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
IndexMap::<K, V, BH>::deserialize(deserializer).map(|s| OrderedHashMap(s))
}
}
pub fn serialize_ordered_hashmap_vec<'de, K, V, BH, S>(
v: &OrderedHashMap<K, V, BH>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
K: Serialize + Deserialize<'de> + Hash + Eq,
V: Serialize + Deserialize<'de>,
{
v.iter().collect_vec().serialize(serializer)
}
pub fn deserialize_ordered_hashmap_vec<'de, K, V, BH: BuildHasher + Default, D>(
deserializer: D,
) -> Result<OrderedHashMap<K, V, BH>, D::Error>
where
D: Deserializer<'de>,
K: Serialize + Deserialize<'de> + Hash + Eq,
V: Serialize + Deserialize<'de>,
{
Ok(Vec::<(K, V)>::deserialize(deserializer)?.into_iter().collect())
}
}
#[cfg(feature = "serde")]
pub use impl_serde::*;