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::{ffi, AsyncResult, Cancellable, InputStream, OutputStream};
6use glib::{
7    prelude::*,
8    signal::{connect_raw, SignalHandlerId},
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            let mut error = std::ptr::null_mut();
215            let _ = ffi::g_io_stream_close_finish(_source_object as *mut _, res, &mut error);
216            let result = if error.is_null() {
217                Ok(())
218            } else {
219                Err(from_glib_full(error))
220            };
221            let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
222                Box_::from_raw(user_data as *mut _);
223            let callback: P = callback.into_inner();
224            callback(result);
225        }
226        let callback = close_async_trampoline::<P>;
227        unsafe {
228            ffi::g_io_stream_close_async(
229                self.as_ref().to_glib_none().0,
230                io_priority.into_glib(),
231                cancellable.map(|p| p.as_ref()).to_glib_none().0,
232                Some(callback),
233                Box_::into_raw(user_data) as *mut _,
234            );
235        }
236    }
237
238    fn close_future(
239        &self,
240        io_priority: glib::Priority,
241    ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
242        Box_::pin(crate::GioFuture::new(
243            self,
244            move |obj, cancellable, send| {
245                obj.close_async(io_priority, Some(cancellable), move |res| {
246                    send.resolve(res);
247                });
248            },
249        ))
250    }
251
252    /// Gets the input stream for this object. This is used
253    /// for reading.
254    ///
255    /// # Returns
256    ///
257    /// a #GInputStream, owned by the #GIOStream.
258    /// Do not free.
259    #[doc(alias = "g_io_stream_get_input_stream")]
260    #[doc(alias = "get_input_stream")]
261    #[doc(alias = "input-stream")]
262    fn input_stream(&self) -> InputStream {
263        unsafe {
264            from_glib_none(ffi::g_io_stream_get_input_stream(
265                self.as_ref().to_glib_none().0,
266            ))
267        }
268    }
269
270    /// Gets the output stream for this object. This is used for
271    /// writing.
272    ///
273    /// # Returns
274    ///
275    /// a #GOutputStream, owned by the #GIOStream.
276    /// Do not free.
277    #[doc(alias = "g_io_stream_get_output_stream")]
278    #[doc(alias = "get_output_stream")]
279    #[doc(alias = "output-stream")]
280    fn output_stream(&self) -> OutputStream {
281        unsafe {
282            from_glib_none(ffi::g_io_stream_get_output_stream(
283                self.as_ref().to_glib_none().0,
284            ))
285        }
286    }
287
288    /// Checks if a stream has pending actions.
289    ///
290    /// # Returns
291    ///
292    /// [`true`] if @self has pending actions.
293    #[doc(alias = "g_io_stream_has_pending")]
294    fn has_pending(&self) -> bool {
295        unsafe { from_glib(ffi::g_io_stream_has_pending(self.as_ref().to_glib_none().0)) }
296    }
297
298    /// Checks if a stream is closed.
299    ///
300    /// # Returns
301    ///
302    /// [`true`] if the stream is closed.
303    #[doc(alias = "g_io_stream_is_closed")]
304    #[doc(alias = "closed")]
305    fn is_closed(&self) -> bool {
306        unsafe { from_glib(ffi::g_io_stream_is_closed(self.as_ref().to_glib_none().0)) }
307    }
308
309    /// Sets @self to have actions pending. If the pending flag is
310    /// already set or @self is closed, it will return [`false`] and set
311    /// @error.
312    ///
313    /// # Returns
314    ///
315    /// [`true`] if pending was previously unset and is now set.
316    #[doc(alias = "g_io_stream_set_pending")]
317    fn set_pending(&self) -> Result<(), glib::Error> {
318        unsafe {
319            let mut error = std::ptr::null_mut();
320            let is_ok = ffi::g_io_stream_set_pending(self.as_ref().to_glib_none().0, &mut error);
321            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
322            if error.is_null() {
323                Ok(())
324            } else {
325                Err(from_glib_full(error))
326            }
327        }
328    }
329
330    #[doc(alias = "closed")]
331    fn connect_closed_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
332        unsafe extern "C" fn notify_closed_trampoline<P: IsA<IOStream>, F: Fn(&P) + 'static>(
333            this: *mut ffi::GIOStream,
334            _param_spec: glib::ffi::gpointer,
335            f: glib::ffi::gpointer,
336        ) {
337            let f: &F = &*(f as *const F);
338            f(IOStream::from_glib_borrow(this).unsafe_cast_ref())
339        }
340        unsafe {
341            let f: Box_<F> = Box_::new(f);
342            connect_raw(
343                self.as_ptr() as *mut _,
344                c"notify::closed".as_ptr() as *const _,
345                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
346                    notify_closed_trampoline::<Self, F> as *const (),
347                )),
348                Box_::into_raw(f),
349            )
350        }
351    }
352}
353
354impl<O: IsA<IOStream>> IOStreamExt for O {}