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