use crate::eval::value::Value;
use crate::containers::{Container, ContainerError, ContainerResult};
use crate::containers::comparator::HashComparator;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
#[derive(Debug, Clone)]
pub struct Set {
elements: HashMap<Value, ()>,
comparator: HashComparator,
debug_name: Option<String>,
}
impl Set {
pub fn new() -> Self {
Self {
elements: HashMap::new(),
comparator: HashComparator::with_default(),
debug_name: None,
}
}
pub fn with_comparator(comparator: HashComparator) -> Self {
Self {
elements: HashMap::new(),
comparator,
debug_name: None,
}
}
pub fn from_iter_with_comparator<I>(iter: I, comparator: HashComparator) -> Self
where
I: IntoIterator<Item = Value>,
{
let mut set = Self::with_comparator(comparator);
for value in iter {
set.adjoin(value);
}
set
}
pub fn adjoin(&mut self, value: Value) -> bool {
self.elements.insert(value, ()).is_none()
}
pub fn delete(&mut self, value: &Value) -> bool {
self.elements.remove(value).is_some()
}
pub fn contains(&self, value: &Value) -> bool {
self.elements.contains_key(value)
}
pub fn size(&self) -> usize {
self.elements.len()
}
pub fn is_empty(&self) -> bool {
self.elements.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &Value> {
self.elements.keys()
}
pub fn to_vec(&self) -> Vec<Value> {
self.elements.keys().cloned().collect()
}
pub fn comparator(&self) -> &HashComparator {
&self.comparator
}
pub fn set_debug_name(&mut self, name: impl Into<String>) {
self.debug_name = Some(name.into());
}
pub fn debug_name(&self) -> Option<&str> {
self.debug_name.as_deref()
}
pub fn clear_debug_name(&mut self) {
self.debug_name = None;
}
pub fn union(&self, other: &Set) -> Set {
let mut result = self.clone();
for value in other.iter() {
result.adjoin(value.clone());
}
result
}
pub fn intersection(&self, other: &Set) -> Set {
let mut result = Set::with_comparator(self.comparator.clone());
for value in self.iter() {
if other.contains(value) {
result.adjoin(value.clone());
}
}
result
}
pub fn difference(&self, other: &Set) -> Set {
let mut result = Set::with_comparator(self.comparator.clone());
for value in self.iter() {
if !other.contains(value) {
result.adjoin(value.clone());
}
}
result
}
pub fn is_subset(&self, other: &Set) -> bool {
self.iter().all(|value| other.contains(value))
}
pub fn is_superset(&self, other: &Set) -> bool {
other.is_subset(self)
}
pub fn is_disjoint(&self, other: &Set) -> bool {
!self.iter().any(|value| other.contains(value))
}
}
impl Default for Set {
fn default() -> Self {
Self::new()
}
}
impl Container for Set {
fn len(&self) -> usize {
self.size()
}
fn clear(&mut self) {
self.elements.clear();
}
}
impl PartialEq for Set {
fn eq(&self, other: &Self) -> bool {
self.size() == other.size() && self.is_subset(other)
}
}
impl Eq for Set {}
#[derive(Debug, Clone)]
pub struct ThreadSafeSet {
inner: Arc<RwLock<Set>>,
}
impl ThreadSafeSet {
pub fn new() -> Self {
Self {
inner: Arc::new(RwLock::new(Set::new())),
}
}
pub fn with_comparator(comparator: HashComparator) -> Self {
Self {
inner: Arc::new(RwLock::new(Set::with_comparator(comparator))),
}
}
pub fn adjoin(&self, value: Value) -> ContainerResult<bool> {
Ok(self.inner
.write()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire write lock".to_string(),
})?
.adjoin(value))
}
pub fn delete(&self, value: &Value) -> ContainerResult<bool> {
Ok(self
.inner
.write()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire write lock".to_string(),
})?
.delete(value))
}
pub fn contains(&self, value: &Value) -> ContainerResult<bool> {
Ok(self
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?
.contains(value))
}
pub fn size(&self) -> ContainerResult<usize> {
Ok(self
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?
.size())
}
pub fn is_empty(&self) -> ContainerResult<bool> {
Ok(self
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?
.is_empty())
}
pub fn to_vec(&self) -> ContainerResult<Vec<Value>> {
Ok(self
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?
.to_vec())
}
pub fn clear(&self) -> ContainerResult<()> {
self.inner
.write()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire write lock".to_string(),
})?
.clear();
Ok(())
}
pub fn set_debug_name(&self, name: impl Into<String>) -> ContainerResult<()> {
self.inner
.write()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire write lock".to_string(),
})?
.set_debug_name(name);
Ok(())
}
pub fn debug_name(&self) -> ContainerResult<Option<String>> {
Ok(self
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?
.debug_name()
.map(|s| s.to_string()))
}
pub fn union(&self, other: &ThreadSafeSet) -> ContainerResult<ThreadSafeSet> {
let self_set = self
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?;
let other_set = other
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?;
let result = self_set.union(&other_set);
Ok(ThreadSafeSet {
inner: Arc::new(RwLock::new(result)),
})
}
pub fn intersection(&self, other: &ThreadSafeSet) -> ContainerResult<ThreadSafeSet> {
let self_set = self
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?;
let other_set = other
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?;
let result = self_set.intersection(&other_set);
Ok(ThreadSafeSet {
inner: Arc::new(RwLock::new(result)),
})
}
pub fn difference(&self, other: &ThreadSafeSet) -> ContainerResult<ThreadSafeSet> {
let self_set = self
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?;
let other_set = other
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?;
let result = self_set.difference(&other_set);
Ok(ThreadSafeSet {
inner: Arc::new(RwLock::new(result)),
})
}
pub fn is_subset(&self, other: &ThreadSafeSet) -> ContainerResult<bool> {
let self_set = self
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?;
let other_set = other
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?;
Ok(self_set.is_subset(&other_set))
}
pub fn is_superset(&self, other: &ThreadSafeSet) -> ContainerResult<bool> {
let self_set = self
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?;
let other_set = other
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?;
Ok(self_set.is_superset(&other_set))
}
pub fn is_disjoint(&self, other: &ThreadSafeSet) -> ContainerResult<bool> {
let self_set = self
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?;
let other_set = other
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?;
Ok(self_set.is_disjoint(&other_set))
}
pub fn comparator(&self) -> ContainerResult<HashComparator> {
Ok(self
.inner
.read()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire read lock".to_string(),
})?
.comparator()
.clone())
}
pub fn adjoin_all<I>(&self, values: I) -> ContainerResult<()>
where
I: IntoIterator<Item = Value>,
{
let mut set = self
.inner
.write()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire write lock".to_string(),
})?;
for value in values {
set.adjoin(value);
}
Ok(())
}
pub fn delete_all<I>(&self, values: I) -> ContainerResult<()>
where
I: IntoIterator<Item = Value>,
{
let mut set = self
.inner
.write()
.map_err(|_| ContainerError::InvalidComparator {
message: "Failed to acquire write lock".to_string(),
})?;
for value in values {
set.delete(&value);
}
Ok(())
}
pub fn from_iter_with_comparator<I>(iter: I, comparator: HashComparator) -> Self
where
I: IntoIterator<Item = Value>,
{
let set = Set::from_iter_with_comparator(iter, comparator);
Self {
inner: Arc::new(RwLock::new(set)),
}
}
}
impl Default for ThreadSafeSet {
fn default() -> Self {
Self::new()
}
}
impl std::iter::FromIterator<Value> for Set {
fn from_iter<I: IntoIterator<Item = Value>>(iter: I) -> Self {
let mut set = Self::new();
for value in iter {
set.adjoin(value);
}
set
}
}
impl std::iter::FromIterator<Value> for ThreadSafeSet {
fn from_iter<I: IntoIterator<Item = Value>>(iter: I) -> Self {
Self {
inner: Arc::new(RwLock::new(iter.into_iter().collect())),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_set_new() {
let set = Set::new();
assert!(set.is_empty());
assert_eq!(set.size(), 0);
}
#[test]
fn test_set_adjoin() {
let mut set = Set::new();
let v1 = Value::number(42.0);
let v2 = Value::string("hello");
assert!(set.adjoin(v1.clone()));
assert_eq!(set.size(), 1);
assert!(set.contains(&v1));
assert!(!set.adjoin(v1.clone()));
assert_eq!(set.size(), 1);
assert!(set.adjoin(v2.clone()));
assert_eq!(set.size(), 2);
assert!(set.contains(&v2));
}
#[test]
fn test_set_delete() {
let mut set = Set::new();
let v1 = Value::number(42.0);
let v2 = Value::string("hello");
set.adjoin(v1.clone());
set.adjoin(v2.clone());
assert_eq!(set.size(), 2);
assert!(set.delete(&v1));
assert_eq!(set.size(), 1);
assert!(!set.contains(&v1));
assert!(set.contains(&v2));
assert!(!set.delete(&v1));
assert_eq!(set.size(), 1);
}
#[test]
fn test_set_operations() {
let mut set1 = Set::new();
let mut set2 = Set::new();
let v1 = Value::number(1.0);
let v2 = Value::number(2.0);
let v3 = Value::number(3.0);
set1.adjoin(v1.clone());
set1.adjoin(v2.clone());
set2.adjoin(v2.clone());
set2.adjoin(v3.clone());
let union = set1.union(&set2);
assert_eq!(union.size(), 3);
assert!(union.contains(&v1));
assert!(union.contains(&v2));
assert!(union.contains(&v3));
let intersection = set1.intersection(&set2);
assert_eq!(intersection.size(), 1);
assert!(intersection.contains(&v2));
let diff = set1.difference(&set2);
assert_eq!(diff.size(), 1);
assert!(diff.contains(&v1));
assert!(!diff.contains(&v2));
}
#[test]
fn test_set_subset_superset() {
let mut set1 = Set::new();
let mut set2 = Set::new();
let v1 = Value::number(1.0);
let v2 = Value::number(2.0);
set1.adjoin(v1.clone());
set2.adjoin(v1.clone());
set2.adjoin(v2.clone());
assert!(set1.is_subset(&set2));
assert!(!set1.is_superset(&set2));
assert!(set2.is_superset(&set1));
assert!(!set2.is_subset(&set1));
}
#[test]
fn test_thread_safe_set() {
let set = ThreadSafeSet::new();
let v1 = Value::number(42.0);
assert!(set.adjoin(v1.clone()).unwrap());
assert_eq!(set.size().unwrap(), 1);
assert!(set.contains(&v1).unwrap());
assert!(set.delete(&v1).unwrap());
assert_eq!(set.size().unwrap(), 0);
assert!(!set.contains(&v1).unwrap());
}
}