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