1use libc::{c_char, c_void};
78use std::borrow::Borrow;
79use std::ffi::CStr;
80use std::fmt;
81use std::marker::PhantomData;
82use std::mem;
83use std::ops::Deref;
84use std::ptr;
85
86use glib_sys;
87use gobject_sys;
88use gstring::GString;
89use translate::*;
90use types::{StaticType, Type};
91
92#[repr(C)]
105pub struct Value(pub(crate) gobject_sys::GValue, PhantomData<*const c_void>);
106
107impl Value {
108 pub fn from_type(type_: Type) -> Self {
110 unsafe {
111 assert_eq!(
112 gobject_sys::g_type_check_is_value_type(type_.to_glib()),
113 glib_sys::GTRUE
114 );
115 let mut value = Value::uninitialized();
116 gobject_sys::g_value_init(value.to_glib_none_mut().0, type_.to_glib());
117 value
118 }
119 }
120
121 pub fn downcast<'a, T: FromValueOptional<'a> + SetValue>(self) -> Result<TypedValue<T>, Self> {
126 unsafe {
127 let ok = from_glib(gobject_sys::g_type_check_value_holds(
128 mut_override(self.to_glib_none().0),
129 T::static_type().to_glib(),
130 ));
131 if ok {
132 Ok(TypedValue(self, PhantomData))
133 } else {
134 Err(self)
135 }
136 }
137 }
138
139 pub fn downcast_ref<'a, T: FromValueOptional<'a> + SetValue>(&self) -> Option<&TypedValue<T>> {
144 unsafe {
145 let ok = from_glib(gobject_sys::g_type_check_value_holds(
146 mut_override(self.to_glib_none().0),
147 T::static_type().to_glib(),
148 ));
149 if ok {
150 Some(&*(self as *const Value as *const TypedValue<T>))
153 } else {
154 None
155 }
156 }
157 }
158
159 pub fn get<'a, T: FromValueOptional<'a>>(&'a self) -> Option<T> {
166 unsafe {
167 let ok = from_glib(gobject_sys::g_type_check_value_holds(
168 mut_override(self.to_glib_none().0),
169 T::static_type().to_glib(),
170 ));
171 if ok {
172 T::from_value_optional(self)
173 } else {
174 None
175 }
176 }
177 }
178
179 #[inline]
182 pub fn is<'a, T: FromValueOptional<'a> + SetValue>(&self) -> bool {
183 self.type_().is_a(&T::static_type())
184 }
185
186 pub fn type_(&self) -> Type {
188 from_glib(self.0.g_type)
189 }
190
191 pub fn type_transformable(src: Type, dst: Type) -> bool {
193 unsafe {
194 from_glib(gobject_sys::g_value_type_transformable(
195 src.to_glib(),
196 dst.to_glib(),
197 ))
198 }
199 }
200
201 #[doc(hidden)]
202 pub fn into_raw(mut self) -> gobject_sys::GValue {
203 unsafe {
204 let ret = mem::replace(&mut self.0, mem::uninitialized());
205 mem::forget(self);
206 ret
207 }
208 }
209
210 pub fn try_into_send_value<'a, T: Send + FromValueOptional<'a> + SetValue>(
211 self,
212 ) -> Result<SendValue, Self> {
213 self.downcast::<T>().map(TypedValue::into_send_value)
214 }
215}
216
217impl Clone for Value {
218 fn clone(&self) -> Self {
219 unsafe {
220 let mut ret = Value::from_type(from_glib(self.0.g_type));
221 gobject_sys::g_value_copy(self.to_glib_none().0, ret.to_glib_none_mut().0);
222 ret
223 }
224 }
225}
226
227impl Drop for Value {
228 fn drop(&mut self) {
229 if self.type_() != Type::Invalid {
232 unsafe { gobject_sys::g_value_unset(self.to_glib_none_mut().0) }
233 }
234 }
235}
236
237impl fmt::Debug for Value {
238 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
239 unsafe {
240 let s: GString =
241 from_glib_full(gobject_sys::g_strdup_value_contents(self.to_glib_none().0));
242
243 f.debug_tuple("Value").field(&s).finish()
244 }
245 }
246}
247
248impl<'a, T: ?Sized + SetValueOptional> From<Option<&'a T>> for Value {
249 #[inline]
250 fn from(value: Option<&'a T>) -> Self {
251 value.to_value()
252 }
253}
254
255impl<'a, T: ?Sized + SetValue> From<&'a T> for Value {
256 #[inline]
257 fn from(value: &'a T) -> Self {
258 value.to_value()
259 }
260}
261
262impl<T> From<TypedValue<T>> for Value {
263 fn from(value: TypedValue<T>) -> Self {
264 value.0
265 }
266}
267
268impl From<SendValue> for Value {
269 fn from(value: SendValue) -> Self {
270 value.0
271 }
272}
273
274impl Uninitialized for Value {
275 unsafe fn uninitialized() -> Value {
276 Value(mem::zeroed(), PhantomData)
277 }
278}
279
280#[doc(hidden)]
281impl<'a> ToGlibPtr<'a, *const gobject_sys::GValue> for Value {
282 type Storage = &'a Value;
283
284 fn to_glib_none(&'a self) -> Stash<'a, *const gobject_sys::GValue, Self> {
285 Stash(&self.0, self)
286 }
287}
288
289#[doc(hidden)]
290impl<'a> ToGlibPtrMut<'a, *mut gobject_sys::GValue> for Value {
291 type Storage = &'a mut Value;
292
293 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut gobject_sys::GValue, Self> {
294 StashMut(&mut self.0, self)
295 }
296}
297
298#[doc(hidden)]
299impl<'a> ToGlibPtr<'a, *mut gobject_sys::GValue> for &'a [&'a dyn ToValue] {
300 type Storage = ValueArray;
301
302 fn to_glib_none(&'a self) -> Stash<'a, *mut gobject_sys::GValue, Self> {
303 let mut values: Vec<gobject_sys::GValue> =
304 self.iter().map(|v| v.to_value().into_raw()).collect();
305 Stash(values.as_mut_ptr(), ValueArray(values))
306 }
307}
308
309#[doc(hidden)]
310impl<'a> ToGlibContainerFromSlice<'a, *mut gobject_sys::GValue> for &'a Value {
311 type Storage = &'a [&'a Value];
312
313 fn to_glib_none_from_slice(t: &'a [&'a Value]) -> (*mut gobject_sys::GValue, &'a [&'a Value]) {
314 (t.as_ptr() as *mut gobject_sys::GValue, t)
315 }
316
317 fn to_glib_container_from_slice(
318 t: &'a [&'a Value],
319 ) -> (*mut gobject_sys::GValue, &'a [&'a Value]) {
320 if t.is_empty() {
321 return (ptr::null_mut(), t);
322 }
323
324 unsafe {
325 let res = glib_sys::g_malloc(mem::size_of::<gobject_sys::GValue>() * t.len())
326 as *mut gobject_sys::GValue;
327 ptr::copy_nonoverlapping(t.as_ptr() as *const gobject_sys::GValue, res, t.len());
328 (res, t)
329 }
330 }
331
332 fn to_glib_full_from_slice(t: &[&'a Value]) -> *mut gobject_sys::GValue {
333 if t.is_empty() {
334 return ptr::null_mut();
335 }
336
337 unsafe {
338 let res = glib_sys::g_malloc(mem::size_of::<gobject_sys::GValue>() * t.len())
339 as *mut gobject_sys::GValue;
340 for (i, v) in t.iter().enumerate() {
341 gobject_sys::g_value_init(res.add(i), v.type_().to_glib());
342 gobject_sys::g_value_copy(v.to_glib_none().0, res.add(i));
343 }
344 res
345 }
346 }
347}
348
349#[doc(hidden)]
350impl<'a> ToGlibContainerFromSlice<'a, *const gobject_sys::GValue> for &'a Value {
351 type Storage = &'a [&'a Value];
352
353 fn to_glib_none_from_slice(
354 t: &'a [&'a Value],
355 ) -> (*const gobject_sys::GValue, &'a [&'a Value]) {
356 let (ptr, storage) =
357 ToGlibContainerFromSlice::<'a, *mut gobject_sys::GValue>::to_glib_none_from_slice(t);
358 (ptr as *const _, storage)
359 }
360
361 fn to_glib_container_from_slice(
362 _: &'a [&'a Value],
363 ) -> (*const gobject_sys::GValue, &'a [&'a Value]) {
364 unimplemented!()
365 }
366
367 fn to_glib_full_from_slice(_: &[&'a Value]) -> *const gobject_sys::GValue {
368 unimplemented!()
369 }
370}
371
372macro_rules! from_glib {
373 ($name:ident, $wrap:expr) => {
374 impl FromGlibPtrNone<*const gobject_sys::GValue> for $name {
375 unsafe fn from_glib_none(ptr: *const gobject_sys::GValue) -> Self {
376 let mut ret = Value::from_type(from_glib((*ptr).g_type));
377 gobject_sys::g_value_copy(ptr, ret.to_glib_none_mut().0);
378 $wrap(ret)
379 }
380 }
381
382 impl FromGlibPtrNone<*mut gobject_sys::GValue> for $name {
383 unsafe fn from_glib_none(ptr: *mut gobject_sys::GValue) -> Self {
384 from_glib_none(ptr as *const _)
385 }
386 }
387
388 impl FromGlibPtrFull<*mut gobject_sys::GValue> for $name {
389 unsafe fn from_glib_full(ptr: *mut gobject_sys::GValue) -> Self {
390 let mut ret = Value::uninitialized();
391 ptr::swap(&mut ret.0, ptr);
392 glib_sys::g_free(ptr as *mut c_void);
393 $wrap(ret)
394 }
395 }
396
397 impl FromGlibContainerAsVec<*mut gobject_sys::GValue, *mut *mut gobject_sys::GValue>
398 for $name
399 {
400 unsafe fn from_glib_none_num_as_vec(
401 ptr: *mut *mut gobject_sys::GValue,
402 num: usize,
403 ) -> Vec<Self> {
404 if num == 0 || ptr.is_null() {
405 return Vec::new();
406 }
407
408 let mut res = Vec::with_capacity(num);
409 for i in 0..num {
410 res.push(from_glib_none(ptr::read(ptr.add(i))));
411 }
412 res
413 }
414
415 unsafe fn from_glib_container_num_as_vec(
416 ptr: *mut *mut gobject_sys::GValue,
417 num: usize,
418 ) -> Vec<Self> {
419 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
420 glib_sys::g_free(ptr as *mut _);
421 res
422 }
423
424 unsafe fn from_glib_full_num_as_vec(
425 ptr: *mut *mut gobject_sys::GValue,
426 num: usize,
427 ) -> Vec<Self> {
428 if num == 0 || ptr.is_null() {
429 return Vec::new();
430 }
431
432 let mut res = Vec::with_capacity(num);
433 for i in 0..num {
434 res.push(from_glib_full(ptr::read(ptr.add(i))));
435 }
436 glib_sys::g_free(ptr as *mut _);
437 res
438 }
439 }
440
441 impl FromGlibPtrArrayContainerAsVec<*mut gobject_sys::GValue, *mut *mut gobject_sys::GValue>
442 for $name
443 {
444 unsafe fn from_glib_none_as_vec(ptr: *mut *mut gobject_sys::GValue) -> Vec<Self> {
445 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, c_ptr_array_len(ptr))
446 }
447
448 unsafe fn from_glib_container_as_vec(ptr: *mut *mut gobject_sys::GValue) -> Vec<Self> {
449 FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, c_ptr_array_len(ptr))
450 }
451
452 unsafe fn from_glib_full_as_vec(ptr: *mut *mut gobject_sys::GValue) -> Vec<Self> {
453 FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, c_ptr_array_len(ptr))
454 }
455 }
456
457 impl FromGlibContainerAsVec<*mut gobject_sys::GValue, *const *mut gobject_sys::GValue>
458 for $name
459 {
460 unsafe fn from_glib_none_num_as_vec(
461 ptr: *const *mut gobject_sys::GValue,
462 num: usize,
463 ) -> Vec<Self> {
464 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *mut *mut _, num)
465 }
466
467 unsafe fn from_glib_container_num_as_vec(
468 _: *const *mut gobject_sys::GValue,
469 _: usize,
470 ) -> Vec<Self> {
471 unimplemented!()
473 }
474
475 unsafe fn from_glib_full_num_as_vec(
476 _: *const *mut gobject_sys::GValue,
477 _: usize,
478 ) -> Vec<Self> {
479 unimplemented!()
481 }
482 }
483
484 impl
485 FromGlibPtrArrayContainerAsVec<
486 *mut gobject_sys::GValue,
487 *const *mut gobject_sys::GValue,
488 > for $name
489 {
490 unsafe fn from_glib_none_as_vec(ptr: *const *mut gobject_sys::GValue) -> Vec<Self> {
491 FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr as *mut *mut _)
492 }
493
494 unsafe fn from_glib_container_as_vec(_: *const *mut gobject_sys::GValue) -> Vec<Self> {
495 unimplemented!()
497 }
498
499 unsafe fn from_glib_full_as_vec(_: *const *mut gobject_sys::GValue) -> Vec<Self> {
500 unimplemented!()
502 }
503 }
504 };
505}
506
507from_glib!(Value, |v| v);
508
509pub struct ValueArray(Vec<gobject_sys::GValue>);
510
511impl Drop for ValueArray {
512 fn drop(&mut self) {
513 unsafe {
514 for value in &mut self.0 {
515 if value.g_type != gobject_sys::G_TYPE_INVALID {
518 gobject_sys::g_value_unset(value);
519 }
520 }
521 }
522 }
523}
524
525#[derive(Clone)]
532#[repr(C)]
533pub struct TypedValue<T>(Value, PhantomData<*const T>);
534
535impl<'a, T: FromValueOptional<'a> + SetValue> TypedValue<T> {
536 pub fn get(&'a self) -> Option<T> {
541 unsafe { T::from_value_optional(self) }
542 }
543
544 pub fn get_some(&'a self) -> T
549 where
550 T: FromValue<'a>,
551 {
552 unsafe { T::from_value(self) }
553 }
554
555 pub fn set<U: ?Sized + SetValueOptional>(&mut self, value: Option<&U>)
559 where
560 T: Borrow<U>,
561 {
562 unsafe { SetValueOptional::set_value_optional(&mut self.0, value) }
563 }
564
565 pub fn set_none(&mut self)
569 where
570 T: SetValueOptional,
571 {
572 unsafe { T::set_value_optional(&mut self.0, None) }
573 }
574
575 pub fn set_some<U: ?Sized + SetValue>(&mut self, value: &U)
577 where
578 T: Borrow<U>,
579 {
580 unsafe { SetValue::set_value(&mut self.0, value) }
581 }
582}
583
584impl<T> fmt::Debug for TypedValue<T> {
585 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
586 f.debug_tuple("TypedValue").field(&self.0).finish()
587 }
588}
589
590impl<'a, T: FromValueOptional<'a> + SetValue + Send> TypedValue<T> {
591 pub fn into_send_value(self) -> SendValue {
592 SendValue(self.0)
593 }
594}
595
596impl<T> Deref for TypedValue<T> {
597 type Target = Value;
598
599 fn deref(&self) -> &Value {
600 &self.0
601 }
602}
603
604impl<'a, T: FromValueOptional<'a> + SetValueOptional> From<Option<&'a T>> for TypedValue<T> {
605 fn from(value: Option<&'a T>) -> Self {
606 TypedValue(Value::from(value), PhantomData)
607 }
608}
609
610impl<'a, T: FromValueOptional<'a> + SetValue> From<&'a T> for TypedValue<T> {
611 fn from(value: &'a T) -> Self {
612 TypedValue(Value::from(value), PhantomData)
613 }
614}
615
616impl<'a> From<Option<&'a str>> for TypedValue<String> {
617 fn from(value: Option<&'a str>) -> Self {
618 TypedValue(Value::from(value), PhantomData)
619 }
620}
621
622impl<'a> From<&'a str> for TypedValue<String> {
623 fn from(value: &'a str) -> Self {
624 TypedValue(Value::from(value), PhantomData)
625 }
626}
627
628impl<'a> From<TypedValue<&'a str>> for TypedValue<String> {
629 fn from(value: TypedValue<&str>) -> Self {
630 TypedValue(value.0, PhantomData)
631 }
632}
633
634impl<'a> From<TypedValue<String>> for TypedValue<&'a str> {
635 fn from(value: TypedValue<String>) -> Self {
636 TypedValue(value.0, PhantomData)
637 }
638}
639
640#[doc(hidden)]
641impl<'a, T: 'a> ToGlibPtrMut<'a, *mut gobject_sys::GValue> for TypedValue<T> {
642 type Storage = &'a mut TypedValue<T>;
643
644 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut gobject_sys::GValue, Self> {
645 StashMut(&mut (self.0).0, self)
646 }
647}
648
649pub trait ToValue {
651 fn to_value(&self) -> Value;
653
654 fn to_value_type(&self) -> Type;
658}
659
660impl<T: SetValueOptional> ToValue for Option<T> {
661 fn to_value(&self) -> Value {
662 unsafe {
663 let mut ret = Value::from_type(T::static_type());
664 T::set_value_optional(&mut ret, self.as_ref());
665 ret
666 }
667 }
668
669 #[inline]
670 fn to_value_type(&self) -> Type {
671 T::static_type()
672 }
673}
674
675impl<T: ?Sized + SetValue> ToValue for T {
676 fn to_value(&self) -> Value {
677 unsafe {
678 let mut ret = Value::from_type(T::static_type());
679 T::set_value(&mut ret, self);
680 ret
681 }
682 }
683
684 #[inline]
685 fn to_value_type(&self) -> Type {
686 T::static_type()
687 }
688}
689
690impl ToValue for Value {
691 fn to_value(&self) -> Value {
692 self.clone()
693 }
694
695 fn to_value_type(&self) -> Type {
696 self.type_()
697 }
698}
699
700#[derive(Clone)]
705#[repr(C)]
706pub struct SendValue(Value);
707unsafe impl Send for SendValue {}
708
709impl SendValue {
710 pub fn downcast<'a, T: FromValueOptional<'a> + SetValue + Send>(
715 self,
716 ) -> Result<TypedValue<T>, Self> {
717 self.0.downcast().map_err(SendValue)
718 }
719
720 pub fn downcast_ref<'a, T: FromValueOptional<'a> + SetValue>(&self) -> Option<&TypedValue<T>> {
725 unsafe {
726 let ok = from_glib(gobject_sys::g_type_check_value_holds(
727 mut_override(self.to_glib_none().0),
728 T::static_type().to_glib(),
729 ));
730 if ok {
731 Some(&*(self as *const SendValue as *const TypedValue<T>))
734 } else {
735 None
736 }
737 }
738 }
739
740 #[doc(hidden)]
741 pub fn into_raw(self) -> gobject_sys::GValue {
742 self.0.into_raw()
743 }
744}
745
746impl fmt::Debug for SendValue {
747 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
748 f.debug_tuple("SendValue").field(&self.0).finish()
749 }
750}
751
752impl Deref for SendValue {
753 type Target = Value;
754
755 fn deref(&self) -> &Value {
756 &self.0
757 }
758}
759
760impl<'a, T: ?Sized + SetValueOptional + Send> From<Option<&'a T>> for SendValue {
761 #[inline]
762 fn from(value: Option<&'a T>) -> Self {
763 SendValue(value.to_value())
764 }
765}
766
767impl<'a, T: ?Sized + SetValue + Send> From<&'a T> for SendValue {
768 #[inline]
769 fn from(value: &'a T) -> Self {
770 SendValue(value.to_value())
771 }
772}
773
774impl<T: Send> From<TypedValue<T>> for SendValue {
775 fn from(value: TypedValue<T>) -> Self {
776 SendValue(value.0)
777 }
778}
779
780from_glib!(SendValue, SendValue);
781
782#[doc(hidden)]
783impl<'a> ToGlibPtrMut<'a, *mut gobject_sys::GValue> for SendValue {
784 type Storage = &'a mut SendValue;
785
786 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut gobject_sys::GValue, Self> {
787 StashMut(&mut (self.0).0, self)
788 }
789}
790
791pub trait ToSendValue: Send + ToValue {
793 fn to_send_value(&self) -> SendValue;
795}
796
797impl<T: SetValueOptional + Send + ToValue> ToSendValue for Option<T> {
798 fn to_send_value(&self) -> SendValue {
799 SendValue(self.to_value())
800 }
801}
802
803impl<T: ?Sized + SetValue + Send + ToValue> ToSendValue for T {
804 fn to_send_value(&self) -> SendValue {
805 SendValue(self.to_value())
806 }
807}
808
809impl ToSendValue for SendValue {
810 fn to_send_value(&self) -> SendValue {
811 self.clone()
812 }
813}
814
815impl ToValue for SendValue {
816 fn to_value(&self) -> Value {
817 self.0.clone()
818 }
819
820 fn to_value_type(&self) -> Type {
821 self.type_()
822 }
823}
824
825pub trait FromValueOptional<'a>: StaticType + Sized {
829 unsafe fn from_value_optional(&'a Value) -> Option<Self>;
830}
831
832pub trait FromValue<'a>: FromValueOptional<'a> {
836 unsafe fn from_value(&'a Value) -> Self;
837}
838
839pub trait SetValueOptional: SetValue {
843 unsafe fn set_value_optional(&mut Value, Option<&Self>);
844}
845
846pub trait SetValue: StaticType {
848 unsafe fn set_value(&mut Value, &Self);
849}
850
851impl<'a> FromValueOptional<'a> for String {
852 unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
853 from_glib_none(gobject_sys::g_value_get_string(value.to_glib_none().0))
854 }
855}
856
857impl<'a> FromValueOptional<'a> for &'a str {
858 unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
859 let cstr = gobject_sys::g_value_get_string(value.to_glib_none().0);
860 if cstr.is_null() {
861 None
862 } else {
863 CStr::from_ptr(cstr).to_str().ok()
864 }
865 }
866}
867
868impl SetValue for str {
869 unsafe fn set_value(value: &mut Value, this: &Self) {
870 gobject_sys::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
871 }
872}
873
874impl SetValueOptional for str {
875 unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
876 gobject_sys::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
877 }
878}
879
880impl<'a> FromValueOptional<'a> for Vec<String> {
881 unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
882 Some(<Vec<String> as FromValue>::from_value(value))
883 }
884}
885
886impl<'a> FromValue<'a> for Vec<String> {
887 unsafe fn from_value(value: &'a Value) -> Self {
888 let ptr = gobject_sys::g_value_get_boxed(value.to_glib_none().0) as *const *const c_char;
889 FromGlibPtrContainer::from_glib_none(ptr)
890 }
891}
892
893impl<'a> FromValueOptional<'a> for Vec<GString> {
894 unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
895 Some(<Vec<GString> as FromValue>::from_value(value))
896 }
897}
898
899impl<'a> FromValue<'a> for Vec<GString> {
900 unsafe fn from_value(value: &'a Value) -> Self {
901 let ptr = gobject_sys::g_value_get_boxed(value.to_glib_none().0) as *const *const c_char;
902 FromGlibPtrContainer::from_glib_none(ptr)
903 }
904}
905
906impl<'a> SetValue for [&'a str] {
907 unsafe fn set_value(value: &mut Value, this: &Self) {
908 let ptr: *mut *mut c_char = this.to_glib_full();
909 gobject_sys::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void)
910 }
911}
912
913impl<'a> SetValueOptional for [&'a str] {
914 unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
915 let ptr: *mut *mut c_char = this.to_glib_full();
916 gobject_sys::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void)
917 }
918}
919
920impl SetValue for Vec<String> {
921 unsafe fn set_value(value: &mut Value, this: &Self) {
922 let ptr: *mut *mut c_char = this.to_glib_full();
923 gobject_sys::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void)
924 }
925}
926
927impl SetValueOptional for Vec<String> {
928 #[allow(clippy::redundant_closure)]
929 unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
930 let ptr: *mut *mut c_char = this.map(|v| v.to_glib_full()).unwrap_or(ptr::null_mut());
931 gobject_sys::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void)
932 }
933}
934
935impl<'a, T: ?Sized + SetValue> SetValue for &'a T {
936 unsafe fn set_value(value: &mut Value, this: &Self) {
937 SetValue::set_value(value, *this)
938 }
939}
940
941impl<'a, T: ?Sized + SetValueOptional> SetValueOptional for &'a T {
942 unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
943 SetValueOptional::set_value_optional(value, this.cloned())
944 }
945}
946
947impl SetValue for String {
948 unsafe fn set_value(value: &mut Value, this: &Self) {
949 gobject_sys::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
950 }
951}
952
953impl SetValueOptional for String {
954 unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
955 gobject_sys::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
956 }
957}
958
959impl<'a> FromValueOptional<'a> for bool {
960 unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
961 Some(from_glib(gobject_sys::g_value_get_boolean(
962 value.to_glib_none().0,
963 )))
964 }
965}
966
967impl<'a> FromValue<'a> for bool {
968 unsafe fn from_value(value: &'a Value) -> Self {
969 from_glib(gobject_sys::g_value_get_boolean(value.to_glib_none().0))
970 }
971}
972
973impl SetValue for bool {
974 unsafe fn set_value(value: &mut Value, this: &Self) {
975 gobject_sys::g_value_set_boolean(value.to_glib_none_mut().0, this.to_glib())
976 }
977}
978
979macro_rules! numeric {
980 ($name:ident, $get:ident, $set:ident) => {
981 impl<'a> FromValueOptional<'a> for $name {
982 unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
983 Some(gobject_sys::$get(value.to_glib_none().0))
984 }
985 }
986
987 impl<'a> FromValue<'a> for $name {
988 unsafe fn from_value(value: &'a Value) -> Self {
989 gobject_sys::$get(value.to_glib_none().0)
990 }
991 }
992
993 impl SetValue for $name {
994 unsafe fn set_value(value: &mut Value, this: &Self) {
995 gobject_sys::$set(value.to_glib_none_mut().0, *this)
996 }
997 }
998 };
999}
1000
1001numeric!(i8, g_value_get_schar, g_value_set_schar);
1002numeric!(u8, g_value_get_uchar, g_value_set_uchar);
1003numeric!(i32, g_value_get_int, g_value_set_int);
1004numeric!(u32, g_value_get_uint, g_value_set_uint);
1005numeric!(i64, g_value_get_int64, g_value_set_int64);
1006numeric!(u64, g_value_get_uint64, g_value_set_uint64);
1007numeric!(f32, g_value_get_float, g_value_set_float);
1008numeric!(f64, g_value_get_double, g_value_set_double);
1009
1010#[cfg(test)]
1011mod tests {
1012 use super::*;
1013
1014 #[test]
1015 fn test_send_value() {
1016 use std::thread;
1017
1018 let v = SendValue::from(&1i32);
1019
1020 thread::spawn(move || drop(v)).join().unwrap();
1022 }
1023
1024 #[test]
1025 fn test_strv() {
1026 let v = vec!["123", "456"].to_value();
1027 assert_eq!(
1028 v.get::<Vec<GString>>(),
1029 Some(vec![GString::from("123"), GString::from("456")])
1030 );
1031
1032 let v = vec![String::from("123"), String::from("456")].to_value();
1033 assert_eq!(
1034 v.get::<Vec<GString>>(),
1035 Some(vec![GString::from("123"), GString::from("456")])
1036 );
1037 }
1038}