1use gio_sys;
6use glib;
7use glib::object::IsA;
8use glib::translate::*;
9use glib_sys;
10use gobject_sys;
11use std::ptr;
12use Cancellable;
13use Error;
14use File;
15use FileCreateFlags;
16
17#[cfg(feature = "futures")]
18use futures::future;
19
20pub trait FileExtManual: Sized {
21 fn replace_contents_async<
22 B: AsRef<[u8]> + Send + 'static,
23 R: FnOnce(Result<(B, glib::GString), (B, Error)>) + Send + 'static,
24 >(
25 &self,
26 contents: B,
27 etag: Option<&str>,
28 make_backup: bool,
29 flags: FileCreateFlags,
30 cancellable: Option<&Cancellable>,
31 callback: R,
32 );
33
34 #[cfg(feature = "futures")]
35 fn replace_contents_async_future<'a, B: AsRef<[u8]> + Send + 'static>(
36 &self,
37 contents: B,
38 etag: Option<&str>,
39 make_backup: bool,
40 flags: FileCreateFlags,
41 ) -> Box<dyn future::Future<Output = Result<(B, glib::GString), (B, Error)>> + std::marker::Unpin>;
42}
43
44impl<O: IsA<File>> FileExtManual for O {
45 fn replace_contents_async<
46 B: AsRef<[u8]> + Send + 'static,
47 R: FnOnce(Result<(B, glib::GString), (B, Error)>) + Send + 'static,
48 >(
49 &self,
50 contents: B,
51 etag: Option<&str>,
52 make_backup: bool,
53 flags: FileCreateFlags,
54 cancellable: Option<&Cancellable>,
55 callback: R,
56 ) {
57 let etag = etag.to_glib_none();
58 let cancellable = cancellable.to_glib_none();
59 let user_data: Box<Option<(R, B)>> = Box::new(Some((callback, contents)));
60 let (count, contents_ptr) = {
62 let contents = &(*user_data).as_ref().unwrap().1;
63 let slice = contents.as_ref();
64 (slice.len(), slice.as_ptr())
65 };
66 unsafe extern "C" fn replace_contents_async_trampoline<
67 B: AsRef<[u8]> + Send + 'static,
68 R: FnOnce(Result<(B, glib::GString), (B, Error)>) + Send + 'static,
69 >(
70 _source_object: *mut gobject_sys::GObject,
71 res: *mut gio_sys::GAsyncResult,
72 user_data: glib_sys::gpointer,
73 ) {
74 let mut user_data: Box<Option<(R, B)>> = Box::from_raw(user_data as *mut _);
75 let (callback, contents) = user_data.take().unwrap();
76
77 let mut error = ptr::null_mut();
78 let mut new_etag = ptr::null_mut();
79 let _ = gio_sys::g_file_replace_contents_finish(
80 _source_object as *mut _,
81 res,
82 &mut new_etag,
83 &mut error,
84 );
85 let result = if error.is_null() {
86 Ok((contents, from_glib_full(new_etag)))
87 } else {
88 Err((contents, from_glib_full(error)))
89 };
90 callback(result);
91 }
92 let callback = replace_contents_async_trampoline::<B, R>;
93 unsafe {
94 gio_sys::g_file_replace_contents_async(
95 self.as_ref().to_glib_none().0,
96 mut_override(contents_ptr),
97 count,
98 etag.0,
99 make_backup.to_glib(),
100 flags.to_glib(),
101 cancellable.0,
102 Some(callback),
103 Box::into_raw(user_data) as *mut _,
104 );
105 }
106 }
107
108 #[cfg(feature = "futures")]
109 fn replace_contents_async_future<B: AsRef<[u8]> + Send + 'static>(
110 &self,
111 contents: B,
112 etag: Option<&str>,
113 make_backup: bool,
114 flags: FileCreateFlags,
115 ) -> Box<dyn future::Future<Output = Result<(B, glib::GString), (B, Error)>> + std::marker::Unpin>
116 {
117 use fragile::Fragile;
118 use GioFuture;
119
120 let etag = etag.map(glib::GString::from);
121 GioFuture::new(self, move |obj, send| {
122 let cancellable = Cancellable::new();
123 let send = Fragile::new(send);
124 obj.replace_contents_async(
125 contents,
126 etag.as_ref().map(|s| s.as_str()),
127 make_backup,
128 flags,
129 Some(&cancellable),
130 move |res| {
131 let _ = send.into_inner().send(res);
132 },
133 );
134
135 cancellable
136 })
137 }
138}