use core::fmt;
use std::borrow::Borrow;
use std::collections::HashMap;
use std::hash::BuildHasher;
use std::hash::Hash;
use std::num::NonZeroUsize;
#[cfg(feature = "serde")]
use serde::Deserialize;
#[cfg(feature = "serde")]
use serde::Serialize;
use crate::FromNonEmptyIterator;
use crate::IntoIteratorExt;
use crate::IntoNonEmptyIterator;
use crate::NonEmptyIterator;
use crate::Singleton;
#[macro_export]
macro_rules! nem {
($hk:expr => $hv:expr, $( $xk:expr => $xv:expr ),* $(,)?) => {{
let mut map = $crate::NEMap::new($hk, $hv);
$( map.insert($xk, $xv); )*
map
}};
($hk:expr => $hv:expr) => {
$crate::NEMap::new($hk, $hv)
}
}
#[allow(clippy::unsafe_derive_deserialize)]
#[cfg_attr(
feature = "serde",
derive(Deserialize, Serialize),
serde(bound(
serialize = "K: Eq + Hash + Clone + Serialize, V: Clone + Serialize, S: Clone + BuildHasher",
deserialize = "K: Eq + Hash + Clone + Deserialize<'de>, V: Deserialize<'de>, S: Default + BuildHasher"
)),
serde(into = "HashMap<K, V, S>", try_from = "HashMap<K, V, S>")
)]
#[derive(Clone)]
pub struct NEMap<K, V, S = std::collections::hash_map::RandomState> {
inner: HashMap<K, V, S>,
}
impl<K, V> NEMap<K, V>
where
K: Eq + Hash,
{
#[must_use]
pub fn new(k: K, v: V) -> NEMap<K, V> {
let mut inner = HashMap::new();
inner.insert(k, v);
NEMap { inner }
}
#[must_use]
pub fn with_capacity(capacity: NonZeroUsize, k: K, v: V) -> NEMap<K, V> {
let mut inner = HashMap::with_capacity(capacity.get());
inner.insert(k, v);
NEMap { inner }
}
}
impl<K, V, S> NEMap<K, V, S> {
#[must_use]
pub fn try_from_map(map: HashMap<K, V, S>) -> Option<Self> {
if map.is_empty() {
None
} else {
Some(Self { inner: map })
}
}
#[must_use]
pub fn capacity(&self) -> NonZeroUsize {
unsafe { NonZeroUsize::new_unchecked(self.inner.capacity()) }
}
#[must_use]
pub fn hasher(&self) -> &S {
self.inner.hasher()
}
pub fn iter(&self) -> std::collections::hash_map::Iter<'_, K, V> {
self.inner.iter()
}
pub fn iter_mut(&mut self) -> std::collections::hash_map::IterMut<'_, K, V> {
self.inner.iter_mut()
}
pub fn nonempty_iter(&self) -> Iter<'_, K, V> {
Iter {
iter: self.inner.iter(),
}
}
pub fn nonempty_iter_mut(&mut self) -> IterMut<'_, K, V> {
IterMut {
iter: self.inner.iter_mut(),
}
}
pub fn keys(&self) -> Keys<'_, K, V> {
Keys {
inner: self.inner.keys(),
}
}
#[must_use]
pub fn len(&self) -> NonZeroUsize {
unsafe { NonZeroUsize::new_unchecked(self.inner.len()) }
}
#[deprecated(since = "0.1.0", note = "A NEMap is never empty.")]
#[must_use]
pub const fn is_empty(&self) -> bool {
false
}
pub fn values(&self) -> Values<'_, K, V> {
Values {
inner: self.inner.values(),
}
}
}
impl<K, V, S> NEMap<K, V, S>
where
K: Eq + Hash,
S: BuildHasher,
{
#[must_use]
pub fn contains_key<Q>(&self, k: &Q) -> bool
where
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
{
self.inner.contains_key(k)
}
#[must_use]
pub fn get<Q>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
{
self.inner.get(k)
}
#[must_use]
pub fn get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
where
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
{
self.inner.get_key_value(k)
}
#[must_use]
pub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut V>
where
K: Borrow<Q>,
Q: Eq + Hash + ?Sized,
{
self.inner.get_mut(k)
}
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
self.inner.insert(k, v)
}
pub fn shrink_to_fit(&mut self) {
self.inner.shrink_to_fit();
}
#[must_use]
pub fn with_capacity_and_hasher(
capacity: NonZeroUsize,
hasher: S,
k: K,
v: V,
) -> NEMap<K, V, S> {
let mut inner = HashMap::with_capacity_and_hasher(capacity.get(), hasher);
inner.insert(k, v);
NEMap { inner }
}
#[must_use]
pub fn with_hasher(hasher: S, k: K, v: V) -> NEMap<K, V, S> {
let mut inner = HashMap::with_hasher(hasher);
inner.insert(k, v);
NEMap { inner }
}
}
impl<K, V, S> AsRef<HashMap<K, V, S>> for NEMap<K, V, S> {
fn as_ref(&self) -> &HashMap<K, V, S> {
&self.inner
}
}
impl<K, V, S> AsMut<HashMap<K, V, S>> for NEMap<K, V, S> {
fn as_mut(&mut self) -> &mut HashMap<K, V, S> {
&mut self.inner
}
}
impl<K, V, S> PartialEq for NEMap<K, V, S>
where
K: Eq + Hash,
V: PartialEq,
S: BuildHasher,
{
fn eq(&self, other: &Self) -> bool {
self.inner.eq(&other.inner)
}
}
impl<K, V, S> Eq for NEMap<K, V, S>
where
K: Eq + Hash,
V: Eq,
S: BuildHasher,
{
}
impl<K, V, S> From<NEMap<K, V, S>> for HashMap<K, V, S>
where
K: Eq + Hash,
S: BuildHasher,
{
fn from(m: NEMap<K, V, S>) -> Self {
m.inner
}
}
impl<K, V, S> TryFrom<HashMap<K, V, S>> for NEMap<K, V, S>
where
K: Eq + Hash,
S: BuildHasher + Default,
{
type Error = crate::Error;
fn try_from(map: HashMap<K, V, S>) -> Result<Self, Self::Error> {
map.try_into_nonempty_iter()
.map(NonEmptyIterator::collect)
.ok_or(crate::Error::Empty)
}
}
impl<K, V, S> IntoNonEmptyIterator for NEMap<K, V, S> {
type IntoNEIter = IntoIter<K, V>;
fn into_nonempty_iter(self) -> Self::IntoNEIter {
IntoIter {
iter: self.inner.into_iter(),
}
}
}
impl<'a, K, V, S> IntoNonEmptyIterator for &'a NEMap<K, V, S> {
type IntoNEIter = Iter<'a, K, V>;
fn into_nonempty_iter(self) -> Self::IntoNEIter {
self.nonempty_iter()
}
}
impl<K, V, S> IntoIterator for NEMap<K, V, S> {
type Item = (K, V);
type IntoIter = std::collections::hash_map::IntoIter<K, V>;
fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter()
}
}
impl<'a, K, V, S> IntoIterator for &'a NEMap<K, V, S> {
type Item = (&'a K, &'a V);
type IntoIter = std::collections::hash_map::Iter<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, K, V, S> IntoIterator for &'a mut NEMap<K, V, S> {
type Item = (&'a K, &'a mut V);
type IntoIter = std::collections::hash_map::IterMut<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<K, V, S> FromNonEmptyIterator<(K, V)> for NEMap<K, V, S>
where
K: Eq + Hash,
S: BuildHasher + Default,
{
fn from_nonempty_iter<I>(iter: I) -> Self
where
I: IntoNonEmptyIterator<Item = (K, V)>,
{
NEMap {
inner: iter.into_nonempty_iter().into_iter().collect(),
}
}
}
#[must_use = "non-empty iterators are lazy and do nothing unless consumed"]
pub struct Iter<'a, K: 'a, V: 'a> {
iter: std::collections::hash_map::Iter<'a, K, V>,
}
impl<K, V> NonEmptyIterator for Iter<'_, K, V> {}
impl<'a, K, V> IntoIterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);
type IntoIter = std::collections::hash_map::Iter<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter
}
}
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Iter<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.iter.fmt(f)
}
}
#[must_use = "non-empty iterators are lazy and do nothing unless consumed"]
pub struct IterMut<'a, K: 'a, V: 'a> {
iter: std::collections::hash_map::IterMut<'a, K, V>,
}
impl<K, V> NonEmptyIterator for IterMut<'_, K, V> {}
impl<'a, K, V> IntoIterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
type IntoIter = std::collections::hash_map::IterMut<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter
}
}
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IterMut<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.iter.fmt(f)
}
}
pub struct IntoIter<K, V> {
iter: std::collections::hash_map::IntoIter<K, V>,
}
impl<K, V> NonEmptyIterator for IntoIter<K, V> {}
impl<K, V> IntoIterator for IntoIter<K, V> {
type Item = (K, V);
type IntoIter = std::collections::hash_map::IntoIter<K, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter
}
}
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IntoIter<K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.iter.fmt(f)
}
}
#[must_use = "non-empty iterators are lazy and do nothing unless consumed"]
pub struct Keys<'a, K: 'a, V: 'a> {
inner: std::collections::hash_map::Keys<'a, K, V>,
}
impl<K, V> NonEmptyIterator for Keys<'_, K, V> {}
impl<'a, K, V> IntoIterator for Keys<'a, K, V> {
type Item = &'a K;
type IntoIter = std::collections::hash_map::Keys<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.inner
}
}
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Keys<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
#[must_use = "non-empty iterators are lazy and do nothing unless consumed"]
pub struct Values<'a, K: 'a, V: 'a> {
inner: std::collections::hash_map::Values<'a, K, V>,
}
impl<K, V> NonEmptyIterator for Values<'_, K, V> {}
impl<'a, K, V> IntoIterator for Values<'a, K, V> {
type Item = &'a V;
type IntoIter = std::collections::hash_map::Values<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.inner
}
}
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Values<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl<K: fmt::Debug, V: fmt::Debug, S> fmt::Debug for NEMap<K, V, S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl<K, V> Singleton for NEMap<K, V>
where
K: Eq + Hash,
{
type Item = (K, V);
fn singleton((k, v): Self::Item) -> Self {
NEMap::new(k, v)
}
}
impl<K, V> Extend<(K, V)> for NEMap<K, V>
where
K: Eq + Hash,
{
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
self.inner.extend(iter);
}
}
#[cfg(test)]
mod test {
use maplit::hashmap;
use std::num::NonZeroUsize;
struct Foo {
user: String,
}
#[test]
fn debug_impl() {
let expected = format!("{:?}", hashmap! {0 => 10});
let actual = format!("{:?}", nem! {0 => 10});
assert_eq!(expected, actual);
}
#[test]
fn macro_usage() {
let a = Foo {
user: "a".to_string(),
};
let b = Foo {
user: "b".to_string(),
};
let map = nem![1 => a, 2 => b];
assert_eq!("a", map.get(&1).unwrap().user);
assert_eq!("b", map.get(&2).unwrap().user);
}
#[test]
fn macro_length() {
let map = nem![1 => 'a', 2 => 'b', 1 => 'c'];
assert_eq!(unsafe { NonZeroUsize::new_unchecked(2) }, map.len());
assert_eq!('c', *map.get(&1).unwrap());
assert_eq!('b', *map.get(&2).unwrap());
}
#[test]
fn iter_mut() {
let mut v = nem! {"a" => 0, "b" => 1, "c" => 2};
v.iter_mut().for_each(|(_k, v)| {
*v += 1;
});
assert_eq!(nem! {"a" => 1, "b" => 2, "c" => 3}, v);
for (_k, v) in &mut v {
*v -= 1;
}
assert_eq!(nem! {"a" => 0, "b" => 1, "c" => 2}, v);
}
}
#[cfg(feature = "serde")]
#[cfg(test)]
mod serde_tests {
use crate::NEMap;
use std::collections::HashMap;
#[test]
fn json() {
let map0 = nem![1 => 'a', 2 => 'b', 1 => 'c'];
let j = serde_json::to_string(&map0).unwrap();
let map1 = serde_json::from_str(&j).unwrap();
assert_eq!(map0, map1);
let empty: HashMap<usize, char> = HashMap::new();
let j = serde_json::to_string(&empty).unwrap();
let bad = serde_json::from_str::<NEMap<usize, char>>(&j);
assert!(bad.is_err());
}
}