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