toasty_core/stmt/
path_field_set.rs

1use bit_set::BitSet;
2use std::ops::{BitAnd, BitOr, BitOrAssign};
3
4/// A set of field indices, backed by a bit set.
5///
6/// Used to track which fields are present in a [`SparseRecord`](super::SparseRecord)
7/// or which fields are part of a type description. Supports set operations
8/// like union (`|`), intersection (`&`), and membership tests.
9///
10/// # Examples
11///
12/// ```
13/// use toasty_core::stmt::PathFieldSet;
14///
15/// let mut set = PathFieldSet::new();
16/// set.insert(0);
17/// set.insert(2);
18/// assert!(set.contains(0_usize));
19/// assert!(!set.contains(1_usize));
20/// assert_eq!(set.len(), 2);
21/// ```
22#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub struct PathFieldSet {
25    container: BitSet<u32>,
26}
27
28/// An iterator over the field indices in a [`PathFieldSet`].
29pub struct PathFieldSetIter<'a> {
30    inner: bit_set::Iter<'a, u32>,
31    len: usize,
32}
33
34impl<'a> Iterator for PathFieldSetIter<'a> {
35    type Item = usize;
36
37    fn next(&mut self) -> Option<Self::Item> {
38        let result = self.inner.next();
39        if result.is_some() {
40            self.len -= 1;
41        }
42        result
43    }
44
45    fn size_hint(&self) -> (usize, Option<usize>) {
46        (self.len, Some(self.len))
47    }
48}
49
50impl<'a> ExactSizeIterator for PathFieldSetIter<'a> {}
51
52impl PathFieldSet {
53    /// Creates an empty field set.
54    pub fn new() -> Self {
55        Self::default()
56    }
57
58    /// Creates a field set from a slice of values convertible to `usize`.
59    pub fn from_slice<T>(fields: &[T]) -> Self
60    where
61        for<'a> &'a T: Into<usize>,
62    {
63        Self {
64            container: fields.iter().map(Into::into).collect(),
65        }
66    }
67
68    /// Returns `true` if the set contains the given field index.
69    pub fn contains(&self, val: impl Into<usize>) -> bool {
70        self.container.contains(val.into())
71    }
72
73    /// Returns an iterator over the field indices in ascending order.
74    pub fn iter(&self) -> PathFieldSetIter<'_> {
75        PathFieldSetIter {
76            inner: self.container.iter(),
77            len: self.container.count(),
78        }
79    }
80
81    /// Returns `true` if the set contains no field indices.
82    pub fn is_empty(&self) -> bool {
83        self.container.is_empty()
84    }
85
86    /// Returns the number of field indices in the set.
87    pub fn len(&self) -> usize {
88        self.container.count()
89    }
90
91    /// Inserts a field index into the set.
92    pub fn insert(&mut self, val: usize) {
93        self.container.insert(val);
94    }
95}
96
97impl BitOr for PathFieldSet {
98    type Output = Self;
99
100    fn bitor(mut self, rhs: Self) -> Self {
101        self.container.union_with(&rhs.container);
102        self
103    }
104}
105
106impl BitOrAssign for PathFieldSet {
107    fn bitor_assign(&mut self, rhs: Self) {
108        self.container.union_with(&rhs.container);
109    }
110}
111
112impl BitAnd for PathFieldSet {
113    type Output = Self;
114
115    fn bitand(mut self, rhs: Self) -> Self {
116        self.container.intersect_with(&rhs.container);
117        self
118    }
119}
120
121impl FromIterator<usize> for PathFieldSet {
122    fn from_iter<T: IntoIterator<Item = usize>>(iter: T) -> Self {
123        Self {
124            container: BitSet::from_iter(iter),
125        }
126    }
127}