From 815b8563d54f8826af61cf53f7ec6f5fdc3c5152 Mon Sep 17 00:00:00 2001 From: Felix Krull Date: Mon, 2 Sep 2019 13:27:54 +0200 Subject: [PATCH] Implement ostree::checksum_file_async These might not work, I didn't test them... --- rust-bindings/rust/src/functions.rs | 106 ++++++++++++++++++++++------ 1 file changed, 86 insertions(+), 20 deletions(-) diff --git a/rust-bindings/rust/src/functions.rs b/rust-bindings/rust/src/functions.rs index a56e0da2..a017e049 100644 --- a/rust-bindings/rust/src/functions.rs +++ b/rust-bindings/rust/src/functions.rs @@ -1,8 +1,13 @@ use crate::{Checksum, ObjectType}; +#[cfg(feature = "futures")] +use futures::future; use glib::prelude::*; use glib::translate::*; use glib_sys::GFALSE; +#[cfg(feature = "futures")] +use std::boxed::Box as Box_; use std::error::Error; +use std::mem::MaybeUninit; use std::ptr; pub fn checksum_file, Q: IsA>( @@ -20,19 +25,75 @@ pub fn checksum_file, Q: IsA>( cancellable.map(|p| p.as_ref()).to_glib_none().0, &mut error, ); - - if !error.is_null() { - Err(Box::::new(from_glib_full(error))) - } else if ret == GFALSE { - Err(Box::new(glib_bool_error!( - "unknown error in ostree_checksum_file" - ))) - } else { - Ok(Checksum::from_glib_full(out_csum)) - } + checksum_file_error(out_csum, error, ret) } } +pub fn checksum_file_async< + P: IsA, + Q: IsA, + R: FnOnce(Result>) + Send + 'static, +>( + f: &P, + objtype: ObjectType, + io_priority: i32, + cancellable: Option<&Q>, + callback: R, +) { + let user_data: Box = Box::new(callback); + unsafe extern "C" fn checksum_file_async_trampoline< + R: FnOnce(Result>) + Send + 'static, + >( + _source_object: *mut gobject_sys::GObject, + res: *mut gio_sys::GAsyncResult, + user_data: glib_sys::gpointer, + ) { + let mut error = ptr::null_mut(); + let mut out_csum = MaybeUninit::uninit(); + let ret = ostree_sys::ostree_checksum_file_async_finish( + _source_object as *mut _, + res, + out_csum.as_mut_ptr(), + &mut error, + ); + let out_csum = out_csum.assume_init(); + let result = checksum_file_error(out_csum, error, ret); + let callback: Box = Box::from_raw(user_data as *mut _); + callback(result); + } + let callback = checksum_file_async_trampoline::; + unsafe { + ostree_sys::ostree_checksum_file_async( + f.as_ref().to_glib_none().0, + objtype.to_glib(), + io_priority, + cancellable.map(|p| p.as_ref()).to_glib_none().0, + Some(callback), + Box::into_raw(user_data) as *mut _, + ); + } +} + +#[cfg(feature = "futures")] +pub fn checksum_file_async_future + Clone + 'static>( + f: &P, + objtype: ObjectType, + io_priority: i32, +) -> Box_>> + std::marker::Unpin> { + use fragile::Fragile; + use gio::GioFuture; + + let f = f.clone(); + GioFuture::new(&f, move |f, send| { + let cancellable = gio::Cancellable::new(); + let send = Fragile::new(send); + checksum_file_async(f, objtype, io_priority, Some(&cancellable), move |res| { + let _ = send.into_inner().send(res); + }); + cancellable + }) +} + pub fn checksum_file_from_input, Q: IsA>( file_info: &gio::FileInfo, xattrs: Option<&glib::Variant>, @@ -52,15 +113,20 @@ pub fn checksum_file_from_input, Q: IsA::new(from_glib_full(error))) - } else if ret == GFALSE { - Err(Box::new(glib_bool_error!( - "unknown error in ostree_checksum_file_from_input" - ))) - } else { - Ok(Checksum::from_glib_full(out_csum)) - } + checksum_file_error(out_csum, error, ret) + } +} + +unsafe fn checksum_file_error( + out_csum: *mut [*mut u8; 32], + error: *mut glib_sys::GError, + ret: i32, +) -> Result> { + if !error.is_null() { + Err(Box::::new(from_glib_full(error))) + } else if ret == GFALSE { + Err(Box::new(glib_bool_error!("unknown error"))) + } else { + Ok(Checksum::from_glib_full(out_csum)) } }