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}