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