Skip to content
This repository was archived by the owner on Jun 8, 2021. It is now read-only.

Commit 580be8c

Browse files
authored
Merge pull request #513 from fengalin/value_get_result
Value::get: return a Result to account for type mismatch...
2 parents 73bac1a + 64c93c5 commit 580be8c

File tree

7 files changed

+348
-72
lines changed

7 files changed

+348
-72
lines changed

src/closure.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,10 @@ mod tests {
135135

136136
fn closure_fn(values: &[Value]) -> Option<Value> {
137137
assert_eq!(values.len(), 2);
138-
let string: Option<String> = values[0].get();
139-
assert_eq!(string, Some("test".to_string()));
140-
let int: Option<i32> = values[1].get();
141-
assert_eq!(int, Some(42));
138+
let string_arg = values[0].get::<String>();
139+
assert_eq!(string_arg, Ok(Some("test".to_string())));
140+
let int_arg = values[1].get_some::<i32>();
141+
assert_eq!(int_arg, Ok(42));
142142
Some(24.to_value())
143143
}
144144

@@ -150,10 +150,10 @@ mod tests {
150150
let closure = Closure::new(move |values| {
151151
count.fetch_add(1, Ordering::Relaxed);
152152
assert_eq!(values.len(), 2);
153-
let string: Option<String> = values[0].get();
154-
assert_eq!(string, Some("test".to_string()));
155-
let int: Option<i32> = values[1].get();
156-
assert_eq!(int, Some(42));
153+
let string_arg = values[0].get::<String>();
154+
assert_eq!(string_arg, Ok(Some("test".to_string())));
155+
let int_arg = values[1].get_some::<i32>();
156+
assert_eq!(int_arg, Ok(42));
157157
None
158158
});
159159
let result = closure.invoke(&[&"test".to_string(), &42]);
@@ -166,7 +166,7 @@ mod tests {
166166

167167
let closure = Closure::new(closure_fn);
168168
let result = closure.invoke(&[&"test".to_string(), &42]);
169-
let int: Option<i32> = result.and_then(|result| result.get());
170-
assert_eq!(int, Some(24));
169+
let int_res = result.map(|result| result.get_some::<i32>());
170+
assert_eq!(int_res, Some(Ok(24)));
171171
}
172172
}

src/object.rs

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,22 +1047,33 @@ impl<T: ObjectType> ObjectExt for T {
10471047
// a properly type Value. This can happen if the type field in the
10481048
// Value is set to a more generic type than the contained value
10491049
if !valid_type && property_value.type_().is_a(&Object::static_type()) {
1050-
if let Some(obj) = property_value.get::<Object>() {
1051-
if obj.get_type().is_a(&pspec.get_value_type()) {
1050+
match property_value.get::<Object>() {
1051+
Ok(Some(obj)) => {
1052+
if obj.get_type().is_a(&pspec.get_value_type()) {
1053+
property_value.0.g_type = pspec.get_value_type().to_glib();
1054+
} else {
1055+
return Err(glib_bool_error!(format!(
1056+
concat!(
1057+
"property can't be set from the given object type ",
1058+
"(expected: {:?}, got: {:?})",
1059+
),
1060+
pspec.get_value_type(),
1061+
obj.get_type(),
1062+
)));
1063+
}
1064+
}
1065+
Ok(None) => {
1066+
// If the value is None then the type is compatible too
10521067
property_value.0.g_type = pspec.get_value_type().to_glib();
1053-
} else {
1054-
return Err(glib_bool_error!(
1055-
"property can't be set from the given object type"
1056-
));
10571068
}
1058-
} else {
1059-
// Otherwise if the value is None then the type is compatible too
1060-
property_value.0.g_type = pspec.get_value_type().to_glib();
1069+
Err(_) => unreachable!("property_value type conformity already checked"),
10611070
}
10621071
} else if !valid_type {
1063-
return Err(glib_bool_error!(
1064-
"property can't be set from the given type"
1065-
));
1072+
return Err(glib_bool_error!(format!(
1073+
"property can't be set from the given type (expected: {:?}, got: {:?})",
1074+
pspec.get_value_type(),
1075+
property_value.type_(),
1076+
)));
10661077
}
10671078

10681079
let changed: bool = from_glib(gobject_sys::g_param_value_validate(
@@ -1311,16 +1322,20 @@ impl<T: ObjectType> ObjectExt for T {
13111322
// a properly typed Value. This can happen if the type field in the
13121323
// Value is set to a more generic type than the contained value
13131324
if !valid_type && ret.type_().is_a(&Object::static_type()) {
1314-
if let Some(obj) = ret.get::<Object>() {
1315-
if obj.get_type().is_a(&return_type) {
1325+
match ret.get::<Object>() {
1326+
Ok(Some(obj)) => {
1327+
if obj.get_type().is_a(&return_type) {
1328+
ret.0.g_type = return_type.to_glib();
1329+
} else {
1330+
panic!("Signal required return value of type {} but got {} (actual {})",
1331+
return_type.name(), ret.type_().name(), obj.get_type().name());
1332+
}
1333+
}
1334+
Ok(None) => {
1335+
// If the value is None then the type is compatible too
13161336
ret.0.g_type = return_type.to_glib();
1317-
} else {
1318-
panic!("Signal required return value of type {} but got {} (actual {})",
1319-
return_type.name(), ret.type_().name(), obj.get_type().name());
13201337
}
1321-
} else {
1322-
// Otherwise if the value is None then the type is compatible too
1323-
ret.0.g_type = return_type.to_glib();
1338+
Err(_) => unreachable!("ret type conformity already checked"),
13241339
}
13251340
} else if !valid_type {
13261341
panic!(
@@ -1681,7 +1696,15 @@ impl<'a> BindingBuilder<'a> {
16811696
) -> ::Closure {
16821697
::Closure::new(move |values| {
16831698
assert_eq!(values.len(), 3);
1684-
let binding = values[0].get::<::Binding>().unwrap();
1699+
let binding = values[0].get::<::Binding>().unwrap_or_else(|_| {
1700+
panic!(
1701+
"Type mismatch with the first argument in the closure: expected: `Binding`, got: {:?}",
1702+
values[0].type_(),
1703+
)
1704+
})
1705+
.unwrap_or_else(|| {
1706+
panic!("Found `None` for the first argument in the closure, expected `Some`")
1707+
});
16851708
let from = unsafe {
16861709
let ptr = gobject_sys::g_value_get_boxed(mut_override(
16871710
&values[1] as *const Value as *const gobject_sys::GValue,

src/subclass/boxed.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ mod test {
236236

237237
let b = Boxed(MyBoxed(String::from("abc")));
238238
let v = b.to_value();
239-
let b2 = v.get::<&Boxed<MyBoxed>>().unwrap();
239+
let b2 = v.get_some::<&Boxed<MyBoxed>>().unwrap();
240240
assert_eq!(&b, b2);
241241
}
242242

@@ -246,7 +246,7 @@ mod test {
246246

247247
let b = MyBoxed(String::from("abc"));
248248
let v = b.to_value();
249-
let b2 = v.get::<&MyBoxed>().unwrap();
249+
let b2 = v.get_some::<&MyBoxed>().unwrap();
250250
assert_eq!(&b, b2);
251251
}
252252
}

src/subclass/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@
8585
//!
8686
//! match *prop {
8787
//! subclass::Property("name", ..) => {
88-
//! let name = value.get();
88+
//! let name = value
89+
//! .get()
90+
//! .expect("type conformity checked by `Object::set_property`");
8991
//! self.name.replace(name);
9092
//! }
9193
//! _ => unimplemented!(),
@@ -118,11 +120,11 @@
118120
//! let obj = glib::Object::new(SimpleObject::get_type(), &[]).unwrap();
119121
//!
120122
//! // Get the name property and change its value.
121-
//! assert_eq!(obj.get_property("name").unwrap().get::<&str>(), None);
123+
//! assert_eq!(obj.get_property("name").unwrap().get::<&str>(), Ok(None));
122124
//! obj.set_property("name", &"test").unwrap();
123125
//! assert_eq!(
124126
//! obj.get_property("name").unwrap().get::<&str>(),
125-
//! Some("test")
127+
//! Ok(Some("test"))
126128
//! );
127129
//! }
128130
//! ```
@@ -160,7 +162,7 @@
160162
//!
161163
//! let b = MyBoxed(String::from("abc"));
162164
//! let v = b.to_value();
163-
//! let b2 = v.get::<&MyBoxed>().unwrap();
165+
//! let b2 = v.get::<&MyBoxed>().unwrap().unwrap();
164166
//! assert_eq!(&b, b2);
165167
//! }
166168
//! ```

0 commit comments

Comments
 (0)