Skip to main content

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 been closed.
323    ///
324    /// This only indicates whether the stream has been closed from this end by
325    /// calling [`close()`][Self::close()]. If the stream is a pipe or socket,
326    /// for example, and the process on the other end has closed its end, this method
327    /// will still return false. Methods which try to write to the output stream will
328    /// return an error, however.
329    ///
330    /// # Returns
331    ///
332    /// true if the stream has been closed; false otherwise
333    #[doc(alias = "g_output_stream_is_closed")]
334    fn is_closed(&self) -> bool {
335        unsafe {
336            from_glib(ffi::g_output_stream_is_closed(
337                self.as_ref().to_glib_none().0,
338            ))
339        }
340    }
341
342    /// Checks if an output stream is being closed. This can be
343    /// used inside e.g. a flush implementation to see if the
344    /// flush (or other i/o operation) is called from within
345    /// the closing operation.
346    ///
347    /// # Returns
348    ///
349    /// [`true`] if @self is being closed. [`false`] otherwise.
350    #[doc(alias = "g_output_stream_is_closing")]
351    fn is_closing(&self) -> bool {
352        unsafe {
353            from_glib(ffi::g_output_stream_is_closing(
354                self.as_ref().to_glib_none().0,
355            ))
356        }
357    }
358
359    //#[doc(alias = "g_output_stream_printf")]
360    //fn printf(&self, cancellable: Option<&impl IsA<Cancellable>>, error: &mut glib::Error, format: &str, : /*Unknown conversion*//*Unimplemented*/Basic: VarArgs) -> Option<usize> {
361    //    unsafe { TODO: call ffi:g_output_stream_printf() }
362    //}
363
364    /// Sets @self to have actions pending. If the pending flag is
365    /// already set or @self is closed, it will return [`false`] and set
366    /// @error.
367    ///
368    /// # Returns
369    ///
370    /// [`true`] if pending was previously unset and is now set.
371    #[doc(alias = "g_output_stream_set_pending")]
372    fn set_pending(&self) -> Result<(), glib::Error> {
373        unsafe {
374            let mut error = std::ptr::null_mut();
375            let is_ok =
376                ffi::g_output_stream_set_pending(self.as_ref().to_glib_none().0, &mut error);
377            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
378            if error.is_null() {
379                Ok(())
380            } else {
381                Err(from_glib_full(error))
382            }
383        }
384    }
385
386    /// Splices an input stream into an output stream.
387    /// ## `source`
388    /// a #GInputStream.
389    /// ## `flags`
390    /// a set of #GOutputStreamSpliceFlags.
391    /// ## `cancellable`
392    /// optional #GCancellable object, [`None`] to ignore.
393    ///
394    /// # Returns
395    ///
396    /// a #gssize containing the size of the data spliced, or
397    ///     -1 if an error occurred. Note that if the number of bytes
398    ///     spliced is greater than `G_MAXSSIZE`, then that will be
399    ///     returned, and there is no way to determine the actual number
400    ///     of bytes spliced.
401    #[doc(alias = "g_output_stream_splice")]
402    fn splice(
403        &self,
404        source: &impl IsA<InputStream>,
405        flags: OutputStreamSpliceFlags,
406        cancellable: Option<&impl IsA<Cancellable>>,
407    ) -> Result<isize, glib::Error> {
408        unsafe {
409            let mut error = std::ptr::null_mut();
410            let ret = ffi::g_output_stream_splice(
411                self.as_ref().to_glib_none().0,
412                source.as_ref().to_glib_none().0,
413                flags.into_glib(),
414                cancellable.map(|p| p.as_ref()).to_glib_none().0,
415                &mut error,
416            );
417            if error.is_null() {
418                Ok(ret)
419            } else {
420                Err(from_glib_full(error))
421            }
422        }
423    }
424
425    /// Splices a stream asynchronously.
426    /// When the operation is finished @callback will be called.
427    /// You can then call g_output_stream_splice_finish() to get the
428    /// result of the operation.
429    ///
430    /// For the synchronous, blocking version of this function, see
431    /// g_output_stream_splice().
432    /// ## `source`
433    /// a #GInputStream.
434    /// ## `flags`
435    /// a set of #GOutputStreamSpliceFlags.
436    /// ## `io_priority`
437    /// the io priority of the request.
438    /// ## `cancellable`
439    /// optional #GCancellable object, [`None`] to ignore.
440    /// ## `callback`
441    /// a #GAsyncReadyCallback
442    ///   to call when the request is satisfied
443    #[doc(alias = "g_output_stream_splice_async")]
444    fn splice_async<P: FnOnce(Result<isize, glib::Error>) + 'static>(
445        &self,
446        source: &impl IsA<InputStream>,
447        flags: OutputStreamSpliceFlags,
448        io_priority: glib::Priority,
449        cancellable: Option<&impl IsA<Cancellable>>,
450        callback: P,
451    ) {
452        let main_context = glib::MainContext::ref_thread_default();
453        let is_main_context_owner = main_context.is_owner();
454        let has_acquired_main_context = (!is_main_context_owner)
455            .then(|| main_context.acquire().ok())
456            .flatten();
457        assert!(
458            is_main_context_owner || has_acquired_main_context.is_some(),
459            "Async operations only allowed if the thread is owning the MainContext"
460        );
461
462        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
463            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
464        unsafe extern "C" fn splice_async_trampoline<
465            P: FnOnce(Result<isize, glib::Error>) + 'static,
466        >(
467            _source_object: *mut glib::gobject_ffi::GObject,
468            res: *mut crate::ffi::GAsyncResult,
469            user_data: glib::ffi::gpointer,
470        ) {
471            unsafe {
472                let mut error = std::ptr::null_mut();
473                let ret =
474                    ffi::g_output_stream_splice_finish(_source_object as *mut _, res, &mut error);
475                let result = if error.is_null() {
476                    Ok(ret)
477                } else {
478                    Err(from_glib_full(error))
479                };
480                let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
481                    Box_::from_raw(user_data as *mut _);
482                let callback: P = callback.into_inner();
483                callback(result);
484            }
485        }
486        let callback = splice_async_trampoline::<P>;
487        unsafe {
488            ffi::g_output_stream_splice_async(
489                self.as_ref().to_glib_none().0,
490                source.as_ref().to_glib_none().0,
491                flags.into_glib(),
492                io_priority.into_glib(),
493                cancellable.map(|p| p.as_ref()).to_glib_none().0,
494                Some(callback),
495                Box_::into_raw(user_data) as *mut _,
496            );
497        }
498    }
499
500    fn splice_future(
501        &self,
502        source: &(impl IsA<InputStream> + Clone + 'static),
503        flags: OutputStreamSpliceFlags,
504        io_priority: glib::Priority,
505    ) -> Pin<Box_<dyn std::future::Future<Output = Result<isize, glib::Error>> + 'static>> {
506        let source = source.clone();
507        Box_::pin(crate::GioFuture::new(
508            self,
509            move |obj, cancellable, send| {
510                obj.splice_async(&source, flags, io_priority, Some(cancellable), move |res| {
511                    send.resolve(res);
512                });
513            },
514        ))
515    }
516
517    //#[doc(alias = "g_output_stream_vprintf")]
518    //fn vprintf(&self, cancellable: Option<&impl IsA<Cancellable>>, error: &mut glib::Error, format: &str, args: /*Unknown conversion*//*Unimplemented*/Unsupported) -> Option<usize> {
519    //    unsafe { TODO: call ffi:g_output_stream_vprintf() }
520    //}
521
522    /// Tries to write @count bytes from @buffer into the stream. Will block
523    /// during the operation.
524    ///
525    /// If count is 0, returns 0 and does nothing. A value of @count
526    /// larger than `G_MAXSSIZE` will cause a [`IOErrorEnum::InvalidArgument`][crate::IOErrorEnum::InvalidArgument] error.
527    ///
528    /// On success, the number of bytes written to the stream is returned.
529    /// It is not an error if this is not the same as the requested size, as it
530    /// can happen e.g. on a partial I/O error, or if there is not enough
531    /// storage in the stream. All writes block until at least one byte
532    /// is written or an error occurs; 0 is never returned (unless
533    /// @count is 0).
534    ///
535    /// If @cancellable is not [`None`], then the operation can be cancelled by
536    /// triggering the cancellable object from another thread. If the operation
537    /// was cancelled, the error [`IOErrorEnum::Cancelled`][crate::IOErrorEnum::Cancelled] will be returned. If an
538    /// operation was partially finished when the operation was cancelled the
539    /// partial result will be returned, without an error.
540    ///
541    /// On error -1 is returned and @error is set accordingly.
542    /// ## `buffer`
543    /// the buffer containing the data to write.
544    /// ## `cancellable`
545    /// optional cancellable object
546    ///
547    /// # Returns
548    ///
549    /// Number of bytes written, or -1 on error
550    #[doc(alias = "g_output_stream_write")]
551    fn write(
552        &self,
553        buffer: &[u8],
554        cancellable: Option<&impl IsA<Cancellable>>,
555    ) -> Result<isize, glib::Error> {
556        let count = buffer.len() as _;
557        unsafe {
558            let mut error = std::ptr::null_mut();
559            let ret = ffi::g_output_stream_write(
560                self.as_ref().to_glib_none().0,
561                buffer.to_glib_none().0,
562                count,
563                cancellable.map(|p| p.as_ref()).to_glib_none().0,
564                &mut error,
565            );
566            if error.is_null() {
567                Ok(ret)
568            } else {
569                Err(from_glib_full(error))
570            }
571        }
572    }
573
574    /// A wrapper function for g_output_stream_write() which takes a
575    /// #GBytes as input.  This can be more convenient for use by language
576    /// bindings or in other cases where the refcounted nature of #GBytes
577    /// is helpful over a bare pointer interface.
578    ///
579    /// However, note that this function may still perform partial writes,
580    /// just like g_output_stream_write().  If that occurs, to continue
581    /// writing, you will need to create a new #GBytes containing just the
582    /// remaining bytes, using g_bytes_new_from_bytes(). Passing the same
583    /// #GBytes instance multiple times potentially can result in duplicated
584    /// data in the output stream.
585    /// ## `bytes`
586    /// the #GBytes to write
587    /// ## `cancellable`
588    /// optional cancellable object
589    ///
590    /// # Returns
591    ///
592    /// Number of bytes written, or -1 on error
593    #[doc(alias = "g_output_stream_write_bytes")]
594    fn write_bytes(
595        &self,
596        bytes: &glib::Bytes,
597        cancellable: Option<&impl IsA<Cancellable>>,
598    ) -> Result<isize, glib::Error> {
599        unsafe {
600            let mut error = std::ptr::null_mut();
601            let ret = ffi::g_output_stream_write_bytes(
602                self.as_ref().to_glib_none().0,
603                bytes.to_glib_none().0,
604                cancellable.map(|p| p.as_ref()).to_glib_none().0,
605                &mut error,
606            );
607            if error.is_null() {
608                Ok(ret)
609            } else {
610                Err(from_glib_full(error))
611            }
612        }
613    }
614
615    /// This function is similar to g_output_stream_write_async(), but
616    /// takes a #GBytes as input.  Due to the refcounted nature of #GBytes,
617    /// this allows the stream to avoid taking a copy of the data.
618    ///
619    /// However, note that this function may still perform partial writes,
620    /// just like g_output_stream_write_async(). If that occurs, to continue
621    /// writing, you will need to create a new #GBytes containing just the
622    /// remaining bytes, using g_bytes_new_from_bytes(). Passing the same
623    /// #GBytes instance multiple times potentially can result in duplicated
624    /// data in the output stream.
625    ///
626    /// For the synchronous, blocking version of this function, see
627    /// g_output_stream_write_bytes().
628    /// ## `bytes`
629    /// The bytes to write
630    /// ## `io_priority`
631    /// the io priority of the request.
632    /// ## `cancellable`
633    /// optional #GCancellable object, [`None`] to ignore.
634    /// ## `callback`
635    /// a #GAsyncReadyCallback
636    ///   to call when the request is satisfied
637    #[doc(alias = "g_output_stream_write_bytes_async")]
638    fn write_bytes_async<P: FnOnce(Result<isize, glib::Error>) + 'static>(
639        &self,
640        bytes: &glib::Bytes,
641        io_priority: glib::Priority,
642        cancellable: Option<&impl IsA<Cancellable>>,
643        callback: P,
644    ) {
645        let main_context = glib::MainContext::ref_thread_default();
646        let is_main_context_owner = main_context.is_owner();
647        let has_acquired_main_context = (!is_main_context_owner)
648            .then(|| main_context.acquire().ok())
649            .flatten();
650        assert!(
651            is_main_context_owner || has_acquired_main_context.is_some(),
652            "Async operations only allowed if the thread is owning the MainContext"
653        );
654
655        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
656            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
657        unsafe extern "C" fn write_bytes_async_trampoline<
658            P: FnOnce(Result<isize, glib::Error>) + 'static,
659        >(
660            _source_object: *mut glib::gobject_ffi::GObject,
661            res: *mut crate::ffi::GAsyncResult,
662            user_data: glib::ffi::gpointer,
663        ) {
664            unsafe {
665                let mut error = std::ptr::null_mut();
666                let ret = ffi::g_output_stream_write_bytes_finish(
667                    _source_object as *mut _,
668                    res,
669                    &mut error,
670                );
671                let result = if error.is_null() {
672                    Ok(ret)
673                } else {
674                    Err(from_glib_full(error))
675                };
676                let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
677                    Box_::from_raw(user_data as *mut _);
678                let callback: P = callback.into_inner();
679                callback(result);
680            }
681        }
682        let callback = write_bytes_async_trampoline::<P>;
683        unsafe {
684            ffi::g_output_stream_write_bytes_async(
685                self.as_ref().to_glib_none().0,
686                bytes.to_glib_none().0,
687                io_priority.into_glib(),
688                cancellable.map(|p| p.as_ref()).to_glib_none().0,
689                Some(callback),
690                Box_::into_raw(user_data) as *mut _,
691            );
692        }
693    }
694
695    fn write_bytes_future(
696        &self,
697        bytes: &glib::Bytes,
698        io_priority: glib::Priority,
699    ) -> Pin<Box_<dyn std::future::Future<Output = Result<isize, glib::Error>> + 'static>> {
700        let bytes = bytes.clone();
701        Box_::pin(crate::GioFuture::new(
702            self,
703            move |obj, cancellable, send| {
704                obj.write_bytes_async(&bytes, io_priority, Some(cancellable), move |res| {
705                    send.resolve(res);
706                });
707            },
708        ))
709    }
710}
711
712impl<O: IsA<OutputStream>> OutputStreamExt for O {}