set_theory 1.0.0

A comprehensive mathematical set theory library implementing standard set operations, multisets, and set laws verification
Documentation
//! # FrozenSet Implementation
//!
//! An immutable, thread-safe mathematical set implementation.
//!
//! `FrozenSet` is designed for scenarios where set immutability is required,
//! such as concurrent access or caching.

use std::{collections::HashSet, hash::Hash, sync::Arc};

use crate::CustomSet;

/// An immutable mathematical set containing unique elements.
///
/// `FrozenSet` wraps a `CustomSet` in an `Arc` for thread-safe,
/// immutable access. Once created, the set cannot be modified.
///
/// # Type Parameters
///
/// * `T` - The type of elements. Must implement `Eq + Hash + Clone`
///
/// # Examples
///
/// ```rust
/// use set_theory::models::FrozenSet;
///
/// let frozen = FrozenSet::from(vec![1, 2, 3, 4]);
/// assert_eq!(frozen.cardinality(), 4);
/// ```
///
/// # Thread Safety
///
/// `FrozenSet` is `Send + Sync` and can be safely shared across threads.
#[derive(Clone, Debug)]
pub struct FrozenSet<T: Eq + Hash + Clone> {
    inner: Arc<HashSet<T>>,
}

impl<T: Eq + Hash + Clone> FrozenSet<T> {
    /// Creates an empty frozen set.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use set_theory::models::FrozenSet;
    ///
    /// let empty = FrozenSet::<i32>::empty();
    /// assert_eq!(empty.cardinality(), 0);
    /// ```
    pub fn empty() -> Self {
        Self {
            inner: Arc::new(HashSet::new()),
        }
    }

    /// Creates a frozen set from an iterable.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use set_theory::models::FrozenSet;
    ///
    /// let frozen = FrozenSet::from(vec![1, 2, 3]);
    /// assert_eq!(frozen.cardinality(), 3);
    /// ```
    pub fn new<I: IntoIterator<Item = T>>(iter: I) -> Self {
        Self {
            inner: Arc::new(HashSet::from_iter(iter)),
        }
    }

    /// Creates a frozen set from a CustomSet.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use set_theory::models::{CustomSet, FrozenSet};
    ///
    /// let custom = CustomSet::from(vec![1, 2, 3]);
    /// let frozen = FrozenSet::from_custom_set(&custom);
    /// ```
    pub fn from_custom_set(set: &CustomSet<T>) -> Self {
        FrozenSet {
            inner: Arc::new(set.iter().cloned().collect()),
        }
    }

    /// Returns the cardinality of the set.
    pub fn cardinality(&self) -> usize {
        self.inner.len()
    }

    /// Checks if an element is in the set.
    pub fn contains(&self, element: &T) -> bool {
        self.inner.contains(element)
    }

    /// Checks if the set is empty.
    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }

    /// Returns an iterator over the elements.
    pub fn iter(&self) -> impl Iterator<Item = &T> {
        self.inner.iter()
    }

    /// Converts to a CustomSet for mutable operations.
    pub fn to_custom_set(&self) -> CustomSet<T> {
        CustomSet::new(self.inner.iter().cloned())
    }
}

// Implement From<Vec<T>>
impl<T: Eq + Hash + Clone> From<Vec<T>> for FrozenSet<T> {
    /// Creates a FrozenSet from a Vec.
    ///
    /// # Arguments
    ///
    /// * `vec` - A vector of elements to create the frozen set from
    ///
    /// # Returns
    ///
    /// A new `FrozenSet` containing unique elements from the vector.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use set_theory::models::FrozenSet;
    ///
    /// let frozen = FrozenSet::from(vec![1, 2, 3]);
    /// assert_eq!(frozen.cardinality(), 3);
    /// ```
    fn from(vec: Vec<T>) -> Self {
        FrozenSet::new(vec)
    }
}

// Implement FromIterator
impl<T: Eq + Hash + Clone> FromIterator<T> for FrozenSet<T> {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        FrozenSet::new(iter)
    }
}

// Implement thread safety
unsafe impl<T: Eq + Hash + Clone + Send> Send for FrozenSet<T> {}
unsafe impl<T: Eq + Hash + Clone + Sync> Sync for FrozenSet<T> {}

// Implement Display
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(", ")
            )
        }
    }
}

// Implement PartialEq and Eq
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();
        }
    }
}