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