gio/auto/
output_stream.rs

1// This file was generated by gir (https://github.com/gtk-rs/gir)
2// from gir-files (https://github.com/gtk-rs/gir-files)
3// DO NOT EDIT
4
5use crate::{AsyncResult, Cancellable, InputStream, OutputStreamSpliceFlags, ffi};
6use glib::{prelude::*, translate::*};
7use std::{boxed::Box as Box_, pin::Pin};
8
9glib::wrapper! {
10    /// `GOutputStream` is a base class for implementing streaming output.
11    ///
12    /// It has functions to write to a stream ([`OutputStreamExt::write()`][crate::prelude::OutputStreamExt::write()]),
13    /// to close a stream ([`OutputStreamExt::close()`][crate::prelude::OutputStreamExt::close()]) and to flush pending
14    /// writes ([`OutputStreamExt::flush()`][crate::prelude::OutputStreamExt::flush()]).
15    ///
16    /// To copy the content of an input stream to an output stream without
17    /// manually handling the reads and writes, use [`OutputStreamExt::splice()`][crate::prelude::OutputStreamExt::splice()].
18    ///
19    /// See the documentation for [`IOStream`][crate::IOStream] for details of thread safety
20    /// of streaming APIs.
21    ///
22    /// All of these functions have async variants too.
23    ///
24    /// All classes derived from `GOutputStream` *should* implement synchronous
25    /// writing, splicing, flushing and closing streams, but *may* implement
26    /// asynchronous versions.
27    ///
28    /// This is an Abstract Base Class, you cannot instantiate it.
29    ///
30    /// # Implements
31    ///
32    /// [`OutputStreamExt`][trait@crate::prelude::OutputStreamExt], [`trait@glib::ObjectExt`], [`OutputStreamExtManual`][trait@crate::prelude::OutputStreamExtManual]
33    #[doc(alias = "GOutputStream")]
34    pub struct OutputStream(Object<ffi::GOutputStream, ffi::GOutputStreamClass>);
35
36    match fn {
37        type_ => || ffi::g_output_stream_get_type(),
38    }
39}
40
41impl OutputStream {
42    pub const NONE: Option<&'static OutputStream> = None;
43}
44
45/// Trait containing all [`struct@OutputStream`] methods.
46///
47/// # Implementors
48///
49/// [`FileOutputStream`][struct@crate::FileOutputStream], [`FilterOutputStream`][struct@crate::FilterOutputStream], [`MemoryOutputStream`][struct@crate::MemoryOutputStream], [`OutputStream`][struct@crate::OutputStream], [`PollableOutputStream`][struct@crate::PollableOutputStream]
50pub trait OutputStreamExt: IsA<OutputStream> + 'static {
51    /// Clears the pending flag on @self.
52    #[doc(alias = "g_output_stream_clear_pending")]
53    fn clear_pending(&self) {
54        unsafe {
55            ffi::g_output_stream_clear_pending(self.as_ref().to_glib_none().0);
56        }
57    }
58
59    /// Closes the stream, releasing resources related to it.
60    ///
61    /// Once the stream is closed, all other operations will return [`IOErrorEnum::Closed`][crate::IOErrorEnum::Closed].
62    /// Closing a stream multiple times will not return an error.
63    ///
64    /// Closing a stream will automatically flush any outstanding buffers in the
65    /// stream.
66    ///
67    /// Streams will be automatically closed when the last reference
68    /// is dropped, but you might want to call this function to make sure
69    /// resources are released as early as possible.
70    ///
71    /// Some streams might keep the backing store of the stream (e.g. a file descriptor)
72    /// open after the stream is closed. See the documentation for the individual
73    /// stream for details.
74    ///
75    /// On failure the first error that happened will be reported, but the close
76    /// operation will finish as much as possible. A stream that failed to
77    /// close will still return [`IOErrorEnum::Closed`][crate::IOErrorEnum::Closed] for all operations. Still, it
78    /// is important to check and report the error to the user, otherwise
79    /// there might be a loss of data as all data might not be written.
80    ///
81    /// If @cancellable is not [`None`], then the operation can be cancelled by
82    /// triggering the cancellable object from another thread. If the operation
83    /// was cancelled, the error [`IOErrorEnum::Cancelled`][crate::IOErrorEnum::Cancelled] will be returned.
84    /// Cancelling a close will still leave the stream closed, but there some streams
85    /// can use a faster close that doesn't block to e.g. check errors. On
86    /// cancellation (as with any error) there is no guarantee that all written
87    /// data will reach the target.
88    /// ## `cancellable`
89    /// optional cancellable object
90    ///
91    /// # Returns
92    ///
93    /// [`true`] on success, [`false`] on failure
94    #[doc(alias = "g_output_stream_close")]
95    fn close(&self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<(), glib::Error> {
96        unsafe {
97            let mut error = std::ptr::null_mut();
98            let is_ok = ffi::g_output_stream_close(
99                self.as_ref().to_glib_none().0,
100                cancellable.map(|p| p.as_ref()).to_glib_none().0,
101                &mut error,
102            );
103            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
104            if error.is_null() {
105                Ok(())
106            } else {
107                Err(from_glib_full(error))
108            }
109        }
110    }
111
112    /// Requests an asynchronous close of the stream, releasing resources
113    /// related to it. When the operation is finished @callback will be
114    /// called. You can then call g_output_stream_close_finish() to get
115    /// the result of the operation.
116    ///
117    /// For behaviour details see g_output_stream_close().
118    ///
119    /// The asynchronous methods have a default fallback that uses threads
120    /// to implement asynchronicity, so they are optional for inheriting
121    /// classes. However, if you override one you must override all.
122    /// ## `io_priority`
123    /// the io priority of the request.
124    /// ## `cancellable`
125    /// optional cancellable object
126    /// ## `callback`
127    /// a #GAsyncReadyCallback
128    ///   to call when the request is satisfied
129    #[doc(alias = "g_output_stream_close_async")]
130    fn close_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
131        &self,
132        io_priority: glib::Priority,
133        cancellable: Option<&impl IsA<Cancellable>>,
134        callback: P,
135    ) {
136        let main_context = glib::MainContext::ref_thread_default();
137        let is_main_context_owner = main_context.is_owner();
138        let has_acquired_main_context = (!is_main_context_owner)
139            .then(|| main_context.acquire().ok())
140            .flatten();
141        assert!(
142            is_main_context_owner || has_acquired_main_context.is_some(),
143            "Async operations only allowed if the thread is owning the MainContext"
144        );
145
146        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
147            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
148        unsafe extern "C" fn close_async_trampoline<
149            P: FnOnce(Result<(), glib::Error>) + 'static,
150        >(
151            _source_object: *mut glib::gobject_ffi::GObject,
152            res: *mut crate::ffi::GAsyncResult,
153            user_data: glib::ffi::gpointer,
154        ) {
155            unsafe {
156                let mut error = std::ptr::null_mut();
157                ffi::g_output_stream_close_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        }
169        let callback = close_async_trampoline::<P>;
170        unsafe {
171            ffi::g_output_stream_close_async(
172                self.as_ref().to_glib_none().0,
173                io_priority.into_glib(),
174                cancellable.map(|p| p.as_ref()).to_glib_none().0,
175                Some(callback),
176                Box_::into_raw(user_data) as *mut _,
177            );
178        }
179    }
180
181    fn close_future(
182        &self,
183        io_priority: glib::Priority,
184    ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
185        Box_::pin(crate::GioFuture::new(
186            self,
187            move |obj, cancellable, send| {
188                obj.close_async(io_priority, Some(cancellable), move |res| {
189                    send.resolve(res);
190                });
191            },
192        ))
193    }
194
195    /// Forces a write of all user-space buffered data for the given
196    /// @self. Will block during the operation. Closing the stream will
197    /// implicitly cause a flush.
198    ///
199    /// This function is optional for inherited classes.
200    ///
201    /// If @cancellable is not [`None`], then the operation can be cancelled by
202    /// triggering the cancellable object from another thread. If the operation
203    /// was cancelled, the error [`IOErrorEnum::Cancelled`][crate::IOErrorEnum::Cancelled] will be returned.
204    /// ## `cancellable`
205    /// optional cancellable object
206    ///
207    /// # Returns
208    ///
209    /// [`true`] on success, [`false`] on error
210    #[doc(alias = "g_output_stream_flush")]
211    fn flush(&self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<(), glib::Error> {
212        unsafe {
213            let mut error = std::ptr::null_mut();
214            let is_ok = ffi::g_output_stream_flush(
215                self.as_ref().to_glib_none().0,
216                cancellable.map(|p| p.as_ref()).to_glib_none().0,
217                &mut error,
218            );
219            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
220            if error.is_null() {
221                Ok(())
222            } else {
223                Err(from_glib_full(error))
224            }
225        }
226    }
227
228    /// Forces an asynchronous write of all user-space buffered data for
229    /// the given @self.
230    /// For behaviour details see g_output_stream_flush().
231    ///
232    /// When the operation is finished @callback will be
233    /// called. You can then call g_output_stream_flush_finish() to get the
234    /// result of the operation.
235    /// ## `io_priority`
236    /// the io priority of the request.
237    /// ## `cancellable`
238    /// optional #GCancellable object, [`None`] to ignore.
239    /// ## `callback`
240    /// a #GAsyncReadyCallback
241    ///   to call when the request is satisfied
242    #[doc(alias = "g_output_stream_flush_async")]
243    fn flush_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
244        &self,
245        io_priority: glib::Priority,
246        cancellable: Option<&impl IsA<Cancellable>>,
247        callback: P,
248    ) {
249        let main_context = glib::MainContext::ref_thread_default();
250        let is_main_context_owner = main_context.is_owner();
251        let has_acquired_main_context = (!is_main_context_owner)
252            .then(|| main_context.acquire().ok())
253            .flatten();
254        assert!(
255            is_main_context_owner || has_acquired_main_context.is_some(),
256            "Async operations only allowed if the thread is owning the MainContext"
257        );
258
259        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
260            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
261        unsafe extern "C" fn flush_async_trampoline<
262            P: FnOnce(Result<(), glib::Error>) + 'static,
263        >(
264            _source_object: *mut glib::gobject_ffi::GObject,
265            res: *mut crate::ffi::GAsyncResult,
266            user_data: glib::ffi::gpointer,
267        ) {
268            unsafe {
269                let mut error = std::ptr::null_mut();
270                ffi::g_output_stream_flush_finish(_source_object as *mut _, res, &mut error);
271                let result = if error.is_null() {
272                    Ok(())
273                } else {
274                    Err(from_glib_full(error))
275                };
276                let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
277                    Box_::from_raw(user_data as *mut _);
278                let callback: P = callback.into_inner();
279                callback(result);
280            }
281        }
282        let callback = flush_async_trampoline::<P>;
283        unsafe {
284            ffi::g_output_stream_flush_async(
285                self.as_ref().to_glib_none().0,
286                io_priority.into_glib(),
287                cancellable.map(|p| p.as_ref()).to_glib_none().0,
288                Some(callback),
289                Box_::into_raw(user_data) as *mut _,
290            );
291        }
292    }
293
294    fn flush_future(
295        &self,
296        io_priority: glib::Priority,
297    ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
298        Box_::pin(crate::GioFuture::new(
299            self,
300            move |obj, cancellable, send| {
301                obj.flush_async(io_priority, Some(cancellable), move |res| {
302                    send.resolve(res);
303                });
304            },
305        ))
306    }
307
308    /// Checks if an output stream has pending actions.
309    ///
310    /// # Returns
311    ///
312    /// [`true`] if @self has pending actions.
313    #[doc(alias = "g_output_stream_has_pending")]
314    fn has_pending(&self) -> bool {
315        unsafe {
316            from_glib(ffi::g_output_stream_has_pending(
317                self.as_ref().to_glib_none().0,
318            ))
319        }
320    }
321
322    /// Checks if an output stream has already been closed.
323    ///
324    /// # Returns
325    ///
326    /// [`true`] if @self is closed. [`false`] otherwise.
327    #[doc(alias = "g_output_stream_is_closed")]
328    fn is_closed(&self) -> bool {
329        unsafe {
330            from_glib(ffi::g_output_stream_is_closed(
331                self.as_ref().to_glib_none().0,
332            ))
333        }
334    }
335
336    /// Checks if an output stream is being closed. This can be
337    /// used inside e.g. a flush implementation to see if the
338    /// flush (or other i/o operation) is called from within
339    /// the closing operation.
340    ///
341    /// # Returns
342    ///
343    /// [`true`] if @self is being closed. [`false`] otherwise.
344    #[doc(alias = "g_output_stream_is_closing")]
345    fn is_closing(&self) -> bool {
346        unsafe {
347            from_glib(ffi::g_output_stream_is_closing(
348                self.as_ref().to_glib_none().0,
349            ))
350        }
351    }
352
353    //#[doc(alias = "g_output_stream_printf")]
354    //fn printf(&self, cancellable: Option<&impl IsA<Cancellable>>, error: &mut glib::Error, format: &str, : /*Unknown conversion*//*Unimplemented*/Basic: VarArgs) -> Option<usize> {
355    //    unsafe { TODO: call ffi:g_output_stream_printf() }
356    //}
357
358    /// Sets @self to have actions pending. If the pending flag is
359    /// already set or @self is closed, it will return [`false`] and set
360    /// @error.
361    ///
362    /// # Returns
363    ///
364    /// [`true`] if pending was previously unset and is now set.
365    #[doc(alias = "g_output_stream_set_pending")]
366    fn set_pending(&self) -> Result<(), glib::Error> {
367        unsafe {
368            let mut error = std::ptr::null_mut();
369            let is_ok =
370                ffi::g_output_stream_set_pending(self.as_ref().to_glib_none().0, &mut error);
371            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
372            if error.is_null() {
373                Ok(())
374            } else {
375                Err(from_glib_full(error))
376            }
377        }
378    }
379
380    /// Splices an input stream into an output stream.
381    /// ## `source`
382    /// a #GInputStream.
383    /// ## `flags`
384    /// a set of #GOutputStreamSpliceFlags.
385    /// ## `cancellable`
386    /// optional #GCancellable object, [`None`] to ignore.
387    ///
388    /// # Returns
389    ///
390    /// a #gssize containing the size of the data spliced, or
391    ///     -1 if an error occurred. Note that if the number of bytes
392    ///     spliced is greater than `G_MAXSSIZE`, then that will be
393    ///     returned, and there is no way to determine the actual number
394    ///     of bytes spliced.
395    #[doc(alias = "g_output_stream_splice")]
396    fn splice(
397        &self,
398        source: &impl IsA<InputStream>,
399        flags: OutputStreamSpliceFlags,
400        cancellable: Option<&impl IsA<Cancellable>>,
401    ) -> Result<isize, glib::Error> {
402        unsafe {
403            let mut error = std::ptr::null_mut();
404            let ret = ffi::g_output_stream_splice(
405                self.as_ref().to_glib_none().0,
406                source.as_ref().to_glib_none().0,
407                flags.into_glib(),
408                cancellable.map(|p| p.as_ref()).to_glib_none().0,
409                &mut error,
410            );
411            if error.is_null() {
412                Ok(ret)
413            } else {
414                Err(from_glib_full(error))
415            }
416        }
417    }
418
419    /// Splices a stream asynchronously.
420    /// When the operation is finished @callback will be called.
421    /// You can then call g_output_stream_splice_finish() to get the
422    /// result of the operation.
423    ///
424    /// For the synchronous, blocking version of this function, see
425    /// g_output_stream_splice().
426    /// ## `source`
427    /// a #GInputStream.
428    /// ## `flags`
429    /// a set of #GOutputStreamSpliceFlags.
430    /// ## `io_priority`
431    /// the io priority of the request.
432    /// ## `cancellable`
433    /// optional #GCancellable object, [`None`] to ignore.
434    /// ## `callback`
435    /// a #GAsyncReadyCallback
436    ///   to call when the request is satisfied
437    #[doc(alias = "g_output_stream_splice_async")]
438    fn splice_async<P: FnOnce(Result<isize, glib::Error>) + 'static>(
439        &self,
440        source: &impl IsA<InputStream>,
441        flags: OutputStreamSpliceFlags,
442        io_priority: glib::Priority,
443        cancellable: Option<&impl IsA<Cancellable>>,
444        callback: P,
445    ) {
446        let main_context = glib::MainContext::ref_thread_default();
447        let is_main_context_owner = main_context.is_owner();
448        let has_acquired_main_context = (!is_main_context_owner)
449            .then(|| main_context.acquire().ok())
450            .flatten();
451        assert!(
452            is_main_context_owner || has_acquired_main_context.is_some(),
453            "Async operations only allowed if the thread is owning the MainContext"
454        );
455
456        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
457            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
458        unsafe extern "C" fn splice_async_trampoline<
459            P: FnOnce(Result<isize, glib::Error>) + 'static,
460        >(
461            _source_object: *mut glib::gobject_ffi::GObject,
462            res: *mut crate::ffi::GAsyncResult,
463            user_data: glib::ffi::gpointer,
464        ) {
465            unsafe {
466                let mut error = std::ptr::null_mut();
467                let ret =
468                    ffi::g_output_stream_splice_finish(_source_object as *mut _, res, &mut error);
469                let result = if error.is_null() {
470                    Ok(ret)
471                } else {
472                    Err(from_glib_full(error))
473                };
474                let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
475                    Box_::from_raw(user_data as *mut _);
476                let callback: P = callback.into_inner();
477                callback(result);
478            }
479        }
480        let callback = splice_async_trampoline::<P>;
481        unsafe {
482            ffi::g_output_stream_splice_async(
483                self.as_ref().to_glib_none().0,
484                source.as_ref().to_glib_none().0,
485                flags.into_glib(),
486                io_priority.into_glib(),
487                cancellable.map(|p| p.as_ref()).to_glib_none().0,
488                Some(callback),
489                Box_::into_raw(user_data) as *mut _,
490            );
491        }
492    }
493
494    fn splice_future(
495        &self,
496        source: &(impl IsA<InputStream> + Clone + 'static),
497        flags: OutputStreamSpliceFlags,
498        io_priority: glib::Priority,
499    ) -> Pin<Box_<dyn std::future::Future<Output = Result<isize, glib::Error>> + 'static>> {
500        let source = source.clone();
501        Box_::pin(crate::GioFuture::new(
502            self,
503            move |obj, cancellable, send| {
504                obj.splice_async(&source, flags, io_priority, Some(cancellable), move |res| {
505                    send.resolve(res);
506                });
507            },
508        ))
509    }
510
511    //#[doc(alias = "g_output_stream_vprintf")]
512    //fn vprintf(&self, cancellable: Option<&impl IsA<Cancellable>>, error: &mut glib::Error, format: &str, args: /*Unknown conversion*//*Unimplemented*/Unsupported) -> Option<usize> {
513    //    unsafe { TODO: call ffi:g_output_stream_vprintf() }
514    //}
515
516    /// Tries to write @count bytes from @buffer into the stream. Will block
517    /// during the operation.
518    ///
519    /// If count is 0, returns 0 and does nothing. A value of @count
520    /// larger than `G_MAXSSIZE` will cause a [`IOErrorEnum::InvalidArgument`][crate::IOErrorEnum::InvalidArgument] error.
521    ///
522    /// On success, the number of bytes written to the stream is returned.
523    /// It is not an error if this is not the same as the requested size, as it
524    /// can happen e.g. on a partial I/O error, or if there is not enough
525    /// storage in the stream. All writes block until at least one byte
526    /// is written or an error occurs; 0 is never returned (unless
527    /// @count is 0).
528    ///
529    /// If @cancellable is not [`None`], then the operation can be cancelled by
530    /// triggering the cancellable object from another thread. If the operation
531    /// was cancelled, the error [`IOErrorEnum::Cancelled`][crate::IOErrorEnum::Cancelled] will be returned. If an
532    /// operation was partially finished when the operation was cancelled the
533    /// partial result will be returned, without an error.
534    ///
535    /// On error -1 is returned and @error is set accordingly.
536    /// ## `buffer`
537    /// the buffer containing the data to write.
538    /// ## `cancellable`
539    /// optional cancellable object
540    ///
541    /// # Returns
542    ///
543    /// Number of bytes written, or -1 on error
544    #[doc(alias = "g_output_stream_write")]
545    fn write(
546        &self,
547        buffer: &[u8],
548        cancellable: Option<&impl IsA<Cancellable>>,
549    ) -> Result<isize, glib::Error> {
550        let count = buffer.len() as _;
551        unsafe {
552            let mut error = std::ptr::null_mut();
553            let ret = ffi::g_output_stream_write(
554                self.as_ref().to_glib_none().0,
555                buffer.to_glib_none().0,
556                count,
557                cancellable.map(|p| p.as_ref()).to_glib_none().0,
558                &mut error,
559            );
560            if error.is_null() {
561                Ok(ret)
562            } else {
563                Err(from_glib_full(error))
564            }
565        }
566    }
567
568    /// A wrapper function for g_output_stream_write() which takes a
569    /// #GBytes as input.  This can be more convenient for use by language
570    /// bindings or in other cases where the refcounted nature of #GBytes
571    /// is helpful over a bare pointer interface.
572    ///
573    /// However, note that this function may still perform partial writes,
574    /// just like g_output_stream_write().  If that occurs, to continue
575    /// writing, you will need to create a new #GBytes containing just the
576    /// remaining bytes, using g_bytes_new_from_bytes(). Passing the same
577    /// #GBytes instance multiple times potentially can result in duplicated
578    /// data in the output stream.
579    /// ## `bytes`
580    /// the #GBytes to write
581    /// ## `cancellable`
582    /// optional cancellable object
583    ///
584    /// # Returns
585    ///
586    /// Number of bytes written, or -1 on error
587    #[doc(alias = "g_output_stream_write_bytes")]
588    fn write_bytes(
589        &self,
590        bytes: &glib::Bytes,
591        cancellable: Option<&impl IsA<Cancellable>>,
592    ) -> Result<isize, glib::Error> {
593        unsafe {
594            let mut error = std::ptr::null_mut();
595            let ret = ffi::g_output_stream_write_bytes(
596                self.as_ref().to_glib_none().0,
597                bytes.to_glib_none().0,
598                cancellable.map(|p| p.as_ref()).to_glib_none().0,
599                &mut error,
600            );
601            if error.is_null() {
602                Ok(ret)
603            } else {
604                Err(from_glib_full(error))
605            }
606        }
607    }
608
609    /// This function is similar to g_output_stream_write_async(), but
610    /// takes a #GBytes as input.  Due to the refcounted nature of #GBytes,
611    /// this allows the stream to avoid taking a copy of the data.
612    ///
613    /// However, note that this function may still perform partial writes,
614    /// just like g_output_stream_write_async(). If that occurs, to continue
615    /// writing, you will need to create a new #GBytes containing just the
616    /// remaining bytes, using g_bytes_new_from_bytes(). Passing the same
617    /// #GBytes instance multiple times potentially can result in duplicated
618    /// data in the output stream.
619    ///
620    /// For the synchronous, blocking version of this function, see
621    /// g_output_stream_write_bytes().
622    /// ## `bytes`
623    /// The bytes to write
624    /// ## `io_priority`
625    /// the io priority of the request.
626    /// ## `cancellable`
627    /// optional #GCancellable object, [`None`] to ignore.
628    /// ## `callback`
629    /// a #GAsyncReadyCallback
630    ///   to call when the request is satisfied
631    #[doc(alias = "g_output_stream_write_bytes_async")]
632    fn write_bytes_async<P: FnOnce(Result<isize, glib::Error>) + 'static>(
633        &self,
634        bytes: &glib::Bytes,
635        io_priority: glib::Priority,
636        cancellable: Option<&impl IsA<Cancellable>>,
637        callback: P,
638    ) {
639        let main_context = glib::MainContext::ref_thread_default();
640        let is_main_context_owner = main_context.is_owner();
641        let has_acquired_main_context = (!is_main_context_owner)
642            .then(|| main_context.acquire().ok())
643            .flatten();
644        assert!(
645            is_main_context_owner || has_acquired_main_context.is_some(),
646            "Async operations only allowed if the thread is owning the MainContext"
647        );
648
649        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
650            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
651        unsafe extern "C" fn write_bytes_async_trampoline<
652            P: FnOnce(Result<isize, glib::Error>) + 'static,
653        >(
654            _source_object: *mut glib::gobject_ffi::GObject,
655            res: *mut crate::ffi::GAsyncResult,
656            user_data: glib::ffi::gpointer,
657        ) {
658            unsafe {
659                let mut error = std::ptr::null_mut();
660                let ret = ffi::g_output_stream_write_bytes_finish(
661                    _source_object as *mut _,
662                    res,
663                    &mut error,
664                );
665                let result = if error.is_null() {
666                    Ok(ret)
667                } else {
668                    Err(from_glib_full(error))
669                };
670                let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
671                    Box_::from_raw(user_data as *mut _);
672                let callback: P = callback.into_inner();
673                callback(result);
674            }
675        }
676        let callback = write_bytes_async_trampoline::<P>;
677        unsafe {
678            ffi::g_output_stream_write_bytes_async(
679                self.as_ref().to_glib_none().0,
680                bytes.to_glib_none().0,
681                io_priority.into_glib(),
682                cancellable.map(|p| p.as_ref()).to_glib_none().0,
683                Some(callback),
684                Box_::into_raw(user_data) as *mut _,
685            );
686        }
687    }
688
689    fn write_bytes_future(
690        &self,
691        bytes: &glib::Bytes,
692        io_priority: glib::Priority,
693    ) -> Pin<Box_<dyn std::future::Future<Output = Result<isize, glib::Error>> + 'static>> {
694        let bytes = bytes.clone();
695        Box_::pin(crate::GioFuture::new(
696            self,
697            move |obj, cancellable, send| {
698                obj.write_bytes_async(&bytes, io_priority, Some(cancellable), move |res| {
699                    send.resolve(res);
700                });
701            },
702        ))
703    }
704}
705
706impl<O: IsA<OutputStream>> OutputStreamExt for O {}