1use std::{
2 any::TypeId,
3 fmt,
4 hash::Hash,
5 iter::{FilterMap, FusedIterator},
6 marker::PhantomData,
7 ops::{Bound, RangeBounds},
8};
9
10use crate::{sys, AllocationError, Tag};
11
12pub struct Set<'a, T>(InnerSet, PhantomData<(&'a (), T)>);
16
17impl<T> Set<'static, T> {
18 #[doc(alias = "hb_set_create")]
20 pub fn new() -> Result<Self, AllocationError> {
21 let set = unsafe { sys::hb_set_create() };
22 if set.is_null() {
23 return Err(AllocationError);
24 }
25 Ok(Self(InnerSet(set), PhantomData))
26 }
27}
28
29impl<'a, T> Set<'a, T> {
30 #[doc(alias = "hb_set_is_empty")]
32 pub fn is_empty(&self) -> bool {
33 (unsafe { sys::hb_set_is_empty(self.as_raw()) }) != 0
34 }
35
36 #[doc(alias = "hb_set_get_population")]
51 pub fn len(&self) -> usize {
52 (unsafe { sys::hb_set_get_population(self.as_raw()) }) as usize
53 }
54
55 #[doc(alias = "hb_set_clear")]
57 pub fn clear(&mut self) {
58 unsafe { sys::hb_set_clear(self.as_raw()) }
59 }
60
61 #[doc(alias = "hb_set_set")]
63 pub fn copy_from(&mut self, other: &Self) {
64 unsafe { sys::hb_set_set(self.as_raw(), other.as_raw()) }
65 }
66
67 #[doc(alias = "hb_set_is_subset")]
69 pub fn contains_set(&self, other: &Self) -> bool {
70 (unsafe { sys::hb_set_is_subset(other.as_raw(), self.as_raw()) }) != 0
71 }
72
73 #[doc(alias = "hb_set_copy")]
75 pub fn clone_static(&self) -> Set<'static, T> {
76 Set(
77 InnerSet(unsafe { sys::hb_set_copy(self.as_raw()) }),
78 PhantomData,
79 )
80 }
81}
82
83impl<'a, T> Set<'a, T>
84where
85 T: Into<u32>,
86{
87 #[doc(alias = "hb_set_has")]
89 pub fn contains(&self, value: T) -> bool {
90 (unsafe { sys::hb_set_has(self.as_raw(), value.into()) }) != 0
91 }
92
93 #[doc(alias = "hb_set_add")]
99 pub fn insert(&mut self, value: T) {
100 let value = value.into();
101 assert_ne!(value, sys::HB_SET_VALUE_INVALID);
102 unsafe { sys::hb_set_add(self.as_raw(), value) }
103 }
104
105 #[doc(alias = "hb_set_del")]
107 pub fn remove(&mut self, value: T) {
108 unsafe { sys::hb_set_del(self.as_raw(), value.into()) }
109 }
110
111 fn range_to_bounds(range: impl RangeBounds<T>) -> Option<(u32, u32)>
113 where
114 T: Clone + 'static,
115 {
116 fn bound_to_u32<T: Clone + Into<u32>>(bound: Bound<&T>) -> Bound<u32> {
117 match bound {
118 Bound::Included(b) => Bound::Included(b.clone().into()),
119 Bound::Excluded(b) => Bound::Excluded(b.clone().into()),
120 Bound::Unbounded => Bound::Unbounded,
121 }
122 }
123 let lower = match bound_to_u32(range.start_bound()) {
124 Bound::Included(lower) => lower,
125 Bound::Excluded(lower) => {
126 if lower == u32::MAX {
127 return None;
128 } else {
129 lower + 1
130 }
131 }
132 Bound::Unbounded => 0,
133 };
134 let upper = match bound_to_u32(range.end_bound()) {
135 Bound::Included(upper) => {
136 assert_ne!(upper, sys::HB_SET_VALUE_INVALID);
137 upper
138 }
139 Bound::Excluded(upper) => {
140 if upper == 0 {
141 return None;
142 } else {
143 upper - 1
144 }
145 }
146 Bound::Unbounded => {
147 if TypeId::of::<T>() == TypeId::of::<char>() {
149 char::MAX as u32
150 } else {
151 u32::MAX - 1
152 }
153 }
154 };
155 if upper < lower {
156 return None;
157 }
158 Some((lower, upper))
159 }
160
161 #[doc(alias = "hb_set_add_range")]
183 pub fn insert_range(&mut self, range: impl RangeBounds<T>)
184 where
185 T: Clone + 'static,
186 {
187 let Some((lower, upper)) = Self::range_to_bounds(range) else {
188 return;
189 };
190 unsafe { sys::hb_set_add_range(self.as_raw(), lower, upper) }
191 }
192
193 #[doc(alias = "hb_set_del_range")]
195 pub fn remove_range(&mut self, range: impl RangeBounds<T>)
196 where
197 T: Clone + 'static,
198 {
199 #[allow(clippy::assertions_on_constants, clippy::absurd_extreme_comparisons)]
201 const _: () = assert!(u32::MAX <= sys::HB_SET_VALUE_INVALID);
202 let Some((lower, upper)) = Self::range_to_bounds(range) else {
203 return;
204 };
205 unsafe { sys::hb_set_del_range(self.as_raw(), lower, upper) }
206 }
207}
208
209impl<'a, T> Set<'a, T>
210where
211 T: TryFrom<u32>,
212{
213 #[doc(alias = "hb_set_next")]
215 #[doc(alias = "hb_set_previous")]
216 pub fn iter(&self) -> SetIter<'_, 'a, T> {
217 SetIter(SetIterImpl::new(self).filter_map(|v| v.try_into().ok()))
218 }
219}
220
221impl<'a, T> Set<'a, T> {
222 pub fn into_raw(self) -> *mut sys::hb_set_t {
227 let ptr = self.0 .0;
228 std::mem::forget(self);
229 ptr
230 }
231
232 pub fn as_raw(&self) -> *mut sys::hb_set_t {
236 self.0 .0
237 }
238
239 pub unsafe fn from_raw(set: *mut sys::hb_set_t) -> Self {
245 Self(InnerSet(set), PhantomData)
246 }
247}
248
249impl<'a, T> Hash for Set<'a, T> {
250 #[doc(alias = "hb_set_hash")]
251 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
252 unsafe { sys::hb_set_hash(self.as_raw()) }.hash(state);
253 }
254}
255
256impl<'a, T> PartialEq for Set<'a, T> {
257 #[doc(alias = "hb_set_is_equal")]
258 fn eq(&self, other: &Self) -> bool {
259 (unsafe { sys::hb_set_is_equal(self.as_raw(), other.as_raw()) }) != 0
260 }
261}
262
263impl<'a, T> Eq for Set<'a, T> where T: Eq {}
264
265impl<'a, T> Clone for Set<'a, T> {
266 fn clone(&self) -> Self {
267 self.clone_static()
268 }
269}
270
271impl<'a, T> fmt::Debug for Set<'a, T>
272where
273 T: TryFrom<u32> + fmt::Debug,
274{
275 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276 f.debug_set().entries(self).finish()
277 }
278}
279
280impl<'a, T> FromIterator<T> for Set<'a, T>
281where
282 T: Into<u32>,
283{
284 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
285 let mut set = Set::new().unwrap();
286 for item in iter {
287 set.insert(item);
288 }
289 set
290 }
291}
292
293impl<'s, 'a, T> IntoIterator for &'s Set<'a, T>
294where
295 T: TryFrom<u32>,
296{
297 type Item = T;
298 type IntoIter = SetIter<'s, 'a, T>;
299
300 fn into_iter(self) -> Self::IntoIter {
301 self.iter()
302 }
303}
304
305pub struct SetIter<'s, 'a, T>(SetIterFilter<'s, 'a, T>);
309type SetIterFilter<'s, 'a, T> = FilterMap<SetIterImpl<'s, 'a, T>, fn(u32) -> Option<T>>;
310
311impl<'s, 'a, T> Iterator for SetIter<'s, 'a, T>
312where
313 T: TryFrom<u32>,
314{
315 type Item = T;
316
317 fn next(&mut self) -> Option<Self::Item> {
318 self.0.next()
319 }
320}
321
322impl<'s, 'a, T> DoubleEndedIterator for SetIter<'s, 'a, T>
323where
324 T: TryFrom<u32>,
325{
326 fn next_back(&mut self) -> Option<Self::Item> {
327 self.0.next_back()
328 }
329}
330
331impl<'s, 'a, T> FusedIterator for SetIter<'s, 'a, T> where T: TryFrom<u32> {}
332
333struct SetIterImpl<'s, 'a, T>(&'s Set<'a, T>, u32, u32);
338
339impl<'s, 'a, T> SetIterImpl<'s, 'a, T> {
340 const LAST_VALUE: u32 = sys::HB_SET_VALUE_INVALID - 1;
341 fn new(set: &'s Set<'a, T>) -> Self {
342 #[allow(clippy::assertions_on_constants, clippy::absurd_extreme_comparisons)]
343 const _: () = assert!(u32::MAX == sys::HB_SET_VALUE_INVALID);
344 Self(set, sys::HB_SET_VALUE_INVALID, sys::HB_SET_VALUE_INVALID)
345 }
346
347 fn mark_ended(&mut self) {
348 self.1 = Self::LAST_VALUE;
349 self.2 = 0;
350 }
351}
352
353impl<'s, 'a, T> Iterator for SetIterImpl<'s, 'a, T> {
354 type Item = u32;
355
356 fn next(&mut self) -> Option<Self::Item> {
357 match self.1 {
358 Self::LAST_VALUE => {
359 None
361 }
362 _ => {
363 let has_value =
364 (unsafe { sys::hb_set_next(self.0.as_raw(), &mut self.1 as *mut u32) }) != 0;
365 if has_value {
366 if self.1 >= self.2 {
367 self.mark_ended();
368 None
369 } else {
370 Some(self.1)
371 }
372 } else {
373 self.mark_ended();
374 None
375 }
376 }
377 }
378 }
379}
380
381impl<'s, 'a, T> DoubleEndedIterator for SetIterImpl<'s, 'a, T> {
382 fn next_back(&mut self) -> Option<Self::Item> {
383 match self.2 {
384 0 => {
385 None
387 }
388 _ => {
389 let has_value =
390 (unsafe { sys::hb_set_previous(self.0.as_raw(), &mut self.2 as *mut u32) })
391 != 0;
392 if has_value {
393 if self.1 != sys::HB_SET_VALUE_INVALID && self.1 >= self.2 {
394 self.mark_ended();
395 None
396 } else {
397 Some(self.2)
398 }
399 } else {
400 self.mark_ended();
401 None
402 }
403 }
404 }
405 }
406}
407
408struct InnerSet(*mut sys::hb_set_t);
424
425impl Drop for InnerSet {
426 #[doc(alias = "hb_set_destroy")]
427 fn drop(&mut self) {
428 unsafe { sys::hb_set_destroy(self.0) }
429 }
430}
431
432pub type CharSet<'a> = Set<'a, char>;
434
435pub type U32Set<'a> = Set<'a, u32>;
439
440pub type TagSet<'a> = Set<'a, Tag>;
442
443#[cfg(test)]
444mod tests {
445 use super::*;
446
447 #[test]
448 fn is_empty_works() {
449 let mut set = U32Set::new().unwrap();
450 assert!(set.is_empty());
451 assert!(set.is_empty());
452 set.insert(10);
453 assert!(!set.is_empty());
454 set.insert(20);
455 assert!(!set.is_empty());
456 set.remove(10);
457 assert!(!set.is_empty());
458 set.remove(20);
459 assert!(set.is_empty());
460 }
461
462 #[test]
463 fn len_works() {
464 let mut set = U32Set::new().unwrap();
465 assert_eq!(set.len(), 0);
466 set.insert(10);
467 assert_eq!(set.len(), 1);
468 set.insert_range(5..15);
469 assert_eq!(set.len(), 10);
470 set.remove(13);
471 assert_eq!(set.len(), 9);
472 }
473
474 #[test]
475 fn clear_empties_set() {
476 let mut set = U32Set::new().unwrap();
477 set.insert_range(123..456);
478 assert!(!set.is_empty());
479 assert_eq!(set.len(), 333);
480 set.clear();
481 assert!(set.is_empty());
482 assert_eq!(set.len(), 0);
483 }
484
485 #[test]
486 #[should_panic]
487 fn cannot_insert_u32_max() {
488 let mut set = U32Set::new().unwrap();
489 set.insert(u32::MAX);
490 }
491
492 #[test]
493 #[should_panic]
494 fn cannot_insert_range_u32_max() {
495 let mut set = U32Set::new().unwrap();
496 set.insert_range(..=u32::MAX);
497 }
498
499 #[test]
500 fn does_not_contain_u32_max() {
501 let mut set = U32Set::new().unwrap();
502 set.insert_range(..);
503 assert!(!set.contains(u32::MAX));
504 }
505
506 #[test]
507 fn can_contain_max_value() {
508 let mut set = U32Set::new().unwrap();
509 set.insert(u32::MAX - 1);
510 assert!(set.contains(u32::MAX - 1));
511 assert!(!set.is_empty());
512 assert_eq!(set.len(), 1);
513 }
514
515 #[test]
516 fn copy_from_works() {
517 let mut a = U32Set::new().unwrap();
518 a.insert(5);
519 let mut b = U32Set::new().unwrap();
520 b.insert(10);
521 assert_eq!(a.iter().collect::<Vec<_>>(), [5]);
522 assert_eq!(b.iter().collect::<Vec<_>>(), [10]);
523 a.copy_from(&b);
524 assert_eq!(a.iter().collect::<Vec<_>>(), [10]);
525 b.insert(1);
526 assert_eq!(a.iter().collect::<Vec<_>>(), [10]);
527 a.remove(10);
528 assert_eq!(b.iter().collect::<Vec<_>>(), [1, 10]);
529 }
530
531 #[test]
532 fn contains_its_subset() {
533 let mut a = U32Set::new().unwrap();
534 a.insert_range(5..=15);
535 a.insert_range(55..=65);
536 assert!(a.contains_set(&a));
537 let mut b = U32Set::new().unwrap();
538 b.insert_range(7..=14);
539 b.insert(60);
540 assert!(b.contains_set(&b));
541 assert!(a.contains_set(&b));
542 assert!(!b.contains_set(&a));
543 b.insert(65);
544 assert!(a.contains_set(&b));
545 b.insert(66);
546 assert!(!a.contains_set(&b));
547 assert!(!b.contains_set(&a));
548 }
549
550 #[test]
551 fn contains_inserted_values() {
552 let mut set = U32Set::new().unwrap();
553 set.insert(1);
554 assert!(!set.contains(3));
555 set.insert(1);
556 assert!(!set.contains(3));
557 set.insert(3);
558 assert!(set.contains(3));
559 set.remove(1);
560 assert!(set.contains(3));
561 set.remove(3);
562 assert!(!set.contains(3));
563 }
564
565 #[test]
566 fn range_insertions_and_deletions_work() {
567 let mut set = U32Set::new().unwrap();
568 set.insert_range(0..100);
569 assert_eq!(set.len(), 100);
570 set.remove_range(21..=30);
571 assert_eq!(set.len(), 90);
572 set.remove_range(90..200);
573 assert_eq!(set.len(), 80);
574 }
575
576 #[test]
577 fn convert_into_raw_and_back() {
578 let set = U32Set::new().unwrap();
579 let set_ptr = set.into_raw();
580 let set = unsafe { U32Set::from_raw(set_ptr) };
581 drop(set);
582 }
583
584 #[test]
585 fn equal_works() {
586 let mut a = U32Set::new().unwrap();
587 for i in 0..10 {
588 a.insert(i);
589 }
590 assert_eq!(a, a);
591 let mut b = U32Set::new().unwrap();
592 assert_ne!(a, b);
593 b.insert_range(0..10);
594 assert_eq!(a, b);
595 }
596
597 #[test]
598 fn debug_works() {
599 let mut set = U32Set::new().unwrap();
600 set.insert_range(3..=5);
601 set.insert(7);
602 let mut str = String::new();
603 use fmt::Write;
604 write!(&mut str, "{set:?}").unwrap();
605 assert_eq!(str, "{3, 4, 5, 7}");
606 }
607
608 #[test]
609 fn cloned_set_does_not_modify_original() {
610 let mut a = U32Set::new().unwrap();
611 a.insert(3);
612 a.insert(5);
613 let mut b = a.clone();
614 assert_eq!(a.len(), 2);
615 assert_eq!(b.len(), 2);
616 a.insert(10);
617 assert_eq!(a.len(), 3);
618 assert_eq!(b.len(), 2);
619 b.remove(3);
620 assert_eq!(a.len(), 3);
621 assert_eq!(b.len(), 1);
622 }
623
624 #[test]
625 fn iter_works() {
626 let mut set = U32Set::new().unwrap();
627 assert!(set.iter().next().is_none());
628 set.insert(0);
629 assert_eq!(set.iter().collect::<Vec<_>>(), [0]);
630 set.insert(0);
631 assert_eq!(set.iter().collect::<Vec<_>>(), [0]);
632 set.insert(10);
633 assert_eq!(set.iter().collect::<Vec<_>>(), [0, 10]);
634 set.insert_range(6..12);
635 assert_eq!(set.iter().collect::<Vec<_>>(), [0, 6, 7, 8, 9, 10, 11]);
636 set.remove_range(8..=10);
637 assert_eq!(set.iter().collect::<Vec<_>>(), [0, 6, 7, 11]);
638 }
639
640 #[test]
641 fn iter_near_max_works() {
642 let mut set = U32Set::new().unwrap();
643 set.insert(u32::MAX - 3);
644 set.insert(u32::MAX - 2);
645 assert_eq!(set.iter().collect::<Vec<_>>(), [u32::MAX - 3, u32::MAX - 2]);
646 set.insert(u32::MAX - 1);
647 assert_eq!(
648 set.iter().collect::<Vec<_>>(),
649 [u32::MAX - 3, u32::MAX - 2, u32::MAX - 1]
650 );
651 set.clear();
652 assert!(set.is_empty());
653 set.insert_range((Bound::Excluded(u32::MAX - 3), Bound::Unbounded));
654 assert_eq!(set.iter().collect::<Vec<_>>(), [u32::MAX - 2, u32::MAX - 1]);
655 }
656
657 #[test]
658 fn iter_of_invalid_codepoints_works() {
659 let mut set = CharSet::new().unwrap();
660 set.insert_range('\u{D7FF}'..'\u{E001}'); assert_eq!(set.iter().collect::<Vec<_>>(), ['\u{D7FF}', '\u{E000}']);
662
663 let mut set = CharSet::new().unwrap();
664 set.insert_range('\u{10FFFF}'..);
665 assert_eq!(set.iter().collect::<Vec<_>>(), ['\u{10FFFF}']);
666 }
667
668 #[test]
669 fn iter_is_fused() {
670 fn assert_fused(mut iter: impl Iterator) {
671 while let Some(_) = iter.next() {}
672 for _ in 0..10 {
673 assert!(iter.next().is_none());
674 }
675 }
677 let mut set = U32Set::new().unwrap();
678 assert_fused(set.iter());
679 assert_fused(set.iter().rev());
680 set.insert(0);
681 assert_fused(set.iter());
682 assert_fused(set.iter().rev());
683 set.insert(1);
684 assert_fused(set.iter());
685 assert_fused(set.iter().rev());
686 set.insert(u32::MAX - 3);
687 assert_fused(set.iter());
688 assert_fused(set.iter().rev());
689 set.insert(u32::MAX - 2);
690 assert_fused(set.iter());
691 assert_fused(set.iter().rev());
692 set.insert(u32::MAX - 1);
693 assert_fused(set.iter());
694 assert_fused(set.iter().rev());
695
696 let mut iter = set.iter();
697 assert_eq!(iter.next_back(), Some(u32::MAX - 1));
698 assert_fused(iter);
699
700 let mut iter = set.iter().rev();
701 assert_eq!(iter.next_back(), Some(0));
702 assert_fused(iter);
703 }
704
705 #[test]
706 fn iter_next_back_works() {
707 let mut set = U32Set::new().unwrap();
708 assert!(set.iter().next().is_none());
709 set.insert(0);
710 set.insert_range(6..12);
711 assert_eq!(
712 set.iter().rev().collect::<Vec<_>>(),
713 [11, 10, 9, 8, 7, 6, 0]
714 );
715 set.remove_range(8..=10);
716 assert_eq!(set.iter().rev().collect::<Vec<_>>(), [11, 7, 6, 0]);
717
718 let mut iter = set.iter();
719 assert_eq!(iter.next(), Some(0));
720 assert_eq!(iter.next_back(), Some(11));
721 assert_eq!(iter.next_back(), Some(7));
722 assert_eq!(iter.next(), Some(6));
723 assert_eq!(iter.next(), None);
724 assert_eq!(iter.next_back(), None);
725
726 let mut iter = set.iter();
727 assert_eq!(iter.next_back(), Some(11));
728 assert_eq!(iter.next_back(), Some(7));
729 assert_eq!(iter.next(), Some(0));
730 assert_eq!(iter.next(), Some(6));
731 assert_eq!(iter.next_back(), None);
732 assert_eq!(iter.next(), None);
733
734 let mut iter = set.iter();
735 assert_eq!(iter.next_back(), Some(11));
736 assert_eq!(iter.next_back(), Some(7));
737 assert_eq!(iter.next(), Some(0));
738 assert_eq!(iter.next_back(), Some(6));
739 assert_eq!(iter.next_back(), None);
740 assert_eq!(iter.next(), None);
741
742 let mut iter = set.iter();
743 assert_eq!(iter.next_back(), Some(11));
744 assert_eq!(iter.next_back(), Some(7));
745 assert_eq!(iter.next(), Some(0));
746 assert_eq!(iter.next_back(), Some(6));
747 assert_eq!(iter.next(), None);
748 assert_eq!(iter.next_back(), None);
749 }
750}