gio/auto/
io_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, OutputStream, ffi};
6use glib::{
7    prelude::*,
8    signal::{SignalHandlerId, connect_raw},
9    translate::*,
10};
11use std::{boxed::Box as Box_, pin::Pin};
12
13glib::wrapper! {
14    /// `GIOStream` represents an object that has both read and write streams.
15    /// Generally the two streams act as separate input and output streams,
16    /// but they share some common resources and state. For instance, for
17    /// seekable streams, both streams may use the same position.
18    ///
19    /// Examples of `GIOStream` objects are [`SocketConnection`][crate::SocketConnection], which represents
20    /// a two-way network connection; and [`FileIOStream`][crate::FileIOStream], which represents a
21    /// file handle opened in read-write mode.
22    ///
23    /// To do the actual reading and writing you need to get the substreams
24    /// with [`IOStreamExt::input_stream()`][crate::prelude::IOStreamExt::input_stream()] and
25    /// [`IOStreamExt::output_stream()`][crate::prelude::IOStreamExt::output_stream()].
26    ///
27    /// The `GIOStream` object owns the input and the output streams, not the other
28    /// way around, so keeping the substreams alive will not keep the `GIOStream`
29    /// object alive. If the `GIOStream` object is freed it will be closed, thus
30    /// closing the substreams, so even if the substreams stay alive they will
31    /// always return `G_IO_ERROR_CLOSED` for all operations.
32    ///
33    /// To close a stream use [`IOStreamExt::close()`][crate::prelude::IOStreamExt::close()] which will close the common
34    /// stream object and also the individual substreams. You can also close
35    /// the substreams themselves. In most cases this only marks the
36    /// substream as closed, so further I/O on it fails but common state in the
37    /// `GIOStream` may still be open. However, some streams may support
38    /// ‘half-closed’ states where one direction of the stream is actually shut down.
39    ///
40    /// Operations on `GIOStream`s cannot be started while another operation on the
41    /// `GIOStream` or its substreams is in progress. Specifically, an application can
42    /// read from the [`InputStream`][crate::InputStream] and write to the
43    /// [`OutputStream`][crate::OutputStream] simultaneously (either in separate threads, or as
44    /// asynchronous operations in the same thread), but an application cannot start
45    /// any `GIOStream` operation while there is a `GIOStream`, `GInputStream` or
46    /// `GOutputStream` operation in progress, and an application can’t start any
47    /// `GInputStream` or `GOutputStream` operation while there is a `GIOStream`
48    /// operation in progress.
49    ///
50    /// This is a product of individual stream operations being associated with a
51    /// given [type@GLib.MainContext] (the thread-default context at the time the
52    /// operation was started), rather than entire streams being associated with a
53    /// single `GMainContext`.
54    ///
55    /// GIO may run operations on `GIOStream`s from other (worker) threads, and this
56    /// may be exposed to application code in the behaviour of wrapper streams, such
57    /// as [`BufferedInputStream`][crate::BufferedInputStream] or [`TlsConnection`][crate::TlsConnection]. With such
58    /// wrapper APIs, application code may only run operations on the base (wrapped)
59    /// stream when the wrapper stream is idle. Note that the semantics of such
60    /// operations may not be well-defined due to the state the wrapper stream leaves
61    /// the base stream in (though they are guaranteed not to crash).
62    ///
63    /// This is an Abstract Base Class, you cannot instantiate it.
64    ///
65    /// ## Properties
66    ///
67    ///
68    /// #### `closed`
69    ///  Whether the stream is closed.
70    ///
71    /// Readable
72    ///
73    ///
74    /// #### `input-stream`
75    ///  The [`InputStream`][crate::InputStream] to read from.
76    ///
77    /// Readable
78    ///
79    ///
80    /// #### `output-stream`
81    ///  The [`OutputStream`][crate::OutputStream] to write to.
82    ///
83    /// Readable
84    ///
85    /// # Implements
86    ///
87    /// [`IOStreamExt`][trait@crate::prelude::IOStreamExt], [`trait@glib::ObjectExt`], [`IOStreamExtManual`][trait@crate::prelude::IOStreamExtManual]
88    #[doc(alias = "GIOStream")]
89    pub struct IOStream(Object<ffi::GIOStream, ffi::GIOStreamClass>);
90
91    match fn {
92        type_ => || ffi::g_io_stream_get_type(),
93    }
94}
95
96impl IOStream {
97    pub const NONE: Option<&'static IOStream> = None;
98}
99
100/// Trait containing all [`struct@IOStream`] methods.
101///
102/// # Implementors
103///
104/// [`FileIOStream`][struct@crate::FileIOStream], [`IOStream`][struct@crate::IOStream], [`SimpleIOStream`][struct@crate::SimpleIOStream], [`SocketConnection`][struct@crate::SocketConnection], [`TlsConnection`][struct@crate::TlsConnection]
105pub trait IOStreamExt: IsA<IOStream> + 'static {
106    /// Clears the pending flag on @self.
107    #[doc(alias = "g_io_stream_clear_pending")]
108    fn clear_pending(&self) {
109        unsafe {
110            ffi::g_io_stream_clear_pending(self.as_ref().to_glib_none().0);
111        }
112    }
113
114    /// Closes the stream, releasing resources related to it. This will also
115    /// close the individual input and output streams, if they are not already
116    /// closed.
117    ///
118    /// Once the stream is closed, all other operations will return
119    /// [`IOErrorEnum::Closed`][crate::IOErrorEnum::Closed]. Closing a stream multiple times will not
120    /// return an error.
121    ///
122    /// Closing a stream will automatically flush any outstanding buffers
123    /// in the stream.
124    ///
125    /// Streams will be automatically closed when the last reference
126    /// is dropped, but you might want to call this function to make sure
127    /// resources are released as early as possible.
128    ///
129    /// Some streams might keep the backing store of the stream (e.g. a file
130    /// descriptor) open after the stream is closed. See the documentation for
131    /// the individual stream for details.
132    ///
133    /// On failure the first error that happened will be reported, but the
134    /// close operation will finish as much as possible. A stream that failed
135    /// to close will still return [`IOErrorEnum::Closed`][crate::IOErrorEnum::Closed] for all operations.
136    /// Still, it is important to check and report the error to the user,
137    /// otherwise there might be a loss of data as all data might not be written.
138    ///
139    /// If @cancellable is not NULL, then the operation can be cancelled by
140    /// triggering the cancellable object from another thread. If the operation
141    /// was cancelled, the error [`IOErrorEnum::Cancelled`][crate::IOErrorEnum::Cancelled] will be returned.
142    /// Cancelling a close will still leave the stream closed, but some streams
143    /// can use a faster close that doesn't block to e.g. check errors.
144    ///
145    /// The default implementation of this method just calls close on the
146    /// individual input/output streams.
147    /// ## `cancellable`
148    /// optional #GCancellable object, [`None`] to ignore
149    ///
150    /// # Returns
151    ///
152    /// [`true`] on success, [`false`] on failure
153    #[doc(alias = "g_io_stream_close")]
154    fn close(&self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<(), glib::Error> {
155        unsafe {
156            let mut error = std::ptr::null_mut();
157            let is_ok = ffi::g_io_stream_close(
158                self.as_ref().to_glib_none().0,
159                cancellable.map(|p| p.as_ref()).to_glib_none().0,
160                &mut error,
161            );
162            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
163            if error.is_null() {
164                Ok(())
165            } else {
166                Err(from_glib_full(error))
167            }
168        }
169    }
170
171    /// Requests an asynchronous close of the stream, releasing resources
172    /// related to it. When the operation is finished @callback will be
173    /// called. You can then call g_io_stream_close_finish() to get
174    /// the result of the operation.
175    ///
176    /// For behaviour details see g_io_stream_close().
177    ///
178    /// The asynchronous methods have a default fallback that uses threads
179    /// to implement asynchronicity, so they are optional for inheriting
180    /// classes. However, if you override one you must override all.
181    /// ## `io_priority`
182    /// the io priority of the request
183    /// ## `cancellable`
184    /// optional cancellable object
185    /// ## `callback`
186    /// a #GAsyncReadyCallback
187    ///   to call when the request is satisfied
188    #[doc(alias = "g_io_stream_close_async")]
189    fn close_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
190        &self,
191        io_priority: glib::Priority,
192        cancellable: Option<&impl IsA<Cancellable>>,
193        callback: P,
194    ) {
195        let main_context = glib::MainContext::ref_thread_default();
196        let is_main_context_owner = main_context.is_owner();
197        let has_acquired_main_context = (!is_main_context_owner)
198            .then(|| main_context.acquire().ok())
199            .flatten();
200        assert!(
201            is_main_context_owner || has_acquired_main_context.is_some(),
202            "Async operations only allowed if the thread is owning the MainContext"
203        );
204
205        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
206            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
207        unsafe extern "C" fn close_async_trampoline<
208            P: FnOnce(Result<(), glib::Error>) + 'static,
209        >(
210            _source_object: *mut glib::gobject_ffi::GObject,
211            res: *mut crate::ffi::GAsyncResult,
212            user_data: glib::ffi::gpointer,
213        ) {
214            unsafe {
215                let mut error = std::ptr::null_mut();
216                ffi::g_io_stream_close_finish(_source_object as *mut _, res, &mut error);
217                let result = if error.is_null() {
218                    Ok(())
219                } else {
220                    Err(from_glib_full(error))
221                };
222                let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
223                    Box_::from_raw(user_data as *mut _);
224                let callback: P = callback.into_inner();
225                callback(result);
226            }
227        }
228        let callback = close_async_trampoline::<P>;
229        unsafe {
230            ffi::g_io_stream_close_async(
231                self.as_ref().to_glib_none().0,
232                io_priority.into_glib(),
233                cancellable.map(|p| p.as_ref()).to_glib_none().0,
234                Some(callback),
235                Box_::into_raw(user_data) as *mut _,
236            );
237        }
238    }
239
240    fn close_future(
241        &self,
242        io_priority: glib::Priority,
243    ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
244        Box_::pin(crate::GioFuture::new(
245            self,
246            move |obj, cancellable, send| {
247                obj.close_async(io_priority, Some(cancellable), move |res| {
248                    send.resolve(res);
249                });
250            },
251        ))
252    }
253
254    /// Gets the input stream for this object. This is used
255    /// for reading.
256    ///
257    /// # Returns
258    ///
259    /// a #GInputStream, owned by the #GIOStream.
260    /// Do not free.
261    #[doc(alias = "g_io_stream_get_input_stream")]
262    #[doc(alias = "get_input_stream")]
263    #[doc(alias = "input-stream")]
264    fn input_stream(&self) -> InputStream {
265        unsafe {
266            from_glib_none(ffi::g_io_stream_get_input_stream(
267                self.as_ref().to_glib_none().0,
268            ))
269        }
270    }
271
272    /// Gets the output stream for this object. This is used for
273    /// writing.
274    ///
275    /// # Returns
276    ///
277    /// a #GOutputStream, owned by the #GIOStream.
278    /// Do not free.
279    #[doc(alias = "g_io_stream_get_output_stream")]
280    #[doc(alias = "get_output_stream")]
281    #[doc(alias = "output-stream")]
282    fn output_stream(&self) -> OutputStream {
283        unsafe {
284            from_glib_none(ffi::g_io_stream_get_output_stream(
285                self.as_ref().to_glib_none().0,
286            ))
287        }
288    }
289
290    /// Checks if a stream has pending actions.
291    ///
292    /// # Returns
293    ///
294    /// [`true`] if @self has pending actions.
295    #[doc(alias = "g_io_stream_has_pending")]
296    fn has_pending(&self) -> bool {
297        unsafe { from_glib(ffi::g_io_stream_has_pending(self.as_ref().to_glib_none().0)) }
298    }
299
300    /// Checks if a stream is closed.
301    ///
302    /// # Returns
303    ///
304    /// [`true`] if the stream is closed.
305    #[doc(alias = "g_io_stream_is_closed")]
306    #[doc(alias = "closed")]
307    fn is_closed(&self) -> bool {
308        unsafe { from_glib(ffi::g_io_stream_is_closed(self.as_ref().to_glib_none().0)) }
309    }
310
311    /// Sets @self to have actions pending. If the pending flag is
312    /// already set or @self is closed, it will return [`false`] and set
313    /// @error.
314    ///
315    /// # Returns
316    ///
317    /// [`true`] if pending was previously unset and is now set.
318    #[doc(alias = "g_io_stream_set_pending")]
319    fn set_pending(&self) -> Result<(), glib::Error> {
320        unsafe {
321            let mut error = std::ptr::null_mut();
322            let is_ok = ffi::g_io_stream_set_pending(self.as_ref().to_glib_none().0, &mut error);
323            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
324            if error.is_null() {
325                Ok(())
326            } else {
327                Err(from_glib_full(error))
328            }
329        }
330    }
331
332    #[doc(alias = "closed")]
333    fn connect_closed_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
334        unsafe extern "C" fn notify_closed_trampoline<P: IsA<IOStream>, F: Fn(&P) + 'static>(
335            this: *mut ffi::GIOStream,
336            _param_spec: glib::ffi::gpointer,
337            f: glib::ffi::gpointer,
338        ) {
339            unsafe {
340                let f: &F = &*(f as *const F);
341                f(IOStream::from_glib_borrow(this).unsafe_cast_ref())
342            }
343        }
344        unsafe {
345            let f: Box_<F> = Box_::new(f);
346            connect_raw(
347                self.as_ptr() as *mut _,
348                c"notify::closed".as_ptr() as *const _,
349                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
350                    notify_closed_trampoline::<Self, F> as *const (),
351                )),
352                Box_::into_raw(f),
353            )
354        }
355    }
356}
357
358impl<O: IsA<IOStream>> IOStreamExt for O {}