use std::{collections::HashSet, hash::Hash, sync::Arc};
use crate::CustomSet;
#[derive(Clone, Debug)]
pub struct FrozenSet<T: Eq + Hash + Clone> {
inner: Arc<HashSet<T>>,
}
impl<T: Eq + Hash + Clone> FrozenSet<T> {
pub fn empty() -> Self {
Self {
inner: Arc::new(HashSet::new()),
}
}
pub fn new<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self {
inner: Arc::new(HashSet::from_iter(iter)),
}
}
pub fn from_custom_set(set: &CustomSet<T>) -> Self {
FrozenSet {
inner: Arc::new(set.iter().cloned().collect()),
}
}
pub fn cardinality(&self) -> usize {
self.inner.len()
}
pub fn contains(&self, element: &T) -> bool {
self.inner.contains(element)
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.inner.iter()
}
pub fn to_custom_set(&self) -> CustomSet<T> {
CustomSet::new(self.inner.iter().cloned())
}
}
impl<T: Eq + Hash + Clone> From<Vec<T>> for FrozenSet<T> {
fn from(vec: Vec<T>) -> Self {
FrozenSet::new(vec)
}
}
impl<T: Eq + Hash + Clone> FromIterator<T> for FrozenSet<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
FrozenSet::new(iter)
}
}
unsafe impl<T: Eq + Hash + Clone + Send> Send for FrozenSet<T> {}
unsafe impl<T: Eq + Hash + Clone + Sync> Sync for FrozenSet<T> {}
impl<T: Eq + Hash + Clone + std::fmt::Display> std::fmt::Display for FrozenSet<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.is_empty() {
write!(f, "∅")
} else {
let elements: Vec<_> = self.inner.iter().collect();
write!(
f,
"{{{}}}",
elements
.iter()
.map(|e| e.to_string())
.collect::<Vec<_>>()
.join(", ")
)
}
}
}
impl<T: Eq + Hash + Clone> PartialEq for FrozenSet<T> {
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}
impl<T: Eq + Hash + Clone> Eq for FrozenSet<T> {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_frozen_set_create() {
let frozen = FrozenSet::from(vec![1, 2, 3]);
assert_eq!(frozen.cardinality(), 3);
}
#[test]
fn test_frozen_set_immutable() {
let frozen = FrozenSet::from(vec![1, 2, 3]);
let cloned = frozen.clone();
assert_eq!(frozen, cloned);
}
#[test]
fn test_frozen_set_thread_safe() {
use std::thread;
let frozen = FrozenSet::from(vec![1, 2, 3, 4, 5]);
let handles: Vec<_> = (0..5)
.map(|_| {
let frozen_clone = frozen.clone();
thread::spawn(move || {
assert_eq!(frozen_clone.cardinality(), 5);
})
})
.collect();
for handle in handles {
handle.join().unwrap();
}
}
}