use crate::io::Text;
use crate::task::Join;
use bytes::Bytes;
use futures_io::AsyncRead;
use futures_util::io::AsyncReadExt;
use std::fmt;
use std::io::{self, Cursor, Read};
use std::pin::Pin;
use std::str;
use std::task::{Context, Poll};
pub struct Body(Inner);
enum Inner {
Empty,
Bytes(Cursor<Bytes>),
AsyncRead(Pin<Box<dyn AsyncRead + Send>>, Option<usize>),
}
impl Body {
pub const fn empty() -> Self {
Body(Inner::Empty)
}
pub fn bytes(bytes: impl Into<Bytes>) -> Self {
Body(Inner::Bytes(Cursor::new(bytes.into())))
}
pub fn reader(read: impl AsyncRead + Send + 'static) -> Self {
Body(Inner::AsyncRead(Box::pin(read), None))
}
pub fn reader_sized(read: impl AsyncRead + Send + 'static, length: usize) -> Self {
Body(Inner::AsyncRead(Box::pin(read), Some(length)))
}
pub fn is_empty(&self) -> bool {
self.len() == Some(0)
}
pub fn len(&self) -> Option<usize> {
match &self.0 {
Inner::Empty => Some(0),
Inner::Bytes(bytes) => Some(bytes.get_ref().len()),
Inner::AsyncRead(_, len) => *len,
}
}
pub fn reset(&mut self) -> bool {
match &mut self.0 {
Inner::Empty => true,
Inner::Bytes(cursor) => {
cursor.set_position(0);
true
}
Inner::AsyncRead(_, _) => false,
}
}
pub fn text(&mut self) -> Result<String, io::Error> {
let mut s = String::default();
self.read_to_string(&mut s)?;
Ok(s)
}
pub fn text_async(&mut self) -> Text<'_, Body> {
Text::new(self)
}
#[cfg(feature = "json")]
pub fn json<T: serde::de::DeserializeOwned>(&mut self) -> Result<T, serde_json::Error> {
serde_json::from_reader(self)
}
}
impl Read for Body {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
AsyncReadExt::read(self, buf).join()
}
}
impl AsyncRead for Body {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
match &mut self.0 {
Inner::Empty => Poll::Ready(Ok(0)),
Inner::Bytes(cursor) => AsyncRead::poll_read(Pin::new(cursor), cx, buf),
Inner::AsyncRead(read, _) => AsyncRead::poll_read(read.as_mut(), cx, buf),
}
}
}
impl Default for Body {
fn default() -> Self {
Self::empty()
}
}
impl From<()> for Body {
fn from(_: ()) -> Self {
Self::empty()
}
}
impl From<Vec<u8>> for Body {
fn from(body: Vec<u8>) -> Self {
Self::bytes(body)
}
}
impl From<&'static [u8]> for Body {
fn from(body: &'static [u8]) -> Self {
Bytes::from_static(body).into()
}
}
impl From<Bytes> for Body {
fn from(body: Bytes) -> Self {
Self::bytes(body)
}
}
impl From<String> for Body {
fn from(body: String) -> Self {
body.into_bytes().into()
}
}
impl From<&'static str> for Body {
fn from(body: &'static str) -> Self {
body.as_bytes().into()
}
}
impl<T: Into<Body>> From<Option<T>> for Body {
fn from(body: Option<T>) -> Self {
match body {
Some(body) => body.into(),
None => Self::default(),
}
}
}
impl fmt::Debug for Body {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.len() {
Some(len) => write!(f, "Body({})", len),
None => write!(f, "Body(?)"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn is_send<T: Send>() {}
#[test]
fn traits() {
is_send::<Body>();
}
}