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