1use 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")]
32 fn read_line<P: IsA<Cancellable>>(
33 &self,
34 cancellable: Option<&P>,
35 ) -> Result<glib::collections::Slice<u8>, glib::Error> {
36 unsafe {
37 let mut length = mem::MaybeUninit::uninit();
38 let mut error = ptr::null_mut();
39 let ret = ffi::g_data_input_stream_read_line(
40 self.as_ref().to_glib_none().0,
41 length.as_mut_ptr(),
42 cancellable.map(|p| p.as_ref()).to_glib_none().0,
43 &mut error,
44 );
45 let length = length.assume_init();
46 if error.is_null() {
47 Ok(FromGlibContainer::from_glib_full_num(ret, length))
48 } else {
49 Err(from_glib_full(error))
50 }
51 }
52 }
53
54 #[doc(alias = "g_data_input_stream_read_line_async")]
67 fn read_line_async<
68 P: IsA<Cancellable>,
69 Q: FnOnce(Result<glib::collections::Slice<u8>, glib::Error>) + 'static,
70 >(
71 &self,
72 io_priority: glib::Priority,
73 cancellable: Option<&P>,
74 callback: Q,
75 ) {
76 let main_context = glib::MainContext::ref_thread_default();
77 let is_main_context_owner = main_context.is_owner();
78 let has_acquired_main_context = (!is_main_context_owner)
79 .then(|| main_context.acquire().ok())
80 .flatten();
81 assert!(
82 is_main_context_owner || has_acquired_main_context.is_some(),
83 "Async operations only allowed if the thread is owning the MainContext"
84 );
85
86 let user_data: Box_<glib::thread_guard::ThreadGuard<Q>> =
87 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
88 unsafe extern "C" fn read_line_async_trampoline<
89 Q: FnOnce(Result<glib::collections::Slice<u8>, glib::Error>) + 'static,
90 >(
91 _source_object: *mut glib::gobject_ffi::GObject,
92 res: *mut ffi::GAsyncResult,
93 user_data: glib::ffi::gpointer,
94 ) {
95 let mut error = ptr::null_mut();
96 let mut length = mem::MaybeUninit::uninit();
97 let ret = ffi::g_data_input_stream_read_line_finish(
98 _source_object as *mut _,
99 res,
100 length.as_mut_ptr(),
101 &mut error,
102 );
103 let length = length.assume_init();
104 let result = if error.is_null() {
105 Ok(FromGlibContainer::from_glib_full_num(ret, length))
106 } else {
107 Err(from_glib_full(error))
108 };
109 let callback: Box_<glib::thread_guard::ThreadGuard<Q>> =
110 Box_::from_raw(user_data as *mut _);
111 let callback = callback.into_inner();
112 callback(result);
113 }
114 let callback = read_line_async_trampoline::<Q>;
115 unsafe {
116 ffi::g_data_input_stream_read_line_async(
117 self.as_ref().to_glib_none().0,
118 io_priority.into_glib(),
119 cancellable.map(|p| p.as_ref()).to_glib_none().0,
120 Some(callback),
121 Box_::into_raw(user_data) as *mut _,
122 );
123 }
124 }
125
126 fn read_line_future(
127 &self,
128 io_priority: glib::Priority,
129 ) -> Pin<
130 Box_<
131 dyn std::future::Future<Output = Result<glib::collections::Slice<u8>, glib::Error>>
132 + 'static,
133 >,
134 > {
135 Box_::pin(crate::GioFuture::new(
136 self,
137 move |obj, cancellable, send| {
138 obj.read_line_async(io_priority, Some(cancellable), move |res| {
139 send.resolve(res);
140 });
141 },
142 ))
143 }
144
145 #[doc(alias = "g_data_input_stream_read_line_utf8")]
166 fn read_line_utf8<P: IsA<Cancellable>>(
167 &self,
168 cancellable: Option<&P>,
169 ) -> Result<Option<GString>, glib::Error> {
170 unsafe {
171 let mut error = ptr::null_mut();
172 let ret = ffi::g_data_input_stream_read_line_utf8(
173 self.as_ref().to_glib_none().0,
174 ptr::null_mut(),
175 cancellable.map(|p| p.as_ref()).to_glib_none().0,
176 &mut error,
177 );
178 if error.is_null() {
179 Ok(from_glib_full(ret))
180 } else {
181 Err(from_glib_full(error))
182 }
183 }
184 }
185
186 fn read_line_utf8_async<
187 P: IsA<Cancellable>,
188 Q: FnOnce(Result<Option<GString>, glib::Error>) + 'static,
189 >(
190 &self,
191 io_priority: glib::Priority,
192 cancellable: Option<&P>,
193 callback: Q,
194 ) {
195 let main_context = glib::MainContext::ref_thread_default();
196 let is_main_context_owner = main_context.is_owner();
197 let has_acquired_main_context = (!is_main_context_owner)
198 .then(|| main_context.acquire().ok())
199 .flatten();
200 assert!(
201 is_main_context_owner || has_acquired_main_context.is_some(),
202 "Async operations only allowed if the thread is owning the MainContext"
203 );
204
205 let user_data: Box_<glib::thread_guard::ThreadGuard<Q>> =
206 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
207 unsafe extern "C" fn read_line_async_trampoline<
208 Q: FnOnce(Result<Option<GString>, glib::Error>) + 'static,
209 >(
210 _source_object: *mut glib::gobject_ffi::GObject,
211 res: *mut ffi::GAsyncResult,
212 user_data: glib::ffi::gpointer,
213 ) {
214 let mut error = ptr::null_mut();
215 let ret = ffi::g_data_input_stream_read_line_finish(
216 _source_object as *mut _,
217 res,
218 ptr::null_mut(),
219 &mut error,
220 );
221 let result = if error.is_null() {
222 Ok(from_glib_full(ret))
223 } else {
224 Err(from_glib_full(error))
225 };
226 let callback: Box_<glib::thread_guard::ThreadGuard<Q>> =
227 Box_::from_raw(user_data as *mut _);
228 let callback = callback.into_inner();
229 callback(result);
230 }
231 let callback = read_line_async_trampoline::<Q>;
232 unsafe {
233 ffi::g_data_input_stream_read_line_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 read_line_utf8_future(
244 &self,
245 io_priority: glib::Priority,
246 ) -> Pin<Box_<dyn std::future::Future<Output = Result<Option<GString>, glib::Error>> + 'static>>
247 {
248 Box_::pin(crate::GioFuture::new(
249 self,
250 move |obj, cancellable, send| {
251 obj.read_line_utf8_async(io_priority, Some(cancellable), move |res| {
252 send.resolve(res);
253 });
254 },
255 ))
256 }
257
258 #[doc(alias = "g_data_input_stream_read_upto")]
288 fn read_upto<P: IsA<Cancellable>>(
289 &self,
290 stop_chars: &[u8],
291 cancellable: Option<&P>,
292 ) -> Result<glib::collections::Slice<u8>, glib::Error> {
293 let stop_chars_len = stop_chars.len() as isize;
294 unsafe {
295 let mut error = ptr::null_mut();
296 let mut length = mem::MaybeUninit::uninit();
297 let ret = ffi::g_data_input_stream_read_upto(
298 self.as_ref().to_glib_none().0,
299 stop_chars.to_glib_none().0 as *const _,
300 stop_chars_len,
301 length.as_mut_ptr(),
302 cancellable.map(|p| p.as_ref()).to_glib_none().0,
303 &mut error,
304 );
305 if error.is_null() {
306 let length = length.assume_init();
307 Ok(FromGlibContainer::from_glib_full_num(
308 ret as *mut u8,
309 length,
310 ))
311 } else {
312 Err(from_glib_full(error))
313 }
314 }
315 }
316
317 #[doc(alias = "g_data_input_stream_read_upto_async")]
343 fn read_upto_async<
344 P: IsA<Cancellable>,
345 Q: FnOnce(Result<glib::collections::Slice<u8>, glib::Error>) + 'static,
346 >(
347 &self,
348 stop_chars: &[u8],
349 io_priority: glib::Priority,
350 cancellable: Option<&P>,
351 callback: Q,
352 ) {
353 let main_context = glib::MainContext::ref_thread_default();
354 let is_main_context_owner = main_context.is_owner();
355 let has_acquired_main_context = (!is_main_context_owner)
356 .then(|| main_context.acquire().ok())
357 .flatten();
358 assert!(
359 is_main_context_owner || has_acquired_main_context.is_some(),
360 "Async operations only allowed if the thread is owning the MainContext"
361 );
362
363 let stop_chars_len = stop_chars.len() as isize;
364 let user_data: Box_<glib::thread_guard::ThreadGuard<Q>> =
365 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
366 unsafe extern "C" fn read_upto_async_trampoline<
367 Q: FnOnce(Result<glib::collections::Slice<u8>, glib::Error>) + 'static,
368 >(
369 _source_object: *mut glib::gobject_ffi::GObject,
370 res: *mut ffi::GAsyncResult,
371 user_data: glib::ffi::gpointer,
372 ) {
373 let mut error = ptr::null_mut();
374 let mut length = mem::MaybeUninit::uninit();
375 let ret = ffi::g_data_input_stream_read_upto_finish(
376 _source_object as *mut _,
377 res,
378 length.as_mut_ptr(),
379 &mut error,
380 );
381 let result = if error.is_null() {
382 let length = length.assume_init();
383 Ok(FromGlibContainer::from_glib_full_num(
384 ret as *mut u8,
385 length,
386 ))
387 } else {
388 Err(from_glib_full(error))
389 };
390 let callback: Box_<glib::thread_guard::ThreadGuard<Q>> =
391 Box_::from_raw(user_data as *mut _);
392 let callback = callback.into_inner();
393 callback(result);
394 }
395 let callback = read_upto_async_trampoline::<Q>;
396 unsafe {
397 ffi::g_data_input_stream_read_upto_async(
398 self.as_ref().to_glib_none().0,
399 stop_chars.to_glib_none().0 as *const _,
400 stop_chars_len,
401 io_priority.into_glib(),
402 cancellable.map(|p| p.as_ref()).to_glib_none().0,
403 Some(callback),
404 Box_::into_raw(user_data) as *mut _,
405 );
406 }
407 }
408
409 fn read_upto_future(
410 &self,
411 stop_chars: &[u8],
412 io_priority: glib::Priority,
413 ) -> Pin<
414 Box_<
415 dyn std::future::Future<Output = Result<glib::collections::Slice<u8>, glib::Error>>
416 + 'static,
417 >,
418 > {
419 let stop_chars = Vec::from(stop_chars);
420 Box_::pin(crate::GioFuture::new(
421 self,
422 move |obj, cancellable, send| {
423 obj.read_upto_async(&stop_chars, io_priority, Some(cancellable), move |res| {
424 send.resolve(res);
425 });
426 },
427 ))
428 }
429}
430
431impl<O: IsA<DataInputStream>> DataInputStreamExtManual for O {}