1use crate::{ffi, AsyncResult, Cancellable};
6use glib::{prelude::*, translate::*};
7use std::{boxed::Box as Box_, pin::Pin};
8
9glib::wrapper! {
10 #[doc(alias = "GInputStream")]
11 pub struct InputStream(Object<ffi::GInputStream, ffi::GInputStreamClass>);
12
13 match fn {
14 type_ => || ffi::g_input_stream_get_type(),
15 }
16}
17
18impl InputStream {
19 pub const NONE: Option<&'static InputStream> = None;
20}
21
22mod sealed {
23 pub trait Sealed {}
24 impl<T: super::IsA<super::InputStream>> Sealed for T {}
25}
26
27pub trait InputStreamExt: IsA<InputStream> + sealed::Sealed + 'static {
28 #[doc(alias = "g_input_stream_clear_pending")]
29 fn clear_pending(&self) {
30 unsafe {
31 ffi::g_input_stream_clear_pending(self.as_ref().to_glib_none().0);
32 }
33 }
34
35 #[doc(alias = "g_input_stream_close")]
36 fn close(&self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<(), glib::Error> {
37 unsafe {
38 let mut error = std::ptr::null_mut();
39 let is_ok = ffi::g_input_stream_close(
40 self.as_ref().to_glib_none().0,
41 cancellable.map(|p| p.as_ref()).to_glib_none().0,
42 &mut error,
43 );
44 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
45 if error.is_null() {
46 Ok(())
47 } else {
48 Err(from_glib_full(error))
49 }
50 }
51 }
52
53 #[doc(alias = "g_input_stream_close_async")]
54 fn close_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
55 &self,
56 io_priority: glib::Priority,
57 cancellable: Option<&impl IsA<Cancellable>>,
58 callback: P,
59 ) {
60 let main_context = glib::MainContext::ref_thread_default();
61 let is_main_context_owner = main_context.is_owner();
62 let has_acquired_main_context = (!is_main_context_owner)
63 .then(|| main_context.acquire().ok())
64 .flatten();
65 assert!(
66 is_main_context_owner || has_acquired_main_context.is_some(),
67 "Async operations only allowed if the thread is owning the MainContext"
68 );
69
70 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
71 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
72 unsafe extern "C" fn close_async_trampoline<
73 P: FnOnce(Result<(), glib::Error>) + 'static,
74 >(
75 _source_object: *mut glib::gobject_ffi::GObject,
76 res: *mut crate::ffi::GAsyncResult,
77 user_data: glib::ffi::gpointer,
78 ) {
79 let mut error = std::ptr::null_mut();
80 ffi::g_input_stream_close_finish(_source_object as *mut _, res, &mut error);
81 let result = if error.is_null() {
82 Ok(())
83 } else {
84 Err(from_glib_full(error))
85 };
86 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
87 Box_::from_raw(user_data as *mut _);
88 let callback: P = callback.into_inner();
89 callback(result);
90 }
91 let callback = close_async_trampoline::<P>;
92 unsafe {
93 ffi::g_input_stream_close_async(
94 self.as_ref().to_glib_none().0,
95 io_priority.into_glib(),
96 cancellable.map(|p| p.as_ref()).to_glib_none().0,
97 Some(callback),
98 Box_::into_raw(user_data) as *mut _,
99 );
100 }
101 }
102
103 fn close_future(
104 &self,
105 io_priority: glib::Priority,
106 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
107 Box_::pin(crate::GioFuture::new(
108 self,
109 move |obj, cancellable, send| {
110 obj.close_async(io_priority, Some(cancellable), move |res| {
111 send.resolve(res);
112 });
113 },
114 ))
115 }
116
117 #[doc(alias = "g_input_stream_has_pending")]
118 fn has_pending(&self) -> bool {
119 unsafe {
120 from_glib(ffi::g_input_stream_has_pending(
121 self.as_ref().to_glib_none().0,
122 ))
123 }
124 }
125
126 #[doc(alias = "g_input_stream_is_closed")]
127 fn is_closed(&self) -> bool {
128 unsafe {
129 from_glib(ffi::g_input_stream_is_closed(
130 self.as_ref().to_glib_none().0,
131 ))
132 }
133 }
134
135 #[doc(alias = "g_input_stream_read_bytes")]
136 fn read_bytes(
137 &self,
138 count: usize,
139 cancellable: Option<&impl IsA<Cancellable>>,
140 ) -> Result<glib::Bytes, glib::Error> {
141 unsafe {
142 let mut error = std::ptr::null_mut();
143 let ret = ffi::g_input_stream_read_bytes(
144 self.as_ref().to_glib_none().0,
145 count,
146 cancellable.map(|p| p.as_ref()).to_glib_none().0,
147 &mut error,
148 );
149 if error.is_null() {
150 Ok(from_glib_full(ret))
151 } else {
152 Err(from_glib_full(error))
153 }
154 }
155 }
156
157 #[doc(alias = "g_input_stream_read_bytes_async")]
158 fn read_bytes_async<P: FnOnce(Result<glib::Bytes, glib::Error>) + 'static>(
159 &self,
160 count: usize,
161 io_priority: glib::Priority,
162 cancellable: Option<&impl IsA<Cancellable>>,
163 callback: P,
164 ) {
165 let main_context = glib::MainContext::ref_thread_default();
166 let is_main_context_owner = main_context.is_owner();
167 let has_acquired_main_context = (!is_main_context_owner)
168 .then(|| main_context.acquire().ok())
169 .flatten();
170 assert!(
171 is_main_context_owner || has_acquired_main_context.is_some(),
172 "Async operations only allowed if the thread is owning the MainContext"
173 );
174
175 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
176 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
177 unsafe extern "C" fn read_bytes_async_trampoline<
178 P: FnOnce(Result<glib::Bytes, glib::Error>) + 'static,
179 >(
180 _source_object: *mut glib::gobject_ffi::GObject,
181 res: *mut crate::ffi::GAsyncResult,
182 user_data: glib::ffi::gpointer,
183 ) {
184 let mut error = std::ptr::null_mut();
185 let ret =
186 ffi::g_input_stream_read_bytes_finish(_source_object as *mut _, res, &mut error);
187 let result = if error.is_null() {
188 Ok(from_glib_full(ret))
189 } else {
190 Err(from_glib_full(error))
191 };
192 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
193 Box_::from_raw(user_data as *mut _);
194 let callback: P = callback.into_inner();
195 callback(result);
196 }
197 let callback = read_bytes_async_trampoline::<P>;
198 unsafe {
199 ffi::g_input_stream_read_bytes_async(
200 self.as_ref().to_glib_none().0,
201 count,
202 io_priority.into_glib(),
203 cancellable.map(|p| p.as_ref()).to_glib_none().0,
204 Some(callback),
205 Box_::into_raw(user_data) as *mut _,
206 );
207 }
208 }
209
210 fn read_bytes_future(
211 &self,
212 count: usize,
213 io_priority: glib::Priority,
214 ) -> Pin<Box_<dyn std::future::Future<Output = Result<glib::Bytes, glib::Error>> + 'static>>
215 {
216 Box_::pin(crate::GioFuture::new(
217 self,
218 move |obj, cancellable, send| {
219 obj.read_bytes_async(count, io_priority, Some(cancellable), move |res| {
220 send.resolve(res);
221 });
222 },
223 ))
224 }
225
226 #[doc(alias = "g_input_stream_set_pending")]
227 fn set_pending(&self) -> Result<(), glib::Error> {
228 unsafe {
229 let mut error = std::ptr::null_mut();
230 let is_ok = ffi::g_input_stream_set_pending(self.as_ref().to_glib_none().0, &mut error);
231 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
232 if error.is_null() {
233 Ok(())
234 } else {
235 Err(from_glib_full(error))
236 }
237 }
238 }
239
240 #[doc(alias = "g_input_stream_skip")]
241 fn skip(
242 &self,
243 count: usize,
244 cancellable: Option<&impl IsA<Cancellable>>,
245 ) -> Result<isize, glib::Error> {
246 unsafe {
247 let mut error = std::ptr::null_mut();
248 let ret = ffi::g_input_stream_skip(
249 self.as_ref().to_glib_none().0,
250 count,
251 cancellable.map(|p| p.as_ref()).to_glib_none().0,
252 &mut error,
253 );
254 if error.is_null() {
255 Ok(ret)
256 } else {
257 Err(from_glib_full(error))
258 }
259 }
260 }
261
262 #[doc(alias = "g_input_stream_skip_async")]
263 fn skip_async<P: FnOnce(Result<isize, glib::Error>) + 'static>(
264 &self,
265 count: usize,
266 io_priority: glib::Priority,
267 cancellable: Option<&impl IsA<Cancellable>>,
268 callback: P,
269 ) {
270 let main_context = glib::MainContext::ref_thread_default();
271 let is_main_context_owner = main_context.is_owner();
272 let has_acquired_main_context = (!is_main_context_owner)
273 .then(|| main_context.acquire().ok())
274 .flatten();
275 assert!(
276 is_main_context_owner || has_acquired_main_context.is_some(),
277 "Async operations only allowed if the thread is owning the MainContext"
278 );
279
280 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
281 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
282 unsafe extern "C" fn skip_async_trampoline<
283 P: FnOnce(Result<isize, glib::Error>) + 'static,
284 >(
285 _source_object: *mut glib::gobject_ffi::GObject,
286 res: *mut crate::ffi::GAsyncResult,
287 user_data: glib::ffi::gpointer,
288 ) {
289 let mut error = std::ptr::null_mut();
290 let ret = ffi::g_input_stream_skip_finish(_source_object as *mut _, res, &mut error);
291 let result = if error.is_null() {
292 Ok(ret)
293 } else {
294 Err(from_glib_full(error))
295 };
296 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
297 Box_::from_raw(user_data as *mut _);
298 let callback: P = callback.into_inner();
299 callback(result);
300 }
301 let callback = skip_async_trampoline::<P>;
302 unsafe {
303 ffi::g_input_stream_skip_async(
304 self.as_ref().to_glib_none().0,
305 count,
306 io_priority.into_glib(),
307 cancellable.map(|p| p.as_ref()).to_glib_none().0,
308 Some(callback),
309 Box_::into_raw(user_data) as *mut _,
310 );
311 }
312 }
313
314 fn skip_future(
315 &self,
316 count: usize,
317 io_priority: glib::Priority,
318 ) -> Pin<Box_<dyn std::future::Future<Output = Result<isize, glib::Error>> + 'static>> {
319 Box_::pin(crate::GioFuture::new(
320 self,
321 move |obj, cancellable, send| {
322 obj.skip_async(count, io_priority, Some(cancellable), move |res| {
323 send.resolve(res);
324 });
325 },
326 ))
327 }
328}
329
330impl<O: IsA<InputStream>> InputStreamExt for O {}