Skip to main content

cidre/ns/
index_set.rs

1#[cfg(feature = "blocks")]
2use crate::blocks;
3use crate::{arc, define_obj_type, ns, objc};
4
5impl arc::A<IndexSet> {
6    #[objc::msg_send(initWithIndex:)]
7    pub fn init_with_index(self, val: usize) -> arc::R<IndexSet>;
8
9    #[objc::msg_send(initWithIndexSet:)]
10    pub fn init_with_index_set(self, val: &ns::IndexSet) -> arc::R<IndexSet>;
11
12    #[objc::msg_send(initWithIndexesInRange:)]
13    pub fn init_with_range(self, val: ns::Range) -> arc::R<IndexSet>;
14}
15
16impl arc::A<IndexSetMut> {
17    #[objc::msg_send(initWithIndex:)]
18    pub fn init_with_index(self, val: usize) -> arc::R<IndexSetMut>;
19
20    #[objc::msg_send(initWithIndexSet:)]
21    pub fn init_with_index_set(self, val: &ns::IndexSet) -> arc::R<IndexSetMut>;
22
23    #[objc::msg_send(initWithIndexesInRange:)]
24    pub fn init_with_range(self, val: ns::Range) -> arc::R<IndexSetMut>;
25}
26
27define_obj_type!(
28    #[doc(alias = "NSIndexSet")]
29    pub IndexSet(ns::Id),
30    NS_INDEX_SET
31);
32
33define_obj_type!(
34    #[doc(alias = "NSMutableIndexSet")]
35    pub IndexSetMut(ns::IndexSet),
36    NS_MUTABLE_INDEX_SET
37);
38
39impl IndexSet {
40    #[objc::msg_send(count)]
41    pub fn len(&self) -> usize;
42
43    #[inline]
44    pub fn is_empty(&self) -> bool {
45        self.len() == 0
46    }
47
48    #[inline]
49    pub fn with_index(val: usize) -> arc::R<Self> {
50        Self::alloc().init_with_index(val)
51    }
52
53    #[inline]
54    pub fn with_index_set(val: impl AsRef<IndexSet>) -> arc::R<Self> {
55        Self::alloc().init_with_index_set(val.as_ref())
56    }
57
58    #[inline]
59    pub fn with_range(val: ns::Range) -> arc::R<Self> {
60        Self::alloc().init_with_range(val)
61    }
62
63    #[objc::msg_send(firstIndex)]
64    pub fn first_index(&self) -> usize;
65
66    #[objc::msg_send(lastIndex)]
67    pub fn last_index(&self) -> usize;
68
69    #[objc::msg_send(indexGreaterThanIndex:)]
70    pub fn index_gt(&self, val: usize) -> usize;
71
72    #[objc::msg_send(indexLessThanIndex:)]
73    pub fn index_lt(&self, val: usize) -> usize;
74
75    #[objc::msg_send(indexGreaterThanOrEqualToIndex:)]
76    pub fn index_ge(&self, val: usize) -> usize;
77
78    #[objc::msg_send(indexLessThanOrEqualToIndex:)]
79    pub fn index_le(&self, val: usize) -> usize;
80
81    #[objc::msg_send(containsIndex:)]
82    pub fn contains_index(&self, val: usize) -> bool;
83
84    #[objc::msg_send(containsIndexesInRange:)]
85    pub fn contains_index_in(&self, val: ns::Range) -> bool;
86
87    #[objc::msg_send(containsIndexes:)]
88    pub fn contains_indexes(&self, val: &ns::IndexSet) -> bool;
89
90    #[objc::msg_send(intersectsIndexesInRange:)]
91    pub fn intersects_range(&self, val: ns::Range) -> bool;
92
93    #[objc::msg_send(countOfIndexesInRange:)]
94    pub fn count_in_range(&self, val: ns::Range) -> usize;
95
96    #[objc::msg_send(isEqualToIndexSet:)]
97    pub fn is_equal_to_index_set(&self, val: &ns::IndexSet) -> bool;
98
99    #[objc::msg_send(mutableCopy)]
100    pub fn copy_mut(&self) -> arc::Retained<IndexSetMut>;
101
102    #[objc::msg_send(copy)]
103    pub fn copy(&self) -> arc::Retained<IndexSet>;
104}
105
106#[cfg(feature = "blocks")]
107impl IndexSet {
108    #[objc::msg_send(enumerateIndexesUsingBlock:)]
109    pub fn enum_indexes_block(&self, block: &mut blocks::NoEscBlock<fn(usize, &mut bool)>);
110
111    #[objc::msg_send(enumerateRangesUsingBlock:)]
112    pub fn enum_ranges_block(&self, block: &mut blocks::NoEscBlock<fn(ns::Range, &mut bool)>);
113
114    #[objc::msg_send(enumerateIndexesWithOptions:usingBlock:)]
115    pub fn enum_indexes_with_opts_block(
116        &self,
117        opts: ns::EnumerationOpts,
118        block: &mut blocks::NoEscBlock<fn(usize, &mut bool)>,
119    );
120
121    #[objc::msg_send(indexPassingTest:)]
122    pub fn index_passing_test_block(
123        &self,
124        predicate: &mut blocks::NoEscBlock<fn(usize, &mut bool) -> bool>,
125    ) -> usize;
126
127    #[inline]
128    pub fn enum_indexes(&self, mut block: impl FnMut(usize, &mut bool)) {
129        unsafe {
130            let mut block = blocks::NoEscBlock::stack2(&mut block);
131            self.enum_indexes_block(&mut block)
132        }
133    }
134
135    #[inline]
136    pub fn enum_ranges(&self, mut block: impl FnMut(ns::Range, &mut bool)) {
137        unsafe {
138            let mut block = blocks::NoEscBlock::stack2(&mut block);
139            self.enum_ranges_block(&mut block)
140        }
141    }
142
143    #[inline]
144    pub fn enum_indexes_with_opts(
145        &self,
146        opts: ns::EnumerationOpts,
147        mut block: impl FnMut(usize, &mut bool),
148    ) {
149        unsafe {
150            let mut block = blocks::NoEscBlock::stack2(&mut block);
151            self.enum_indexes_with_opts_block(opts, &mut block)
152        }
153    }
154
155    #[inline]
156    pub fn index_passing_test(&self, mut predicate: impl FnMut(usize, &mut bool) -> bool) -> usize {
157        unsafe {
158            let mut predicate = blocks::NoEscBlock::stack2(&mut predicate);
159            self.index_passing_test_block(&mut predicate)
160        }
161    }
162}
163
164impl IndexSetMut {
165    #[inline]
166    pub fn with_index(val: usize) -> arc::R<Self> {
167        Self::alloc().init_with_index(val)
168    }
169
170    #[inline]
171    pub fn with_index_set(val: &ns::IndexSet) -> arc::R<Self> {
172        Self::alloc().init_with_index_set(val)
173    }
174
175    #[inline]
176    pub fn with_range(val: ns::Range) -> arc::R<Self> {
177        Self::alloc().init_with_range(val)
178    }
179
180    #[objc::msg_send(addIndexes:)]
181    pub fn add_indexes(&mut self, val: &ns::IndexSet);
182
183    #[objc::msg_send(removeIndexes:)]
184    pub fn remove_indexes(&mut self, val: &ns::IndexSet);
185
186    #[objc::msg_send(removeAllIndexes)]
187    pub fn clear(&mut self);
188
189    #[objc::msg_send(addIndex:)]
190    pub fn add(&mut self, val: usize);
191
192    #[objc::msg_send(removeIndex:)]
193    pub fn remove(&mut self, val: usize);
194
195    #[objc::msg_send(addIndexesInRange:)]
196    pub fn add_range(&mut self, val: ns::Range);
197
198    #[objc::msg_send(removeIndexesInRange:)]
199    pub fn remove_range(&mut self, val: ns::Range);
200
201    #[objc::msg_send(shiftIndexesStartingAtIndex:by:)]
202    pub fn shift_starting_at(&mut self, index: usize, delta: ns::Integer);
203}
204
205impl Default for arc::R<IndexSetMut> {
206    fn default() -> Self {
207        IndexSetMut::with_range(Default::default())
208    }
209}
210
211unsafe extern "C" {
212    static NS_INDEX_SET: &'static objc::Class<IndexSet>;
213    static NS_MUTABLE_INDEX_SET: &'static objc::Class<IndexSetMut>;
214}
215
216#[cfg(test)]
217mod tests {
218    use crate::ns;
219
220    #[test]
221    fn basics() {
222        let set_a = ns::IndexSet::with_index(10);
223        assert_eq!(set_a.len(), 1);
224
225        assert!(set_a.contains_index(10));
226        assert!(!set_a.contains_index(0));
227
228        let set_b = ns::IndexSet::with_index_set(&set_a);
229        assert_eq!(set_b.len(), 1);
230
231        assert!(set_a.contains_indexes(&set_b));
232
233        let range_set = ns::IndexSet::with_range(ns::Range::new(0, 100));
234        assert_eq!(range_set.len(), 100);
235        assert_eq!(range_set.first_index(), 0);
236        assert_eq!(range_set.last_index(), 99);
237        assert_eq!(range_set.index_gt(0), 1);
238        assert_eq!(range_set.index_lt(50), 49);
239        assert_eq!(range_set.index_ge(0), 0);
240        assert_eq!(range_set.index_le(50), 50);
241        assert!(range_set.intersects_range(ns::Range::new(50, 10)));
242        assert_eq!(range_set.count_in_range(ns::Range::new(10, 10)), 10);
243        assert!(range_set.is_equal_to_index_set(&ns::IndexSet::with_range(ns::Range::new(0, 100))));
244
245        let mut shifted = range_set.copy_mut();
246        shifted.shift_starting_at(50, 2);
247        assert!(!shifted.contains_index(50));
248        assert!(shifted.contains_index(52));
249
250        let mut copy = range_set.copy_mut();
251        assert!(copy.contains_index(10));
252        copy.remove(10);
253        assert!(!copy.contains_index(10));
254
255        copy.remove_range(ns::Range::new(0, 100));
256        assert!(copy.is_empty());
257
258        let _copy = copy.copy();
259    }
260
261    #[cfg(feature = "blocks")]
262    #[test]
263    fn enum_indexes() {
264        let range_set = ns::IndexSet::with_range(ns::Range::new(0, 5));
265        let mut seen = Vec::new();
266        range_set.enum_indexes(|idx, stop| {
267            seen.push(idx);
268            if idx == 2 {
269                *stop = true;
270            }
271        });
272        assert_eq!(seen, vec![0, 1, 2]);
273    }
274
275    #[cfg(feature = "blocks")]
276    #[test]
277    fn enum_ranges() {
278        let mut set = ns::IndexSetMut::with_range(ns::Range::new(0, 3));
279        set.add_range(ns::Range::new(5, 2));
280        let mut ranges = Vec::new();
281        set.enum_ranges(|range, _| ranges.push(range));
282        assert_eq!(&ranges, &[ns::Range::new(0, 3), ns::Range::new(5, 2)]);
283    }
284}