1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-02-24 04:43:21 +01:00

157 lines
3.7 KiB
Rust
Raw Normal View History

2021-02-15 12:20:43 +00:00
use std::{
fmt, mem,
pin::Pin,
task::{Context, Poll},
};
use bytes::{Bytes, BytesMut};
use futures_core::Stream;
use crate::error::Error;
use super::{BodySize, BodyStream, MessageBody, SizedStream};
/// Represents various types of HTTP message body.
2021-04-13 11:16:12 +01:00
// #[deprecated(since = "4.0.0", note = "Use body types directly.")]
2021-02-15 12:20:43 +00:00
pub enum Body {
/// Empty response. `Content-Length` header is not set.
None,
2021-04-13 11:16:12 +01:00
2021-02-15 12:20:43 +00:00
/// Zero sized response body. `Content-Length` header is set to `0`.
Empty,
2021-04-13 11:16:12 +01:00
2021-02-15 12:20:43 +00:00
/// Specific response body.
Bytes(Bytes),
2021-04-13 11:16:12 +01:00
2021-02-15 12:20:43 +00:00
/// Generic message body.
2021-04-13 11:16:12 +01:00
Message(Pin<Box<dyn MessageBody>>),
2021-02-15 12:20:43 +00:00
}
impl Body {
/// Create body from slice (copy)
pub fn from_slice(s: &[u8]) -> Body {
Body::Bytes(Bytes::copy_from_slice(s))
}
/// Create body from generic message body.
2021-04-13 11:16:12 +01:00
pub fn from_message<B: MessageBody + 'static>(body: B) -> Body {
Body::Message(Box::pin(body))
2021-02-15 12:20:43 +00:00
}
}
impl MessageBody for Body {
fn size(&self) -> BodySize {
match self {
Body::None => BodySize::None,
Body::Empty => BodySize::Empty,
Body::Bytes(ref bin) => BodySize::Sized(bin.len() as u64),
Body::Message(ref body) => body.size(),
}
}
fn poll_next(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Bytes, Error>>> {
match self.get_mut() {
Body::None => Poll::Ready(None),
Body::Empty => Poll::Ready(None),
Body::Bytes(ref mut bin) => {
let len = bin.len();
if len == 0 {
Poll::Ready(None)
} else {
Poll::Ready(Some(Ok(mem::take(bin))))
}
}
2021-04-13 11:16:12 +01:00
Body::Message(body) => body.as_mut().poll_next(cx),
2021-02-15 12:20:43 +00:00
}
}
}
impl PartialEq for Body {
fn eq(&self, other: &Body) -> bool {
match *self {
Body::None => matches!(*other, Body::None),
Body::Empty => matches!(*other, Body::Empty),
Body::Bytes(ref b) => match *other {
Body::Bytes(ref b2) => b == b2,
_ => false,
},
Body::Message(_) => false,
}
}
}
impl fmt::Debug for Body {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Body::None => write!(f, "Body::None"),
Body::Empty => write!(f, "Body::Empty"),
Body::Bytes(ref b) => write!(f, "Body::Bytes({:?})", b),
Body::Message(_) => write!(f, "Body::Message(_)"),
}
}
}
impl From<&'static str> for Body {
fn from(s: &'static str) -> Body {
Body::Bytes(Bytes::from_static(s.as_ref()))
}
}
impl From<&'static [u8]> for Body {
fn from(s: &'static [u8]) -> Body {
Body::Bytes(Bytes::from_static(s))
}
}
impl From<Vec<u8>> for Body {
fn from(vec: Vec<u8>) -> Body {
Body::Bytes(Bytes::from(vec))
}
}
impl From<String> for Body {
fn from(s: String) -> Body {
s.into_bytes().into()
}
}
impl<'a> From<&'a String> for Body {
fn from(s: &'a String) -> Body {
Body::Bytes(Bytes::copy_from_slice(AsRef::<[u8]>::as_ref(&s)))
}
}
impl From<Bytes> for Body {
fn from(s: Bytes) -> Body {
Body::Bytes(s)
}
}
impl From<BytesMut> for Body {
fn from(s: BytesMut) -> Body {
Body::Bytes(s.freeze())
}
}
impl<S> From<SizedStream<S>> for Body
where
2021-04-13 11:16:12 +01:00
S: Stream<Item = Result<Bytes, Error>> + 'static,
2021-02-15 12:20:43 +00:00
{
fn from(s: SizedStream<S>) -> Body {
Body::from_message(s)
}
}
impl<S, E> From<BodyStream<S>> for Body
where
2021-04-13 11:16:12 +01:00
S: Stream<Item = Result<Bytes, E>> + 'static,
2021-02-15 12:20:43 +00:00
E: Into<Error> + 'static,
{
fn from(s: BodyStream<S>) -> Body {
Body::from_message(s)
}
}