glib/
value_array.rs
1use std::{cmp::Ordering, ops, slice};
4
5use crate::{
6 ffi, gobject_ffi, prelude::*, translate::*, ParamSpecValueArray, ParamSpecValueArrayBuilder,
7 Type, Value,
8};
9
10wrapper! {
11 #[derive(Debug)]
12 #[doc(alias = "GValueArray")]
13 pub struct ValueArray(Boxed<gobject_ffi::GValueArray>);
14
15 match fn {
16 copy => |ptr| gobject_ffi::g_value_array_copy(mut_override(ptr)),
17 free => |ptr| gobject_ffi::g_value_array_free(ptr),
18 }
19}
20
21impl ValueArray {
22 #[inline]
23 pub fn new(values: impl IntoIterator<Item = impl ToValue>) -> Self {
24 let iter = values.into_iter();
25 let mut array = Self::with_capacity(iter.size_hint().0);
26 for v in iter {
27 array.append(v.to_value());
28 }
29
30 array
31 }
32
33 #[inline]
34 pub fn from_values(values: impl IntoIterator<Item = Value>) -> Self {
35 Self::new(values)
36 }
37
38 #[doc(alias = "g_value_array_new")]
39 #[inline]
40 pub fn with_capacity(capacity: usize) -> ValueArray {
41 assert!(capacity <= u32::MAX as usize);
42
43 unsafe { from_glib_full(gobject_ffi::g_value_array_new(capacity as u32)) }
44 }
45
46 #[inline]
47 pub fn is_empty(&self) -> bool {
48 self.len() == 0
49 }
50
51 #[inline]
52 pub fn len(&self) -> usize {
53 self.inner.n_values as usize
54 }
55
56 #[doc(alias = "g_value_array_append")]
57 #[inline]
58 pub fn append(&mut self, value: impl ToValue) {
59 self.append_value(&value.to_value());
60 }
61
62 #[doc(alias = "g_value_array_append")]
63 #[inline]
64 pub fn append_value(&mut self, value: &Value) {
65 unsafe {
66 gobject_ffi::g_value_array_append(self.to_glib_none_mut().0, value.to_glib_none().0);
67 }
68 }
69
70 #[doc(alias = "g_value_array_insert")]
71 #[inline]
72 pub fn insert(&mut self, index_: usize, value: impl ToValue) {
73 self.insert_value(index_, &value.to_value());
74 }
75
76 #[doc(alias = "g_value_array_insert")]
77 #[inline]
78 pub fn insert_value(&mut self, index_: usize, value: &Value) {
79 assert!(index_ <= self.len());
80
81 unsafe {
82 gobject_ffi::g_value_array_insert(
83 self.to_glib_none_mut().0,
84 index_ as u32,
85 value.to_glib_none().0,
86 );
87 }
88 }
89
90 #[doc(alias = "g_value_array_prepend")]
91 #[inline]
92 pub fn prepend(&mut self, value: impl ToValue) {
93 self.prepend_value(&value.to_value());
94 }
95
96 #[doc(alias = "g_value_array_prepend")]
97 #[inline]
98 pub fn prepend_value(&mut self, value: &Value) {
99 unsafe {
100 gobject_ffi::g_value_array_prepend(self.to_glib_none_mut().0, value.to_glib_none().0);
101 }
102 }
103
104 #[doc(alias = "g_value_array_remove")]
105 #[inline]
106 pub fn remove(&mut self, index_: usize) {
107 assert!(index_ < self.len());
108
109 unsafe {
110 gobject_ffi::g_value_array_remove(self.to_glib_none_mut().0, index_ as u32);
111 }
112 }
113
114 #[doc(alias = "g_value_array_sort_with_data")]
115 pub fn sort_with_data<F: FnMut(&Value, &Value) -> Ordering>(&mut self, compare_func: F) {
116 unsafe extern "C" fn compare_func_trampoline(
117 a: ffi::gconstpointer,
118 b: ffi::gconstpointer,
119 func: ffi::gpointer,
120 ) -> i32 {
121 let func = func as *mut &mut (dyn FnMut(&Value, &Value) -> Ordering);
122
123 let a = &*(a as *const Value);
124 let b = &*(b as *const Value);
125
126 (*func)(a, b).into_glib()
127 }
128 unsafe {
129 let mut func = compare_func;
130 let func_obj: &mut (dyn FnMut(&Value, &Value) -> Ordering) = &mut func;
131 let func_ptr =
132 &func_obj as *const &mut (dyn FnMut(&Value, &Value) -> Ordering) as ffi::gpointer;
133
134 gobject_ffi::g_value_array_sort_with_data(
135 self.to_glib_none_mut().0,
136 Some(compare_func_trampoline),
137 func_ptr,
138 );
139 }
140 }
141
142 #[inline]
143 pub fn as_slice(&self) -> &[Value] {
144 if self.is_empty() {
145 return &[];
146 }
147
148 unsafe {
149 slice::from_raw_parts(
150 (*self.as_ptr()).values as *const Value,
151 (*self.as_ptr()).n_values as usize,
152 )
153 }
154 }
155
156 #[inline]
157 pub fn as_mut_slice(&mut self) -> &mut [Value] {
158 if self.is_empty() {
159 return &mut [];
160 }
161
162 unsafe {
163 slice::from_raw_parts_mut(
164 (*self.as_ptr()).values as *mut Value,
165 (*self.as_ptr()).n_values as usize,
166 )
167 }
168 }
169}
170
171impl ops::Deref for ValueArray {
172 type Target = [Value];
173
174 #[inline]
175 fn deref(&self) -> &[Value] {
176 self.as_slice()
177 }
178}
179
180impl ops::DerefMut for ValueArray {
181 #[inline]
182 fn deref_mut(&mut self) -> &mut [Value] {
183 self.as_mut_slice()
184 }
185}
186
187impl Default for ValueArray {
188 fn default() -> Self {
189 Self::with_capacity(8)
190 }
191}
192
193impl std::iter::FromIterator<Value> for ValueArray {
194 fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
195 Self::from_values(iter)
196 }
197}
198
199impl std::iter::Extend<Value> for ValueArray {
200 fn extend<T: IntoIterator<Item = Value>>(&mut self, iter: T) {
201 for v in iter.into_iter() {
202 self.append_value(&v);
203 }
204 }
205}
206
207impl StaticType for ValueArray {
209 #[inline]
210 fn static_type() -> Type {
211 unsafe { from_glib(gobject_ffi::g_value_array_get_type()) }
212 }
213}
214
215#[doc(hidden)]
216impl ValueType for ValueArray {
217 type Type = Self;
218}
219
220#[doc(hidden)]
221impl crate::value::ValueTypeOptional for ValueArray {}
222
223#[doc(hidden)]
224unsafe impl<'a> crate::value::FromValue<'a> for ValueArray {
225 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
226
227 #[inline]
228 unsafe fn from_value(value: &'a Value) -> Self {
229 let ptr = gobject_ffi::g_value_dup_boxed(value.to_glib_none().0);
230 debug_assert!(!ptr.is_null());
231 from_glib_full(ptr as *mut gobject_ffi::GValueArray)
232 }
233}
234
235#[doc(hidden)]
236unsafe impl<'a> crate::value::FromValue<'a> for &'a ValueArray {
237 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
238
239 #[inline]
240 unsafe fn from_value(value: &'a Value) -> Self {
241 debug_assert_eq!(
242 std::mem::size_of::<Self>(),
243 std::mem::size_of::<ffi::gpointer>()
244 );
245 let value = &*(value as *const Value as *const gobject_ffi::GValue);
246 debug_assert!(!value.data[0].v_pointer.is_null());
247 <ValueArray>::from_glib_ptr_borrow(
248 &*(&value.data[0].v_pointer as *const ffi::gpointer
249 as *const *mut gobject_ffi::GValueArray),
250 )
251 }
252}
253
254#[doc(hidden)]
255impl ToValue for ValueArray {
256 #[inline]
257 fn to_value(&self) -> Value {
258 unsafe {
259 let mut value = Value::from_type_unchecked(<Self as StaticType>::static_type());
260 gobject_ffi::g_value_take_boxed(
261 value.to_glib_none_mut().0,
262 ToGlibPtr::<*mut gobject_ffi::GValueArray>::to_glib_full(self) as *mut _,
263 );
264 value
265 }
266 }
267
268 #[inline]
269 fn value_type(&self) -> Type {
270 <Self as StaticType>::static_type()
271 }
272}
273
274impl std::convert::From<ValueArray> for Value {
275 #[inline]
276 fn from(o: ValueArray) -> Self {
277 unsafe {
278 let mut value = Value::from_type_unchecked(<ValueArray as StaticType>::static_type());
279 gobject_ffi::g_value_take_boxed(
280 value.to_glib_none_mut().0,
281 IntoGlibPtr::<*mut gobject_ffi::GValueArray>::into_glib_ptr(o) as *mut _,
282 );
283 value
284 }
285 }
286}
287
288#[doc(hidden)]
289impl crate::value::ToValueOptional for ValueArray {
290 #[inline]
291 fn to_value_optional(s: Option<&Self>) -> Value {
292 let mut value = Value::for_value_type::<Self>();
293 unsafe {
294 gobject_ffi::g_value_take_boxed(
295 value.to_glib_none_mut().0,
296 ToGlibPtr::<*mut gobject_ffi::GValueArray>::to_glib_full(&s) as *mut _,
297 );
298 }
299
300 value
301 }
302}
303
304impl HasParamSpec for ValueArray {
305 type ParamSpec = ParamSpecValueArray;
306 type SetValue = Self;
307 type BuilderFn = fn(&str) -> ParamSpecValueArrayBuilder;
308
309 fn param_spec_builder() -> Self::BuilderFn {
310 Self::ParamSpec::builder
311 }
312}
313
314#[cfg(test)]
315mod tests {
316 use super::*;
317
318 #[test]
319 fn test_new() {
320 let arr = ValueArray::new(["123", "456"]);
321 assert_eq!(
322 arr.first().and_then(|v| v.get::<String>().ok()),
323 Some(String::from("123"))
324 );
325 assert_eq!(
326 arr.get(1).and_then(|v| v.get::<String>().ok()),
327 Some(String::from("456"))
328 );
329 }
330
331 #[test]
332 fn test_append() {
333 let mut arr = ValueArray::default();
334 arr.append("123");
335 arr.append(123u32);
336 arr.append_value(&Value::from(456u64));
337
338 assert_eq!(
339 arr.first().and_then(|v| v.get::<String>().ok()),
340 Some(String::from("123"))
341 );
342 assert_eq!(arr.get(1).and_then(|v| v.get::<u32>().ok()), Some(123));
343 assert_eq!(arr.get(2).and_then(|v| v.get::<u64>().ok()), Some(456));
344 }
345}