gio/
data_input_stream.rs

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