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
100mod sealed {
101    pub trait Sealed {}
102    impl<T: super::IsA<super::IOStream>> Sealed for T {}
103}
104
105/// Trait containing all [`struct@IOStream`] methods.
106///
107/// # Implementors
108///
109/// [`FileIOStream`][struct@crate::FileIOStream], [`IOStream`][struct@crate::IOStream], [`SimpleIOStream`][struct@crate::SimpleIOStream], [`SocketConnection`][struct@crate::SocketConnection], [`TlsConnection`][struct@crate::TlsConnection]
110pub trait IOStreamExt: IsA<IOStream> + sealed::Sealed + 'static {
111    /// Clears the pending flag on @self.
112    #[doc(alias = "g_io_stream_clear_pending")]
113    fn clear_pending(&self) {
114        unsafe {
115            ffi::g_io_stream_clear_pending(self.as_ref().to_glib_none().0);
116        }
117    }
118
119    /// Closes the stream, releasing resources related to it. This will also
120    /// close the individual input and output streams, if they are not already
121    /// closed.
122    ///
123    /// Once the stream is closed, all other operations will return
124    /// [`IOErrorEnum::Closed`][crate::IOErrorEnum::Closed]. Closing a stream multiple times will not
125    /// return an error.
126    ///
127    /// Closing a stream will automatically flush any outstanding buffers
128    /// in the stream.
129    ///
130    /// Streams will be automatically closed when the last reference
131    /// is dropped, but you might want to call this function to make sure
132    /// resources are released as early as possible.
133    ///
134    /// Some streams might keep the backing store of the stream (e.g. a file
135    /// descriptor) open after the stream is closed. See the documentation for
136    /// the individual stream for details.
137    ///
138    /// On failure the first error that happened will be reported, but the
139    /// close operation will finish as much as possible. A stream that failed
140    /// to close will still return [`IOErrorEnum::Closed`][crate::IOErrorEnum::Closed] for all operations.
141    /// Still, it is important to check and report the error to the user,
142    /// otherwise there might be a loss of data as all data might not be written.
143    ///
144    /// If @cancellable is not NULL, then the operation can be cancelled by
145    /// triggering the cancellable object from another thread. If the operation
146    /// was cancelled, the error [`IOErrorEnum::Cancelled`][crate::IOErrorEnum::Cancelled] will be returned.
147    /// Cancelling a close will still leave the stream closed, but some streams
148    /// can use a faster close that doesn't block to e.g. check errors.
149    ///
150    /// The default implementation of this method just calls close on the
151    /// individual input/output streams.
152    /// ## `cancellable`
153    /// optional #GCancellable object, [`None`] to ignore
154    ///
155    /// # Returns
156    ///
157    /// [`true`] on success, [`false`] on failure
158    #[doc(alias = "g_io_stream_close")]
159    fn close(&self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<(), glib::Error> {
160        unsafe {
161            let mut error = std::ptr::null_mut();
162            let is_ok = ffi::g_io_stream_close(
163                self.as_ref().to_glib_none().0,
164                cancellable.map(|p| p.as_ref()).to_glib_none().0,
165                &mut error,
166            );
167            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
168            if error.is_null() {
169                Ok(())
170            } else {
171                Err(from_glib_full(error))
172            }
173        }
174    }
175
176    /// Requests an asynchronous close of the stream, releasing resources
177    /// related to it. When the operation is finished @callback will be
178    /// called. You can then call g_io_stream_close_finish() to get
179    /// the result of the operation.
180    ///
181    /// For behaviour details see g_io_stream_close().
182    ///
183    /// The asynchronous methods have a default fallback that uses threads
184    /// to implement asynchronicity, so they are optional for inheriting
185    /// classes. However, if you override one you must override all.
186    /// ## `io_priority`
187    /// the io priority of the request
188    /// ## `cancellable`
189    /// optional cancellable object
190    /// ## `callback`
191    /// a #GAsyncReadyCallback
192    ///   to call when the request is satisfied
193    #[doc(alias = "g_io_stream_close_async")]
194    fn close_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
195        &self,
196        io_priority: glib::Priority,
197        cancellable: Option<&impl IsA<Cancellable>>,
198        callback: P,
199    ) {
200        let main_context = glib::MainContext::ref_thread_default();
201        let is_main_context_owner = main_context.is_owner();
202        let has_acquired_main_context = (!is_main_context_owner)
203            .then(|| main_context.acquire().ok())
204            .flatten();
205        assert!(
206            is_main_context_owner || has_acquired_main_context.is_some(),
207            "Async operations only allowed if the thread is owning the MainContext"
208        );
209
210        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
211            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
212        unsafe extern "C" fn close_async_trampoline<
213            P: FnOnce(Result<(), glib::Error>) + 'static,
214        >(
215            _source_object: *mut glib::gobject_ffi::GObject,
216            res: *mut crate::ffi::GAsyncResult,
217            user_data: glib::ffi::gpointer,
218        ) {
219            let mut error = std::ptr::null_mut();
220            let _ = ffi::g_io_stream_close_finish(_source_object as *mut _, res, &mut error);
221            let result = if error.is_null() {
222                Ok(())
223            } else {
224                Err(from_glib_full(error))
225            };
226            let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
227                Box_::from_raw(user_data as *mut _);
228            let callback: P = callback.into_inner();
229            callback(result);
230        }
231        let callback = close_async_trampoline::<P>;
232        unsafe {
233            ffi::g_io_stream_close_async(
234                self.as_ref().to_glib_none().0,
235                io_priority.into_glib(),
236                cancellable.map(|p| p.as_ref()).to_glib_none().0,
237                Some(callback),
238                Box_::into_raw(user_data) as *mut _,
239            );
240        }
241    }
242
243    fn close_future(
244        &self,
245        io_priority: glib::Priority,
246    ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
247        Box_::pin(crate::GioFuture::new(
248            self,
249            move |obj, cancellable, send| {
250                obj.close_async(io_priority, Some(cancellable), move |res| {
251                    send.resolve(res);
252                });
253            },
254        ))
255    }
256
257    /// Gets the input stream for this object. This is used
258    /// for reading.
259    ///
260    /// # Returns
261    ///
262    /// a #GInputStream, owned by the #GIOStream.
263    /// Do not free.
264    #[doc(alias = "g_io_stream_get_input_stream")]
265    #[doc(alias = "get_input_stream")]
266    #[doc(alias = "input-stream")]
267    fn input_stream(&self) -> InputStream {
268        unsafe {
269            from_glib_none(ffi::g_io_stream_get_input_stream(
270                self.as_ref().to_glib_none().0,
271            ))
272        }
273    }
274
275    /// Gets the output stream for this object. This is used for
276    /// writing.
277    ///
278    /// # Returns
279    ///
280    /// a #GOutputStream, owned by the #GIOStream.
281    /// Do not free.
282    #[doc(alias = "g_io_stream_get_output_stream")]
283    #[doc(alias = "get_output_stream")]
284    #[doc(alias = "output-stream")]
285    fn output_stream(&self) -> OutputStream {
286        unsafe {
287            from_glib_none(ffi::g_io_stream_get_output_stream(
288                self.as_ref().to_glib_none().0,
289            ))
290        }
291    }
292
293    /// Checks if a stream has pending actions.
294    ///
295    /// # Returns
296    ///
297    /// [`true`] if @self has pending actions.
298    #[doc(alias = "g_io_stream_has_pending")]
299    fn has_pending(&self) -> bool {
300        unsafe { from_glib(ffi::g_io_stream_has_pending(self.as_ref().to_glib_none().0)) }
301    }
302
303    /// Checks if a stream is closed.
304    ///
305    /// # Returns
306    ///
307    /// [`true`] if the stream is closed.
308    #[doc(alias = "g_io_stream_is_closed")]
309    #[doc(alias = "closed")]
310    fn is_closed(&self) -> bool {
311        unsafe { from_glib(ffi::g_io_stream_is_closed(self.as_ref().to_glib_none().0)) }
312    }
313
314    /// Sets @self to have actions pending. If the pending flag is
315    /// already set or @self is closed, it will return [`false`] and set
316    /// @error.
317    ///
318    /// # Returns
319    ///
320    /// [`true`] if pending was previously unset and is now set.
321    #[doc(alias = "g_io_stream_set_pending")]
322    fn set_pending(&self) -> Result<(), glib::Error> {
323        unsafe {
324            let mut error = std::ptr::null_mut();
325            let is_ok = ffi::g_io_stream_set_pending(self.as_ref().to_glib_none().0, &mut error);
326            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
327            if error.is_null() {
328                Ok(())
329            } else {
330                Err(from_glib_full(error))
331            }
332        }
333    }
334
335    #[doc(alias = "closed")]
336    fn connect_closed_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
337        unsafe extern "C" fn notify_closed_trampoline<P: IsA<IOStream>, F: Fn(&P) + 'static>(
338            this: *mut ffi::GIOStream,
339            _param_spec: glib::ffi::gpointer,
340            f: glib::ffi::gpointer,
341        ) {
342            let f: &F = &*(f as *const F);
343            f(IOStream::from_glib_borrow(this).unsafe_cast_ref())
344        }
345        unsafe {
346            let f: Box_<F> = Box_::new(f);
347            connect_raw(
348                self.as_ptr() as *mut _,
349                b"notify::closed\0".as_ptr() as *const _,
350                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
351                    notify_closed_trampoline::<Self, F> as *const (),
352                )),
353                Box_::into_raw(f),
354            )
355        }
356    }
357}
358
359impl<O: IsA<IOStream>> IOStreamExt for O {}