gstreamer/
utils.rs
1use glib::prelude::*;
4
5pub 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;