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

Value::get: return a Result to account for type mismatch... #513

Merged
merged 7 commits into from
Aug 11, 2019
20 changes: 10 additions & 10 deletions src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@ mod tests {

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

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

let closure = Closure::new(closure_fn);
let result = closure.invoke(&[&"test".to_string(), &42]);
let int: Option<i32> = result.and_then(|result| result.get());
assert_eq!(int, Some(24));
let int_res = result.map(|result| result.get_some::<i32>());
assert_eq!(int_res, Some(Ok(24)));
}
}
65 changes: 44 additions & 21 deletions src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1047,22 +1047,33 @@ impl<T: ObjectType> ObjectExt for T {
// a properly type Value. This can happen if the type field in the
// Value is set to a more generic type than the contained value
if !valid_type && property_value.type_().is_a(&Object::static_type()) {
if let Some(obj) = property_value.get::<Object>() {
if obj.get_type().is_a(&pspec.get_value_type()) {
match property_value.get::<Object>() {
Ok(Some(obj)) => {
if obj.get_type().is_a(&pspec.get_value_type()) {
property_value.0.g_type = pspec.get_value_type().to_glib();
} else {
return Err(glib_bool_error!(format!(
concat!(
"property can't be set from the given object type ",
"(expected: {:?}, got: {:?})",
),
pspec.get_value_type(),
obj.get_type(),
)));
}
}
Ok(None) => {
// If the value is None then the type is compatible too
property_value.0.g_type = pspec.get_value_type().to_glib();
} else {
return Err(glib_bool_error!(
"property can't be set from the given object type"
));
}
} else {
// Otherwise if the value is None then the type is compatible too
property_value.0.g_type = pspec.get_value_type().to_glib();
Err(_) => unreachable!("property_value type conformity already checked"),
}
} else if !valid_type {
return Err(glib_bool_error!(
"property can't be set from the given type"
));
return Err(glib_bool_error!(format!(
"property can't be set from the given type (expected: {:?}, got: {:?})",
pspec.get_value_type(),
property_value.type_(),
)));
}

let changed: bool = from_glib(gobject_sys::g_param_value_validate(
Expand Down Expand Up @@ -1311,16 +1322,20 @@ impl<T: ObjectType> ObjectExt for T {
// a properly typed Value. This can happen if the type field in the
// Value is set to a more generic type than the contained value
if !valid_type && ret.type_().is_a(&Object::static_type()) {
if let Some(obj) = ret.get::<Object>() {
if obj.get_type().is_a(&return_type) {
match ret.get::<Object>() {
Ok(Some(obj)) => {
if obj.get_type().is_a(&return_type) {
ret.0.g_type = return_type.to_glib();
} else {
panic!("Signal required return value of type {} but got {} (actual {})",
return_type.name(), ret.type_().name(), obj.get_type().name());
}
}
Ok(None) => {
// If the value is None then the type is compatible too
ret.0.g_type = return_type.to_glib();
} else {
panic!("Signal required return value of type {} but got {} (actual {})",
return_type.name(), ret.type_().name(), obj.get_type().name());
}
} else {
// Otherwise if the value is None then the type is compatible too
ret.0.g_type = return_type.to_glib();
Err(_) => unreachable!("ret type conformity already checked"),
}
} else if !valid_type {
panic!(
Expand Down Expand Up @@ -1681,7 +1696,15 @@ impl<'a> BindingBuilder<'a> {
) -> ::Closure {
::Closure::new(move |values| {
assert_eq!(values.len(), 3);
let binding = values[0].get::<::Binding>().unwrap();
let binding = values[0].get::<::Binding>().unwrap_or_else(|_| {
panic!(
"Type mismatch with the first argument in the closure: expected: `Binding`, got: {:?}",
values[0].type_(),
)
})
.unwrap_or_else(|| {
panic!("Found `None` for the first argument in the closure, expected `Some`")
});
let from = unsafe {
let ptr = gobject_sys::g_value_get_boxed(mut_override(
&values[1] as *const Value as *const gobject_sys::GValue,
Expand Down
4 changes: 2 additions & 2 deletions src/subclass/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ mod test {

let b = Boxed(MyBoxed(String::from("abc")));
let v = b.to_value();
let b2 = v.get::<&Boxed<MyBoxed>>().unwrap();
let b2 = v.get_some::<&Boxed<MyBoxed>>().unwrap();
assert_eq!(&b, b2);
}

Expand All @@ -246,7 +246,7 @@ mod test {

let b = MyBoxed(String::from("abc"));
let v = b.to_value();
let b2 = v.get::<&MyBoxed>().unwrap();
let b2 = v.get_some::<&MyBoxed>().unwrap();
assert_eq!(&b, b2);
}
}
10 changes: 6 additions & 4 deletions src/subclass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@
//!
//! match *prop {
//! subclass::Property("name", ..) => {
//! let name = value.get();
//! let name = value
//! .get()
//! .expect("type conformity checked by `Object::set_property`");
//! self.name.replace(name);
//! }
//! _ => unimplemented!(),
Expand Down Expand Up @@ -118,11 +120,11 @@
//! let obj = glib::Object::new(SimpleObject::get_type(), &[]).unwrap();
//!
//! // Get the name property and change its value.
//! assert_eq!(obj.get_property("name").unwrap().get::<&str>(), None);
//! assert_eq!(obj.get_property("name").unwrap().get::<&str>(), Ok(None));
//! obj.set_property("name", &"test").unwrap();
//! assert_eq!(
//! obj.get_property("name").unwrap().get::<&str>(),
//! Some("test")
//! Ok(Some("test"))
//! );
//! }
//! ```
Expand Down Expand Up @@ -160,7 +162,7 @@
//!
//! let b = MyBoxed(String::from("abc"));
//! let v = b.to_value();
//! let b2 = v.get::<&MyBoxed>().unwrap();
//! let b2 = v.get::<&MyBoxed>().unwrap().unwrap();
//! assert_eq!(&b, b2);
//! }
//! ```
Expand Down
Loading