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