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.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    /// Creates a field set from a slice of values convertible to `usize`.
63    pub fn from_slice<T>(fields: &[T]) -> Self
64    where
65        for<'a> &'a T: Into<usize>,
66    {
67        Self {
68            container: fields.iter().map(Into::into).collect(),
69        }
70    }
71
72    /// Returns `true` if the set contains the given field index.
73    pub fn contains(&self, val: impl Into<usize>) -> bool {
74        self.container.contains(val.into())
75    }
76
77    /// Returns an iterator over the field indices in ascending order.
78    pub fn iter(&self) -> PathFieldSetIter<impl Iterator<Item = usize> + '_> {
79        PathFieldSetIter {
80            inner: self.container.iter(),
81            len: self.container.count(),
82        }
83    }
84
85    /// Returns `true` if the set contains no field indices.
86    pub fn is_empty(&self) -> bool {
87        self.container.is_empty()
88    }
89
90    /// Returns the number of field indices in the set.
91    pub fn len(&self) -> usize {
92        self.container.count()
93    }
94
95    /// Inserts a field index into the set.
96    pub fn insert(&mut self, val: usize) {
97        self.container.insert(val);
98    }
99}
100
101impl BitOr for PathFieldSet {
102    type Output = Self;
103
104    fn bitor(mut self, rhs: Self) -> Self {
105        self.container.union_with(&rhs.container);
106        self
107    }
108}
109
110impl BitOrAssign for PathFieldSet {
111    fn bitor_assign(&mut self, rhs: Self) {
112        self.container.union_with(&rhs.container);
113    }
114}
115
116impl BitAnd for PathFieldSet {
117    type Output = Self;
118
119    fn bitand(mut self, rhs: Self) -> Self {
120        self.container.intersect_with(&rhs.container);
121        self
122    }
123}
124
125impl FromIterator<usize> for PathFieldSet {
126    fn from_iter<T: IntoIterator<Item = usize>>(iter: T) -> Self {
127        Self {
128            container: BitSet::from_iter(iter),
129        }
130    }
131}