1use crate::{AsyncResult, Cancellable, InputStream, OutputStreamSpliceFlags, ffi};
6use glib::{prelude::*, translate::*};
7use std::{boxed::Box as Box_, pin::Pin};
8
9glib::wrapper! {
10 #[doc(alias = "GOutputStream")]
11 pub struct OutputStream(Object<ffi::GOutputStream, ffi::GOutputStreamClass>);
12
13 match fn {
14 type_ => || ffi::g_output_stream_get_type(),
15 }
16}
17
18impl OutputStream {
19 pub const NONE: Option<&'static OutputStream> = None;
20}
21
22pub trait OutputStreamExt: IsA<OutputStream> + 'static {
23 #[doc(alias = "g_output_stream_clear_pending")]
24 fn clear_pending(&self) {
25 unsafe {
26 ffi::g_output_stream_clear_pending(self.as_ref().to_glib_none().0);
27 }
28 }
29
30 #[doc(alias = "g_output_stream_close")]
31 fn close(&self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<(), glib::Error> {
32 unsafe {
33 let mut error = std::ptr::null_mut();
34 let is_ok = ffi::g_output_stream_close(
35 self.as_ref().to_glib_none().0,
36 cancellable.map(|p| p.as_ref()).to_glib_none().0,
37 &mut error,
38 );
39 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
40 if error.is_null() {
41 Ok(())
42 } else {
43 Err(from_glib_full(error))
44 }
45 }
46 }
47
48 #[doc(alias = "g_output_stream_close_async")]
49 fn close_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
50 &self,
51 io_priority: glib::Priority,
52 cancellable: Option<&impl IsA<Cancellable>>,
53 callback: P,
54 ) {
55 let main_context = glib::MainContext::ref_thread_default();
56 let is_main_context_owner = main_context.is_owner();
57 let has_acquired_main_context = (!is_main_context_owner)
58 .then(|| main_context.acquire().ok())
59 .flatten();
60 assert!(
61 is_main_context_owner || has_acquired_main_context.is_some(),
62 "Async operations only allowed if the thread is owning the MainContext"
63 );
64
65 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
66 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
67 unsafe extern "C" fn close_async_trampoline<
68 P: FnOnce(Result<(), glib::Error>) + 'static,
69 >(
70 _source_object: *mut glib::gobject_ffi::GObject,
71 res: *mut crate::ffi::GAsyncResult,
72 user_data: glib::ffi::gpointer,
73 ) {
74 unsafe {
75 let mut error = std::ptr::null_mut();
76 ffi::g_output_stream_close_finish(_source_object as *mut _, res, &mut error);
77 let result = if error.is_null() {
78 Ok(())
79 } else {
80 Err(from_glib_full(error))
81 };
82 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
83 Box_::from_raw(user_data as *mut _);
84 let callback: P = callback.into_inner();
85 callback(result);
86 }
87 }
88 let callback = close_async_trampoline::<P>;
89 unsafe {
90 ffi::g_output_stream_close_async(
91 self.as_ref().to_glib_none().0,
92 io_priority.into_glib(),
93 cancellable.map(|p| p.as_ref()).to_glib_none().0,
94 Some(callback),
95 Box_::into_raw(user_data) as *mut _,
96 );
97 }
98 }
99
100 fn close_future(
101 &self,
102 io_priority: glib::Priority,
103 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
104 Box_::pin(crate::GioFuture::new(
105 self,
106 move |obj, cancellable, send| {
107 obj.close_async(io_priority, Some(cancellable), move |res| {
108 send.resolve(res);
109 });
110 },
111 ))
112 }
113
114 #[doc(alias = "g_output_stream_flush")]
115 fn flush(&self, cancellable: Option<&impl IsA<Cancellable>>) -> Result<(), glib::Error> {
116 unsafe {
117 let mut error = std::ptr::null_mut();
118 let is_ok = ffi::g_output_stream_flush(
119 self.as_ref().to_glib_none().0,
120 cancellable.map(|p| p.as_ref()).to_glib_none().0,
121 &mut error,
122 );
123 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
124 if error.is_null() {
125 Ok(())
126 } else {
127 Err(from_glib_full(error))
128 }
129 }
130 }
131
132 #[doc(alias = "g_output_stream_flush_async")]
133 fn flush_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
134 &self,
135 io_priority: glib::Priority,
136 cancellable: Option<&impl IsA<Cancellable>>,
137 callback: P,
138 ) {
139 let main_context = glib::MainContext::ref_thread_default();
140 let is_main_context_owner = main_context.is_owner();
141 let has_acquired_main_context = (!is_main_context_owner)
142 .then(|| main_context.acquire().ok())
143 .flatten();
144 assert!(
145 is_main_context_owner || has_acquired_main_context.is_some(),
146 "Async operations only allowed if the thread is owning the MainContext"
147 );
148
149 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
150 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
151 unsafe extern "C" fn flush_async_trampoline<
152 P: FnOnce(Result<(), glib::Error>) + 'static,
153 >(
154 _source_object: *mut glib::gobject_ffi::GObject,
155 res: *mut crate::ffi::GAsyncResult,
156 user_data: glib::ffi::gpointer,
157 ) {
158 unsafe {
159 let mut error = std::ptr::null_mut();
160 ffi::g_output_stream_flush_finish(_source_object as *mut _, res, &mut error);
161 let result = if error.is_null() {
162 Ok(())
163 } else {
164 Err(from_glib_full(error))
165 };
166 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
167 Box_::from_raw(user_data as *mut _);
168 let callback: P = callback.into_inner();
169 callback(result);
170 }
171 }
172 let callback = flush_async_trampoline::<P>;
173 unsafe {
174 ffi::g_output_stream_flush_async(
175 self.as_ref().to_glib_none().0,
176 io_priority.into_glib(),
177 cancellable.map(|p| p.as_ref()).to_glib_none().0,
178 Some(callback),
179 Box_::into_raw(user_data) as *mut _,
180 );
181 }
182 }
183
184 fn flush_future(
185 &self,
186 io_priority: glib::Priority,
187 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
188 Box_::pin(crate::GioFuture::new(
189 self,
190 move |obj, cancellable, send| {
191 obj.flush_async(io_priority, Some(cancellable), move |res| {
192 send.resolve(res);
193 });
194 },
195 ))
196 }
197
198 #[doc(alias = "g_output_stream_has_pending")]
199 fn has_pending(&self) -> bool {
200 unsafe {
201 from_glib(ffi::g_output_stream_has_pending(
202 self.as_ref().to_glib_none().0,
203 ))
204 }
205 }
206
207 #[doc(alias = "g_output_stream_is_closed")]
208 fn is_closed(&self) -> bool {
209 unsafe {
210 from_glib(ffi::g_output_stream_is_closed(
211 self.as_ref().to_glib_none().0,
212 ))
213 }
214 }
215
216 #[doc(alias = "g_output_stream_is_closing")]
217 fn is_closing(&self) -> bool {
218 unsafe {
219 from_glib(ffi::g_output_stream_is_closing(
220 self.as_ref().to_glib_none().0,
221 ))
222 }
223 }
224
225 #[doc(alias = "g_output_stream_set_pending")]
231 fn set_pending(&self) -> Result<(), glib::Error> {
232 unsafe {
233 let mut error = std::ptr::null_mut();
234 let is_ok =
235 ffi::g_output_stream_set_pending(self.as_ref().to_glib_none().0, &mut error);
236 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
237 if error.is_null() {
238 Ok(())
239 } else {
240 Err(from_glib_full(error))
241 }
242 }
243 }
244
245 #[doc(alias = "g_output_stream_splice")]
246 fn splice(
247 &self,
248 source: &impl IsA<InputStream>,
249 flags: OutputStreamSpliceFlags,
250 cancellable: Option<&impl IsA<Cancellable>>,
251 ) -> Result<isize, glib::Error> {
252 unsafe {
253 let mut error = std::ptr::null_mut();
254 let ret = ffi::g_output_stream_splice(
255 self.as_ref().to_glib_none().0,
256 source.as_ref().to_glib_none().0,
257 flags.into_glib(),
258 cancellable.map(|p| p.as_ref()).to_glib_none().0,
259 &mut error,
260 );
261 if error.is_null() {
262 Ok(ret)
263 } else {
264 Err(from_glib_full(error))
265 }
266 }
267 }
268
269 #[doc(alias = "g_output_stream_splice_async")]
270 fn splice_async<P: FnOnce(Result<isize, glib::Error>) + 'static>(
271 &self,
272 source: &impl IsA<InputStream>,
273 flags: OutputStreamSpliceFlags,
274 io_priority: glib::Priority,
275 cancellable: Option<&impl IsA<Cancellable>>,
276 callback: P,
277 ) {
278 let main_context = glib::MainContext::ref_thread_default();
279 let is_main_context_owner = main_context.is_owner();
280 let has_acquired_main_context = (!is_main_context_owner)
281 .then(|| main_context.acquire().ok())
282 .flatten();
283 assert!(
284 is_main_context_owner || has_acquired_main_context.is_some(),
285 "Async operations only allowed if the thread is owning the MainContext"
286 );
287
288 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
289 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
290 unsafe extern "C" fn splice_async_trampoline<
291 P: FnOnce(Result<isize, glib::Error>) + 'static,
292 >(
293 _source_object: *mut glib::gobject_ffi::GObject,
294 res: *mut crate::ffi::GAsyncResult,
295 user_data: glib::ffi::gpointer,
296 ) {
297 unsafe {
298 let mut error = std::ptr::null_mut();
299 let ret =
300 ffi::g_output_stream_splice_finish(_source_object as *mut _, res, &mut error);
301 let result = if error.is_null() {
302 Ok(ret)
303 } else {
304 Err(from_glib_full(error))
305 };
306 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
307 Box_::from_raw(user_data as *mut _);
308 let callback: P = callback.into_inner();
309 callback(result);
310 }
311 }
312 let callback = splice_async_trampoline::<P>;
313 unsafe {
314 ffi::g_output_stream_splice_async(
315 self.as_ref().to_glib_none().0,
316 source.as_ref().to_glib_none().0,
317 flags.into_glib(),
318 io_priority.into_glib(),
319 cancellable.map(|p| p.as_ref()).to_glib_none().0,
320 Some(callback),
321 Box_::into_raw(user_data) as *mut _,
322 );
323 }
324 }
325
326 fn splice_future(
327 &self,
328 source: &(impl IsA<InputStream> + Clone + 'static),
329 flags: OutputStreamSpliceFlags,
330 io_priority: glib::Priority,
331 ) -> Pin<Box_<dyn std::future::Future<Output = Result<isize, glib::Error>> + 'static>> {
332 let source = source.clone();
333 Box_::pin(crate::GioFuture::new(
334 self,
335 move |obj, cancellable, send| {
336 obj.splice_async(&source, flags, io_priority, Some(cancellable), move |res| {
337 send.resolve(res);
338 });
339 },
340 ))
341 }
342
343 #[doc(alias = "g_output_stream_write")]
349 fn write(
350 &self,
351 buffer: &[u8],
352 cancellable: Option<&impl IsA<Cancellable>>,
353 ) -> Result<isize, glib::Error> {
354 let count = buffer.len() as _;
355 unsafe {
356 let mut error = std::ptr::null_mut();
357 let ret = ffi::g_output_stream_write(
358 self.as_ref().to_glib_none().0,
359 buffer.to_glib_none().0,
360 count,
361 cancellable.map(|p| p.as_ref()).to_glib_none().0,
362 &mut error,
363 );
364 if error.is_null() {
365 Ok(ret)
366 } else {
367 Err(from_glib_full(error))
368 }
369 }
370 }
371
372 #[doc(alias = "g_output_stream_write_bytes")]
373 fn write_bytes(
374 &self,
375 bytes: &glib::Bytes,
376 cancellable: Option<&impl IsA<Cancellable>>,
377 ) -> Result<isize, glib::Error> {
378 unsafe {
379 let mut error = std::ptr::null_mut();
380 let ret = ffi::g_output_stream_write_bytes(
381 self.as_ref().to_glib_none().0,
382 bytes.to_glib_none().0,
383 cancellable.map(|p| p.as_ref()).to_glib_none().0,
384 &mut error,
385 );
386 if error.is_null() {
387 Ok(ret)
388 } else {
389 Err(from_glib_full(error))
390 }
391 }
392 }
393
394 #[doc(alias = "g_output_stream_write_bytes_async")]
395 fn write_bytes_async<P: FnOnce(Result<isize, glib::Error>) + 'static>(
396 &self,
397 bytes: &glib::Bytes,
398 io_priority: glib::Priority,
399 cancellable: Option<&impl IsA<Cancellable>>,
400 callback: P,
401 ) {
402 let main_context = glib::MainContext::ref_thread_default();
403 let is_main_context_owner = main_context.is_owner();
404 let has_acquired_main_context = (!is_main_context_owner)
405 .then(|| main_context.acquire().ok())
406 .flatten();
407 assert!(
408 is_main_context_owner || has_acquired_main_context.is_some(),
409 "Async operations only allowed if the thread is owning the MainContext"
410 );
411
412 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
413 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
414 unsafe extern "C" fn write_bytes_async_trampoline<
415 P: FnOnce(Result<isize, glib::Error>) + 'static,
416 >(
417 _source_object: *mut glib::gobject_ffi::GObject,
418 res: *mut crate::ffi::GAsyncResult,
419 user_data: glib::ffi::gpointer,
420 ) {
421 unsafe {
422 let mut error = std::ptr::null_mut();
423 let ret = ffi::g_output_stream_write_bytes_finish(
424 _source_object as *mut _,
425 res,
426 &mut error,
427 );
428 let result = if error.is_null() {
429 Ok(ret)
430 } else {
431 Err(from_glib_full(error))
432 };
433 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
434 Box_::from_raw(user_data as *mut _);
435 let callback: P = callback.into_inner();
436 callback(result);
437 }
438 }
439 let callback = write_bytes_async_trampoline::<P>;
440 unsafe {
441 ffi::g_output_stream_write_bytes_async(
442 self.as_ref().to_glib_none().0,
443 bytes.to_glib_none().0,
444 io_priority.into_glib(),
445 cancellable.map(|p| p.as_ref()).to_glib_none().0,
446 Some(callback),
447 Box_::into_raw(user_data) as *mut _,
448 );
449 }
450 }
451
452 fn write_bytes_future(
453 &self,
454 bytes: &glib::Bytes,
455 io_priority: glib::Priority,
456 ) -> Pin<Box_<dyn std::future::Future<Output = Result<isize, glib::Error>> + 'static>> {
457 let bytes = bytes.clone();
458 Box_::pin(crate::GioFuture::new(
459 self,
460 move |obj, cancellable, send| {
461 obj.write_bytes_async(&bytes, io_priority, Some(cancellable), move |res| {
462 send.resolve(res);
463 });
464 },
465 ))
466 }
467}
468
469impl<O: IsA<OutputStream>> OutputStreamExt for O {}