use std::{
collections::{HashMap, HashSet},
fmt::{Debug, Display},
hash::Hash,
};
use ustr::Ustr;
pub trait SetLike {
type Item: Hash + Eq + Display + Clone;
fn contains(&self, item: &Self::Item) -> bool;
fn is_empty(&self) -> bool;
}
impl<T, S> SetLike for HashSet<T, S>
where
T: Eq + Hash + Display + Clone,
S: std::hash::BuildHasher,
{
type Item = T;
#[inline]
fn contains(&self, v: &T) -> bool {
Self::contains(self, v)
}
#[inline]
fn is_empty(&self) -> bool {
Self::is_empty(self)
}
}
impl<T, S> SetLike for indexmap::IndexSet<T, S>
where
T: Eq + Hash + Display + Clone,
S: std::hash::BuildHasher,
{
type Item = T;
#[inline]
fn contains(&self, v: &T) -> bool {
Self::contains(self, v)
}
#[inline]
fn is_empty(&self) -> bool {
Self::is_empty(self)
}
}
impl<T, S> SetLike for ahash::AHashSet<T, S>
where
T: Eq + Hash + Display + Clone,
S: std::hash::BuildHasher,
{
type Item = T;
#[inline]
fn contains(&self, v: &T) -> bool {
self.get(v).is_some()
}
#[inline]
fn is_empty(&self) -> bool {
self.len() == 0
}
}
pub trait MapLike {
type Key: Hash + Eq + Display + Clone;
type Value: Debug;
fn contains_key(&self, key: &Self::Key) -> bool;
fn is_empty(&self) -> bool;
}
impl<K, V, S> MapLike for HashMap<K, V, S>
where
K: Eq + Hash + Display + Clone,
V: Debug,
S: std::hash::BuildHasher,
{
type Key = K;
type Value = V;
#[inline]
fn contains_key(&self, k: &K) -> bool {
self.contains_key(k)
}
#[inline]
fn is_empty(&self) -> bool {
self.is_empty()
}
}
impl<K, V, S> MapLike for indexmap::IndexMap<K, V, S>
where
K: Eq + Hash + Display + Clone,
V: Debug,
S: std::hash::BuildHasher,
{
type Key = K;
type Value = V;
#[inline]
fn contains_key(&self, k: &K) -> bool {
self.get(k).is_some()
}
#[inline]
fn is_empty(&self) -> bool {
self.is_empty()
}
}
impl<K, V, S> MapLike for ahash::AHashMap<K, V, S>
where
K: Eq + Hash + Display + Clone,
V: Debug,
S: std::hash::BuildHasher,
{
type Key = K;
type Value = V;
#[inline]
fn contains_key(&self, k: &K) -> bool {
self.get(k).is_some()
}
#[inline]
fn is_empty(&self) -> bool {
self.len() == 0
}
}
#[must_use]
pub fn into_ustr_vec<I, T>(iter: I) -> Vec<Ustr>
where
I: IntoIterator<Item = T>,
T: AsRef<str>, {
let iter = iter.into_iter();
let (lower, _) = iter.size_hint();
let mut result = Vec::with_capacity(lower);
for item in iter {
result.push(Ustr::from(item.as_ref()));
}
result
}
#[cfg(test)]
#[allow(clippy::unnecessary_to_owned, reason = "Required for trait bound satisfaction")]
mod tests {
use std::collections::{HashMap, HashSet};
use ahash::{AHashMap, AHashSet};
use indexmap::{IndexMap, IndexSet};
use ustr::Ustr;
use super::*;
#[test]
fn test_hashset_setlike() {
let mut set: HashSet<String> = HashSet::new();
set.insert("test".to_string());
set.insert("value".to_string());
assert!(set.contains(&"test".to_string()));
assert!(!set.contains(&"missing".to_string()));
assert!(!set.is_empty());
let empty_set: HashSet<String> = HashSet::new();
assert!(empty_set.is_empty());
}
#[test]
fn test_indexset_setlike() {
let mut set: IndexSet<String> = IndexSet::new();
set.insert("test".to_string());
set.insert("value".to_string());
assert!(set.contains(&"test".to_string()));
assert!(!set.contains(&"missing".to_string()));
assert!(!set.is_empty());
let empty_set: IndexSet<String> = IndexSet::new();
assert!(empty_set.is_empty());
}
#[test]
fn test_into_ustr_vec_from_strings() {
let items = vec!["foo".to_string(), "bar".to_string()];
let ustrs = super::into_ustr_vec(items);
assert_eq!(ustrs.len(), 2);
assert_eq!(ustrs[0], Ustr::from("foo"));
assert_eq!(ustrs[1], Ustr::from("bar"));
}
#[test]
fn test_into_ustr_vec_from_str_slices() {
let items = ["alpha", "beta", "gamma"];
let ustrs = super::into_ustr_vec(items);
assert_eq!(ustrs.len(), 3);
assert_eq!(ustrs[2], Ustr::from("gamma"));
}
#[test]
fn test_ahashset_setlike() {
let mut set: AHashSet<String> = AHashSet::new();
set.insert("test".to_string());
set.insert("value".to_string());
assert!(set.contains(&"test".to_string()));
assert!(!set.contains(&"missing".to_string()));
assert!(!set.is_empty());
let empty_set: AHashSet<String> = AHashSet::new();
assert!(empty_set.is_empty());
}
#[test]
fn test_hashmap_maplike() {
let mut map: HashMap<String, i32> = HashMap::new();
map.insert("key1".to_string(), 42);
map.insert("key2".to_string(), 100);
assert!(map.contains_key(&"key1".to_string()));
assert!(!map.contains_key(&"missing".to_string()));
assert!(!map.is_empty());
let empty_map: HashMap<String, i32> = HashMap::new();
assert!(empty_map.is_empty());
}
#[test]
fn test_indexmap_maplike() {
let mut map: IndexMap<String, i32> = IndexMap::new();
map.insert("key1".to_string(), 42);
map.insert("key2".to_string(), 100);
assert!(map.contains_key(&"key1".to_string()));
assert!(!map.contains_key(&"missing".to_string()));
assert!(!map.is_empty());
let empty_map: IndexMap<String, i32> = IndexMap::new();
assert!(empty_map.is_empty());
}
#[test]
fn test_ahashmap_maplike() {
let mut map: AHashMap<String, i32> = AHashMap::new();
map.insert("key1".to_string(), 42);
map.insert("key2".to_string(), 100);
assert!(map.contains_key(&"key1".to_string()));
assert!(!map.contains_key(&"missing".to_string()));
assert!(!map.is_empty());
let empty_map: AHashMap<String, i32> = AHashMap::new();
assert!(empty_map.is_empty());
}
#[test]
fn test_trait_object_setlike() {
let mut hashset: HashSet<String> = HashSet::new();
hashset.insert("test".to_string());
let mut indexset: IndexSet<String> = IndexSet::new();
indexset.insert("test".to_string());
let sets: Vec<&dyn SetLike<Item = String>> = vec![&hashset, &indexset];
for set in sets {
assert!(set.contains(&"test".to_string()));
assert!(!set.is_empty());
}
}
#[test]
fn test_trait_object_maplike() {
let mut hashmap: HashMap<String, i32> = HashMap::new();
hashmap.insert("key".to_string(), 42);
let mut indexmap: IndexMap<String, i32> = IndexMap::new();
indexmap.insert("key".to_string(), 42);
let maps: Vec<&dyn MapLike<Key = String, Value = i32>> = vec![&hashmap, &indexmap];
for map in maps {
assert!(map.contains_key(&"key".to_string()));
assert!(!map.is_empty());
}
}
}