servlin/
body_async_reader.rs

1use crate::event::EventReceiver;
2use std::io::{Cursor, Read};
3use std::path::Path;
4use std::pin::Pin;
5use std::sync::Mutex;
6use std::task::{Context, Poll};
7
8/// Struct returned by `RequestBody::async_reader` and `ResponseBody::async_reader`.
9pub enum BodyAsyncReader<'x> {
10    Cursor(Cursor<&'x [u8]>),
11    EventReceiver(&'x Mutex<EventReceiver>),
12    File(async_fs::File),
13}
14impl<'x> BodyAsyncReader<'x> {
15    #[must_use]
16    pub fn bytes(bytes: &'x [u8]) -> Self {
17        Self::Cursor(Cursor::new(bytes))
18    }
19
20    /// # Errors
21    /// Returns an error when it fails to open the file for reading.
22    pub async fn file(path: impl AsRef<Path>) -> Result<BodyAsyncReader<'x>, std::io::Error> {
23        let file = async_fs::File::open(path.as_ref()).await?;
24        Ok(BodyAsyncReader::File(file))
25    }
26}
27impl futures_io::AsyncRead for BodyAsyncReader<'_> {
28    fn poll_read(
29        mut self: Pin<&mut Self>,
30        cx: &mut Context<'_>,
31        buf: &mut [u8],
32    ) -> Poll<Result<usize, std::io::Error>> {
33        match &mut *self {
34            BodyAsyncReader::Cursor(cursor) => Poll::Ready(cursor.read(buf)),
35            BodyAsyncReader::EventReceiver(mutex_event_receiver) =>
36            {
37                #[allow(clippy::mut_mutex_lock)]
38                Pin::new(&mut *mutex_event_receiver.lock().unwrap()).poll_read(cx, buf)
39            }
40            BodyAsyncReader::File(async_fs_file) => Pin::new(async_fs_file).poll_read(cx, buf),
41        }
42    }
43}