1use std::{cmp::Ordering, ops, slice};
4
5use crate::{
6 ParamSpecValueArray, ParamSpecValueArrayBuilder, Type, Value, ffi, gobject_ffi, prelude::*,
7 translate::*,
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 unsafe {
122 let func = func as *mut &mut dyn FnMut(&Value, &Value) -> Ordering;
123
124 let a = &*(a as *const Value);
125 let b = &*(b as *const Value);
126
127 (*func)(a, b).into_glib()
128 }
129 }
130 unsafe {
131 let mut func = compare_func;
132 let func_obj: &mut dyn FnMut(&Value, &Value) -> Ordering = &mut func;
133 let func_ptr =
134 &func_obj as *const &mut dyn FnMut(&Value, &Value) -> Ordering as ffi::gpointer;
135
136 gobject_ffi::g_value_array_sort_with_data(
137 self.to_glib_none_mut().0,
138 Some(compare_func_trampoline),
139 func_ptr,
140 );
141 }
142 }
143
144 #[inline]
145 pub fn as_slice(&self) -> &[Value] {
146 if self.is_empty() {
147 return &[];
148 }
149
150 unsafe {
151 slice::from_raw_parts(
152 (*self.as_ptr()).values as *const Value,
153 (*self.as_ptr()).n_values as usize,
154 )
155 }
156 }
157
158 #[inline]
159 pub fn as_mut_slice(&mut self) -> &mut [Value] {
160 if self.is_empty() {
161 return &mut [];
162 }
163
164 unsafe {
165 slice::from_raw_parts_mut(
166 (*self.as_ptr()).values as *mut Value,
167 (*self.as_ptr()).n_values as usize,
168 )
169 }
170 }
171}
172
173impl ops::Deref for ValueArray {
174 type Target = [Value];
175
176 #[inline]
177 fn deref(&self) -> &[Value] {
178 self.as_slice()
179 }
180}
181
182impl ops::DerefMut for ValueArray {
183 #[inline]
184 fn deref_mut(&mut self) -> &mut [Value] {
185 self.as_mut_slice()
186 }
187}
188
189impl Default for ValueArray {
190 fn default() -> Self {
191 Self::with_capacity(8)
192 }
193}
194
195impl std::iter::FromIterator<Value> for ValueArray {
196 fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
197 Self::from_values(iter)
198 }
199}
200
201impl std::iter::Extend<Value> for ValueArray {
202 fn extend<T: IntoIterator<Item = Value>>(&mut self, iter: T) {
203 for v in iter.into_iter() {
204 self.append_value(&v);
205 }
206 }
207}
208
209impl StaticType for ValueArray {
211 #[inline]
212 fn static_type() -> Type {
213 unsafe { from_glib(gobject_ffi::g_value_array_get_type()) }
214 }
215}
216
217#[doc(hidden)]
218impl ValueType for ValueArray {
219 type Type = Self;
220}
221
222#[doc(hidden)]
223impl crate::value::ValueTypeOptional for ValueArray {}
224
225#[doc(hidden)]
226unsafe impl<'a> crate::value::FromValue<'a> for ValueArray {
227 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
228
229 #[inline]
230 unsafe fn from_value(value: &'a Value) -> Self {
231 unsafe {
232 let ptr = gobject_ffi::g_value_dup_boxed(value.to_glib_none().0);
233 debug_assert!(!ptr.is_null());
234 from_glib_full(ptr as *mut gobject_ffi::GValueArray)
235 }
236 }
237}
238
239#[doc(hidden)]
240unsafe impl<'a> crate::value::FromValue<'a> for &'a ValueArray {
241 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
242
243 #[inline]
244 unsafe fn from_value(value: &'a Value) -> Self {
245 unsafe {
246 debug_assert_eq!(
247 std::mem::size_of::<Self>(),
248 std::mem::size_of::<ffi::gpointer>()
249 );
250 let value = &*(value as *const Value as *const gobject_ffi::GValue);
251 debug_assert!(!value.data[0].v_pointer.is_null());
252 <ValueArray>::from_glib_ptr_borrow(
253 &*(&value.data[0].v_pointer as *const ffi::gpointer
254 as *const *mut gobject_ffi::GValueArray),
255 )
256 }
257 }
258}
259
260#[doc(hidden)]
261impl ToValue for ValueArray {
262 #[inline]
263 fn to_value(&self) -> Value {
264 unsafe {
265 let mut value = Value::from_type_unchecked(<Self as StaticType>::static_type());
266 gobject_ffi::g_value_take_boxed(
267 value.to_glib_none_mut().0,
268 ToGlibPtr::<*mut gobject_ffi::GValueArray>::to_glib_full(self) as *mut _,
269 );
270 value
271 }
272 }
273
274 #[inline]
275 fn value_type(&self) -> Type {
276 <Self as StaticType>::static_type()
277 }
278}
279
280impl std::convert::From<ValueArray> for Value {
281 #[inline]
282 fn from(o: ValueArray) -> Self {
283 unsafe {
284 let mut value = Value::from_type_unchecked(<ValueArray as StaticType>::static_type());
285 gobject_ffi::g_value_take_boxed(
286 value.to_glib_none_mut().0,
287 IntoGlibPtr::<*mut gobject_ffi::GValueArray>::into_glib_ptr(o) as *mut _,
288 );
289 value
290 }
291 }
292}
293
294#[doc(hidden)]
295impl crate::value::ToValueOptional for ValueArray {
296 #[inline]
297 fn to_value_optional(s: Option<&Self>) -> Value {
298 let mut value = Value::for_value_type::<Self>();
299 unsafe {
300 gobject_ffi::g_value_take_boxed(
301 value.to_glib_none_mut().0,
302 ToGlibPtr::<*mut gobject_ffi::GValueArray>::to_glib_full(&s) as *mut _,
303 );
304 }
305
306 value
307 }
308}
309
310impl HasParamSpec for ValueArray {
311 type ParamSpec = ParamSpecValueArray;
312 type SetValue = Self;
313 type BuilderFn = fn(&str) -> ParamSpecValueArrayBuilder;
314
315 fn param_spec_builder() -> Self::BuilderFn {
316 Self::ParamSpec::builder
317 }
318}
319
320#[cfg(test)]
321mod tests {
322 use super::*;
323
324 #[test]
325 fn test_new() {
326 let arr = ValueArray::new(["123", "456"]);
327 assert_eq!(
328 arr.first().and_then(|v| v.get::<String>().ok()),
329 Some(String::from("123"))
330 );
331 assert_eq!(
332 arr.get(1).and_then(|v| v.get::<String>().ok()),
333 Some(String::from("456"))
334 );
335 }
336
337 #[test]
338 fn test_append() {
339 let mut arr = ValueArray::default();
340 arr.append("123");
341 arr.append(123u32);
342 arr.append_value(&Value::from(456u64));
343
344 assert_eq!(
345 arr.first().and_then(|v| v.get::<String>().ok()),
346 Some(String::from("123"))
347 );
348 assert_eq!(arr.get(1).and_then(|v| v.get::<u32>().ok()), Some(123));
349 assert_eq!(arr.get(2).and_then(|v| v.get::<u64>().ok()), Some(456));
350 }
351}