1use std::{io, mem, pin::Pin, ptr};
4
5use glib::{Priority, prelude::*, translate::*};
6
7#[cfg(feature = "v2_60")]
8use crate::OutputVector;
9use crate::{Cancellable, OutputStream, Seekable, error::to_std_io_result, ffi, prelude::*};
10
11pub trait OutputStreamExtManual: IsA<OutputStream> + Sized {
12 #[doc(alias = "g_output_stream_write_async")]
57 fn write_async<
58 B: AsRef<[u8]> + Send + 'static,
59 Q: FnOnce(Result<(B, usize), (B, glib::Error)>) + 'static,
60 C: IsA<Cancellable>,
61 >(
62 &self,
63 buffer: B,
64 io_priority: Priority,
65 cancellable: Option<&C>,
66 callback: Q,
67 ) {
68 let main_context = glib::MainContext::ref_thread_default();
69 let is_main_context_owner = main_context.is_owner();
70 let has_acquired_main_context = (!is_main_context_owner)
71 .then(|| main_context.acquire().ok())
72 .flatten();
73 assert!(
74 is_main_context_owner || has_acquired_main_context.is_some(),
75 "Async operations only allowed if the thread is owning the MainContext"
76 );
77
78 let cancellable = cancellable.map(|c| c.as_ref());
79 let gcancellable = cancellable.to_glib_none();
80 let user_data: Box<(glib::thread_guard::ThreadGuard<Q>, B)> =
81 Box::new((glib::thread_guard::ThreadGuard::new(callback), buffer));
82 let (count, buffer_ptr) = {
84 let buffer = &user_data.1;
85 let slice = buffer.as_ref();
86 (slice.len(), slice.as_ptr())
87 };
88 unsafe extern "C" fn write_async_trampoline<
89 B: AsRef<[u8]> + Send + 'static,
90 Q: FnOnce(Result<(B, usize), (B, glib::Error)>) + 'static,
91 >(
92 _source_object: *mut glib::gobject_ffi::GObject,
93 res: *mut ffi::GAsyncResult,
94 user_data: glib::ffi::gpointer,
95 ) {
96 unsafe {
97 let user_data: Box<(glib::thread_guard::ThreadGuard<Q>, B)> =
98 Box::from_raw(user_data as *mut _);
99 let (callback, buffer) = *user_data;
100 let callback = callback.into_inner();
101
102 let mut error = ptr::null_mut();
103 let ret =
104 ffi::g_output_stream_write_finish(_source_object as *mut _, res, &mut error);
105 let result = if error.is_null() {
106 Ok((buffer, ret as usize))
107 } else {
108 Err((buffer, from_glib_full(error)))
109 };
110 callback(result);
111 }
112 }
113 let callback = write_async_trampoline::<B, Q>;
114 unsafe {
115 ffi::g_output_stream_write_async(
116 self.as_ref().to_glib_none().0,
117 mut_override(buffer_ptr),
118 count,
119 io_priority.into_glib(),
120 gcancellable.0,
121 Some(callback),
122 Box::into_raw(user_data) as *mut _,
123 );
124 }
125 }
126
127 #[doc(alias = "g_output_stream_write_all")]
159 fn write_all<C: IsA<Cancellable>>(
160 &self,
161 buffer: &[u8],
162 cancellable: Option<&C>,
163 ) -> Result<(usize, Option<glib::Error>), glib::Error> {
164 let cancellable = cancellable.map(|c| c.as_ref());
165 let gcancellable = cancellable.to_glib_none();
166 let count = buffer.len();
167 unsafe {
168 let mut bytes_written = mem::MaybeUninit::uninit();
169 let mut error = ptr::null_mut();
170 let _ = ffi::g_output_stream_write_all(
171 self.as_ref().to_glib_none().0,
172 buffer.to_glib_none().0,
173 count,
174 bytes_written.as_mut_ptr(),
175 gcancellable.0,
176 &mut error,
177 );
178
179 let bytes_written = bytes_written.assume_init();
180 if error.is_null() {
181 Ok((bytes_written, None))
182 } else if bytes_written != 0 {
183 Ok((bytes_written, Some(from_glib_full(error))))
184 } else {
185 Err(from_glib_full(error))
186 }
187 }
188 }
189
190 #[doc(alias = "g_output_stream_write_all_async")]
215 fn write_all_async<
216 B: AsRef<[u8]> + Send + 'static,
217 Q: FnOnce(Result<(B, usize), (B, usize, glib::Error)>) + 'static,
218 C: IsA<Cancellable>,
219 >(
220 &self,
221 buffer: B,
222 io_priority: Priority,
223 cancellable: Option<&C>,
224 callback: Q,
225 ) {
226 let main_context = glib::MainContext::ref_thread_default();
227 let is_main_context_owner = main_context.is_owner();
228 let has_acquired_main_context = (!is_main_context_owner)
229 .then(|| main_context.acquire().ok())
230 .flatten();
231 assert!(
232 is_main_context_owner || has_acquired_main_context.is_some(),
233 "Async operations only allowed if the thread is owning the MainContext"
234 );
235
236 let cancellable = cancellable.map(|c| c.as_ref());
237 let gcancellable = cancellable.to_glib_none();
238 let user_data: Box<(glib::thread_guard::ThreadGuard<Q>, B)> =
239 Box::new((glib::thread_guard::ThreadGuard::new(callback), buffer));
240 let (count, buffer_ptr) = {
242 let buffer = &user_data.1;
243 let slice = buffer.as_ref();
244 (slice.len(), slice.as_ptr())
245 };
246 unsafe extern "C" fn write_all_async_trampoline<
247 B: AsRef<[u8]> + Send + 'static,
248 Q: FnOnce(Result<(B, usize), (B, usize, glib::Error)>) + 'static,
249 >(
250 _source_object: *mut glib::gobject_ffi::GObject,
251 res: *mut ffi::GAsyncResult,
252 user_data: glib::ffi::gpointer,
253 ) {
254 unsafe {
255 let user_data: Box<(glib::thread_guard::ThreadGuard<Q>, B)> =
256 Box::from_raw(user_data as *mut _);
257 let (callback, buffer) = *user_data;
258 let callback = callback.into_inner();
259
260 let mut error = ptr::null_mut();
261 let mut bytes_written = mem::MaybeUninit::uninit();
262 let _ = ffi::g_output_stream_write_all_finish(
263 _source_object as *mut _,
264 res,
265 bytes_written.as_mut_ptr(),
266 &mut error,
267 );
268 let bytes_written = bytes_written.assume_init();
269 let result = if error.is_null() {
270 Ok((buffer, bytes_written))
271 } else {
272 Err((buffer, bytes_written, from_glib_full(error)))
273 };
274 callback(result);
275 }
276 }
277 let callback = write_all_async_trampoline::<B, Q>;
278 unsafe {
279 ffi::g_output_stream_write_all_async(
280 self.as_ref().to_glib_none().0,
281 mut_override(buffer_ptr),
282 count,
283 io_priority.into_glib(),
284 gcancellable.0,
285 Some(callback),
286 Box::into_raw(user_data) as *mut _,
287 );
288 }
289 }
290
291 fn write_future<B: AsRef<[u8]> + Send + 'static>(
292 &self,
293 buffer: B,
294 io_priority: Priority,
295 ) -> Pin<Box<dyn std::future::Future<Output = Result<(B, usize), (B, glib::Error)>> + 'static>>
296 {
297 Box::pin(crate::GioFuture::new(
298 self,
299 move |obj, cancellable, send| {
300 obj.write_async(buffer, io_priority, Some(cancellable), move |res| {
301 send.resolve(res);
302 });
303 },
304 ))
305 }
306
307 fn write_all_future<B: AsRef<[u8]> + Send + 'static>(
308 &self,
309 buffer: B,
310 io_priority: Priority,
311 ) -> Pin<
312 Box<
313 dyn std::future::Future<Output = Result<(B, usize), (B, usize, glib::Error)>> + 'static,
314 >,
315 > {
316 Box::pin(crate::GioFuture::new(
317 self,
318 move |obj, cancellable, send| {
319 obj.write_all_async(buffer, io_priority, Some(cancellable), move |res| {
320 send.resolve(res);
321 });
322 },
323 ))
324 }
325
326 #[cfg(feature = "v2_60")]
362 #[cfg_attr(docsrs, doc(cfg(feature = "v2_60")))]
363 #[doc(alias = "g_output_stream_writev")]
364 fn writev(
365 &self,
366 vectors: &[OutputVector],
367 cancellable: Option<&impl IsA<Cancellable>>,
368 ) -> Result<usize, glib::Error> {
369 unsafe {
370 let mut error = ptr::null_mut();
371 let mut bytes_written = mem::MaybeUninit::uninit();
372
373 ffi::g_output_stream_writev(
374 self.as_ref().to_glib_none().0,
375 vectors.as_ptr() as *const _,
376 vectors.len(),
377 bytes_written.as_mut_ptr(),
378 cancellable.map(|p| p.as_ref()).to_glib_none().0,
379 &mut error,
380 );
381 if error.is_null() {
382 Ok(bytes_written.assume_init())
383 } else {
384 Err(from_glib_full(error))
385 }
386 }
387 }
388
389 #[cfg(feature = "v2_60")]
429 #[cfg_attr(docsrs, doc(cfg(feature = "v2_60")))]
430 #[doc(alias = "g_output_stream_writev_async")]
431 fn writev_async<
432 B: AsRef<[u8]> + Send + 'static,
433 P: FnOnce(Result<(Vec<B>, usize), (Vec<B>, glib::Error)>) + 'static,
434 >(
435 &self,
436 vectors: impl IntoIterator<Item = B> + 'static,
437 io_priority: glib::Priority,
438 cancellable: Option<&impl IsA<Cancellable>>,
439 callback: P,
440 ) {
441 let main_context = glib::MainContext::ref_thread_default();
442 let is_main_context_owner = main_context.is_owner();
443 let has_acquired_main_context = (!is_main_context_owner)
444 .then(|| main_context.acquire().ok())
445 .flatten();
446 assert!(
447 is_main_context_owner || has_acquired_main_context.is_some(),
448 "Async operations only allowed if the thread is owning the MainContext"
449 );
450
451 let cancellable = cancellable.map(|c| c.as_ref());
452 let gcancellable = cancellable.to_glib_none();
453 let buffers = vectors.into_iter().collect::<Vec<_>>();
454 let vectors = buffers
455 .iter()
456 .map(|v| ffi::GOutputVector {
457 buffer: v.as_ref().as_ptr() as *const _,
458 size: v.as_ref().len(),
459 })
460 .collect::<Vec<_>>();
461 let vectors_ptr = vectors.as_ptr();
462 let num_vectors = vectors.len();
463 let user_data: Box<(
464 glib::thread_guard::ThreadGuard<P>,
465 Vec<B>,
466 Vec<ffi::GOutputVector>,
467 )> = Box::new((
468 glib::thread_guard::ThreadGuard::new(callback),
469 buffers,
470 vectors,
471 ));
472
473 unsafe extern "C" fn writev_async_trampoline<
474 B: AsRef<[u8]> + Send + 'static,
475 P: FnOnce(Result<(Vec<B>, usize), (Vec<B>, glib::Error)>) + 'static,
476 >(
477 _source_object: *mut glib::gobject_ffi::GObject,
478 res: *mut ffi::GAsyncResult,
479 user_data: glib::ffi::gpointer,
480 ) {
481 unsafe {
482 let user_data: Box<(
483 glib::thread_guard::ThreadGuard<P>,
484 Vec<B>,
485 Vec<ffi::GOutputVector>,
486 )> = Box::from_raw(user_data as *mut _);
487 let (callback, buffers, _) = *user_data;
488 let callback = callback.into_inner();
489
490 let mut error = ptr::null_mut();
491 let mut bytes_written = mem::MaybeUninit::uninit();
492 ffi::g_output_stream_writev_finish(
493 _source_object as *mut _,
494 res,
495 bytes_written.as_mut_ptr(),
496 &mut error,
497 );
498 let bytes_written = bytes_written.assume_init();
499 let result = if error.is_null() {
500 Ok((buffers, bytes_written))
501 } else {
502 Err((buffers, from_glib_full(error)))
503 };
504 callback(result);
505 }
506 }
507 let callback = writev_async_trampoline::<B, P>;
508 unsafe {
509 ffi::g_output_stream_writev_async(
510 self.as_ref().to_glib_none().0,
511 vectors_ptr,
512 num_vectors,
513 io_priority.into_glib(),
514 gcancellable.0,
515 Some(callback),
516 Box::into_raw(user_data) as *mut _,
517 );
518 }
519 }
520
521 #[cfg(feature = "v2_60")]
522 #[cfg_attr(docsrs, doc(cfg(feature = "v2_60")))]
523 fn writev_future<B: AsRef<[u8]> + Send + 'static>(
524 &self,
525 vectors: impl IntoIterator<Item = B> + 'static,
526 io_priority: glib::Priority,
527 ) -> Pin<
528 Box<
529 dyn std::future::Future<Output = Result<(Vec<B>, usize), (Vec<B>, glib::Error)>>
530 + 'static,
531 >,
532 > {
533 Box::pin(crate::GioFuture::new(
534 self,
535 move |obj, cancellable, send| {
536 obj.writev_async(vectors, io_priority, Some(cancellable), move |res| {
537 send.resolve(res);
538 });
539 },
540 ))
541 }
542
543 #[cfg(feature = "v2_60")]
578 #[cfg_attr(docsrs, doc(cfg(feature = "v2_60")))]
579 #[doc(alias = "g_output_stream_writev_all")]
580 fn writev_all(
581 &self,
582 vectors: &[OutputVector],
583 cancellable: Option<&impl IsA<Cancellable>>,
584 ) -> Result<(usize, Option<glib::Error>), glib::Error> {
585 unsafe {
586 let mut error = ptr::null_mut();
587 let mut bytes_written = mem::MaybeUninit::uninit();
588
589 ffi::g_output_stream_writev_all(
590 self.as_ref().to_glib_none().0,
591 mut_override(vectors.as_ptr() as *const _),
592 vectors.len(),
593 bytes_written.as_mut_ptr(),
594 cancellable.map(|p| p.as_ref()).to_glib_none().0,
595 &mut error,
596 );
597 let bytes_written = bytes_written.assume_init();
598 if error.is_null() {
599 Ok((bytes_written, None))
600 } else if bytes_written != 0 {
601 Ok((bytes_written, Some(from_glib_full(error))))
602 } else {
603 Err(from_glib_full(error))
604 }
605 }
606 }
607
608 #[cfg(feature = "v2_60")]
634 #[cfg_attr(docsrs, doc(cfg(feature = "v2_60")))]
635 #[doc(alias = "g_output_stream_writev_all_async")]
636 fn writev_all_async<
637 B: AsRef<[u8]> + Send + 'static,
638 P: FnOnce(Result<(Vec<B>, usize, Option<glib::Error>), (Vec<B>, glib::Error)>) + 'static,
639 >(
640 &self,
641 vectors: impl IntoIterator<Item = B> + 'static,
642 io_priority: glib::Priority,
643 cancellable: Option<&impl IsA<Cancellable>>,
644 callback: P,
645 ) {
646 let main_context = glib::MainContext::ref_thread_default();
647 let is_main_context_owner = main_context.is_owner();
648 let has_acquired_main_context = (!is_main_context_owner)
649 .then(|| main_context.acquire().ok())
650 .flatten();
651 assert!(
652 is_main_context_owner || has_acquired_main_context.is_some(),
653 "Async operations only allowed if the thread is owning the MainContext"
654 );
655
656 let cancellable = cancellable.map(|c| c.as_ref());
657 let gcancellable = cancellable.to_glib_none();
658 let buffers = vectors.into_iter().collect::<Vec<_>>();
659 let vectors = buffers
660 .iter()
661 .map(|v| ffi::GOutputVector {
662 buffer: v.as_ref().as_ptr() as *const _,
663 size: v.as_ref().len(),
664 })
665 .collect::<Vec<_>>();
666 let vectors_ptr = vectors.as_ptr();
667 let num_vectors = vectors.len();
668 let user_data: Box<(
669 glib::thread_guard::ThreadGuard<P>,
670 Vec<B>,
671 Vec<ffi::GOutputVector>,
672 )> = Box::new((
673 glib::thread_guard::ThreadGuard::new(callback),
674 buffers,
675 vectors,
676 ));
677
678 unsafe extern "C" fn writev_all_async_trampoline<
679 B: AsRef<[u8]> + Send + 'static,
680 P: FnOnce(Result<(Vec<B>, usize, Option<glib::Error>), (Vec<B>, glib::Error)>) + 'static,
681 >(
682 _source_object: *mut glib::gobject_ffi::GObject,
683 res: *mut ffi::GAsyncResult,
684 user_data: glib::ffi::gpointer,
685 ) {
686 unsafe {
687 let user_data: Box<(
688 glib::thread_guard::ThreadGuard<P>,
689 Vec<B>,
690 Vec<ffi::GOutputVector>,
691 )> = Box::from_raw(user_data as *mut _);
692 let (callback, buffers, _) = *user_data;
693 let callback = callback.into_inner();
694
695 let mut error = ptr::null_mut();
696 let mut bytes_written = mem::MaybeUninit::uninit();
697 ffi::g_output_stream_writev_all_finish(
698 _source_object as *mut _,
699 res,
700 bytes_written.as_mut_ptr(),
701 &mut error,
702 );
703 let bytes_written = bytes_written.assume_init();
704 let result = if error.is_null() {
705 Ok((buffers, bytes_written, None))
706 } else if bytes_written != 0 {
707 Ok((buffers, bytes_written, from_glib_full(error)))
708 } else {
709 Err((buffers, from_glib_full(error)))
710 };
711 callback(result);
712 }
713 }
714 let callback = writev_all_async_trampoline::<B, P>;
715 unsafe {
716 ffi::g_output_stream_writev_all_async(
717 self.as_ref().to_glib_none().0,
718 mut_override(vectors_ptr),
719 num_vectors,
720 io_priority.into_glib(),
721 gcancellable.0,
722 Some(callback),
723 Box::into_raw(user_data) as *mut _,
724 );
725 }
726 }
727
728 #[cfg(feature = "v2_60")]
729 #[cfg_attr(docsrs, doc(cfg(feature = "v2_60")))]
730 fn writev_all_future<B: AsRef<[u8]> + Send + 'static>(
731 &self,
732 vectors: impl IntoIterator<Item = B> + 'static,
733 io_priority: glib::Priority,
734 ) -> Pin<
735 Box<
736 dyn std::future::Future<
737 Output = Result<(Vec<B>, usize, Option<glib::Error>), (Vec<B>, glib::Error)>,
738 > + 'static,
739 >,
740 > {
741 Box::pin(crate::GioFuture::new(
742 self,
743 move |obj, cancellable, send| {
744 obj.writev_all_async(vectors, io_priority, Some(cancellable), move |res| {
745 send.resolve(res);
746 });
747 },
748 ))
749 }
750
751 fn into_write(self) -> OutputStreamWrite<Self>
752 where
753 Self: IsA<OutputStream>,
754 {
755 OutputStreamWrite(self)
756 }
757}
758
759impl<O: IsA<OutputStream>> OutputStreamExtManual for O {}
760
761#[derive(Debug)]
762pub struct OutputStreamWrite<T: IsA<OutputStream>>(T);
763
764impl<T: IsA<OutputStream>> OutputStreamWrite<T> {
765 pub fn into_output_stream(self) -> T {
766 self.0
767 }
768
769 pub fn output_stream(&self) -> &T {
770 &self.0
771 }
772}
773
774impl<T: IsA<OutputStream>> io::Write for OutputStreamWrite<T> {
775 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
776 let result = self
777 .0
778 .as_ref()
779 .write(buf, crate::Cancellable::NONE)
780 .map(|size| size as usize);
781 to_std_io_result(result)
782 }
783
784 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
785 let result = self
786 .0
787 .as_ref()
788 .write_all(buf, crate::Cancellable::NONE)
789 .and_then(|(_, e)| e.map(Err).unwrap_or(Ok(())));
790 to_std_io_result(result)
791 }
792
793 #[cfg(feature = "v2_60")]
794 #[cfg_attr(docsrs, doc(cfg(feature = "v2_60")))]
795 fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
796 let vectors = bufs
797 .iter()
798 .map(|v| OutputVector::new(v))
799 .collect::<smallvec::SmallVec<[_; 2]>>();
800 let result = self.0.as_ref().writev(&vectors, crate::Cancellable::NONE);
801 to_std_io_result(result)
802 }
803
804 fn flush(&mut self) -> io::Result<()> {
805 let gio_result = self.0.as_ref().flush(crate::Cancellable::NONE);
806 to_std_io_result(gio_result)
807 }
808}
809
810impl<T: IsA<OutputStream> + IsA<Seekable>> io::Seek for OutputStreamWrite<T> {
811 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
812 let (pos, type_) = match pos {
813 io::SeekFrom::Start(pos) => (pos as i64, glib::SeekType::Set),
814 io::SeekFrom::End(pos) => (pos, glib::SeekType::End),
815 io::SeekFrom::Current(pos) => (pos, glib::SeekType::Cur),
816 };
817 let seekable: &Seekable = self.0.as_ref();
818 let gio_result = seekable
819 .seek(pos, type_, crate::Cancellable::NONE)
820 .map(|_| seekable.tell() as u64);
821 to_std_io_result(gio_result)
822 }
823}
824
825#[cfg(test)]
826mod tests {
827 use std::io::Write;
828
829 use glib::Bytes;
830
831 #[cfg(feature = "v2_60")]
832 use crate::OutputVector;
833 use crate::{MemoryInputStream, MemoryOutputStream, prelude::*, test_util::run_async};
834
835 #[test]
836 fn splice_async() {
837 let ret = run_async(|tx, l| {
838 let input = MemoryInputStream::new();
839 let b = Bytes::from_owned(vec![1, 2, 3]);
840 input.add_bytes(&b);
841
842 let strm = MemoryOutputStream::new_resizable();
843 strm.splice_async(
844 &input,
845 crate::OutputStreamSpliceFlags::CLOSE_SOURCE,
846 glib::Priority::DEFAULT_IDLE,
847 crate::Cancellable::NONE,
848 move |ret| {
849 tx.send(ret).unwrap();
850 l.quit();
851 },
852 );
853 });
854
855 assert_eq!(ret.unwrap(), 3);
856 }
857
858 #[test]
859 fn write_async() {
860 let ret = run_async(|tx, l| {
861 let strm = MemoryOutputStream::new_resizable();
862
863 let buf = vec![1, 2, 3];
864 strm.write_async(
865 buf,
866 glib::Priority::DEFAULT_IDLE,
867 crate::Cancellable::NONE,
868 move |ret| {
869 tx.send(ret).unwrap();
870 l.quit();
871 },
872 );
873 });
874
875 let (buf, size) = ret.unwrap();
876 assert_eq!(buf, vec![1, 2, 3]);
877 assert_eq!(size, 3);
878 }
879
880 #[test]
881 fn write_all_async() {
882 let ret = run_async(|tx, l| {
883 let strm = MemoryOutputStream::new_resizable();
884
885 let buf = vec![1, 2, 3];
886 strm.write_all_async(
887 buf,
888 glib::Priority::DEFAULT_IDLE,
889 crate::Cancellable::NONE,
890 move |ret| {
891 tx.send(ret).unwrap();
892 l.quit();
893 },
894 );
895 });
896
897 let (buf, size) = ret.unwrap();
898 assert_eq!(buf, vec![1, 2, 3]);
899 assert_eq!(size, 3);
900 }
901
902 #[test]
903 fn write_all_future() {
904 let c = glib::MainContext::new();
905 let strm = MemoryOutputStream::new_resizable();
906
907 let (buf, size) = c
908 .block_on(strm.write_all_future(vec![1, 2, 3], glib::Priority::default()))
909 .unwrap();
910
911 assert_eq!(buf, vec![1, 2, 3]);
912 assert_eq!(size, 3);
913 }
914
915 #[test]
916 fn write_all_async_cancelled() {
917 let ret = run_async(|tx, l| {
918 let strm = MemoryOutputStream::new_resizable();
919 let cancellable = crate::Cancellable::new();
920 cancellable.cancel();
921
922 let buf = vec![1, 2, 3];
923 strm.write_all_async(
924 buf,
925 glib::Priority::DEFAULT_IDLE,
926 Some(&cancellable),
927 move |ret| {
928 tx.send(ret).unwrap();
929 l.quit();
930 },
931 );
932 });
933
934 let (buf, size, err) = ret.unwrap_err();
935 assert_eq!(buf, vec![1, 2, 3]);
936 assert_eq!(size, 0);
937 assert!(err.matches::<crate::IOErrorEnum>(crate::IOErrorEnum::Cancelled));
938 }
939
940 #[test]
941 fn write_bytes_async() {
942 let ret = run_async(|tx, l| {
943 let strm = MemoryOutputStream::new_resizable();
944
945 let b = Bytes::from_owned(vec![1, 2, 3]);
946 strm.write_bytes_async(
947 &b,
948 glib::Priority::DEFAULT_IDLE,
949 crate::Cancellable::NONE,
950 move |ret| {
951 tx.send(ret).unwrap();
952 l.quit();
953 },
954 );
955 });
956
957 assert_eq!(ret.unwrap(), 3);
958 }
959
960 #[test]
961 fn std_io_write() {
962 let b = Bytes::from_owned(vec![1, 2, 3]);
963 let mut write = MemoryOutputStream::new_resizable().into_write();
964
965 let ret = write.write(&b);
966
967 let stream = write.into_output_stream();
968 stream.close(crate::Cancellable::NONE).unwrap();
969 assert_eq!(ret.unwrap(), 3);
970 assert_eq!(stream.steal_as_bytes(), [1, 2, 3].as_ref());
971 }
972
973 #[test]
974 fn into_output_stream() {
975 let stream = MemoryOutputStream::new_resizable();
976 let stream_clone = stream.clone();
977 let stream = stream.into_write().into_output_stream();
978
979 assert_eq!(stream, stream_clone);
980 }
981
982 #[test]
983 #[cfg(feature = "v2_60")]
984 fn writev() {
985 let stream = MemoryOutputStream::new_resizable();
986
987 let ret = stream.writev(
988 &[OutputVector::new(&[1, 2, 3]), OutputVector::new(&[4, 5, 6])],
989 crate::Cancellable::NONE,
990 );
991 assert_eq!(ret.unwrap(), 6);
992 stream.close(crate::Cancellable::NONE).unwrap();
993 assert_eq!(stream.steal_as_bytes(), [1, 2, 3, 4, 5, 6].as_ref());
994 }
995
996 #[test]
997 #[cfg(feature = "v2_60")]
998 fn writev_async() {
999 let ret = run_async(|tx, l| {
1000 let strm = MemoryOutputStream::new_resizable();
1001
1002 let strm_clone = strm.clone();
1003 strm.writev_async(
1004 [vec![1, 2, 3], vec![4, 5, 6]],
1005 glib::Priority::DEFAULT_IDLE,
1006 crate::Cancellable::NONE,
1007 move |ret| {
1008 tx.send(ret).unwrap();
1009 strm_clone.close(crate::Cancellable::NONE).unwrap();
1010 assert_eq!(strm_clone.steal_as_bytes(), [1, 2, 3, 4, 5, 6].as_ref());
1011 l.quit();
1012 },
1013 );
1014 });
1015
1016 let (buf, size) = ret.unwrap();
1017 assert_eq!(buf, [[1, 2, 3], [4, 5, 6]]);
1018 assert_eq!(size, 6);
1019 }
1020
1021 #[test]
1022 #[cfg(feature = "v2_60")]
1023 fn writev_all_async() {
1024 let ret = run_async(|tx, l| {
1025 let strm = MemoryOutputStream::new_resizable();
1026
1027 let strm_clone = strm.clone();
1028 strm.writev_all_async(
1029 [vec![1, 2, 3], vec![4, 5, 6]],
1030 glib::Priority::DEFAULT_IDLE,
1031 crate::Cancellable::NONE,
1032 move |ret| {
1033 tx.send(ret).unwrap();
1034 strm_clone.close(crate::Cancellable::NONE).unwrap();
1035 assert_eq!(strm_clone.steal_as_bytes(), [1, 2, 3, 4, 5, 6].as_ref());
1036 l.quit();
1037 },
1038 );
1039 });
1040
1041 let (buf, size, err) = ret.unwrap();
1042 assert_eq!(buf, [[1, 2, 3], [4, 5, 6]]);
1043 assert_eq!(size, 6);
1044 assert!(err.is_none());
1045 }
1046}