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 {}