gtk4/
bitset_iter.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::marker::PhantomData;
4
5use glib::translate::*;
6
7use crate::{ffi, Bitset};
8
9/// An opaque, stack-allocated struct for iterating
10/// over the elements of a [`Bitset`][crate::Bitset].
11///
12/// Before a [`BitsetIter`][crate::BitsetIter] can be used, it needs to be initialized with
13/// [`init_first()`][Self::init_first()], [`init_last()`][Self::init_last()]
14/// or [`init_at()`][Self::init_at()].
15#[derive(Copy, Clone)]
16#[doc(alias = "GtkBitsetIter")]
17#[repr(transparent)]
18pub struct BitsetIter<'a>(ffi::GtkBitsetIter, PhantomData<&'a Bitset>);
19
20impl<'a> BitsetIter<'a> {
21    #[doc(alias = "gtk_bitset_iter_init_at")]
22    pub fn init_at(set: &'a Bitset, target: u32) -> Option<(Self, u32)> {
23        assert_initialized_main_thread!();
24        unsafe {
25            let mut iter = std::mem::MaybeUninit::uninit();
26            let mut value = std::mem::MaybeUninit::uninit();
27            let found: bool = from_glib(ffi::gtk_bitset_iter_init_at(
28                iter.as_mut_ptr(),
29                set.to_glib_none().0,
30                target,
31                value.as_mut_ptr(),
32            ));
33
34            if found {
35                Some((
36                    BitsetIter(iter.assume_init(), PhantomData),
37                    value.assume_init(),
38                ))
39            } else {
40                None
41            }
42        }
43    }
44
45    #[doc(alias = "gtk_bitset_iter_init_first")]
46    pub fn init_first(set: &'a Bitset) -> Option<(Self, u32)> {
47        assert_initialized_main_thread!();
48        unsafe {
49            let mut iter = std::mem::MaybeUninit::uninit();
50            let mut value = std::mem::MaybeUninit::uninit();
51            let found: bool = from_glib(ffi::gtk_bitset_iter_init_first(
52                iter.as_mut_ptr(),
53                set.to_glib_none().0,
54                value.as_mut_ptr(),
55            ));
56            if found {
57                Some((
58                    BitsetIter(iter.assume_init(), PhantomData),
59                    value.assume_init(),
60                ))
61            } else {
62                None
63            }
64        }
65    }
66
67    #[doc(alias = "gtk_bitset_iter_init_last")]
68    pub fn init_last(set: &'a Bitset) -> Option<(Self, u32)> {
69        assert_initialized_main_thread!();
70        unsafe {
71            let mut iter = std::mem::MaybeUninit::uninit();
72            let mut value = std::mem::MaybeUninit::uninit();
73            let found: bool = from_glib(ffi::gtk_bitset_iter_init_last(
74                iter.as_mut_ptr(),
75                set.to_glib_none().0,
76                value.as_mut_ptr(),
77            ));
78            if found {
79                Some((
80                    BitsetIter(iter.assume_init(), PhantomData),
81                    value.assume_init(),
82                ))
83            } else {
84                None
85            }
86        }
87    }
88
89    #[doc(alias = "gtk_bitset_iter_get_value")]
90    pub fn value(&self) -> u32 {
91        unsafe { ffi::gtk_bitset_iter_get_value(self.to_glib_none().0) }
92    }
93
94    #[doc(alias = "gtk_bitset_iter_is_valid")]
95    pub fn is_valid(&self) -> bool {
96        unsafe { from_glib(ffi::gtk_bitset_iter_is_valid(self.to_glib_none().0)) }
97    }
98
99    #[doc(alias = "gtk_bitset_iter_previous")]
100    pub fn previous(&mut self) -> Option<u32> {
101        unsafe {
102            let mut value = std::mem::MaybeUninit::uninit();
103
104            let found: bool = from_glib(ffi::gtk_bitset_iter_previous(
105                &mut self.0 as *mut _,
106                value.as_mut_ptr(),
107            ));
108            if found {
109                Some(value.assume_init())
110            } else {
111                None
112            }
113        }
114    }
115}
116
117impl Iterator for BitsetIter<'_> {
118    type Item = u32;
119
120    #[doc(alias = "gtk_bitset_iter_next")]
121    fn next(&mut self) -> Option<Self::Item> {
122        unsafe {
123            let mut value = std::mem::MaybeUninit::uninit();
124
125            let found: bool = from_glib(ffi::gtk_bitset_iter_next(
126                &mut self.0 as *mut _,
127                value.as_mut_ptr(),
128            ));
129            if found {
130                Some(value.assume_init())
131            } else {
132                None
133            }
134        }
135    }
136}
137
138impl std::iter::FusedIterator for BitsetIter<'_> {}
139
140#[doc(hidden)]
141impl<'a> ToGlibPtr<'a, *const ffi::GtkBitsetIter> for BitsetIter<'a> {
142    type Storage = &'a Self;
143
144    #[inline]
145    fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GtkBitsetIter, Self> {
146        Stash(&self.0 as *const ffi::GtkBitsetIter, self)
147    }
148}
149
150#[cfg(test)]
151mod tests {
152    use super::*;
153    use crate as gtk4;
154
155    #[test]
156    fn test_bitset_iter() {
157        let set = Bitset::new_range(0, 20);
158        let (mut iter, init_value) = BitsetIter::init_first(&set).unwrap();
159        assert_eq!(init_value, 0);
160        assert_eq!(iter.next(), Some(1));
161        assert_eq!(iter.previous(), Some(0));
162
163        let set2 = Bitset::new_range(0, 3);
164        let (mut iter, init_val) = BitsetIter::init_last(&set2).unwrap();
165        assert_eq!(init_val, 2);
166        assert_eq!(iter.previous(), Some(1));
167        assert_eq!(iter.previous(), Some(0));
168        assert_eq!(iter.previous(), None);
169        assert!(!iter.is_valid());
170        assert_eq!(iter.next(), Some(1));
171        assert!(iter.is_valid());
172    }
173}