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")]
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 {}