Skip to main content

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.iter().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`].
29///
30/// Generic over the underlying `bit-set` iterator rather than naming it: as of
31/// `bit-set` 0.10.1 the concrete `Iter` type lives in a private module and can
32/// no longer be referred to directly.
33pub struct PathFieldSetIter<I> {
34    inner: I,
35    len: usize,
36}
37
38impl<I: Iterator<Item = usize>> Iterator for PathFieldSetIter<I> {
39    type Item = usize;
40
41    fn next(&mut self) -> Option<Self::Item> {
42        let result = self.inner.next();
43        if result.is_some() {
44            self.len -= 1;
45        }
46        result
47    }
48
49    fn size_hint(&self) -> (usize, Option<usize>) {
50        (self.len, Some(self.len))
51    }
52}
53
54impl<I: Iterator<Item = usize>> ExactSizeIterator for PathFieldSetIter<I> {}
55
56impl PathFieldSet {
57    /// Creates an empty field set.
58    pub fn new() -> Self {
59        Self::default()
60    }
61
62    /// Returns `true` if the set contains the given field index.
63    pub fn contains(&self, val: impl Into<usize>) -> bool {
64        self.container.contains(val.into())
65    }
66
67    /// Returns an iterator over the field indices in ascending order.
68    pub fn iter(&self) -> PathFieldSetIter<impl Iterator<Item = usize> + '_> {
69        PathFieldSetIter {
70            inner: self.container.iter(),
71            len: self.container.count(),
72        }
73    }
74
75    /// Returns `true` if the set contains no field indices.
76    pub fn is_empty(&self) -> bool {
77        self.container.is_empty()
78    }
79
80    /// Inserts a field index into the set.
81    pub fn insert(&mut self, val: usize) {
82        self.container.insert(val);
83    }
84}
85
86impl BitOr for PathFieldSet {
87    type Output = Self;
88
89    fn bitor(mut self, rhs: Self) -> Self {
90        self.container.union_with(&rhs.container);
91        self
92    }
93}
94
95impl BitOrAssign for PathFieldSet {
96    fn bitor_assign(&mut self, rhs: Self) {
97        self.container.union_with(&rhs.container);
98    }
99}
100
101impl BitAnd for PathFieldSet {
102    type Output = Self;
103
104    fn bitand(mut self, rhs: Self) -> Self {
105        self.container.intersect_with(&rhs.container);
106        self
107    }
108}
109
110impl FromIterator<usize> for PathFieldSet {
111    fn from_iter<T: IntoIterator<Item = usize>>(iter: T) -> Self {
112        Self {
113            container: BitSet::from_iter(iter),
114        }
115    }
116}