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