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")]
524 pub struct Value(BoxedInline<gobject_ffi::GValue>);
525
526 match fn {
527 copy => |ptr| copy_value(ptr),
528 free => |ptr| free_value(ptr),
529 init => |ptr| init_value(ptr),
530 copy_into => |dest, src| copy_into_value(dest, src),
531 clear => |ptr| clear_value(ptr),
532 }
533}
534
535impl Value {
536 pub fn from_type(type_: Type) -> Self {
543 unsafe {
544 assert_eq!(
545 gobject_ffi::g_type_check_is_value_type(type_.into_glib()),
546 ffi::GTRUE
547 );
548 Self::from_type_unchecked(type_)
549 }
550 }
551
552 #[inline]
559 pub unsafe fn from_type_unchecked(type_: Type) -> Self {
560 unsafe {
561 let mut value = Value::uninitialized();
562 gobject_ffi::g_value_init(value.to_glib_none_mut().0, type_.into_glib());
563 value
564 }
565 }
566
567 #[inline]
570 pub fn for_value_type<T: ValueType>() -> Self {
571 unsafe { Value::from_type_unchecked(T::Type::static_type()) }
572 }
573
574 #[inline]
577 #[doc(alias = "g_value_set_static_string")]
578 pub fn from_static_str(s: &'static GStr) -> Self {
579 unsafe {
580 let mut v = Self::from_type_unchecked(Type::STRING);
581 gobject_ffi::g_value_set_static_string(v.to_glib_none_mut().0, s.as_ptr());
582 v
583 }
584 }
585
586 #[cfg(feature = "v2_66")]
587 #[cfg_attr(docsrs, doc(cfg(feature = "v2_66")))]
588 #[inline]
592 #[doc(alias = "g_value_set_interned_string")]
593 pub fn from_interned_str(s: &'static GStr) -> Self {
594 unsafe {
595 let mut v = Self::from_type_unchecked(Type::STRING);
596 gobject_ffi::g_value_set_interned_string(v.to_glib_none_mut().0, s.as_ptr());
597 v
598 }
599 }
600
601 #[inline]
606 pub fn get<'a, T>(
607 &'a self,
608 ) -> Result<T, <<T as FromValue<'a>>::Checker as ValueTypeChecker>::Error>
609 where
610 T: FromValue<'a>,
611 {
612 unsafe {
613 T::Checker::check(self)?;
614 Ok(T::from_value(self))
615 }
616 }
617
618 #[inline]
621 pub fn get_owned<T>(
622 &self,
623 ) -> Result<T, <<T as FromValue<'_>>::Checker as ValueTypeChecker>::Error>
624 where
625 T: for<'b> FromValue<'b> + 'static,
626 {
627 unsafe {
628 T::Checker::check(self)?;
629 Ok(FromValue::from_value(self))
630 }
631 }
632
633 #[inline]
637 pub fn is<T: StaticType>(&self) -> bool {
638 self.is_type(T::static_type())
639 }
640
641 #[inline]
645 pub fn is_type(&self, type_: Type) -> bool {
646 self.type_().is_a(type_)
647 }
648
649 #[inline]
652 pub fn type_(&self) -> Type {
653 unsafe { from_glib(self.inner.g_type) }
654 }
655
656 #[doc(alias = "g_value_type_transformable")]
674 pub fn type_transformable(src: Type, dst: Type) -> bool {
675 unsafe {
676 from_glib(gobject_ffi::g_value_type_transformable(
677 src.into_glib(),
678 dst.into_glib(),
679 ))
680 }
681 }
682
683 #[doc(alias = "g_value_transform")]
705 pub fn transform<T: ValueType>(&self) -> Result<Value, crate::BoolError> {
706 self.transform_with_type(T::Type::static_type())
707 }
708
709 #[doc(alias = "g_value_transform")]
712 pub fn transform_with_type(&self, type_: Type) -> Result<Value, crate::BoolError> {
713 unsafe {
714 let mut dest = Value::from_type(type_);
715 if from_glib(gobject_ffi::g_value_transform(
716 self.to_glib_none().0,
717 dest.to_glib_none_mut().0,
718 )) {
719 Ok(dest)
720 } else {
721 Err(crate::bool_error!(
722 "Can't transform value of type '{}' into '{}'",
723 self.type_(),
724 type_
725 ))
726 }
727 }
728 }
729
730 #[inline]
733 pub fn into_raw(self) -> gobject_ffi::GValue {
734 unsafe {
735 let s = mem::ManuallyDrop::new(self);
736 ptr::read(&s.inner)
737 }
738 }
739
740 #[inline]
744 pub fn try_into_send_value<T: Send + StaticType>(self) -> Result<SendValue, Self> {
745 if self.type_().is_a(T::static_type()) {
746 unsafe { Ok(SendValue::unsafe_from(self.into_raw())) }
747 } else {
748 Err(self)
749 }
750 }
751
752 #[inline]
759 pub unsafe fn into_send_value(self) -> SendValue {
760 unsafe { SendValue::unsafe_from(self.into_raw()) }
761 }
762
763 fn content_debug_string(&self) -> GString {
764 unsafe { from_glib_full(gobject_ffi::g_strdup_value_contents(self.to_glib_none().0)) }
765 }
766}
767
768impl fmt::Debug for Value {
769 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
770 write!(f, "({}) {}", self.type_(), self.content_debug_string())
771 }
772}
773
774impl<'a, T: ?Sized + ToValue> From<&'a T> for Value {
775 #[inline]
776 fn from(value: &'a T) -> Self {
777 value.to_value()
778 }
779}
780
781impl From<SendValue> for Value {
782 #[inline]
783 fn from(value: SendValue) -> Self {
784 unsafe { Value::unsafe_from(value.into_raw()) }
785 }
786}
787
788impl ToValue for Value {
789 #[inline]
790 fn to_value(&self) -> Value {
791 self.clone()
792 }
793
794 #[inline]
795 fn value_type(&self) -> Type {
796 self.type_()
797 }
798}
799
800impl ToValue for &Value {
801 #[inline]
802 fn to_value(&self) -> Value {
803 (*self).clone()
804 }
805
806 #[inline]
807 fn value_type(&self) -> Type {
808 self.type_()
809 }
810}
811
812pub struct NopChecker;
813
814unsafe impl ValueTypeChecker for NopChecker {
815 type Error = Infallible;
816
817 #[inline]
818 fn check(_value: &Value) -> Result<(), Self::Error> {
819 Ok(())
820 }
821}
822
823unsafe impl<'a> FromValue<'a> for Value {
824 type Checker = NopChecker;
825
826 #[inline]
827 unsafe fn from_value(value: &'a Value) -> Self {
828 value.clone()
829 }
830}
831
832unsafe impl<'a> FromValue<'a> for &'a Value {
833 type Checker = NopChecker;
834
835 #[inline]
836 unsafe fn from_value(value: &'a Value) -> Self {
837 value
838 }
839}
840
841impl ToValue for SendValue {
842 #[inline]
843 fn to_value(&self) -> Value {
844 unsafe { from_glib_none(self.to_glib_none().0) }
845 }
846
847 #[inline]
848 fn value_type(&self) -> Type {
849 self.type_()
850 }
851}
852
853impl ToValue for &SendValue {
854 #[inline]
855 fn to_value(&self) -> Value {
856 unsafe { from_glib_none(self.to_glib_none().0) }
857 }
858
859 #[inline]
860 fn value_type(&self) -> Type {
861 self.type_()
862 }
863}
864
865impl StaticType for BoxedValue {
866 #[inline]
867 fn static_type() -> Type {
868 unsafe { from_glib(gobject_ffi::g_value_get_type()) }
869 }
870}
871
872crate::wrapper! {
873 #[doc(alias = "GValue")]
879 pub struct SendValue(BoxedInline<gobject_ffi::GValue>);
880
881 match fn {
882 copy => |ptr| copy_value(ptr),
883 free => |ptr| free_value(ptr),
884 init => |ptr| init_value(ptr),
885 copy_into => |dest, src| copy_into_value(dest, src),
886 clear => |ptr| clear_value(ptr),
887 }
888}
889
890unsafe impl Send for SendValue {}
891
892impl SendValue {
893 #[inline]
896 pub fn into_raw(self) -> gobject_ffi::GValue {
897 unsafe {
898 let s = mem::ManuallyDrop::new(self);
899 ptr::read(&s.inner)
900 }
901 }
902 #[inline]
903 pub fn from_owned<T: Send + Into<Value>>(t: T) -> Self {
904 unsafe { Self::unsafe_from(t.into().into_raw()) }
905 }
906}
907
908impl fmt::Debug for SendValue {
909 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
910 write!(f, "({}) {}", self.type_(), self.content_debug_string())
911 }
912}
913
914impl Deref for SendValue {
915 type Target = Value;
916
917 #[inline]
918 fn deref(&self) -> &Value {
919 unsafe { &*(self as *const SendValue as *const Value) }
920 }
921}
922
923impl<'a, T: ?Sized + ToSendValue> From<&'a T> for SendValue {
924 #[inline]
925 fn from(value: &'a T) -> Self {
926 value.to_send_value()
927 }
928}
929
930pub trait ToSendValue: Send + ToValue {
933 fn to_send_value(&self) -> SendValue;
936}
937
938impl<T: Send + ToValue + ?Sized> ToSendValue for T {
939 #[inline]
940 fn to_send_value(&self) -> SendValue {
941 unsafe { SendValue::unsafe_from(self.to_value().into_raw()) }
942 }
943}
944
945unsafe impl<'a> FromValue<'a> for &'a str {
946 type Checker = GenericValueTypeOrNoneChecker<Self>;
947
948 #[inline]
949 unsafe fn from_value(value: &'a Value) -> Self {
950 unsafe {
951 let ptr = gobject_ffi::g_value_get_string(value.to_glib_none().0);
952 CStr::from_ptr(ptr).to_str().expect("Invalid UTF-8")
953 }
954 }
955}
956
957impl ToValue for str {
958 fn to_value(&self) -> Value {
959 unsafe {
960 let mut value = Value::for_value_type::<String>();
961
962 gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, self.to_glib_full());
963
964 value
965 }
966 }
967
968 fn value_type(&self) -> Type {
969 String::static_type()
970 }
971}
972
973impl ToValue for &str {
974 fn to_value(&self) -> Value {
975 (*self).to_value()
976 }
977
978 fn value_type(&self) -> Type {
979 String::static_type()
980 }
981}
982
983impl ToValueOptional for str {
984 fn to_value_optional(s: Option<&Self>) -> Value {
985 let mut value = Value::for_value_type::<String>();
986 unsafe {
987 gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, s.to_glib_full());
988 }
989
990 value
991 }
992}
993
994impl ValueType for String {
995 type Type = String;
996}
997
998impl ValueTypeOptional for String {}
999
1000unsafe impl<'a> FromValue<'a> for String {
1001 type Checker = GenericValueTypeOrNoneChecker<Self>;
1002
1003 unsafe fn from_value(value: &'a Value) -> Self {
1004 unsafe { String::from(<&str>::from_value(value)) }
1005 }
1006}
1007
1008impl ToValue for String {
1009 fn to_value(&self) -> Value {
1010 <&str>::to_value(&self.as_str())
1011 }
1012
1013 fn value_type(&self) -> Type {
1014 String::static_type()
1015 }
1016}
1017
1018impl From<String> for Value {
1019 #[inline]
1020 fn from(s: String) -> Self {
1021 s.to_value()
1022 }
1023}
1024
1025impl ToValueOptional for String {
1026 fn to_value_optional(s: Option<&Self>) -> Value {
1027 <str>::to_value_optional(s.as_ref().map(|s| s.as_str()))
1028 }
1029}
1030
1031impl ValueType for Box<str> {
1032 type Type = String;
1033}
1034
1035impl ValueTypeOptional for Box<str> {}
1036
1037unsafe impl<'a> FromValue<'a> for Box<str> {
1038 type Checker = GenericValueTypeOrNoneChecker<Self>;
1039
1040 unsafe fn from_value(value: &'a Value) -> Self {
1041 unsafe { Box::<str>::from(<&str>::from_value(value)) }
1042 }
1043}
1044
1045impl StaticType for Box<str> {
1046 fn static_type() -> Type {
1047 String::static_type()
1048 }
1049}
1050
1051impl ToValue for Box<str> {
1052 fn to_value(&self) -> Value {
1053 <&str>::to_value(&self.as_ref())
1054 }
1055
1056 fn value_type(&self) -> Type {
1057 String::static_type()
1058 }
1059}
1060
1061impl From<Box<str>> for Value {
1062 #[inline]
1063 fn from(s: Box<str>) -> Self {
1064 s.to_value()
1065 }
1066}
1067
1068impl ToValueOptional for Box<str> {
1069 fn to_value_optional(s: Option<&Self>) -> Value {
1070 <str>::to_value_optional(s.as_ref().map(|s| s.as_ref()))
1071 }
1072}
1073
1074impl ValueType for Vec<String> {
1075 type Type = Vec<String>;
1076}
1077
1078unsafe impl<'a> FromValue<'a> for Vec<String> {
1079 type Checker = GenericValueTypeChecker<Self>;
1080
1081 unsafe fn from_value(value: &'a Value) -> Self {
1082 unsafe {
1083 let ptr =
1084 gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const *const c_char;
1085 FromGlibPtrContainer::from_glib_none(ptr)
1086 }
1087 }
1088}
1089
1090impl ToValue for Vec<String> {
1091 fn to_value(&self) -> Value {
1092 unsafe {
1093 let mut value = Value::for_value_type::<Self>();
1094 let ptr: *mut *mut c_char = self.to_glib_full();
1095 gobject_ffi::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void);
1096 value
1097 }
1098 }
1099
1100 fn value_type(&self) -> Type {
1101 <Vec<String>>::static_type()
1102 }
1103}
1104
1105impl From<Vec<String>> for Value {
1106 #[inline]
1107 fn from(s: Vec<String>) -> Self {
1108 s.to_value()
1109 }
1110}
1111
1112impl ToValue for [&'_ str] {
1113 fn to_value(&self) -> Value {
1114 unsafe {
1115 let mut value = Value::for_value_type::<Vec<String>>();
1116 let ptr: *mut *mut c_char = self.to_glib_full();
1117 gobject_ffi::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void);
1118 value
1119 }
1120 }
1121
1122 fn value_type(&self) -> Type {
1123 <Vec<String>>::static_type()
1124 }
1125}
1126
1127impl ToValue for &'_ [&'_ str] {
1128 fn to_value(&self) -> Value {
1129 unsafe {
1130 let mut value = Value::for_value_type::<Vec<String>>();
1131 let ptr: *mut *mut c_char = self.to_glib_full();
1132 gobject_ffi::g_value_take_boxed(value.to_glib_none_mut().0, ptr as *const c_void);
1133 value
1134 }
1135 }
1136
1137 fn value_type(&self) -> Type {
1138 <Vec<String>>::static_type()
1139 }
1140}
1141
1142impl ToValue for Path {
1143 fn to_value(&self) -> Value {
1144 unsafe {
1145 let mut value = Value::for_value_type::<PathBuf>();
1146
1147 gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, self.to_glib_full());
1148
1149 value
1150 }
1151 }
1152
1153 fn value_type(&self) -> Type {
1154 PathBuf::static_type()
1155 }
1156}
1157
1158impl ToValue for &Path {
1159 fn to_value(&self) -> Value {
1160 (*self).to_value()
1161 }
1162
1163 fn value_type(&self) -> Type {
1164 PathBuf::static_type()
1165 }
1166}
1167
1168impl ToValueOptional for Path {
1169 fn to_value_optional(s: Option<&Self>) -> Value {
1170 let mut value = Value::for_value_type::<PathBuf>();
1171 unsafe {
1172 gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, s.to_glib_full());
1173 }
1174
1175 value
1176 }
1177}
1178
1179impl ValueType for PathBuf {
1180 type Type = PathBuf;
1181}
1182
1183impl ValueTypeOptional for PathBuf {}
1184
1185unsafe impl<'a> FromValue<'a> for PathBuf {
1186 type Checker = GenericValueTypeOrNoneChecker<Self>;
1187
1188 unsafe fn from_value(value: &'a Value) -> Self {
1189 unsafe { from_glib_none(gobject_ffi::g_value_get_string(value.to_glib_none().0)) }
1190 }
1191}
1192
1193impl ToValue for PathBuf {
1194 fn to_value(&self) -> Value {
1195 <&Path>::to_value(&self.as_path())
1196 }
1197
1198 fn value_type(&self) -> Type {
1199 PathBuf::static_type()
1200 }
1201}
1202
1203impl From<PathBuf> for Value {
1204 #[inline]
1205 fn from(s: PathBuf) -> Self {
1206 s.to_value()
1207 }
1208}
1209
1210impl ToValueOptional for PathBuf {
1211 fn to_value_optional(s: Option<&Self>) -> Value {
1212 <Path>::to_value_optional(s.as_ref().map(|s| s.as_path()))
1213 }
1214}
1215
1216impl ValueType for bool {
1217 type Type = Self;
1218}
1219
1220unsafe impl<'a> FromValue<'a> for bool {
1221 type Checker = GenericValueTypeChecker<Self>;
1222
1223 #[inline]
1224 unsafe fn from_value(value: &'a Value) -> Self {
1225 unsafe { from_glib(gobject_ffi::g_value_get_boolean(value.to_glib_none().0)) }
1226 }
1227}
1228
1229impl ToValue for bool {
1230 #[inline]
1231 fn to_value(&self) -> Value {
1232 let mut value = Value::for_value_type::<Self>();
1233 unsafe {
1234 gobject_ffi::g_value_set_boolean(&mut value.inner, self.into_glib());
1235 }
1236 value
1237 }
1238
1239 #[inline]
1240 fn value_type(&self) -> Type {
1241 Self::static_type()
1242 }
1243}
1244
1245impl From<bool> for Value {
1246 #[inline]
1247 fn from(v: bool) -> Self {
1248 v.to_value()
1249 }
1250}
1251
1252impl ValueType for Pointer {
1253 type Type = Self;
1254}
1255
1256unsafe impl<'a> FromValue<'a> for Pointer {
1257 type Checker = GenericValueTypeChecker<Self>;
1258
1259 #[inline]
1260 unsafe fn from_value(value: &'a Value) -> Self {
1261 unsafe { gobject_ffi::g_value_get_pointer(value.to_glib_none().0) }
1262 }
1263}
1264
1265impl ToValue for Pointer {
1266 #[inline]
1267 fn to_value(&self) -> Value {
1268 let mut value = Value::for_value_type::<Self>();
1269 unsafe {
1270 gobject_ffi::g_value_set_pointer(&mut value.inner, *self);
1271 }
1272 value
1273 }
1274
1275 #[inline]
1276 fn value_type(&self) -> Type {
1277 <<Self as ValueType>::Type as StaticType>::static_type()
1278 }
1279}
1280
1281impl From<Pointer> for Value {
1282 #[inline]
1283 fn from(v: Pointer) -> Self {
1284 v.to_value()
1285 }
1286}
1287
1288impl ValueType for ptr::NonNull<Pointee> {
1289 type Type = Pointer;
1290}
1291
1292unsafe impl<'a> FromValue<'a> for ptr::NonNull<Pointee> {
1293 type Checker = GenericValueTypeOrNoneChecker<Self>;
1294
1295 #[inline]
1296 unsafe fn from_value(value: &'a Value) -> Self {
1297 unsafe { ptr::NonNull::new_unchecked(Pointer::from_value(value)) }
1298 }
1299}
1300
1301impl ToValue for ptr::NonNull<Pointee> {
1302 #[inline]
1303 fn to_value(&self) -> Value {
1304 self.as_ptr().to_value()
1305 }
1306
1307 #[inline]
1308 fn value_type(&self) -> Type {
1309 <<Self as ValueType>::Type as StaticType>::static_type()
1310 }
1311}
1312
1313impl From<ptr::NonNull<Pointee>> for Value {
1314 #[inline]
1315 fn from(v: ptr::NonNull<Pointee>) -> Self {
1316 v.to_value()
1317 }
1318}
1319
1320impl ToValueOptional for ptr::NonNull<Pointee> {
1321 #[inline]
1322 fn to_value_optional(p: Option<&Self>) -> Value {
1323 p.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut()).to_value()
1324 }
1325}
1326
1327macro_rules! numeric {
1328 ($name:ty, $get:expr, $set:expr) => {
1329 impl ValueType for $name {
1330 type Type = Self;
1331 }
1332
1333 unsafe impl<'a> FromValue<'a> for $name {
1334 type Checker = GenericValueTypeChecker<Self>;
1335
1336 #[inline]
1337 #[allow(clippy::redundant_closure_call)]
1338 unsafe fn from_value(value: &'a Value) -> Self {
1339 unsafe { $get(value.to_glib_none().0) }
1340 }
1341 }
1342
1343 impl ToValue for $name {
1344 #[inline]
1345 #[allow(clippy::redundant_closure_call)]
1346 fn to_value(&self) -> Value {
1347 let mut value = Value::for_value_type::<Self>();
1348 unsafe {
1349 $set(&mut value.inner, *self);
1350 }
1351 value
1352 }
1353
1354 #[inline]
1355 fn value_type(&self) -> Type {
1356 Self::static_type()
1357 }
1358 }
1359
1360 impl From<$name> for Value {
1361 #[inline]
1362 fn from(v: $name) -> Self {
1363 v.to_value()
1364 }
1365 }
1366 };
1367}
1368macro_rules! not_zero {
1369 ($name:ty, $num:ty) => {
1370 impl ValueType for $name {
1371 type Type = $name;
1372 }
1373
1374 unsafe impl<'a> FromValue<'a> for $name {
1375 type Checker = GenericValueTypeOrNoneChecker<Self>;
1378
1379 #[inline]
1380 unsafe fn from_value(value: &'a Value) -> Self {
1381 unsafe {
1382 let res = <$num>::from_value(value);
1383 Self::try_from(res).unwrap()
1384 }
1385 }
1386 }
1387
1388 impl ToValue for $name {
1389 #[inline]
1390 fn to_value(&self) -> Value {
1391 <$num>::to_value(&<$num>::from(*self))
1392 }
1393
1394 #[inline]
1395 fn value_type(&self) -> Type {
1396 Self::static_type()
1397 }
1398 }
1399
1400 impl From<$name> for Value {
1401 #[inline]
1402 fn from(v: $name) -> Self {
1403 v.to_value()
1404 }
1405 }
1406
1407 impl ToValueOptional for $name {
1408 fn to_value_optional(s: Option<&Self>) -> Value {
1409 match s {
1410 Some(x) => x.to_value(),
1411 None => <$num>::to_value(&0),
1412 }
1413 }
1414 }
1415 };
1416}
1417
1418numeric!(
1419 i8,
1420 gobject_ffi::g_value_get_schar,
1421 gobject_ffi::g_value_set_schar
1422);
1423not_zero!(NonZeroI8, i8);
1424numeric!(
1425 u8,
1426 gobject_ffi::g_value_get_uchar,
1427 gobject_ffi::g_value_set_uchar
1428);
1429not_zero!(NonZeroU8, u8);
1430numeric!(
1431 i32,
1432 gobject_ffi::g_value_get_int,
1433 gobject_ffi::g_value_set_int
1434);
1435not_zero!(NonZeroI32, i32);
1436numeric!(
1437 u32,
1438 gobject_ffi::g_value_get_uint,
1439 gobject_ffi::g_value_set_uint
1440);
1441not_zero!(NonZeroU32, u32);
1442numeric!(
1443 i64,
1444 gobject_ffi::g_value_get_int64,
1445 gobject_ffi::g_value_set_int64
1446);
1447not_zero!(NonZeroI64, i64);
1448numeric!(
1449 u64,
1450 gobject_ffi::g_value_get_uint64,
1451 gobject_ffi::g_value_set_uint64
1452);
1453not_zero!(NonZeroU64, u64);
1454numeric!(
1455 crate::ILong,
1456 |v| gobject_ffi::g_value_get_long(v).into(),
1457 |v, i: crate::ILong| gobject_ffi::g_value_set_long(v, i.0)
1458);
1459numeric!(
1460 crate::ULong,
1461 |v| gobject_ffi::g_value_get_ulong(v).into(),
1462 |v, i: crate::ULong| gobject_ffi::g_value_set_ulong(v, i.0)
1463);
1464numeric!(
1465 f32,
1466 gobject_ffi::g_value_get_float,
1467 gobject_ffi::g_value_set_float
1468);
1469numeric!(
1470 f64,
1471 gobject_ffi::g_value_get_double,
1472 gobject_ffi::g_value_set_double
1473);
1474
1475impl ValueType for char {
1476 type Type = u32;
1477}
1478
1479unsafe impl<'a> FromValue<'a> for char {
1480 type Checker = CharTypeChecker;
1481
1482 #[inline]
1483 unsafe fn from_value(value: &'a Value) -> Self {
1484 unsafe {
1485 let res: u32 = gobject_ffi::g_value_get_uint(value.to_glib_none().0);
1486 char::from_u32_unchecked(res)
1488 }
1489 }
1490}
1491
1492impl ToValue for char {
1493 #[inline]
1494 fn to_value(&self) -> Value {
1495 let mut value = Value::for_value_type::<Self>();
1496 unsafe {
1497 gobject_ffi::g_value_set_uint(&mut value.inner, *self as u32);
1498 }
1499 value
1500 }
1501
1502 #[inline]
1503 fn value_type(&self) -> Type {
1504 crate::Type::U32
1505 }
1506}
1507
1508impl From<char> for Value {
1509 #[inline]
1510 fn from(v: char) -> Self {
1511 v.to_value()
1512 }
1513}
1514
1515pub struct BoxedValue(pub Value);
1518
1519impl Deref for BoxedValue {
1520 type Target = Value;
1521
1522 #[inline]
1523 fn deref(&self) -> &Value {
1524 &self.0
1525 }
1526}
1527
1528impl ValueType for BoxedValue {
1529 type Type = BoxedValue;
1530}
1531
1532impl ValueTypeOptional for BoxedValue {}
1533
1534unsafe impl<'a> FromValue<'a> for BoxedValue {
1535 type Checker = GenericValueTypeOrNoneChecker<Self>;
1536
1537 #[inline]
1538 unsafe fn from_value(value: &'a Value) -> Self {
1539 unsafe {
1540 let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0);
1541 BoxedValue(from_glib_none(ptr as *const gobject_ffi::GValue))
1542 }
1543 }
1544}
1545
1546impl ToValue for BoxedValue {
1547 #[inline]
1548 fn to_value(&self) -> Value {
1549 unsafe {
1550 let mut value = Value::for_value_type::<BoxedValue>();
1551
1552 gobject_ffi::g_value_set_boxed(
1553 value.to_glib_none_mut().0,
1554 self.0.to_glib_none().0 as ffi::gconstpointer,
1555 );
1556
1557 value
1558 }
1559 }
1560
1561 #[inline]
1562 fn value_type(&self) -> Type {
1563 BoxedValue::static_type()
1564 }
1565}
1566
1567impl From<BoxedValue> for Value {
1568 #[inline]
1569 fn from(v: BoxedValue) -> Self {
1570 unsafe {
1571 let mut value = Value::for_value_type::<BoxedValue>();
1572
1573 gobject_ffi::g_value_take_boxed(
1574 value.to_glib_none_mut().0,
1575 v.0.to_glib_full() as ffi::gconstpointer,
1576 );
1577
1578 value
1579 }
1580 }
1581}
1582
1583impl ToValueOptional for BoxedValue {
1584 #[inline]
1585 fn to_value_optional(s: Option<&Self>) -> Value {
1586 let mut value = Value::for_value_type::<Self>();
1587 unsafe {
1588 gobject_ffi::g_value_set_boxed(
1589 value.to_glib_none_mut().0,
1590 s.map(|s| &s.0).to_glib_none().0 as ffi::gconstpointer,
1591 );
1592 }
1593
1594 value
1595 }
1596}
1597
1598#[cfg(test)]
1599mod tests {
1600 use std::num::NonZeroI32;
1601
1602 use super::*;
1603
1604 #[test]
1605 fn test_send_value() {
1606 use std::thread;
1607
1608 let v = SendValue::from(&1i32);
1609
1610 thread::spawn(move || drop(v)).join().unwrap();
1612 }
1613
1614 #[test]
1615 fn test_strv() {
1616 let v = ["123", "456"].to_value();
1617 assert_eq!(
1618 v.get::<Vec<GString>>(),
1619 Ok(vec![GString::from("123"), GString::from("456")])
1620 );
1621
1622 let v = vec![String::from("123"), String::from("456")].to_value();
1623 assert_eq!(
1624 v.get::<Vec<GString>>(),
1625 Ok(vec![GString::from("123"), GString::from("456")])
1626 );
1627 }
1628
1629 #[test]
1630 fn test_from_to_value() {
1631 let v = 123.to_value();
1632 assert_eq!(v.get(), Ok(123));
1633 assert_eq!(
1634 v.get::<&str>(),
1635 Err(ValueTypeMismatchError::new(Type::I32, Type::STRING).into())
1636 );
1637 assert_eq!(
1638 v.get::<bool>(),
1639 Err(ValueTypeMismatchError::new(Type::I32, Type::BOOL))
1640 );
1641
1642 let v_str = "test".to_value();
1644 assert_eq!(v_str.get::<&str>(), Ok("test"));
1645 assert_eq!(v_str.get::<Option<&str>>(), Ok(Some("test")));
1646 assert_eq!(
1647 v_str.get::<i32>(),
1648 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1649 );
1650
1651 let some_v = Some("test").to_value();
1652 assert_eq!(some_v.get::<&str>(), Ok("test"));
1653 assert_eq!(some_v.get_owned::<String>(), Ok("test".to_string()));
1654 assert_eq!(
1655 some_v.get_owned::<Option<String>>(),
1656 Ok(Some("test".to_string()))
1657 );
1658 assert_eq!(some_v.get::<Option<&str>>(), Ok(Some("test")));
1659 assert_eq!(
1660 some_v.get::<i32>(),
1661 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1662 );
1663
1664 let none_str: Option<&str> = None;
1665 let none_v = none_str.to_value();
1666 assert_eq!(none_v.get::<Option<&str>>(), Ok(None));
1667 assert_eq!(
1668 none_v.get::<i32>(),
1669 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1670 );
1671
1672 let v_str = String::from("test").to_value();
1674 assert_eq!(v_str.get::<String>(), Ok(String::from("test")));
1675 assert_eq!(
1676 v_str.get::<Option<String>>(),
1677 Ok(Some(String::from("test")))
1678 );
1679 assert_eq!(
1680 v_str.get::<i32>(),
1681 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1682 );
1683
1684 let some_v = Some(String::from("test")).to_value();
1685 assert_eq!(some_v.get::<String>(), Ok(String::from("test")));
1686 assert_eq!(
1687 some_v.get::<Option<String>>(),
1688 Ok(Some(String::from("test")))
1689 );
1690 assert_eq!(
1691 some_v.get::<i32>(),
1692 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1693 );
1694
1695 let none_str: Option<String> = None;
1696 let none_v = none_str.to_value();
1697 assert_eq!(none_v.get::<Option<String>>(), Ok(None));
1698 assert_eq!(
1699 none_v.get::<i32>(),
1700 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1701 );
1702
1703 let c_v = 'c'.to_value();
1704 assert_eq!(c_v.get::<char>(), Ok('c'));
1705
1706 let c_v = 0xFFFFFFFFu32.to_value();
1707 assert_eq!(
1708 c_v.get::<char>(),
1709 Err(InvalidCharError::CharConversionError)
1710 );
1711
1712 let v_str = String::from("test").to_value();
1714 assert_eq!(v_str.get::<String>(), Ok(String::from("test")));
1715 assert_eq!(
1716 v_str.get::<Option<String>>(),
1717 Ok(Some(String::from("test")))
1718 );
1719 assert_eq!(
1720 v_str.get::<i32>(),
1721 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1722 );
1723
1724 let some_v = Some(&String::from("test")).to_value();
1725 assert_eq!(some_v.get::<String>(), Ok(String::from("test")));
1726 assert_eq!(
1727 some_v.get::<Option<String>>(),
1728 Ok(Some(String::from("test")))
1729 );
1730 assert_eq!(
1731 some_v.get::<i32>(),
1732 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1733 );
1734
1735 let none_str: Option<&String> = None;
1736 let none_v = none_str.to_value();
1737 assert_eq!(none_v.get::<Option<String>>(), Ok(None));
1738 assert_eq!(
1739 none_v.get::<i32>(),
1740 Err(ValueTypeMismatchError::new(Type::STRING, Type::I32))
1741 );
1742
1743 let v = NonZeroI32::new(123).unwrap().to_value();
1745 assert_eq!(v.get::<NonZeroI32>(), Ok(NonZeroI32::new(123).unwrap()));
1746
1747 let v = 123i32.to_value();
1748 assert_eq!(v.get::<NonZeroI32>(), Ok(NonZeroI32::new(123).unwrap()));
1749
1750 let v = 0i32.to_value();
1751 assert_eq!(
1752 v.get::<NonZeroI32>(),
1753 Err(ValueTypeMismatchOrNoneError::UnexpectedNone)
1754 );
1755
1756 assert_eq!(v.get::<Option<NonZeroI32>>(), Ok(None));
1757 }
1758
1759 #[test]
1760 fn test_transform() {
1761 let v = 123.to_value();
1762 let v2 = v
1763 .transform::<String>()
1764 .expect("Failed to transform to string");
1765 assert_eq!(v2.get::<&str>(), Ok("123"));
1766 }
1767
1768 #[test]
1769 fn test_into_raw() {
1770 unsafe {
1771 let mut v = 123.to_value().into_raw();
1772 assert_eq!(gobject_ffi::g_type_check_value(&v), ffi::GTRUE);
1773 assert_eq!(gobject_ffi::g_value_get_int(&v), 123);
1774 gobject_ffi::g_value_unset(&mut v);
1775 }
1776 }
1777
1778 #[test]
1779 fn test_debug() {
1780 fn value_debug_string<T: ToValue>(val: T) -> String {
1781 format!("{:?}", val.to_value())
1782 }
1783
1784 assert_eq!(value_debug_string(1u32), "(guint) 1");
1785 assert_eq!(value_debug_string(2i32), "(gint) 2");
1786 assert_eq!(value_debug_string(false), "(gboolean) FALSE");
1787 assert_eq!(value_debug_string("FooBar"), r#"(gchararray) "FooBar""#);
1788 }
1789}