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