Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions examples/gio_task/file_size/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ impl FileSize {
callback: Q,
) {
let closure = move |task: gio::LocalTask<i64>, source_object: Option<&glib::Object>| {
let value = task.propagate().unwrap();
// SAFETY: this is safe because we call propagate just once and the
// task sets the result as a value
let value = unsafe { task.propagate() }.unwrap();
let source_object = source_object.unwrap().downcast_ref::<FileSize>().unwrap();
callback(value, source_object);
};
Expand Down Expand Up @@ -68,7 +70,8 @@ impl FileSize {
callback: Q,
) {
let closure = move |task: gio::Task<i64>, source_object: Option<&FileSize>| {
// SAFETY: this is safe because we call propagate just once
// SAFETY: this is safe because we call propagate just once and the
// task sets the result as a value
let value = unsafe { task.propagate().unwrap() };
let source_object = source_object.unwrap().downcast_ref::<FileSize>().unwrap();
callback(value, source_object);
Expand Down
148 changes: 142 additions & 6 deletions gio/src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,14 @@ macro_rules! task_impl {
unsafe { from_glib(ffi::g_task_return_error_if_cancelled(self.to_glib_none().0)) }
}

// rustdoc-stripper-ignore-next
/// Set the result of the task
///
/// # Safety
///
/// The value must be read with [`Task::propagate`],
/// `g_task_propagate_value` or `g_task_propagate_pointer`.
#[doc(alias = "g_task_return_value")]
#[doc(alias = "g_task_return_boolean")]
#[doc(alias = "g_task_return_int")]
#[doc(alias = "g_task_return_pointer")]
#[doc(alias = "g_task_return_error")]
#[allow(unused_unsafe)]
Expand Down Expand Up @@ -272,12 +277,51 @@ macro_rules! task_impl {
}
}

// rustdoc-stripper-ignore-next
/// Set the result of the task as a boolean
///
/// # Safety
///
/// The value must be read with [`Task::propagate_boolean`],
/// or `g_task_propagate_boolean`.
#[doc(alias = "g_task_return_boolean")]
#[allow(unused_unsafe)]
pub $($safety)? fn return_boolean_result(self, result: Result<bool, glib::Error>) {
match result {
Ok(v) => unsafe { ffi::g_task_return_boolean(self.to_glib_none().0, v as i32) },
Err(e) => unsafe { ffi::g_task_return_error(self.to_glib_none().0, e.into_glib_ptr()) },
}
}

// rustdoc-stripper-ignore-next
/// Set the result of the task as an int
///
/// # Safety
///
/// The value must be read with [`Task::propagate_int`],
/// or `g_task_propagate_int`.
#[doc(alias = "g_task_return_int")]
#[allow(unused_unsafe)]
pub $($safety)? fn return_int_result(self, result: Result<isize, glib::Error>) {
match result {
Ok(v) => unsafe { ffi::g_task_return_int(self.to_glib_none().0, v) },
Err(e) => unsafe { ffi::g_task_return_error(self.to_glib_none().0, e.into_glib_ptr()) },
}
}


// rustdoc-stripper-ignore-next
/// Gets the result of the task and transfers ownership of it
///
/// # Safety
///
/// This must only be called once, and only if the result was set
/// via [`Task::return_result`], `g_task_return_value` or
/// `g_task_return_pointer`.
#[doc(alias = "g_task_propagate_value")]
#[doc(alias = "g_task_propagate_boolean")]
#[doc(alias = "g_task_propagate_int")]
#[doc(alias = "g_task_propagate_pointer")]
#[allow(unused_unsafe)]
pub $($safety)? fn propagate(self) -> Result<V, glib::Error> {
pub unsafe fn propagate(self) -> Result<V, glib::Error> {
let mut error = ptr::null_mut();

unsafe {
Expand Down Expand Up @@ -313,6 +357,52 @@ macro_rules! task_impl {
}
}
}

// rustdoc-stripper-ignore-next
/// Gets the result of the task as a boolean, or the error
///
/// # Safety
///
/// This must only be called once, and only if the result was set
/// via [`Task::return_boolean_result`], or `g_task_return_boolean`.
#[doc(alias = "g_task_propagate_boolean")]
#[allow(unused_unsafe)]
pub unsafe fn propagate_boolean(self) -> Result<bool, glib::Error> {
let mut error = ptr::null_mut();

unsafe {
let res = ffi::g_task_propagate_boolean(self.to_glib_none().0, &mut error);

if error.is_null() {
Ok(res != 0)
} else {
Err(from_glib_full(error))
}
}
}

// rustdoc-stripper-ignore-next
/// Gets the result of the task as an int, or the error
///
/// # Safety
///
/// This must only be called once, and only if the result was set
/// via [`Task::return_int_result`], or `g_task_return_int`.
#[doc(alias = "g_task_propagate_int")]
#[allow(unused_unsafe)]
pub unsafe fn propagate_int(self) -> Result<isize, glib::Error> {
let mut error = ptr::null_mut();

unsafe {
let res = ffi::g_task_propagate_int(self.to_glib_none().0, &mut error);

if error.is_null() {
Ok(res)
} else {
Err(from_glib_full(error))
}
}
}
}
}
}
Expand Down Expand Up @@ -447,7 +537,7 @@ mod test {
use crate::{prelude::*, test_util::run_async_local};

#[test]
fn test_int_async_result() {
fn test_int_value_async_result() {
let fut = run_async_local(|tx, l| {
let cancellable = crate::Cancellable::new();
let task = unsafe {
Expand All @@ -469,6 +559,52 @@ mod test {
}
}

#[test]
fn test_boolean_async_result() {
let fut = run_async_local(|tx, l| {
let cancellable = crate::Cancellable::new();
let task = unsafe {
crate::LocalTask::new(
None,
Some(&cancellable),
move |t: LocalTask<bool>, _b: Option<&glib::Object>| {
tx.send(t.propagate_boolean()).unwrap();
l.quit();
},
)
};
task.return_boolean_result(Ok(true));
});

match fut {
Err(_) => panic!(),
Ok(i) => assert!(i),
}
}

#[test]
fn test_int_async_result() {
let fut = run_async_local(|tx, l| {
let cancellable = crate::Cancellable::new();
let task = unsafe {
crate::LocalTask::new(
None,
Some(&cancellable),
move |t: LocalTask<i32>, _b: Option<&glib::Object>| {
tx.send(t.propagate_int()).unwrap();
l.quit();
},
)
};
task.return_int_result(Ok(100_isize));
});

match fut {
Err(_) => panic!(),
Ok(i) => assert_eq!(i, 100),
}
}

#[test]
fn test_object_async_result() {
use glib::subclass::prelude::*;
Expand Down
Loading