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