1use std::{
44 convert::Infallible,
45 error,
46 ffi::CStr,
47 fmt, mem,
48 num::{NonZeroI8, NonZeroI32, NonZeroI64, NonZeroU8, NonZeroU32, NonZeroU64},
49 ops::Deref,
50 path::{Path, PathBuf},
51 ptr,
52};
53
54use libc::{c_char, c_void};
55
56use crate::{
57 GStr, ffi, gobject_ffi,
58 gstring::GString,
59 prelude::*,
60 translate::*,
61 types::{Pointee, Pointer, Type},
62};
63
64pub trait ValueType: ToValue + for<'a> FromValue<'a> + 'static {
67 type Type: StaticType;
74}
75
76pub trait ValueTypeOptional:
81 ValueType + ToValueOptional + FromValueOptional<'static> + StaticType
82{
83}
84
85impl<T, C, E> ValueType for Option<T>
86where
87 T: for<'a> FromValue<'a, Checker = C> + ValueTypeOptional + StaticType + 'static,
88 C: ValueTypeChecker<Error = ValueTypeMismatchOrNoneError<E>>,
89 E: error::Error + Send + Sized + 'static,
90{
91 type Type = T::Type;
92}
93
94pub unsafe trait ValueTypeChecker {
97 type Error: error::Error + Send + Sized + 'static;
98
99 fn check(value: &Value) -> Result<(), Self::Error>;
100}
101
102#[derive(Clone, PartialEq, Eq, Debug)]
106pub struct ValueTypeMismatchError {
107 actual: Type,
108 requested: Type,
109}
110
111impl ValueTypeMismatchError {
112 pub fn new(actual: Type, requested: Type) -> Self {
113 Self { actual, requested }
114 }
115}
116
117impl ValueTypeMismatchError {
118 pub fn actual_type(&self) -> Type {
119 self.actual
120 }
121
122 pub fn requested_type(&self) -> Type {
123 self.requested
124 }
125}
126
127impl fmt::Display for ValueTypeMismatchError {
128 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129 write!(
130 f,
131 "Value type mismatch. Actual {:?}, requested {:?}",
132 self.actual_type(),
133 self.requested_type(),
134 )
135 }
136}
137
138impl error::Error for ValueTypeMismatchError {}
139
140impl From<Infallible> for ValueTypeMismatchError {
141 fn from(e: Infallible) -> Self {
142 match e {}
143 }
144}
145
146pub struct GenericValueTypeChecker<T>(std::marker::PhantomData<T>);
149
150unsafe impl<T: StaticType> ValueTypeChecker for GenericValueTypeChecker<T> {
151 type Error = ValueTypeMismatchError;
152
153 #[doc(alias = "g_type_check_value_holds")]
154 #[inline]
155 fn check(value: &Value) -> Result<(), Self::Error> {
156 unsafe {
157 if gobject_ffi::g_type_check_value_holds(&value.inner, T::static_type().into_glib())
158 == ffi::GFALSE
159 {
160 Err(ValueTypeMismatchError::new(
161 Type::from_glib(value.inner.g_type),
162 T::static_type(),
163 ))
164 } else {
165 Ok(())
166 }
167 }
168 }
169}
170
171pub struct CharTypeChecker();
172unsafe impl ValueTypeChecker for CharTypeChecker {
173 type Error = InvalidCharError;
174
175 #[inline]
176 fn check(value: &Value) -> Result<(), Self::Error> {
177 let v = value.get::<u32>()?;
178 match char::from_u32(v) {
179 Some(_) => Ok(()),
180 None => Err(InvalidCharError::CharConversionError),
181 }
182 }
183}
184
185#[derive(Clone, PartialEq, Eq, Debug)]
189pub enum InvalidCharError {
190 WrongValueType(ValueTypeMismatchError),
191 CharConversionError,
192}
193impl fmt::Display for InvalidCharError {
194 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195 match self {
196 Self::WrongValueType(err) => err.fmt(f),
197 Self::CharConversionError => {
198 write!(f, "couldn't convert to char, invalid u32 contents")
199 }
200 }
201 }
202}
203impl error::Error for InvalidCharError {}
204
205impl From<ValueTypeMismatchError> for InvalidCharError {
206 fn from(err: ValueTypeMismatchError) -> Self {
207 Self::WrongValueType(err)
208 }
209}
210
211impl From<Infallible> for InvalidCharError {
212 fn from(e: Infallible) -> Self {
213 match e {}
214 }
215}
216
217#[derive(Clone, PartialEq, Eq, Debug)]
221pub enum ValueTypeMismatchOrNoneError<E: error::Error> {
222 WrongValueType(E),
223 UnexpectedNone,
224}
225
226impl<E: error::Error> fmt::Display for ValueTypeMismatchOrNoneError<E> {
227 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
228 match self {
229 Self::WrongValueType(err) => <E as fmt::Display>::fmt(err, f),
230 Self::UnexpectedNone => write!(f, "Unexpected None",),
231 }
232 }
233}
234
235impl<E: error::Error> error::Error for ValueTypeMismatchOrNoneError<E> {}
236
237impl<E: error::Error> From<E> for ValueTypeMismatchOrNoneError<E> {
238 fn from(err: E) -> Self {
239 Self::WrongValueType(err)
240 }
241}
242
243pub struct GenericValueTypeOrNoneChecker<T>(std::marker::PhantomData<T>);
246
247unsafe impl<T: StaticType> ValueTypeChecker for GenericValueTypeOrNoneChecker<T> {
248 type Error = ValueTypeMismatchOrNoneError<ValueTypeMismatchError>;
249
250 #[inline]
251 fn check(value: &Value) -> Result<(), Self::Error> {
252 GenericValueTypeChecker::<T>::check(value)?;
253
254 unsafe {
255 if value.inner.data[0].v_uint64 == 0 {
258 return Err(Self::Error::UnexpectedNone);
259 }
260 }
261
262 Ok(())
263 }
264}
265
266pub unsafe trait FromValue<'a>: Sized {
272 type Checker: ValueTypeChecker;
275
276 unsafe fn from_value(value: &'a Value) -> Self;
282}
283
284pub trait FromValueOptional<'a>: private::FromValueOptionalSealed<'a> {}
289
290impl<'a, T, C, E> FromValueOptional<'a> for T
291where
292 T: FromValue<'a, Checker = C>,
293 C: ValueTypeChecker<Error = ValueTypeMismatchOrNoneError<E>>,
294 E: error::Error + Send + Sized + 'static,
295{
296}
297
298mod private {
299 pub trait FromValueOptionalSealed<'a> {}
300
301 impl<'a, T, C, E> FromValueOptionalSealed<'a> for T
302 where
303 T: super::FromValue<'a, Checker = C>,
304 C: super::ValueTypeChecker<Error = super::ValueTypeMismatchOrNoneError<E>>,
305 E: super::error::Error + Send + Sized + 'static,
306 {
307 }
308}
309
310pub struct ValueTypeOrNoneChecker<T, C, E>(std::marker::PhantomData<(T, C, E)>);
313
314unsafe impl<'a, T, C, E> ValueTypeChecker for ValueTypeOrNoneChecker<T, C, E>
315where
316 T: FromValue<'a, Checker = C> + StaticType,
317 C: ValueTypeChecker<Error = ValueTypeMismatchOrNoneError<E>>,
318 E: error::Error + Send + Sized + 'static,
319{
320 type Error = E;
321
322 #[inline]
323 fn check(value: &Value) -> Result<(), Self::Error> {
324 match T::Checker::check(value) {
325 Err(ValueTypeMismatchOrNoneError::UnexpectedNone) => Ok(()),
326 Err(ValueTypeMismatchOrNoneError::WrongValueType(err)) => Err(err),
327 Ok(_) => Ok(()),
328 }
329 }
330}
331
332unsafe impl<'a, T, C, E> FromValue<'a> for Option<T>
335where
336 T: FromValue<'a, Checker = C> + StaticType,
337 C: ValueTypeChecker<Error = ValueTypeMismatchOrNoneError<E>>,
338 E: error::Error + Send + Sized + 'static,
339{
340 type Checker = ValueTypeOrNoneChecker<T, C, E>;
341
342 #[inline]
343 unsafe fn from_value(value: &'a Value) -> Self {
344 unsafe {
345 match T::Checker::check(value) {
346 Err(ValueTypeMismatchOrNoneError::UnexpectedNone) => None,
347 Err(ValueTypeMismatchOrNoneError::WrongValueType(_err)) => {
348 unreachable!();
350 }
351 Ok(_) => Some(T::from_value(value)),
352 }
353 }
354 }
355}
356
357pub trait ToValue {
373 fn to_value(&self) -> Value;
376
377 fn value_type(&self) -> Type;
382}
383
384impl<T: ToValue + StaticType> ToValue for &T {
387 #[inline]
388 fn to_value(&self) -> Value {
389 T::to_value(*self)
390 }
391
392 #[inline]
393 fn value_type(&self) -> Type {
394 T::static_type()
395 }
396}
397
398pub trait ToValueOptional {
401 #[allow(clippy::wrong_self_convention)]
404 fn to_value_optional(s: Option<&Self>) -> Value;
405}
406
407impl<T: ToValueOptional + StaticType> ToValue for Option<T> {
410 #[inline]
411 fn to_value(&self) -> Value {
412 T::to_value_optional(self.as_ref())
413 }
414
415 #[inline]
416 fn value_type(&self) -> Type {
417 T::static_type()
418 }
419}
420
421impl<T: Into<Value> + ToValueOptional> From<Option<T>> for Value {
422 #[inline]
423 fn from(t: Option<T>) -> Self {
424 match t {
425 None => T::to_value_optional(None),
426 Some(t) => t.into(),
427 }
428 }
429}
430
431impl<T: ToValueOptional + StaticType> StaticType for Option<T> {
432 #[inline]
433 fn static_type() -> Type {
434 T::static_type()
435 }
436}
437
438impl<T: ToValueOptional + StaticType + ?Sized> ToValueOptional for &T {
439 #[inline]
440 fn to_value_optional(s: Option<&Self>) -> Value {
441 <T as ToValueOptional>::to_value_optional(s.as_ref().map(|s| **s))
442 }
443}
444
445#[inline]
446unsafe fn copy_value(value: *const gobject_ffi::GValue) -> *mut gobject_ffi::GValue {
447 unsafe {
448 let copy =
449 ffi::g_malloc0(mem::size_of::<gobject_ffi::GValue>()) as *mut gobject_ffi::GValue;
450 copy_into_value(copy, value);
451 copy
452 }
453}
454
455#[inline]
456unsafe fn free_value(value: *mut gobject_ffi::GValue) {
457 unsafe {
458 clear_value(value);
459 ffi::g_free(value as *mut _);
460 }
461}
462
463#[inline]
464unsafe fn init_value(value: *mut gobject_ffi::GValue) {
465 unsafe {
466 ptr::write(value, mem::zeroed());
467 }
468}
469
470#[inline]
471unsafe fn copy_into_value(dest: *mut gobject_ffi::GValue, src: *const gobject_ffi::GValue) {
472 unsafe {
473 gobject_ffi::g_value_init(dest, (*src).g_type);
474 gobject_ffi::g_value_copy(src, dest);
475 }
476}
477
478#[inline]
479unsafe fn clear_value(value: *mut gobject_ffi::GValue) {
480 unsafe {
481 if (*value).g_type != gobject_ffi::G_TYPE_INVALID {
484 gobject_ffi::g_value_unset(value);
485 }
486 }
487}
488
489crate::wrapper! {
491 #[doc(alias = "GValue")]
504 pub struct Value(BoxedInline<gobject_ffi::GValue>);
505
506 match fn {
507 copy => |ptr| copy_value(ptr),
508 free => |ptr| free_value(ptr),
509 init => |ptr| init_value(ptr),
510 copy_into => |dest, src| copy_into_value(dest, src),
511 clear => |ptr| clear_value(ptr),
512 }
513}
514
515impl Value {
516 pub fn from_type(type_: Type) -> Self {
523 unsafe {
524 assert_eq!(
525 gobject_ffi::g_type_check_is_value_type(type_.into_glib()),
526 ffi::GTRUE
527 );
528 Self::from_type_unchecked(type_)
529 }
530 }
531
532 #[inline]
539 pub unsafe fn from_type_unchecked(type_: Type) -> Self {
540 unsafe {
541 let mut value = Value::uninitialized();
542 gobject_ffi::g_value_init(value.to_glib_none_mut().0, type_.into_glib());
543 value
544 }
545 }
546
547 #[inline]
550 pub fn for_value_type<T: ValueType>() -> Self {
551 unsafe { Value::from_type_unchecked(T::Type::static_type()) }
552 }
553
554 #[inline]
557 #[doc(alias = "g_value_set_static_string")]
558 pub fn from_static_str(s: &'static GStr) -> Self {
559 unsafe {
560 let mut v = Self::from_type_unchecked(Type::STRING);
561 gobject_ffi::g_value_set_static_string(v.to_glib_none_mut().0, s.as_ptr());
562 v
563 }
564 }
565
566 #[cfg(feature = "v2_66")]
567 #[cfg_attr(docsrs, doc(cfg(feature = "v2_66")))]
568 #[inline]
572 #[doc(alias = "g_value_set_interned_string")]
573 pub fn from_interned_str(s: &'static GStr) -> Self {
574 unsafe {
575 let mut v = Self::from_type_unchecked(Type::STRING);
576 gobject_ffi::g_value_set_interned_string(v.to_glib_none_mut().0, s.as_ptr());
577 v
578 }
579 }
580
581 #[inline]
586 pub fn get<'a, T>(
587 &'a self,
588 ) -> Result<T, <<T as FromValue<'a>>::Checker as ValueTypeChecker>::Error>
589 where
590 T: FromValue<'a>,
591 {
592 unsafe {
593 T::Checker::check(self)?;
594 Ok(T::from_value(self))
595 }
596 }
597
598 #[inline]
601 pub fn get_owned<T>(
602 &self,
603 ) -> Result<T, <<T as FromValue<'_>>::Checker as ValueTypeChecker>::Error>
604 where
605 T: for<'b> FromValue<'b> + 'static,
606 {
607 unsafe {
608 T::Checker::check(self)?;
609 Ok(FromValue::from_value(self))
610 }
611 }
612
613 #[inline]
617 pub fn is<T: StaticType>(&self) -> bool {
618 self.is_type(T::static_type())
619 }
620
621 #[inline]
625 pub fn is_type(&self, type_: Type) -> bool {
626 self.type_().is_a(type_)
627 }
628
629 #[inline]
632 pub fn type_(&self) -> Type {
633 unsafe { from_glib(self.inner.g_type) }
634 }
635
636 #[doc(alias = "g_value_type_transformable")]
639 pub fn type_transformable(src: Type, dst: Type) -> bool {
640 unsafe {
641 from_glib(gobject_ffi::g_value_type_transformable(
642 src.into_glib(),
643 dst.into_glib(),
644 ))
645 }
646 }
647
648 #[doc(alias = "g_value_transform")]
651 pub fn transform<T: ValueType>(&self) -> Result<Value, crate::BoolError> {
652 self.transform_with_type(T::Type::static_type())
653 }
654
655 #[doc(alias = "g_value_transform")]
658 pub fn transform_with_type(&self, type_: Type) -> Result<Value, crate::BoolError> {
659 unsafe {
660 let mut dest = Value::from_type(type_);
661 if from_glib(gobject_ffi::g_value_transform(
662 self.to_glib_none().0,
663 dest.to_glib_none_mut().0,
664 )) {
665 Ok(dest)
666 } else {
667 Err(crate::bool_error!(
668 "Can't transform value of type '{}' into '{}'",
669 self.type_(),
670 type_
671 ))
672 }
673 }
674 }
675
676 #[inline]
679 pub fn into_raw(self) -> gobject_ffi::GValue {
680 unsafe {
681 let s = mem::ManuallyDrop::new(self);
682 ptr::read(&s.inner)
683 }
684 }
685
686 #[inline]
690 pub fn try_into_send_value<T: Send + StaticType>(self) -> Result<SendValue, Self> {
691 if self.type_().is_a(T::static_type()) {
692 unsafe { Ok(SendValue::unsafe_from(self.into_raw())) }
693 } else {
694 Err(self)
695 }
696 }
697
698 #[inline]
705 pub unsafe fn into_send_value(self) -> SendValue {
706 unsafe { SendValue::unsafe_from(self.into_raw()) }
707 }
708
709 fn content_debug_string(&self) -> GString {
710 unsafe { from_glib_full(gobject_ffi::g_strdup_value_contents(self.to_glib_none().0)) }
711 }
712}
713
714impl fmt::Debug for Value {
715 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
716 write!(f, "({}) {}", self.type_(), self.content_debug_string())
717 }
718}
719
720impl<'a, T: ?Sized + ToValue> From<&'a T> for Value {
721 #[inline]
722 fn from(value: &'a T) -> Self {
723 value.to_value()
724 }
725}
726
727impl From<SendValue> for Value {
728 #[inline]
729 fn from(value: SendValue) -> Self {
730 unsafe { Value::unsafe_from(value.into_raw()) }
731 }
732}
733
734impl ToValue for Value {
735 #[inline]
736 fn to_value(&self) -> Value {
737 self.clone()
738 }
739
740 #[inline]
741 fn value_type(&self) -> Type {
742 self.type_()
743 }
744}
745
746impl ToValue for &Value {
747 #[inline]
748 fn to_value(&self) -> Value {
749 (*self).clone()
750 }
751
752 #[inline]
753 fn value_type(&self) -> Type {
754 self.type_()
755 }
756}
757
758pub struct NopChecker;
759
760unsafe impl ValueTypeChecker for NopChecker {
761 type Error = Infallible;
762
763 #[inline]
764 fn check(_value: &Value) -> Result<(), Self::Error> {
765 Ok(())
766 }
767}
768
769unsafe impl<'a> FromValue<'a> for Value {
770 type Checker = NopChecker;
771
772 #[inline]
773 unsafe fn from_value(value: &'a Value) -> Self {
774 value.clone()
775 }
776}
777
778unsafe impl<'a> FromValue<'a> for &'a Value {
779 type Checker = NopChecker;
780
781 #[inline]
782 unsafe fn from_value(value: &'a Value) -> Self {
783 value
784 }
785}
786
787impl ToValue for SendValue {
788 #[inline]
789 fn to_value(&self) -> Value {
790 unsafe { from_glib_none(self.to_glib_none().0) }
791 }
792
793 #[inline]
794 fn value_type(&self) -> Type {
795 self.type_()
796 }
797}
798
799impl ToValue for &SendValue {
800 #[inline]
801 fn to_value(&self) -> Value {
802 unsafe { from_glib_none(self.to_glib_none().0) }
803 }
804
805 #[inline]
806 fn value_type(&self) -> Type {
807 self.type_()
808 }
809}
810
811impl StaticType for BoxedValue {
812 #[inline]
813 fn static_type() -> Type {
814 unsafe { from_glib(gobject_ffi::g_value_get_type()) }
815 }
816}
817
818crate::wrapper! {
819 #[doc(alias = "GValue")]
825 pub struct SendValue(BoxedInline<gobject_ffi::GValue>);
826
827 match fn {
828 copy => |ptr| copy_value(ptr),
829 free => |ptr| free_value(ptr),
830 init => |ptr| init_value(ptr),
831 copy_into => |dest, src| copy_into_value(dest, src),
832 clear => |ptr| clear_value(ptr),
833 }
834}
835
836unsafe impl Send for SendValue {}
837
838impl SendValue {
839 #[inline]
842 pub fn into_raw(self) -> gobject_ffi::GValue {
843 unsafe {
844 let s = mem::ManuallyDrop::new(self);
845 ptr::read(&s.inner)
846 }
847 }
848 #[inline]
849 pub fn from_owned<T: Send + Into<Value>>(t: T) -> Self {
850 unsafe { Self::unsafe_from(t.into().into_raw()) }
851 }
852}
853
854impl fmt::Debug for SendValue {
855 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
856 write!(f, "({}) {}", self.type_(), self.content_debug_string())
857 }
858}
859
860impl Deref for SendValue {
861 type Target = Value;
862
863 #[inline]
864 fn deref(&self) -> &Value {
865 unsafe { &*(self as *const SendValue as *const Value) }
866 }
867}
868
869impl<'a, T: ?Sized + ToSendValue> From<&'a T> for SendValue {
870 #[inline]
871 fn from(value: &'a T) -> Self {
872 value.to_send_value()
873 }
874}
875
876pub trait ToSendValue: Send + ToValue {
879 fn to_send_value(&self) -> SendValue;
882}
883
884impl<T: Send + ToValue + ?Sized> ToSendValue for T {
885 #[inline]
886 fn to_send_value(&self) -> SendValue {
887 unsafe { SendValue::unsafe_from(self.to_value().into_raw()) }
888 }
889}
890
891unsafe impl<'a> FromValue<'a> for &'a str {
892 type Checker = GenericValueTypeOrNoneChecker<Self>;
893
894 #[inline]
895 unsafe fn from_value(value: &'a Value) -> Self {
896 unsafe {
897 let ptr = gobject_ffi::g_value_get_string(value.to_glib_none().0);
898 CStr::from_ptr(ptr).to_str().expect("Invalid UTF-8")
899 }
900 }
901}
902
903impl ToValue for str {
904 fn to_value(&self) -> Value {
905 unsafe {
906 let mut value = Value::for_value_type::<String>();
907
908 gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, self.to_glib_full());
909
910 value
911 }
912 }
913
914 fn value_type(&self) -> Type {
915 String::static_type()
916 }
917}
918
919impl ToValue for &str {
920 fn to_value(&self) -> Value {
921 (*self).to_value()
922 }
923
924 fn value_type(&self) -> Type {
925 String::static_type()
926 }
927}
928
929impl ToValueOptional for str {
930 fn to_value_optional(s: Option<&Self>) -> Value {
931 let mut value = Value::for_value_type::<String>();
932 unsafe {
933 gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, s.to_glib_full());
934 }
935
936 value
937 }
938}
939
940impl ValueType for String {
941 type Type = String;
942}
943
944impl ValueTypeOptional for String {}
945
946unsafe impl<'a> FromValue<'a> for String {
947 type Checker = GenericValueTypeOrNoneChecker<Self>;
948
949 unsafe fn from_value(value: &'a Value) -> Self {
950 unsafe { String::from(<&str>::from_value(value)) }
951 }
952}
953
954impl ToValue for String {
955 fn to_value(&self) -> Value {
956 <&str>::to_value(&self.as_str())
957 }
958
959 fn value_type(&self) -> Type {
960 String::static_type()
961 }
962}
963
964impl From<String> for Value {
965 #[inline]
966 fn from(s: String) -> Self {
967 s.to_value()
968 }
969}
970
971impl ToValueOptional for String {
972 fn to_value_optional(s: Option<&Self>) -> Value {
973 <str>::to_value_optional(s.as_ref().map(|s| s.as_str()))
974 }
975}
976
977impl ValueType for Box<str> {
978 type Type = String;
979}
980
981impl ValueTypeOptional for Box<str> {}
982
983unsafe impl<'a> FromValue<'a> for Box<str> {
984 type Checker = GenericValueTypeOrNoneChecker<Self>;
985
986 unsafe fn from_value(value: &'a Value) -> Self {
987 unsafe { Box::<str>::from(<&str>::from_value(value)) }
988 }
989}
990
991impl StaticType for Box<str> {
992 fn static_type() -> Type {
993 String::static_type()
994 }
995}
996
997impl ToValue for Box<str> {
998 fn to_value(&self) -> Value {
999 <&str>::to_value(&self.as_ref())
1000 }
1001
1002 fn value_type(&self) -> Type {
1003 String::static_type()
1004 }
1005}
1006
1007impl From<Box<str>> for Value {
1008 #[inline]
1009 fn from(s: Box<str>) -> Self {
1010 s.to_value()
1011 }
1012}
1013
1014impl ToValueOptional for Box<str> {
1015 fn to_value_optional(s: Option<&Self>) -> Value {
1016 <str>::to_value_optional(s.as_ref().map(|s| s.as_ref()))
1017 }
1018}
1019
1020impl ValueType for Vec<String> {
1021 type Type = Vec<String>;
1022}
1023
1024unsafe impl<'a> FromValue<'a> for Vec<String> {
1025 type Checker = GenericValueTypeChecker<Self>;
1026
1027 unsafe fn from_value(value: &'a Value) -> Self {
1028 unsafe {
1029 let ptr =
1030 gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const *const c_char;
1031 FromGlibPtrContainer::from_glib_none(ptr)
1032 }
1033 }
1034}
1035
1036impl ToValue for Vec<String> {
1037 fn to_value(&self) -> Value {
1038 unsafe {
1039 let mut value = Value::for_value_type::<Self>();
1040 let ptr: *mut *mut c_char = self.to_glib_full();
1041 gobject_ffi::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void);
1042 value
1043 }
1044 }
1045
1046 fn value_type(&self) -> Type {
1047 <Vec<String>>::static_type()
1048 }
1049}
1050
1051impl From<Vec<String>> for Value {
1052 #[inline]
1053 fn from(s: Vec<String>) -> Self {
1054 s.to_value()
1055 }
1056}
1057
1058impl ToValue for [&'_ str] {
1059 fn to_value(&self) -> Value {
1060 unsafe {
1061 let mut value = Value::for_value_type::<Vec<String>>();
1062 let ptr: *mut *mut c_char = self.to_glib_full();
1063 gobject_ffi::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void);
1064 value
1065 }
1066 }
1067
1068 fn value_type(&self) -> Type {
1069 <Vec<String>>::static_type()
1070 }
1071}
1072
1073impl ToValue for &'_ [&'_ str] {
1074 fn to_value(&self) -> Value {
1075 unsafe {
1076 let mut value = Value::for_value_type::<Vec<String>>();
1077 let ptr: *mut *mut c_char = self.to_glib_full();
1078 gobject_ffi::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void);
1079 value
1080 }
1081 }
1082
1083 fn value_type(&self) -> Type {
1084 <Vec<String>>::static_type()
1085 }
1086}
1087
1088impl ToValue for Path {
1089 fn to_value(&self) -> Value {
1090 unsafe {
1091 let mut value = Value::for_value_type::<PathBuf>();
1092
1093 gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, self.to_glib_full());
1094
1095 value
1096 }
1097 }
1098
1099 fn value_type(&self) -> Type {
1100 PathBuf::static_type()
1101 }
1102}
1103
1104impl ToValue for &Path {
1105 fn to_value(&self) -> Value {
1106 (*self).to_value()
1107 }
1108
1109 fn value_type(&self) -> Type {
1110 PathBuf::static_type()
1111 }
1112}
1113
1114impl ToValueOptional for Path {
1115 fn to_value_optional(s: Option<&Self>) -> Value {
1116 let mut value = Value::for_value_type::<PathBuf>();
1117 unsafe {
1118 gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, s.to_glib_full());
1119 }
1120
1121 value
1122 }
1123}
1124
1125impl ValueType for PathBuf {
1126 type Type = PathBuf;
1127}
1128
1129impl ValueTypeOptional for PathBuf {}
1130
1131unsafe impl<'a> FromValue<'a> for PathBuf {
1132 type Checker = GenericValueTypeOrNoneChecker<Self>;
1133
1134 unsafe fn from_value(value: &'a Value) -> Self {
1135 unsafe { from_glib_none(gobject_ffi::g_value_get_string(value.to_glib_none().0)) }
1136 }
1137}
1138
1139impl ToValue for PathBuf {
1140 fn to_value(&self) -> Value {
1141 <&Path>::to_value(&self.as_path())
1142 }
1143
1144 fn value_type(&self) -> Type {
1145 PathBuf::static_type()
1146 }
1147}
1148
1149impl From<PathBuf> for Value {
1150 #[inline]
1151 fn from(s: PathBuf) -> Self {
1152 s.to_value()
1153 }
1154}
1155
1156impl ToValueOptional for PathBuf {
1157 fn to_value_optional(s: Option<&Self>) -> Value {
1158 <Path>::to_value_optional(s.as_ref().map(|s| s.as_path()))
1159 }
1160}
1161
1162impl ValueType for bool {
1163 type Type = Self;
1164}
1165
1166unsafe impl<'a> FromValue<'a> for bool {
1167 type Checker = GenericValueTypeChecker<Self>;
1168
1169 #[inline]
1170 unsafe fn from_value(value: &'a Value) -> Self {
1171 unsafe { from_glib(gobject_ffi::g_value_get_boolean(value.to_glib_none().0)) }
1172 }
1173}
1174
1175impl ToValue for bool {
1176 #[inline]
1177 fn to_value(&self) -> Value {
1178 let mut value = Value::for_value_type::<Self>();
1179 unsafe {
1180 gobject_ffi::g_value_set_boolean(&mut value.inner, self.into_glib());
1181 }
1182 value
1183 }
1184
1185 #[inline]
1186 fn value_type(&self) -> Type {
1187 Self::static_type()
1188 }
1189}
1190
1191impl From<bool> for Value {
1192 #[inline]
1193 fn from(v: bool) -> Self {
1194 v.to_value()
1195 }
1196}
1197
1198impl ValueType for Pointer {
1199 type Type = Self;
1200}
1201
1202unsafe impl<'a> FromValue<'a> for Pointer {
1203 type Checker = GenericValueTypeChecker<Self>;
1204
1205 #[inline]
1206 unsafe fn from_value(value: &'a Value) -> Self {
1207 unsafe { gobject_ffi::g_value_get_pointer(value.to_glib_none().0) }
1208 }
1209}
1210
1211impl ToValue for Pointer {
1212 #[inline]
1213 fn to_value(&self) -> Value {
1214 let mut value = Value::for_value_type::<Self>();
1215 unsafe {
1216 gobject_ffi::g_value_set_pointer(&mut value.inner, *self);
1217 }
1218 value
1219 }
1220
1221 #[inline]
1222 fn value_type(&self) -> Type {
1223 <<Self as ValueType>::Type as StaticType>::static_type()
1224 }
1225}
1226
1227impl From<Pointer> for Value {
1228 #[inline]
1229 fn from(v: Pointer) -> Self {
1230 v.to_value()
1231 }
1232}
1233
1234impl ValueType for ptr::NonNull<Pointee> {
1235 type Type = Pointer;
1236}
1237
1238unsafe impl<'a> FromValue<'a> for ptr::NonNull<Pointee> {
1239 type Checker = GenericValueTypeOrNoneChecker<Self>;
1240
1241 #[inline]
1242 unsafe fn from_value(value: &'a Value) -> Self {
1243 unsafe { ptr::NonNull::new_unchecked(Pointer::from_value(value)) }
1244 }
1245}
1246
1247impl ToValue for ptr::NonNull<Pointee> {
1248 #[inline]
1249 fn to_value(&self) -> Value {
1250 self.as_ptr().to_value()
1251 }
1252
1253 #[inline]
1254 fn value_type(&self) -> Type {
1255 <<Self as ValueType>::Type as StaticType>::static_type()
1256 }
1257}
1258
1259impl From<ptr::NonNull<Pointee>> for Value {
1260 #[inline]
1261 fn from(v: ptr::NonNull<Pointee>) -> Self {
1262 v.to_value()
1263 }
1264}
1265
1266impl ToValueOptional for ptr::NonNull<Pointee> {
1267 #[inline]
1268 fn to_value_optional(p: Option<&Self>) -> Value {
1269 p.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut()).to_value()
1270 }
1271}
1272
1273macro_rules! numeric {
1274 ($name:ty, $get:expr, $set:expr) => {
1275 impl ValueType for $name {
1276 type Type = Self;
1277 }
1278
1279 unsafe impl<'a> FromValue<'a> for $name {
1280 type Checker = GenericValueTypeChecker<Self>;
1281
1282 #[inline]
1283 #[allow(clippy::redundant_closure_call)]
1284 unsafe fn from_value(value: &'a Value) -> Self {
1285 unsafe { $get(value.to_glib_none().0) }
1286 }
1287 }
1288
1289 impl ToValue for $name {
1290 #[inline]
1291 #[allow(clippy::redundant_closure_call)]
1292 fn to_value(&self) -> Value {
1293 let mut value = Value::for_value_type::<Self>();
1294 unsafe {
1295 $set(&mut value.inner, *self);
1296 }
1297 value
1298 }
1299
1300 #[inline]
1301 fn value_type(&self) -> Type {
1302 Self::static_type()
1303 }
1304 }
1305
1306 impl From<$name> for Value {
1307 #[inline]
1308 fn from(v: $name) -> Self {
1309 v.to_value()
1310 }
1311 }
1312 };
1313}
1314macro_rules! not_zero {
1315 ($name:ty, $num:ty) => {
1316 impl ValueType for $name {
1317 type Type = $name;
1318 }
1319
1320 unsafe impl<'a> FromValue<'a> for $name {
1321 type Checker = GenericValueTypeOrNoneChecker<Self>;
1324
1325 #[inline]
1326 unsafe fn from_value(value: &'a Value) -> Self {
1327 unsafe {
1328 let res = <$num>::from_value(value);
1329 Self::try_from(res).unwrap()
1330 }
1331 }
1332 }
1333
1334 impl ToValue for $name {
1335 #[inline]
1336 fn to_value(&self) -> Value {
1337 <$num>::to_value(&<$num>::from(*self))
1338 }
1339
1340 #[inline]
1341 fn value_type(&self) -> Type {
1342 Self::static_type()
1343 }
1344 }
1345
1346 impl From<$name> for Value {
1347 #[inline]
1348 fn from(v: $name) -> Self {
1349 v.to_value()
1350 }
1351 }
1352
1353 impl ToValueOptional for $name {
1354 fn to_value_optional(s: Option<&Self>) -> Value {
1355 match s {
1356 Some(x) => x.to_value(),
1357 None => <$num>::to_value(&0),
1358 }
1359 }
1360 }
1361 };
1362}
1363
1364numeric!(
1365 i8,
1366 gobject_ffi::g_value_get_schar,
1367 gobject_ffi::g_value_set_schar
1368);
1369not_zero!(NonZeroI8, i8);
1370numeric!(
1371 u8,
1372 gobject_ffi::g_value_get_uchar,
1373 gobject_ffi::g_value_set_uchar
1374);
1375not_zero!(NonZeroU8, u8);
1376numeric!(
1377 i32,
1378 gobject_ffi::g_value_get_int,
1379 gobject_ffi::g_value_set_int
1380);
1381not_zero!(NonZeroI32, i32);
1382numeric!(
1383 u32,
1384 gobject_ffi::g_value_get_uint,
1385 gobject_ffi::g_value_set_uint
1386);
1387not_zero!(NonZeroU32, u32);
1388numeric!(
1389 i64,
1390 gobject_ffi::g_value_get_int64,
1391 gobject_ffi::g_value_set_int64
1392);
1393not_zero!(NonZeroI64, i64);
1394numeric!(
1395 u64,
1396 gobject_ffi::g_value_get_uint64,
1397 gobject_ffi::g_value_set_uint64
1398);
1399not_zero!(NonZeroU64, u64);
1400numeric!(
1401 crate::ILong,
1402 |v| gobject_ffi::g_value_get_long(v).into(),
1403 |v, i: crate::ILong| gobject_ffi::g_value_set_long(v, i.0)
1404);
1405numeric!(
1406 crate::ULong,
1407 |v| gobject_ffi::g_value_get_ulong(v).into(),
1408 |v, i: crate::ULong| gobject_ffi::g_value_set_ulong(v, i.0)
1409);
1410numeric!(
1411 f32,
1412 gobject_ffi::g_value_get_float,
1413 gobject_ffi::g_value_set_float
1414);
1415numeric!(
1416 f64,
1417 gobject_ffi::g_value_get_double,
1418 gobject_ffi::g_value_set_double
1419);
1420
1421impl ValueType for char {
1422 type Type = u32;
1423}
1424
1425unsafe impl<'a> FromValue<'a> for char {
1426 type Checker = CharTypeChecker;
1427
1428 #[inline]
1429 unsafe fn from_value(value: &'a Value) -> Self {
1430 unsafe {
1431 let res: u32 = gobject_ffi::g_value_get_uint(value.to_glib_none().0);
1432 char::from_u32_unchecked(res)
1434 }
1435 }
1436}
1437
1438impl ToValue for char {
1439 #[inline]
1440 fn to_value(&self) -> Value {
1441 let mut value = Value::for_value_type::<Self>();
1442 unsafe {
1443 gobject_ffi::g_value_set_uint(&mut value.inner, *self as u32);
1444 }
1445 value
1446 }
1447
1448 #[inline]
1449 fn value_type(&self) -> Type {
1450 crate::Type::U32
1451 }
1452}
1453
1454impl From<char> for Value {
1455 #[inline]
1456 fn from(v: char) -> Self {
1457 v.to_value()
1458 }
1459}
1460
1461pub struct BoxedValue(pub Value);
1464
1465impl Deref for BoxedValue {
1466 type Target = Value;
1467
1468 #[inline]
1469 fn deref(&self) -> &Value {
1470 &self.0
1471 }
1472}
1473
1474impl ValueType for BoxedValue {
1475 type Type = BoxedValue;
1476}
1477
1478impl ValueTypeOptional for BoxedValue {}
1479
1480unsafe impl<'a> FromValue<'a> for BoxedValue {
1481 type Checker = GenericValueTypeOrNoneChecker<Self>;
1482
1483 #[inline]
1484 unsafe fn from_value(value: &'a Value) -> Self {
1485 unsafe {
1486 let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0);
1487 BoxedValue(from_glib_none(ptr as *const gobject_ffi::GValue))
1488 }
1489 }
1490}
1491
1492impl ToValue for BoxedValue {
1493 #[inline]
1494 fn to_value(&self) -> Value {
1495 unsafe {
1496 let mut value = Value::for_value_type::<BoxedValue>();
1497
1498 gobject_ffi::g_value_set_boxed(
1499 value.to_glib_none_mut().0,
1500 self.0.to_glib_none().0 as ffi::gconstpointer,
1501 );
1502
1503 value
1504 }
1505 }
1506
1507 #[inline]
1508 fn value_type(&self) -> Type {
1509 BoxedValue::static_type()
1510 }
1511}
1512
1513impl From<BoxedValue> for Value {
1514 #[inline]
1515 fn from(v: BoxedValue) -> Self {
1516 unsafe {
1517 let mut value = Value::for_value_type::<BoxedValue>();
1518
1519 gobject_ffi::g_value_take_boxed(
1520 value.to_glib_none_mut().0,
1521 v.0.to_glib_full() as ffi::gconstpointer,
1522 );
1523
1524 value
1525 }
1526 }
1527}
1528
1529impl ToValueOptional for BoxedValue {
1530 #[inline]
1531 fn to_value_optional(s: Option<&Self>) -> Value {
1532 let mut value = Value::for_value_type::<Self>();
1533 unsafe {
1534 gobject_ffi::g_value_set_boxed(
1535 value.to_glib_none_mut().0,
1536 s.map(|s| &s.0).to_glib_none().0 as ffi::gconstpointer,
1537 );
1538 }
1539
1540 value
1541 }
1542}
1543
1544#[cfg(test)]
1545mod tests {
1546 use std::num::NonZeroI32;
1547
1548 use super::*;
1549
1550 #[test]
1551 fn test_send_value() {
1552 use std::thread;
1553
1554 let v = SendValue::from(&1i32);
1555
1556 thread::spawn(move || drop(v)).join().unwrap();
1558 }
1559
1560 #[test]
1561 fn test_strv() {
1562 let v = ["123", "456"].to_value();
1563 assert_eq!(
1564 v.get::<Vec<GString>>(),
1565 Ok(vec![GString::from("123"), GString::from("456")])
1566 );
1567
1568 let v = vec![String::from("123"), String::from("456")].to_value();
1569 assert_eq!(
1570 v.get::<Vec<GString>>(),
1571 Ok(vec![GString::from("123"), GString::from("456")])
1572 );
1573 }
1574
1575 #[test]
1576 fn test_from_to_value() {
1577 let v = 123.to_value();
1578 assert_eq!(v.get(), Ok(123));
1579 assert_eq!(
1580 v.get::<&str>(),
1581 Err(ValueTypeMismatchError::new(Type::I32, Type::STRING).into())
1582 );
1583 assert_eq!(
1584 v.get::<bool>(),
1585 Err(ValueTypeMismatchError::new(Type::I32, Type::BOOL))
1586 );
1587
1588 let v_str = "test".to_value();
1590 assert_eq!(v_str.get::<&str>(), Ok("test"));
1591 assert_eq!(v_str.get::<Option<&str>>(), Ok(Some("test")));
1592 assert_eq!(
1593 v_str.get::<i32>(),
1594 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1595 );
1596
1597 let some_v = Some("test").to_value();
1598 assert_eq!(some_v.get::<&str>(), Ok("test"));
1599 assert_eq!(some_v.get_owned::<String>(), Ok("test".to_string()));
1600 assert_eq!(
1601 some_v.get_owned::<Option<String>>(),
1602 Ok(Some("test".to_string()))
1603 );
1604 assert_eq!(some_v.get::<Option<&str>>(), Ok(Some("test")));
1605 assert_eq!(
1606 some_v.get::<i32>(),
1607 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1608 );
1609
1610 let none_str: Option<&str> = None;
1611 let none_v = none_str.to_value();
1612 assert_eq!(none_v.get::<Option<&str>>(), Ok(None));
1613 assert_eq!(
1614 none_v.get::<i32>(),
1615 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1616 );
1617
1618 let v_str = String::from("test").to_value();
1620 assert_eq!(v_str.get::<String>(), Ok(String::from("test")));
1621 assert_eq!(
1622 v_str.get::<Option<String>>(),
1623 Ok(Some(String::from("test")))
1624 );
1625 assert_eq!(
1626 v_str.get::<i32>(),
1627 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1628 );
1629
1630 let some_v = Some(String::from("test")).to_value();
1631 assert_eq!(some_v.get::<String>(), Ok(String::from("test")));
1632 assert_eq!(
1633 some_v.get::<Option<String>>(),
1634 Ok(Some(String::from("test")))
1635 );
1636 assert_eq!(
1637 some_v.get::<i32>(),
1638 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1639 );
1640
1641 let none_str: Option<String> = None;
1642 let none_v = none_str.to_value();
1643 assert_eq!(none_v.get::<Option<String>>(), Ok(None));
1644 assert_eq!(
1645 none_v.get::<i32>(),
1646 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1647 );
1648
1649 let c_v = 'c'.to_value();
1650 assert_eq!(c_v.get::<char>(), Ok('c'));
1651
1652 let c_v = 0xFFFFFFFFu32.to_value();
1653 assert_eq!(
1654 c_v.get::<char>(),
1655 Err(InvalidCharError::CharConversionError)
1656 );
1657
1658 let v_str = String::from("test").to_value();
1660 assert_eq!(v_str.get::<String>(), Ok(String::from("test")));
1661 assert_eq!(
1662 v_str.get::<Option<String>>(),
1663 Ok(Some(String::from("test")))
1664 );
1665 assert_eq!(
1666 v_str.get::<i32>(),
1667 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1668 );
1669
1670 let some_v = Some(&String::from("test")).to_value();
1671 assert_eq!(some_v.get::<String>(), Ok(String::from("test")));
1672 assert_eq!(
1673 some_v.get::<Option<String>>(),
1674 Ok(Some(String::from("test")))
1675 );
1676 assert_eq!(
1677 some_v.get::<i32>(),
1678 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1679 );
1680
1681 let none_str: Option<&String> = None;
1682 let none_v = none_str.to_value();
1683 assert_eq!(none_v.get::<Option<String>>(), Ok(None));
1684 assert_eq!(
1685 none_v.get::<i32>(),
1686 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1687 );
1688
1689 let v = NonZeroI32::new(123).unwrap().to_value();
1691 assert_eq!(v.get::<NonZeroI32>(), Ok(NonZeroI32::new(123).unwrap()));
1692
1693 let v = 123i32.to_value();
1694 assert_eq!(v.get::<NonZeroI32>(), Ok(NonZeroI32::new(123).unwrap()));
1695
1696 let v = 0i32.to_value();
1697 assert_eq!(
1698 v.get::<NonZeroI32>(),
1699 Err(ValueTypeMismatchOrNoneError::UnexpectedNone)
1700 );
1701
1702 assert_eq!(v.get::<Option<NonZeroI32>>(), Ok(None));
1703 }
1704
1705 #[test]
1706 fn test_transform() {
1707 let v = 123.to_value();
1708 let v2 = v
1709 .transform::<String>()
1710 .expect("Failed to transform to string");
1711 assert_eq!(v2.get::<&str>(), Ok("123"));
1712 }
1713
1714 #[test]
1715 fn test_into_raw() {
1716 unsafe {
1717 let mut v = 123.to_value().into_raw();
1718 assert_eq!(gobject_ffi::g_type_check_value(&v), ffi::GTRUE);
1719 assert_eq!(gobject_ffi::g_value_get_int(&v), 123);
1720 gobject_ffi::g_value_unset(&mut v);
1721 }
1722 }
1723
1724 #[test]
1725 fn test_debug() {
1726 fn value_debug_string<T: ToValue>(val: T) -> String {
1727 format!("{:?}", val.to_value())
1728 }
1729
1730 assert_eq!(value_debug_string(1u32), "(guint) 1");
1731 assert_eq!(value_debug_string(2i32), "(gint) 2");
1732 assert_eq!(value_debug_string(false), "(gboolean) FALSE");
1733 assert_eq!(value_debug_string("FooBar"), r#"(gchararray) "FooBar""#);
1734 }
1735}