1use 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 {}