1use crate::{ffi, AsyncResult, Cancellable, InputStream, OutputStreamSpliceFlags};
6use glib::{prelude::*, translate::*};
7use std::{boxed::Box as Box_, pin::Pin};
8
9glib::wrapper! {
10 #[doc(alias = "GOutputStream")]
11 pub struct OutputStream(Object<ffi::GOutputStream, ffi::GOutputStreamClass>);
12
13 match fn {
14 type_ => || ffi::g_output_stream_get_type(),
15 }
16}
17
18impl OutputStream {
19 pub const NONE: Option<&'static OutputStream> = None;
20}
21
22pub trait OutputStreamExt: IsA<OutputStream> + 'static {
23 #[doc(alias = "g_output_stream_clear_pending")]
24 fn clear_pending(&self) {
25 unsafe {
26 ffi::g_output_stream_clear_pending(self.as_ref().to_glib_none().0);
27 }
28 }
29
30 #[doc(alias = "g_output_stream_close")]
31 fn close(&self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<(), glib::Error> {
32 unsafe {
33 let mut error = std::ptr::null_mut();
34 let is_ok = ffi::g_output_stream_close(
35 self.as_ref().to_glib_none().0,
36 cancellable.map(|p| p.as_ref()).to_glib_none().0,
37 &mut error,
38 );
39 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
40 if error.is_null() {
41 Ok(())
42 } else {
43 Err(from_glib_full(error))
44 }
45 }
46 }
47
48 #[doc(alias = "g_output_stream_close_async")]
49 fn close_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
50 &self,
51 io_priority: glib::Priority,
52 cancellable: Option<&impl IsA<Cancellable>>,
53 callback: P,
54 ) {
55 let main_context = glib::MainContext::ref_thread_default();
56 let is_main_context_owner = main_context.is_owner();
57 let has_acquired_main_context = (!is_main_context_owner)
58 .then(|| main_context.acquire().ok())
59 .flatten();
60 assert!(
61 is_main_context_owner || has_acquired_main_context.is_some(),
62 "Async operations only allowed if the thread is owning the MainContext"
63 );
64
65 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
66 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
67 unsafe extern "C" fn close_async_trampoline<
68 P: FnOnce(Result<(), glib::Error>) + 'static,
69 >(
70 _source_object: *mut glib::gobject_ffi::GObject,
71 res: *mut crate::ffi::GAsyncResult,
72 user_data: glib::ffi::gpointer,
73 ) {
74 let mut error = std::ptr::null_mut();
75 ffi::g_output_stream_close_finish(_source_object as *mut _, res, &mut error);
76 let result = if error.is_null() {
77 Ok(())
78 } else {
79 Err(from_glib_full(error))
80 };
81 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
82 Box_::from_raw(user_data as *mut _);
83 let callback: P = callback.into_inner();
84 callback(result);
85 }
86 let callback = close_async_trampoline::<P>;
87 unsafe {
88 ffi::g_output_stream_close_async(
89 self.as_ref().to_glib_none().0,
90 io_priority.into_glib(),
91 cancellable.map(|p| p.as_ref()).to_glib_none().0,
92 Some(callback),
93 Box_::into_raw(user_data) as *mut _,
94 );
95 }
96 }
97
98 fn close_future(
99 &self,
100 io_priority: glib::Priority,
101 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
102 Box_::pin(crate::GioFuture::new(
103 self,
104 move |obj, cancellable, send| {
105 obj.close_async(io_priority, Some(cancellable), move |res| {
106 send.resolve(res);
107 });
108 },
109 ))
110 }
111
112 #[doc(alias = "g_output_stream_flush")]
113 fn flush(&self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<(), glib::Error> {
114 unsafe {
115 let mut error = std::ptr::null_mut();
116 let is_ok = ffi::g_output_stream_flush(
117 self.as_ref().to_glib_none().0,
118 cancellable.map(|p| p.as_ref()).to_glib_none().0,
119 &mut error,
120 );
121 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
122 if error.is_null() {
123 Ok(())
124 } else {
125 Err(from_glib_full(error))
126 }
127 }
128 }
129
130 #[doc(alias = "g_output_stream_flush_async")]
131 fn flush_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
132 &self,
133 io_priority: glib::Priority,
134 cancellable: Option<&impl IsA<Cancellable>>,
135 callback: P,
136 ) {
137 let main_context = glib::MainContext::ref_thread_default();
138 let is_main_context_owner = main_context.is_owner();
139 let has_acquired_main_context = (!is_main_context_owner)
140 .then(|| main_context.acquire().ok())
141 .flatten();
142 assert!(
143 is_main_context_owner || has_acquired_main_context.is_some(),
144 "Async operations only allowed if the thread is owning the MainContext"
145 );
146
147 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
148 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
149 unsafe extern "C" fn flush_async_trampoline<
150 P: FnOnce(Result<(), glib::Error>) + 'static,
151 >(
152 _source_object: *mut glib::gobject_ffi::GObject,
153 res: *mut crate::ffi::GAsyncResult,
154 user_data: glib::ffi::gpointer,
155 ) {
156 let mut error = std::ptr::null_mut();
157 ffi::g_output_stream_flush_finish(_source_object as *mut _, res, &mut error);
158 let result = if error.is_null() {
159 Ok(())
160 } else {
161 Err(from_glib_full(error))
162 };
163 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
164 Box_::from_raw(user_data as *mut _);
165 let callback: P = callback.into_inner();
166 callback(result);
167 }
168 let callback = flush_async_trampoline::<P>;
169 unsafe {
170 ffi::g_output_stream_flush_async(
171 self.as_ref().to_glib_none().0,
172 io_priority.into_glib(),
173 cancellable.map(|p| p.as_ref()).to_glib_none().0,
174 Some(callback),
175 Box_::into_raw(user_data) as *mut _,
176 );
177 }
178 }
179
180 fn flush_future(
181 &self,
182 io_priority: glib::Priority,
183 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
184 Box_::pin(crate::GioFuture::new(
185 self,
186 move |obj, cancellable, send| {
187 obj.flush_async(io_priority, Some(cancellable), move |res| {
188 send.resolve(res);
189 });
190 },
191 ))
192 }
193
194 #[doc(alias = "g_output_stream_has_pending")]
195 fn has_pending(&self) -> bool {
196 unsafe {
197 from_glib(ffi::g_output_stream_has_pending(
198 self.as_ref().to_glib_none().0,
199 ))
200 }
201 }
202
203 #[doc(alias = "g_output_stream_is_closed")]
204 fn is_closed(&self) -> bool {
205 unsafe {
206 from_glib(ffi::g_output_stream_is_closed(
207 self.as_ref().to_glib_none().0,
208 ))
209 }
210 }
211
212 #[doc(alias = "g_output_stream_is_closing")]
213 fn is_closing(&self) -> bool {
214 unsafe {
215 from_glib(ffi::g_output_stream_is_closing(
216 self.as_ref().to_glib_none().0,
217 ))
218 }
219 }
220
221 #[doc(alias = "g_output_stream_set_pending")]
227 fn set_pending(&self) -> Result<(), glib::Error> {
228 unsafe {
229 let mut error = std::ptr::null_mut();
230 let is_ok =
231 ffi::g_output_stream_set_pending(self.as_ref().to_glib_none().0, &mut error);
232 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
233 if error.is_null() {
234 Ok(())
235 } else {
236 Err(from_glib_full(error))
237 }
238 }
239 }
240
241 #[doc(alias = "g_output_stream_splice")]
242 fn splice(
243 &self,
244 source: &impl IsA<InputStream>,
245 flags: OutputStreamSpliceFlags,
246 cancellable: Option<&impl IsA<Cancellable>>,
247 ) -> Result<isize, glib::Error> {
248 unsafe {
249 let mut error = std::ptr::null_mut();
250 let ret = ffi::g_output_stream_splice(
251 self.as_ref().to_glib_none().0,
252 source.as_ref().to_glib_none().0,
253 flags.into_glib(),
254 cancellable.map(|p| p.as_ref()).to_glib_none().0,
255 &mut error,
256 );
257 if error.is_null() {
258 Ok(ret)
259 } else {
260 Err(from_glib_full(error))
261 }
262 }
263 }
264
265 #[doc(alias = "g_output_stream_splice_async")]
266 fn splice_async<P: FnOnce(Result<isize, glib::Error>) + 'static>(
267 &self,
268 source: &impl IsA<InputStream>,
269 flags: OutputStreamSpliceFlags,
270 io_priority: glib::Priority,
271 cancellable: Option<&impl IsA<Cancellable>>,
272 callback: P,
273 ) {
274 let main_context = glib::MainContext::ref_thread_default();
275 let is_main_context_owner = main_context.is_owner();
276 let has_acquired_main_context = (!is_main_context_owner)
277 .then(|| main_context.acquire().ok())
278 .flatten();
279 assert!(
280 is_main_context_owner || has_acquired_main_context.is_some(),
281 "Async operations only allowed if the thread is owning the MainContext"
282 );
283
284 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
285 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
286 unsafe extern "C" fn splice_async_trampoline<
287 P: FnOnce(Result<isize, glib::Error>) + 'static,
288 >(
289 _source_object: *mut glib::gobject_ffi::GObject,
290 res: *mut crate::ffi::GAsyncResult,
291 user_data: glib::ffi::gpointer,
292 ) {
293 let mut error = std::ptr::null_mut();
294 let ret = ffi::g_output_stream_splice_finish(_source_object as *mut _, res, &mut error);
295 let result = if error.is_null() {
296 Ok(ret)
297 } else {
298 Err(from_glib_full(error))
299 };
300 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
301 Box_::from_raw(user_data as *mut _);
302 let callback: P = callback.into_inner();
303 callback(result);
304 }
305 let callback = splice_async_trampoline::<P>;
306 unsafe {
307 ffi::g_output_stream_splice_async(
308 self.as_ref().to_glib_none().0,
309 source.as_ref().to_glib_none().0,
310 flags.into_glib(),
311 io_priority.into_glib(),
312 cancellable.map(|p| p.as_ref()).to_glib_none().0,
313 Some(callback),
314 Box_::into_raw(user_data) as *mut _,
315 );
316 }
317 }
318
319 fn splice_future(
320 &self,
321 source: &(impl IsA<InputStream> + Clone + 'static),
322 flags: OutputStreamSpliceFlags,
323 io_priority: glib::Priority,
324 ) -> Pin<Box_<dyn std::future::Future<Output = Result<isize, glib::Error>> + 'static>> {
325 let source = source.clone();
326 Box_::pin(crate::GioFuture::new(
327 self,
328 move |obj, cancellable, send| {
329 obj.splice_async(&source, flags, io_priority, Some(cancellable), move |res| {
330 send.resolve(res);
331 });
332 },
333 ))
334 }
335
336 #[doc(alias = "g_output_stream_write")]
342 fn write(
343 &self,
344 buffer: &[u8],
345 cancellable: Option<&impl IsA<Cancellable>>,
346 ) -> Result<isize, glib::Error> {
347 let count = buffer.len() as _;
348 unsafe {
349 let mut error = std::ptr::null_mut();
350 let ret = ffi::g_output_stream_write(
351 self.as_ref().to_glib_none().0,
352 buffer.to_glib_none().0,
353 count,
354 cancellable.map(|p| p.as_ref()).to_glib_none().0,
355 &mut error,
356 );
357 if error.is_null() {
358 Ok(ret)
359 } else {
360 Err(from_glib_full(error))
361 }
362 }
363 }
364
365 #[doc(alias = "g_output_stream_write_bytes")]
366 fn write_bytes(
367 &self,
368 bytes: &glib::Bytes,
369 cancellable: Option<&impl IsA<Cancellable>>,
370 ) -> Result<isize, glib::Error> {
371 unsafe {
372 let mut error = std::ptr::null_mut();
373 let ret = ffi::g_output_stream_write_bytes(
374 self.as_ref().to_glib_none().0,
375 bytes.to_glib_none().0,
376 cancellable.map(|p| p.as_ref()).to_glib_none().0,
377 &mut error,
378 );
379 if error.is_null() {
380 Ok(ret)
381 } else {
382 Err(from_glib_full(error))
383 }
384 }
385 }
386
387 #[doc(alias = "g_output_stream_write_bytes_async")]
388 fn write_bytes_async<P: FnOnce(Result<isize, glib::Error>) + 'static>(
389 &self,
390 bytes: &glib::Bytes,
391 io_priority: glib::Priority,
392 cancellable: Option<&impl IsA<Cancellable>>,
393 callback: P,
394 ) {
395 let main_context = glib::MainContext::ref_thread_default();
396 let is_main_context_owner = main_context.is_owner();
397 let has_acquired_main_context = (!is_main_context_owner)
398 .then(|| main_context.acquire().ok())
399 .flatten();
400 assert!(
401 is_main_context_owner || has_acquired_main_context.is_some(),
402 "Async operations only allowed if the thread is owning the MainContext"
403 );
404
405 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
406 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
407 unsafe extern "C" fn write_bytes_async_trampoline<
408 P: FnOnce(Result<isize, glib::Error>) + 'static,
409 >(
410 _source_object: *mut glib::gobject_ffi::GObject,
411 res: *mut crate::ffi::GAsyncResult,
412 user_data: glib::ffi::gpointer,
413 ) {
414 let mut error = std::ptr::null_mut();
415 let ret =
416 ffi::g_output_stream_write_bytes_finish(_source_object as *mut _, res, &mut error);
417 let result = if error.is_null() {
418 Ok(ret)
419 } else {
420 Err(from_glib_full(error))
421 };
422 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
423 Box_::from_raw(user_data as *mut _);
424 let callback: P = callback.into_inner();
425 callback(result);
426 }
427 let callback = write_bytes_async_trampoline::<P>;
428 unsafe {
429 ffi::g_output_stream_write_bytes_async(
430 self.as_ref().to_glib_none().0,
431 bytes.to_glib_none().0,
432 io_priority.into_glib(),
433 cancellable.map(|p| p.as_ref()).to_glib_none().0,
434 Some(callback),
435 Box_::into_raw(user_data) as *mut _,
436 );
437 }
438 }
439
440 fn write_bytes_future(
441 &self,
442 bytes: &glib::Bytes,
443 io_priority: glib::Priority,
444 ) -> Pin<Box_<dyn std::future::Future<Output = Result<isize, glib::Error>> + 'static>> {
445 let bytes = bytes.clone();
446 Box_::pin(crate::GioFuture::new(
447 self,
448 move |obj, cancellable, send| {
449 obj.write_bytes_async(&bytes, io_priority, Some(cancellable), move |res| {
450 send.resolve(res);
451 });
452 },
453 ))
454 }
455}
456
457impl<O: IsA<OutputStream>> OutputStreamExt for O {}