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