Skip to main content

gio/
input_stream.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{fmt, future::Future, io, mem, pin::Pin, ptr};
4
5use futures_core::task::{Context, Poll};
6use futures_io::{AsyncBufRead, AsyncRead};
7use glib::{Priority, prelude::*, translate::*};
8
9use crate::{Cancellable, InputStream, Seekable, error::to_std_io_result, ffi, prelude::*};
10
11pub trait InputStreamExtManual: IsA<InputStream> + Sized {
12    /// Tries to read @count bytes from the stream into the buffer starting at
13    /// @buffer. Will block during this read.
14    ///
15    /// If count is zero returns zero and does nothing. A value of @count
16    /// larger than `G_MAXSSIZE` will cause a [`IOErrorEnum::InvalidArgument`][crate::IOErrorEnum::InvalidArgument] error.
17    ///
18    /// On success, the number of bytes read into the buffer is returned.
19    /// It is not an error if this is not the same as the requested size, as it
20    /// can happen e.g. near the end of a file. Zero is returned on end of file
21    /// (or if @count is zero),  but never otherwise.
22    ///
23    /// The returned @buffer is not a nul-terminated string, it can contain nul bytes
24    /// at any position, and this function doesn't nul-terminate the @buffer.
25    ///
26    /// If @cancellable is not [`None`], then the operation can be cancelled by
27    /// triggering the cancellable object from another thread. If the operation
28    /// was cancelled, the error [`IOErrorEnum::Cancelled`][crate::IOErrorEnum::Cancelled] will be returned. If an
29    /// operation was partially finished when the operation was cancelled the
30    /// partial result will be returned, without an error.
31    ///
32    /// On error -1 is returned and @error is set accordingly.
33    /// ## `cancellable`
34    /// optional #GCancellable object, [`None`] to ignore.
35    ///
36    /// # Returns
37    ///
38    /// Number of bytes read, or -1 on error, or 0 on end of file.
39    ///
40    /// ## `buffer`
41    ///
42    ///   a buffer to read data into (which should be at least count bytes long).
43    #[doc(alias = "g_input_stream_read")]
44    fn read<B: AsMut<[u8]>, C: IsA<Cancellable>>(
45        &self,
46        mut buffer: B,
47        cancellable: Option<&C>,
48    ) -> Result<usize, glib::Error> {
49        let cancellable = cancellable.map(|c| c.as_ref());
50        let gcancellable = cancellable.to_glib_none();
51        let buffer = buffer.as_mut();
52        let buffer_ptr = buffer.as_mut_ptr();
53        let count = buffer.len();
54        unsafe {
55            let mut error = ptr::null_mut();
56            let ret = ffi::g_input_stream_read(
57                self.as_ref().to_glib_none().0,
58                buffer_ptr,
59                count,
60                gcancellable.0,
61                &mut error,
62            );
63            if error.is_null() {
64                Ok(ret as usize)
65            } else {
66                Err(from_glib_full(error))
67            }
68        }
69    }
70
71    /// Tries to read @count bytes from the stream into the buffer starting at
72    /// @buffer. Will block during this read.
73    ///
74    /// This function is similar to g_input_stream_read(), except it tries to
75    /// read as many bytes as requested, only stopping on an error or end of stream.
76    ///
77    /// On a successful read of @count bytes, or if we reached the end of the
78    /// stream,  [`true`] is returned, and @bytes_read is set to the number of bytes
79    /// read into @buffer.
80    ///
81    /// If there is an error during the operation [`false`] is returned and @error
82    /// is set to indicate the error status.
83    ///
84    /// As a special exception to the normal conventions for functions that
85    /// use #GError, if this function returns [`false`] (and sets @error) then
86    /// @bytes_read will be set to the number of bytes that were successfully
87    /// read before the error was encountered.  This functionality is only
88    /// available from C.  If you need it from another language then you must
89    /// write your own loop around g_input_stream_read().
90    /// ## `cancellable`
91    /// optional #GCancellable object, [`None`] to ignore.
92    ///
93    /// # Returns
94    ///
95    /// [`true`] on success, [`false`] if there was an error
96    ///
97    /// ## `buffer`
98    ///
99    ///   a buffer to read data into (which should be at least count bytes long).
100    ///
101    /// ## `bytes_read`
102    /// location to store the number of bytes that was read from the stream
103    #[doc(alias = "g_input_stream_read_all")]
104    fn read_all<B: AsMut<[u8]>, C: IsA<Cancellable>>(
105        &self,
106        mut buffer: B,
107        cancellable: Option<&C>,
108    ) -> Result<(B, usize), (B, usize, glib::Error)> {
109        let cancellable = cancellable.map(|c| c.as_ref());
110        let gcancellable = cancellable.to_glib_none();
111        let (count, buffer_ptr) = {
112            let buffer = buffer.as_mut();
113            (buffer.len(), buffer.as_mut_ptr())
114        };
115        unsafe {
116            let mut bytes_read = mem::MaybeUninit::uninit();
117            let mut error = ptr::null_mut();
118            let _ = ffi::g_input_stream_read_all(
119                self.as_ref().to_glib_none().0,
120                buffer_ptr,
121                count,
122                bytes_read.as_mut_ptr(),
123                gcancellable.0,
124                &mut error,
125            );
126
127            let bytes_read = bytes_read.assume_init();
128            if error.is_null() {
129                Ok((buffer, bytes_read))
130            } else {
131                Err((buffer, bytes_read, from_glib_full(error)))
132            }
133        }
134    }
135
136    /// Request an asynchronous read of @count bytes from the stream into the
137    /// buffer starting at @buffer.
138    ///
139    /// This is the asynchronous equivalent of [`InputStreamExtManual::read_all()`][crate::prelude::InputStreamExtManual::read_all()].
140    ///
141    /// Call `InputStream::read_all_finish()` to collect the result.
142    ///
143    /// Any outstanding I/O request with higher priority (lower numerical
144    /// value) will be executed before an outstanding request with lower
145    /// priority. Default priority is `G_PRIORITY_DEFAULT`.
146    /// ## `io_priority`
147    /// the [I/O priority](iface.AsyncResult.html#io-priority) of the request
148    /// ## `cancellable`
149    /// optional #GCancellable object, [`None`] to ignore
150    /// ## `callback`
151    /// a #GAsyncReadyCallback
152    ///   to call when the request is satisfied
153    ///
154    /// # Returns
155    ///
156    ///
157    /// ## `buffer`
158    ///
159    ///   a buffer to read data into (which should be at least count bytes long)
160    #[doc(alias = "g_input_stream_read_all_async")]
161    fn read_all_async<
162        B: AsMut<[u8]> + Send + 'static,
163        Q: FnOnce(Result<(B, usize), (B, usize, glib::Error)>) + 'static,
164        C: IsA<Cancellable>,
165    >(
166        &self,
167        buffer: B,
168        io_priority: Priority,
169        cancellable: Option<&C>,
170        callback: Q,
171    ) {
172        let main_context = glib::MainContext::ref_thread_default();
173        let is_main_context_owner = main_context.is_owner();
174        let has_acquired_main_context = (!is_main_context_owner)
175            .then(|| main_context.acquire().ok())
176            .flatten();
177        assert!(
178            is_main_context_owner || has_acquired_main_context.is_some(),
179            "Async operations only allowed if the thread is owning the MainContext"
180        );
181
182        let cancellable = cancellable.map(|c| c.as_ref());
183        let gcancellable = cancellable.to_glib_none();
184        let mut user_data: Box<(glib::thread_guard::ThreadGuard<Q>, B)> =
185            Box::new((glib::thread_guard::ThreadGuard::new(callback), buffer));
186        // Need to do this after boxing as the contents pointer might change by moving into the box
187        let (count, buffer_ptr) = {
188            let buffer = &mut user_data.1;
189            let slice = (*buffer).as_mut();
190            (slice.len(), slice.as_mut_ptr())
191        };
192        unsafe extern "C" fn read_all_async_trampoline<
193            B: AsMut<[u8]> + Send + 'static,
194            Q: FnOnce(Result<(B, usize), (B, usize, glib::Error)>) + 'static,
195        >(
196            _source_object: *mut glib::gobject_ffi::GObject,
197            res: *mut ffi::GAsyncResult,
198            user_data: glib::ffi::gpointer,
199        ) {
200            unsafe {
201                let user_data: Box<(glib::thread_guard::ThreadGuard<Q>, B)> =
202                    Box::from_raw(user_data as *mut _);
203                let (callback, buffer) = *user_data;
204                let callback = callback.into_inner();
205
206                let mut error = ptr::null_mut();
207                let mut bytes_read = mem::MaybeUninit::uninit();
208                let _ = ffi::g_input_stream_read_all_finish(
209                    _source_object as *mut _,
210                    res,
211                    bytes_read.as_mut_ptr(),
212                    &mut error,
213                );
214
215                let bytes_read = bytes_read.assume_init();
216                let result = if error.is_null() {
217                    Ok((buffer, bytes_read))
218                } else {
219                    Err((buffer, bytes_read, from_glib_full(error)))
220                };
221
222                callback(result);
223            }
224        }
225        let callback = read_all_async_trampoline::<B, Q>;
226        unsafe {
227            ffi::g_input_stream_read_all_async(
228                self.as_ref().to_glib_none().0,
229                buffer_ptr,
230                count,
231                io_priority.into_glib(),
232                gcancellable.0,
233                Some(callback),
234                Box::into_raw(user_data) as *mut _,
235            );
236        }
237    }
238
239    /// Request an asynchronous read of @count bytes from the stream into the buffer
240    /// starting at @buffer. When the operation is finished @callback will be called.
241    /// You can then call g_input_stream_read_finish() to get the result of the
242    /// operation.
243    ///
244    /// During an async request no other sync and async calls are allowed on @self, and will
245    /// result in [`IOErrorEnum::Pending`][crate::IOErrorEnum::Pending] errors.
246    ///
247    /// A value of @count larger than `G_MAXSSIZE` will cause a [`IOErrorEnum::InvalidArgument`][crate::IOErrorEnum::InvalidArgument] error.
248    ///
249    /// On success, the number of bytes read into the buffer will be passed to the
250    /// callback. It is not an error if this is not the same as the requested size, as it
251    /// can happen e.g. near the end of a file, but generally we try to read
252    /// as many bytes as requested. Zero is returned on end of file
253    /// (or if @count is zero),  but never otherwise.
254    ///
255    /// Any outstanding i/o request with higher priority (lower numerical value) will
256    /// be executed before an outstanding request with lower priority. Default
257    /// priority is `G_PRIORITY_DEFAULT`.
258    ///
259    /// The asynchronous methods have a default fallback that uses threads to implement
260    /// asynchronicity, so they are optional for inheriting classes. However, if you
261    /// override one you must override all.
262    /// ## `io_priority`
263    /// the [I/O priority](iface.AsyncResult.html#io-priority)
264    /// of the request.
265    /// ## `cancellable`
266    /// optional #GCancellable object, [`None`] to ignore.
267    /// ## `callback`
268    /// a #GAsyncReadyCallback
269    ///   to call when the request is satisfied
270    ///
271    /// # Returns
272    ///
273    ///
274    /// ## `buffer`
275    ///
276    ///   a buffer to read data into (which should be at least count bytes long).
277    #[doc(alias = "g_input_stream_read_async")]
278    fn read_async<
279        B: AsMut<[u8]> + Send + 'static,
280        Q: FnOnce(Result<(B, usize), (B, glib::Error)>) + 'static,
281        C: IsA<Cancellable>,
282    >(
283        &self,
284        buffer: B,
285        io_priority: Priority,
286        cancellable: Option<&C>,
287        callback: Q,
288    ) {
289        let main_context = glib::MainContext::ref_thread_default();
290        let is_main_context_owner = main_context.is_owner();
291        let has_acquired_main_context = (!is_main_context_owner)
292            .then(|| main_context.acquire().ok())
293            .flatten();
294        assert!(
295            is_main_context_owner || has_acquired_main_context.is_some(),
296            "Async operations only allowed if the thread is owning the MainContext"
297        );
298
299        let cancellable = cancellable.map(|c| c.as_ref());
300        let gcancellable = cancellable.to_glib_none();
301        let mut user_data: Box<(glib::thread_guard::ThreadGuard<Q>, B)> =
302            Box::new((glib::thread_guard::ThreadGuard::new(callback), buffer));
303        // Need to do this after boxing as the contents pointer might change by moving into the box
304        let (count, buffer_ptr) = {
305            let buffer = &mut user_data.1;
306            let slice = (*buffer).as_mut();
307            (slice.len(), slice.as_mut_ptr())
308        };
309        unsafe extern "C" fn read_async_trampoline<
310            B: AsMut<[u8]> + Send + 'static,
311            Q: FnOnce(Result<(B, usize), (B, glib::Error)>) + 'static,
312        >(
313            _source_object: *mut glib::gobject_ffi::GObject,
314            res: *mut ffi::GAsyncResult,
315            user_data: glib::ffi::gpointer,
316        ) {
317            unsafe {
318                let user_data: Box<(glib::thread_guard::ThreadGuard<Q>, B)> =
319                    Box::from_raw(user_data as *mut _);
320                let (callback, buffer) = *user_data;
321                let callback = callback.into_inner();
322
323                let mut error = ptr::null_mut();
324                let ret =
325                    ffi::g_input_stream_read_finish(_source_object as *mut _, res, &mut error);
326
327                let result = if error.is_null() {
328                    Ok((buffer, ret as usize))
329                } else {
330                    Err((buffer, from_glib_full(error)))
331                };
332
333                callback(result);
334            }
335        }
336        let callback = read_async_trampoline::<B, Q>;
337        unsafe {
338            ffi::g_input_stream_read_async(
339                self.as_ref().to_glib_none().0,
340                buffer_ptr,
341                count,
342                io_priority.into_glib(),
343                gcancellable.0,
344                Some(callback),
345                Box::into_raw(user_data) as *mut _,
346            );
347        }
348    }
349
350    fn read_all_future<B: AsMut<[u8]> + Send + 'static>(
351        &self,
352        buffer: B,
353        io_priority: Priority,
354    ) -> Pin<
355        Box<
356            dyn std::future::Future<Output = Result<(B, usize), (B, usize, glib::Error)>> + 'static,
357        >,
358    > {
359        Box::pin(crate::GioFuture::new(
360            self,
361            move |obj, cancellable, send| {
362                obj.read_all_async(buffer, io_priority, Some(cancellable), move |res| {
363                    send.resolve(res);
364                });
365            },
366        ))
367    }
368
369    fn read_future<B: AsMut<[u8]> + Send + 'static>(
370        &self,
371        buffer: B,
372        io_priority: Priority,
373    ) -> Pin<Box<dyn std::future::Future<Output = Result<(B, usize), (B, glib::Error)>> + 'static>>
374    {
375        Box::pin(crate::GioFuture::new(
376            self,
377            move |obj, cancellable, send| {
378                obj.read_async(buffer, io_priority, Some(cancellable), move |res| {
379                    send.resolve(res);
380                });
381            },
382        ))
383    }
384
385    fn into_read(self) -> InputStreamRead<Self>
386    where
387        Self: IsA<InputStream>,
388    {
389        InputStreamRead(self)
390    }
391
392    fn into_async_buf_read(self, buffer_size: usize) -> InputStreamAsyncBufRead<Self>
393    where
394        Self: IsA<InputStream>,
395    {
396        InputStreamAsyncBufRead::new(self, buffer_size)
397    }
398}
399
400impl<O: IsA<InputStream>> InputStreamExtManual for O {}
401
402#[derive(Debug)]
403pub struct InputStreamRead<T: IsA<InputStream>>(T);
404
405impl<T: IsA<InputStream>> InputStreamRead<T> {
406    pub fn into_input_stream(self) -> T {
407        self.0
408    }
409
410    pub fn input_stream(&self) -> &T {
411        &self.0
412    }
413}
414
415impl<T: IsA<InputStream>> io::Read for InputStreamRead<T> {
416    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
417        let gio_result = self.0.as_ref().read(buf, crate::Cancellable::NONE);
418        to_std_io_result(gio_result)
419    }
420}
421
422impl<T: IsA<InputStream> + IsA<Seekable>> io::Seek for InputStreamRead<T> {
423    fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
424        let (pos, type_) = match pos {
425            io::SeekFrom::Start(pos) => (pos as i64, glib::SeekType::Set),
426            io::SeekFrom::End(pos) => (pos, glib::SeekType::End),
427            io::SeekFrom::Current(pos) => (pos, glib::SeekType::Cur),
428        };
429        let seekable: &Seekable = self.0.as_ref();
430        let gio_result = seekable
431            .seek(pos, type_, crate::Cancellable::NONE)
432            .map(|_| seekable.tell() as u64);
433        to_std_io_result(gio_result)
434    }
435}
436
437enum State {
438    Waiting {
439        buffer: Vec<u8>,
440    },
441    Transitioning,
442    Reading {
443        pending: Pin<
444            Box<
445                dyn std::future::Future<Output = Result<(Vec<u8>, usize), (Vec<u8>, glib::Error)>>
446                    + 'static,
447            >,
448        >,
449    },
450    HasData {
451        buffer: Vec<u8>,
452        valid: (usize, usize), // first index is inclusive, second is exclusive
453    },
454    Failed(crate::IOErrorEnum),
455}
456
457impl State {
458    fn into_buffer(self) -> Vec<u8> {
459        match self {
460            State::Waiting { buffer } => buffer,
461            _ => panic!("Invalid state"),
462        }
463    }
464
465    #[doc(alias = "get_pending")]
466    fn pending(
467        &mut self,
468    ) -> &mut Pin<
469        Box<
470            dyn std::future::Future<Output = Result<(Vec<u8>, usize), (Vec<u8>, glib::Error)>>
471                + 'static,
472        >,
473    > {
474        match self {
475            State::Reading { pending } => pending,
476            _ => panic!("Invalid state"),
477        }
478    }
479}
480pub struct InputStreamAsyncBufRead<T: IsA<InputStream>> {
481    stream: T,
482    state: State,
483}
484
485impl<T: IsA<InputStream>> InputStreamAsyncBufRead<T> {
486    pub fn into_input_stream(self) -> T {
487        self.stream
488    }
489
490    pub fn input_stream(&self) -> &T {
491        &self.stream
492    }
493
494    fn new(stream: T, buffer_size: usize) -> Self {
495        let buffer = vec![0; buffer_size];
496
497        Self {
498            stream,
499            state: State::Waiting { buffer },
500        }
501    }
502    fn set_reading(
503        &mut self,
504    ) -> &mut Pin<
505        Box<
506            dyn std::future::Future<Output = Result<(Vec<u8>, usize), (Vec<u8>, glib::Error)>>
507                + 'static,
508        >,
509    > {
510        match self.state {
511            State::Waiting { .. } => {
512                let waiting = mem::replace(&mut self.state, State::Transitioning);
513                let buffer = waiting.into_buffer();
514                let pending = self.input_stream().read_future(buffer, Priority::default());
515                self.state = State::Reading { pending };
516            }
517            State::Reading { .. } => {}
518            _ => panic!("Invalid state"),
519        };
520
521        self.state.pending()
522    }
523
524    #[doc(alias = "get_data")]
525    fn data(&self) -> Poll<io::Result<&[u8]>> {
526        if let State::HasData {
527            ref buffer,
528            valid: (i, j),
529        } = self.state
530        {
531            return Poll::Ready(Ok(&buffer[i..j]));
532        }
533        panic!("Invalid state")
534    }
535
536    fn set_waiting(&mut self, buffer: Vec<u8>) {
537        match self.state {
538            State::Reading { .. } | State::Transitioning => self.state = State::Waiting { buffer },
539            _ => panic!("Invalid state"),
540        }
541    }
542
543    fn set_has_data(&mut self, buffer: Vec<u8>, valid: (usize, usize)) {
544        match self.state {
545            State::Reading { .. } | State::Transitioning => {
546                self.state = State::HasData { buffer, valid }
547            }
548            _ => panic!("Invalid state"),
549        }
550    }
551
552    fn poll_fill_buf(&mut self, cx: &mut Context) -> Poll<Result<&[u8], futures_io::Error>> {
553        match self.state {
554            State::Failed(kind) => Poll::Ready(Err(io::Error::new(
555                io::ErrorKind::from(kind),
556                BufReadError::Failed,
557            ))),
558            State::HasData { .. } => self.data(),
559            State::Transitioning => panic!("Invalid state"),
560            State::Waiting { .. } | State::Reading { .. } => {
561                let pending = self.set_reading();
562                match Pin::new(pending).poll(cx) {
563                    Poll::Ready(Ok((buffer, res))) => {
564                        if res == 0 {
565                            self.set_waiting(buffer);
566                            Poll::Ready(Ok(&[]))
567                        } else {
568                            self.set_has_data(buffer, (0, res));
569                            self.data()
570                        }
571                    }
572                    Poll::Ready(Err((_, err))) => {
573                        let kind = err
574                            .kind::<crate::IOErrorEnum>()
575                            .unwrap_or(crate::IOErrorEnum::Failed);
576                        self.state = State::Failed(kind);
577                        Poll::Ready(Err(io::Error::new(io::ErrorKind::from(kind), err)))
578                    }
579                    Poll::Pending => Poll::Pending,
580                }
581            }
582        }
583    }
584
585    fn consume(&mut self, amt: usize) {
586        if amt == 0 {
587            return;
588        }
589
590        if let State::HasData { .. } = self.state {
591            let has_data = mem::replace(&mut self.state, State::Transitioning);
592            if let State::HasData {
593                buffer,
594                valid: (i, j),
595            } = has_data
596            {
597                let available = j - i;
598                if amt > available {
599                    panic!("Cannot consume {amt} bytes as only {available} are available",)
600                }
601                let remaining = available - amt;
602                if remaining == 0 {
603                    return self.set_waiting(buffer);
604                } else {
605                    return self.set_has_data(buffer, (i + amt, j));
606                }
607            }
608        }
609
610        panic!("Invalid state")
611    }
612}
613
614#[derive(Debug)]
615enum BufReadError {
616    Failed,
617}
618
619impl std::error::Error for BufReadError {}
620
621impl fmt::Display for BufReadError {
622    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
623        match self {
624            Self::Failed => fmt.write_str("Previous read operation failed"),
625        }
626    }
627}
628
629impl<T: IsA<InputStream>> AsyncRead for InputStreamAsyncBufRead<T> {
630    fn poll_read(
631        self: Pin<&mut Self>,
632        cx: &mut Context,
633        out_buf: &mut [u8],
634    ) -> Poll<io::Result<usize>> {
635        let reader = self.get_mut();
636        let poll = reader.poll_fill_buf(cx);
637
638        let poll = poll.map_ok(|buffer| {
639            let copied = buffer.len().min(out_buf.len());
640            out_buf[..copied].copy_from_slice(&buffer[..copied]);
641            copied
642        });
643
644        if let Poll::Ready(Ok(consumed)) = poll {
645            reader.consume(consumed);
646        }
647        poll
648    }
649}
650
651impl<T: IsA<InputStream>> AsyncBufRead for InputStreamAsyncBufRead<T> {
652    fn poll_fill_buf(
653        self: Pin<&mut Self>,
654        cx: &mut Context,
655    ) -> Poll<Result<&[u8], futures_io::Error>> {
656        self.get_mut().poll_fill_buf(cx)
657    }
658
659    fn consume(self: Pin<&mut Self>, amt: usize) {
660        self.get_mut().consume(amt);
661    }
662}
663
664impl<T: IsA<InputStream>> Unpin for InputStreamAsyncBufRead<T> {}
665
666#[cfg(test)]
667mod tests {
668    use std::io::Read;
669
670    use glib::Bytes;
671
672    use crate::{MemoryInputStream, prelude::*, test_util::run_async};
673
674    #[test]
675    fn read_all_async() {
676        let ret = run_async(|tx, l| {
677            let b = Bytes::from_owned(vec![1, 2, 3]);
678            let strm = MemoryInputStream::from_bytes(&b);
679
680            let buf = vec![0; 10];
681            strm.read_all_async(
682                buf,
683                glib::Priority::DEFAULT_IDLE,
684                crate::Cancellable::NONE,
685                move |ret| {
686                    tx.send(ret).unwrap();
687                    l.quit();
688                },
689            );
690        });
691
692        let (buf, count) = ret.unwrap();
693        assert_eq!(count, 3);
694        assert_eq!(buf[0], 1);
695        assert_eq!(buf[1], 2);
696        assert_eq!(buf[2], 3);
697    }
698
699    #[test]
700    fn read_all_future() {
701        let c = glib::MainContext::new();
702        let b = Bytes::from_owned(vec![1, 2, 3]);
703        let strm = MemoryInputStream::from_bytes(&b);
704
705        let (buf, count) = c
706            .block_on(strm.read_all_future(vec![0; 10], glib::Priority::default()))
707            .unwrap();
708
709        assert_eq!(count, 3);
710        assert_eq!(buf[0], 1);
711        assert_eq!(buf[1], 2);
712        assert_eq!(buf[2], 3);
713    }
714
715    #[test]
716    fn read_all_async_cancelled() {
717        let ret = run_async(|tx, l| {
718            let b = Bytes::from_owned(vec![1, 2, 3]);
719            let strm = MemoryInputStream::from_bytes(&b);
720            let cancellable = crate::Cancellable::new();
721            cancellable.cancel();
722
723            let buf = vec![0; 10];
724            strm.read_all_async(
725                buf,
726                glib::Priority::DEFAULT_IDLE,
727                Some(&cancellable),
728                move |ret| {
729                    tx.send(ret).unwrap();
730                    l.quit();
731                },
732            );
733        });
734
735        let (buf, count, err) = ret.unwrap_err();
736        assert_eq!(count, 0);
737        assert_eq!(buf, vec![0; 10]);
738        assert!(err.matches::<crate::IOErrorEnum>(crate::IOErrorEnum::Cancelled));
739    }
740
741    #[test]
742    fn read_all() {
743        let b = Bytes::from_owned(vec![1, 2, 3]);
744        let strm = MemoryInputStream::from_bytes(&b);
745
746        let (buf, count) = strm
747            .read_all(vec![0; 10], crate::Cancellable::NONE)
748            .unwrap();
749
750        assert_eq!(count, 3);
751        assert_eq!(buf[0], 1);
752        assert_eq!(buf[1], 2);
753        assert_eq!(buf[2], 3);
754    }
755
756    #[test]
757    fn read_all_closed() {
758        let b = Bytes::from_owned(vec![1, 2, 3]);
759        let strm = MemoryInputStream::from_bytes(&b);
760        strm.close(crate::Cancellable::NONE).unwrap();
761
762        let (buf, count, err) = strm
763            .read_all(vec![0; 10], crate::Cancellable::NONE)
764            .unwrap_err();
765
766        assert_eq!(count, 0);
767        assert_eq!(buf, vec![0; 10]);
768        assert!(err.matches::<crate::IOErrorEnum>(crate::IOErrorEnum::Closed));
769    }
770
771    #[test]
772    fn read() {
773        let b = Bytes::from_owned(vec![1, 2, 3]);
774        let strm = MemoryInputStream::from_bytes(&b);
775        let mut buf = vec![0; 10];
776
777        let ret = strm.read(&mut buf, crate::Cancellable::NONE);
778
779        assert_eq!(ret.unwrap(), 3);
780        assert_eq!(buf[0], 1);
781        assert_eq!(buf[1], 2);
782        assert_eq!(buf[2], 3);
783    }
784
785    #[test]
786    fn read_async() {
787        let ret = run_async(|tx, l| {
788            let b = Bytes::from_owned(vec![1, 2, 3]);
789            let strm = MemoryInputStream::from_bytes(&b);
790
791            let buf = vec![0; 10];
792            strm.read_async(
793                buf,
794                glib::Priority::DEFAULT_IDLE,
795                crate::Cancellable::NONE,
796                move |ret| {
797                    tx.send(ret).unwrap();
798                    l.quit();
799                },
800            );
801        });
802
803        let (buf, count) = ret.unwrap();
804        assert_eq!(count, 3);
805        assert_eq!(buf[0], 1);
806        assert_eq!(buf[1], 2);
807        assert_eq!(buf[2], 3);
808    }
809
810    #[test]
811    fn read_bytes_async() {
812        let ret = run_async(|tx, l| {
813            let b = Bytes::from_owned(vec![1, 2, 3]);
814            let strm = MemoryInputStream::from_bytes(&b);
815
816            strm.read_bytes_async(
817                10,
818                glib::Priority::DEFAULT_IDLE,
819                crate::Cancellable::NONE,
820                move |ret| {
821                    tx.send(ret).unwrap();
822                    l.quit();
823                },
824            );
825        });
826
827        let bytes = ret.unwrap();
828        assert_eq!(bytes, vec![1, 2, 3]);
829    }
830
831    #[test]
832    fn skip_async() {
833        let ret = run_async(|tx, l| {
834            let b = Bytes::from_owned(vec![1, 2, 3]);
835            let strm = MemoryInputStream::from_bytes(&b);
836
837            strm.skip_async(
838                10,
839                glib::Priority::DEFAULT_IDLE,
840                crate::Cancellable::NONE,
841                move |ret| {
842                    tx.send(ret).unwrap();
843                    l.quit();
844                },
845            );
846        });
847
848        let skipped = ret.unwrap();
849        assert_eq!(skipped, 3);
850    }
851
852    #[test]
853    fn std_io_read() {
854        let b = Bytes::from_owned(vec![1, 2, 3]);
855        let mut read = MemoryInputStream::from_bytes(&b).into_read();
856        let mut buf = [0u8; 10];
857
858        let ret = read.read(&mut buf);
859
860        assert_eq!(ret.unwrap(), 3);
861        assert_eq!(buf[0], 1);
862        assert_eq!(buf[1], 2);
863        assert_eq!(buf[2], 3);
864    }
865
866    #[test]
867    fn into_input_stream() {
868        let b = Bytes::from_owned(vec![1, 2, 3]);
869        let stream = MemoryInputStream::from_bytes(&b);
870        let stream_clone = stream.clone();
871        let stream = stream.into_read().into_input_stream();
872
873        assert_eq!(stream, stream_clone);
874    }
875}