gstreamer/
utils.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::prelude::*;
4
5// rustdoc-stripper-ignore-next
6/// Trait that allows accessing `Display` implementation on types external to this crate.
7pub trait Displayable {
8    type DisplayImpl: std::fmt::Display;
9
10    fn display(self) -> Self::DisplayImpl;
11}
12
13#[must_use = "if unused the object lock will immediately be released"]
14pub struct ObjectLockGuard<'a, T: ?Sized> {
15    obj: &'a T,
16    mutex: &'a mut glib::ffi::GMutex,
17}
18
19impl<'a, T> ObjectLockGuard<'a, T>
20where
21    T: IsA<crate::Object>,
22{
23    #[inline]
24    pub fn acquire(obj: &'a T) -> ObjectLockGuard<'a, T> {
25        skip_assert_initialized!();
26        unsafe {
27            let mutex = &mut (*obj.as_ref().as_ptr()).lock;
28            glib::ffi::g_mutex_lock(mutex);
29            Self { obj, mutex }
30        }
31    }
32}
33
34impl<T> AsRef<T> for ObjectLockGuard<'_, T> {
35    #[inline]
36    fn as_ref(&self) -> &T {
37        self.obj
38    }
39}
40
41impl<T> std::ops::Deref for ObjectLockGuard<'_, T> {
42    type Target = T;
43
44    #[inline]
45    fn deref(&self) -> &Self::Target {
46        self.obj
47    }
48}
49
50impl<T> std::fmt::Debug for ObjectLockGuard<'_, T>
51where
52    T: std::fmt::Debug,
53{
54    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55        self.obj.fmt(f)
56    }
57}
58
59impl<T> std::cmp::PartialEq for ObjectLockGuard<'_, T>
60where
61    T: std::cmp::PartialEq,
62{
63    fn eq(&self, other: &Self) -> bool {
64        self.obj.eq(other)
65    }
66}
67
68impl<T> std::cmp::Eq for ObjectLockGuard<'_, T> where T: std::cmp::Eq {}
69
70impl<T> Drop for ObjectLockGuard<'_, T>
71where
72    T: ?Sized,
73{
74    #[inline]
75    fn drop(&mut self) {
76        unsafe {
77            glib::ffi::g_mutex_unlock(self.mutex);
78        }
79    }
80}
81
82macro_rules! define_fixed_size_iter(
83    ($name:ident, $typ:ty, $ityp:ty, $get_len:expr, $get_item:expr) => {
84        #[must_use = "iterators are lazy and do nothing unless consumed"]
85        #[derive(Debug)]
86        pub struct $name<'a> {
87            pub(crate) collection: $typ,
88            idx: usize,
89            size: usize,
90        }
91
92        impl<'a> $name<'a> {
93            #[inline]
94            fn new(collection: $typ) -> $name<'a> {
95                skip_assert_initialized!();
96                let size = $get_len(collection) as usize;
97                $name {
98                    collection,
99                    idx: 0,
100                    size,
101                }
102            }
103        }
104
105        impl<'a> Iterator for $name<'a> {
106            type Item = $ityp;
107
108            #[inline]
109            fn next(&mut self) -> Option<Self::Item> {
110                if self.idx >= self.size {
111                    return None;
112                }
113
114                let item = $get_item(self.collection, self.idx);
115                self.idx += 1;
116
117                Some(item)
118            }
119
120            #[inline]
121            fn size_hint(&self) -> (usize, Option<usize>) {
122                let remaining = self.size - self.idx;
123
124                (remaining, Some(remaining))
125            }
126
127            #[inline]
128            fn count(self) -> usize {
129                self.size - self.idx
130            }
131
132            #[inline]
133            fn nth(&mut self, n: usize) -> Option<Self::Item> {
134                let (end, overflow) = self.idx.overflowing_add(n);
135                if end >= self.size || overflow {
136                    self.idx = self.size;
137                    None
138                } else {
139                    self.idx = end + 1;
140                    Some($get_item(self.collection, end))
141                }
142            }
143
144            #[inline]
145            fn last(self) -> Option<Self::Item> {
146                if self.idx == self.size {
147                    None
148                } else {
149                    Some($get_item(self.collection, self.size - 1))
150                }
151            }
152        }
153
154        impl DoubleEndedIterator for $name<'_> {
155            #[inline]
156            fn next_back(&mut self) -> Option<Self::Item> {
157                if self.idx == self.size {
158                    return None;
159                }
160
161                self.size -= 1;
162                Some($get_item(self.collection, self.size))
163            }
164
165            #[inline]
166            fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
167                let (end, overflow) = self.size.overflowing_sub(n);
168                if end <= self.idx || overflow {
169                    self.idx = self.size;
170                    None
171                } else {
172                    self.size = end - 1;
173                    Some($get_item(self.collection, self.size))
174                }
175            }
176        }
177
178        impl ExactSizeIterator for $name<'_> {}
179
180        impl std::iter::FusedIterator for $name<'_> {}
181    }
182);
183
184pub(crate) use define_fixed_size_iter;