@@ -158,6 +158,51 @@ unsafe impl<T: StaticType> ValueTypeChecker for GenericValueTypeChecker<T> {
158
158
}
159
159
}
160
160
161
+ pub struct CharTypeChecker ( ) ;
162
+ unsafe impl ValueTypeChecker for CharTypeChecker {
163
+ type Error = InvalidCharError ;
164
+
165
+ fn check ( value : & Value ) -> Result < ( ) , Self :: Error > {
166
+ let v = value. get :: < u32 > ( ) ?;
167
+ match char:: from_u32 ( v) {
168
+ Some ( _) => Ok ( ( ) ) ,
169
+ None => Err ( InvalidCharError :: CharConversionError ) ,
170
+ }
171
+ }
172
+ }
173
+
174
+ // rustdoc-stripper-ignore-next
175
+ /// An error returned from the [`get`](struct.Value.html#method.get) function
176
+ /// on a [`Value`](struct.Value.html) for char (which are internally u32) types.
177
+ #[ derive( Clone , PartialEq , Eq , Debug ) ]
178
+ pub enum InvalidCharError {
179
+ WrongValueType ( ValueTypeMismatchError ) ,
180
+ CharConversionError ,
181
+ }
182
+ impl fmt:: Display for InvalidCharError {
183
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
184
+ match self {
185
+ Self :: WrongValueType ( err) => err. fmt ( f) ,
186
+ Self :: CharConversionError => {
187
+ write ! ( f, "couldn't convert to char, invalid u32 contents" )
188
+ }
189
+ }
190
+ }
191
+ }
192
+ impl error:: Error for InvalidCharError { }
193
+
194
+ impl From < ValueTypeMismatchError > for InvalidCharError {
195
+ fn from ( err : ValueTypeMismatchError ) -> Self {
196
+ Self :: WrongValueType ( err)
197
+ }
198
+ }
199
+
200
+ impl From < Infallible > for InvalidCharError {
201
+ fn from ( e : Infallible ) -> Self {
202
+ match e { }
203
+ }
204
+ }
205
+
161
206
// rustdoc-stripper-ignore-next
162
207
/// An error returned from the [`get`](struct.Value.html#method.get)
163
208
/// function on a [`Value`](struct.Value.html) for optional types.
@@ -980,6 +1025,34 @@ numeric!(
980
1025
gobject_ffi:: g_value_set_double
981
1026
) ;
982
1027
1028
+ impl ValueType for char {
1029
+ type Type = u32 ;
1030
+ }
1031
+
1032
+ unsafe impl < ' a > FromValue < ' a > for char {
1033
+ type Checker = CharTypeChecker ;
1034
+
1035
+ unsafe fn from_value ( value : & ' a Value ) -> Self {
1036
+ let res: u32 = gobject_ffi:: g_value_get_uint ( value. to_glib_none ( ) . 0 ) ;
1037
+ // safe because the check is done by `Self::Checker`
1038
+ char:: from_u32_unchecked ( res)
1039
+ }
1040
+ }
1041
+
1042
+ impl ToValue for char {
1043
+ fn to_value ( & self ) -> Value {
1044
+ let mut value = Value :: for_value_type :: < Self > ( ) ;
1045
+ unsafe {
1046
+ gobject_ffi:: g_value_set_uint ( & mut value. inner , * self as u32 ) ;
1047
+ }
1048
+ value
1049
+ }
1050
+
1051
+ fn value_type ( & self ) -> Type {
1052
+ crate :: Type :: U32
1053
+ }
1054
+ }
1055
+
983
1056
// rustdoc-stripper-ignore-next
984
1057
/// A [`Value`] containing another [`Value`].
985
1058
pub struct BoxedValue ( pub Value ) ;
@@ -1141,6 +1214,15 @@ mod tests {
1141
1214
Err ( ValueTypeMismatchError :: new( Type :: STRING , Type :: I32 ) )
1142
1215
) ;
1143
1216
1217
+ let c_v = 'c' . to_value ( ) ;
1218
+ assert_eq ! ( c_v. get:: <char >( ) , Ok ( 'c' ) ) ;
1219
+
1220
+ let c_v = 0xFFFFFFFFu32 . to_value ( ) ;
1221
+ assert_eq ! (
1222
+ c_v. get:: <char >( ) ,
1223
+ Err ( InvalidCharError :: CharConversionError )
1224
+ ) ;
1225
+
1144
1226
// Check if &T and Option<&T> can be converted and retrieved
1145
1227
let v_str = ( & String :: from ( "test" ) ) . to_value ( ) ;
1146
1228
assert_eq ! ( v_str. get:: <String >( ) , Ok ( String :: from( "test" ) ) ) ;
0 commit comments