diff --git a/rust-bindings/rust/src/checksum.rs b/rust-bindings/rust/src/checksum.rs index 9f07c7d7..070e07ed 100644 --- a/rust-bindings/rust/src/checksum.rs +++ b/rust-bindings/rust/src/checksum.rs @@ -32,6 +32,12 @@ impl FromGlibPtrFull<*mut [u8; 32]> for Checksum { } } +impl FromGlibPtrFull<*mut u8> for Checksum { + unsafe fn from_glib_full(ptr: *mut u8) -> Self { + Checksum::new(ptr as *mut [u8; 32]) + } +} + impl fmt::Display for Checksum { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.to_gstring()) diff --git a/rust-bindings/rust/src/repo.rs b/rust-bindings/rust/src/repo.rs index e84aa198..617bc3a2 100644 --- a/rust-bindings/rust/src/repo.rs +++ b/rust-bindings/rust/src/repo.rs @@ -1,16 +1,20 @@ #[cfg(any(feature = "v2016_4", feature = "dox"))] use crate::RepoListRefsExtFlags; use crate::{Checksum, ObjectName, ObjectType, Repo}; +#[cfg(feature = "futures")] +use futures::future; use gio; +use gio_sys; use glib; use glib::translate::*; use glib::Error; use glib::IsA; use glib_sys; use ostree_sys; +use std::boxed::Box as Box_; use std::collections::{HashMap, HashSet}; use std::path::Path; -use std::ptr; +use std::{mem::MaybeUninit, ptr}; unsafe extern "C" fn read_variant_table( _key: glib_sys::gpointer, @@ -168,4 +172,86 @@ impl Repo { } } } + + pub fn write_content_async< + P: IsA, + Q: IsA, + R: FnOnce(Result) + Send + 'static, + >( + &self, + expected_checksum: Option<&str>, + object: &P, + length: u64, + cancellable: Option<&Q>, + callback: R, + ) { + let user_data: Box = Box::new(callback); + unsafe extern "C" fn write_content_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 _ = ostree_sys::ostree_repo_write_content_finish( + _source_object as *mut _, + res, + out_csum.as_mut_ptr(), + &mut error, + ); + let out_csum = out_csum.assume_init(); + let result = if error.is_null() { + Ok(Checksum::from_glib_full(out_csum)) + } else { + Err(from_glib_full(error)) + }; + let callback: Box = Box::from_raw(user_data as *mut _); + callback(result); + } + let callback = write_content_async_trampoline::; + unsafe { + ostree_sys::ostree_repo_write_content_async( + self.to_glib_none().0, + expected_checksum.to_glib_none().0, + object.as_ref().to_glib_none().0, + length, + cancellable.map(|p| p.as_ref()).to_glib_none().0, + Some(callback), + Box::into_raw(user_data) as *mut _, + ); + } + } + + #[cfg(feature = "futures")] + pub fn write_content_async_future + Clone + 'static>( + &self, + expected_checksum: Option<&str>, + object: &P, + length: u64, + ) -> Box_> + std::marker::Unpin> { + use fragile::Fragile; + use gio::GioFuture; + + let expected_checksum = expected_checksum.map(ToOwned::to_owned); + let object = object.clone(); + GioFuture::new(self, move |obj, send| { + let cancellable = gio::Cancellable::new(); + let send = Fragile::new(send); + obj.write_content_async( + expected_checksum + .as_ref() + .map(::std::borrow::Borrow::borrow), + &object, + length, + Some(&cancellable), + move |res| { + let _ = send.into_inner().send(res); + }, + ); + + cancellable + }) + } }