1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-08-20 04:35:38 +02:00

simplify AnyBody and BodySize (#2446)

This commit is contained in:
Rob Ede
2021-11-16 09:21:10 +00:00
committed by GitHub
parent e8a0e16863
commit 4df1cd78b7
17 changed files with 67 additions and 65 deletions

View File

@@ -20,17 +20,19 @@ pub enum AnyBody {
/// Empty response. `Content-Length` header is not set.
None,
/// Zero sized response body. `Content-Length` header is set to `0`.
Empty,
/// Specific response body.
Bytes(Bytes),
/// Generic message body.
Message(BoxAnyBody),
Stream(BoxAnyBody),
}
impl AnyBody {
/// Constructs a new, empty body.
pub fn empty() -> Self {
Self::Bytes(Bytes::new())
}
/// Create body from slice (copy)
pub fn from_slice(s: &[u8]) -> Self {
Self::Bytes(Bytes::copy_from_slice(s))
@@ -42,7 +44,7 @@ impl AnyBody {
B: MessageBody + 'static,
B::Error: Into<Box<dyn StdError + 'static>>,
{
Self::Message(BoxAnyBody::from_body(body))
Self::Stream(BoxAnyBody::from_body(body))
}
}
@@ -52,9 +54,8 @@ impl MessageBody for AnyBody {
fn size(&self) -> BodySize {
match self {
AnyBody::None => BodySize::None,
AnyBody::Empty => BodySize::Empty,
AnyBody::Bytes(ref bin) => BodySize::Sized(bin.len() as u64),
AnyBody::Message(ref body) => body.size(),
AnyBody::Stream(ref body) => body.size(),
}
}
@@ -64,7 +65,6 @@ impl MessageBody for AnyBody {
) -> Poll<Option<Result<Bytes, Self::Error>>> {
match self.get_mut() {
AnyBody::None => Poll::Ready(None),
AnyBody::Empty => Poll::Ready(None),
AnyBody::Bytes(ref mut bin) => {
let len = bin.len();
if len == 0 {
@@ -74,7 +74,7 @@ impl MessageBody for AnyBody {
}
}
AnyBody::Message(body) => body
AnyBody::Stream(body) => body
.as_pin_mut()
.poll_next(cx)
.map_err(|err| Error::new_body().with_cause(err)),
@@ -86,12 +86,11 @@ impl PartialEq for AnyBody {
fn eq(&self, other: &Body) -> bool {
match *self {
AnyBody::None => matches!(*other, AnyBody::None),
AnyBody::Empty => matches!(*other, AnyBody::Empty),
AnyBody::Bytes(ref b) => match *other {
AnyBody::Bytes(ref b2) => b == b2,
_ => false,
},
AnyBody::Message(_) => false,
AnyBody::Stream(_) => false,
}
}
}
@@ -100,9 +99,8 @@ impl fmt::Debug for AnyBody {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
AnyBody::None => write!(f, "AnyBody::None"),
AnyBody::Empty => write!(f, "AnyBody::Empty"),
AnyBody::Bytes(ref b) => write!(f, "AnyBody::Bytes({:?})", b),
AnyBody::Message(_) => write!(f, "AnyBody::Message(_)"),
AnyBody::Stream(_) => write!(f, "AnyBody::Message(_)"),
}
}
}

View File

@@ -31,7 +31,7 @@ impl MessageBody for () {
type Error = Infallible;
fn size(&self) -> BodySize {
BodySize::Empty
BodySize::Sized(0)
}
fn poll_next(

View File

@@ -33,7 +33,7 @@ pub use self::sized_stream::SizedStream;
/// use bytes::Bytes;
///
/// # async fn test_to_bytes() {
/// let body = Body::Empty;
/// let body = Body::None;
/// let bytes = to_bytes(body).await.unwrap();
/// assert!(bytes.is_empty());
///
@@ -44,8 +44,9 @@ pub use self::sized_stream::SizedStream;
/// ```
pub async fn to_bytes<B: MessageBody>(body: B) -> Result<Bytes, B::Error> {
let cap = match body.size() {
BodySize::None | BodySize::Empty | BodySize::Sized(0) => return Ok(Bytes::new()),
BodySize::None | BodySize::Sized(0) => return Ok(Bytes::new()),
BodySize::Sized(size) => size as usize,
// good enough first guess for chunk size
BodySize::Stream => 32_768,
};
@@ -184,7 +185,7 @@ mod tests {
#[actix_rt::test]
async fn test_unit() {
assert_eq!(().size(), BodySize::Empty);
assert_eq!(().size(), BodySize::Sized(0));
assert!(poll_fn(|cx| Pin::new(&mut ()).poll_next(cx))
.await
.is_none());
@@ -194,11 +195,11 @@ mod tests {
async fn test_box_and_pin() {
let val = Box::new(());
pin!(val);
assert_eq!(val.size(), BodySize::Empty);
assert_eq!(val.size(), BodySize::Sized(0));
assert!(poll_fn(|cx| val.as_mut().poll_next(cx)).await.is_none());
let mut val = Box::pin(());
assert_eq!(val.size(), BodySize::Empty);
assert_eq!(val.size(), BodySize::Sized(0));
assert!(poll_fn(|cx| val.as_mut().poll_next(cx)).await.is_none());
}
@@ -214,7 +215,6 @@ mod tests {
#[actix_rt::test]
async fn test_body_debug() {
assert!(format!("{:?}", Body::None).contains("Body::None"));
assert!(format!("{:?}", Body::Empty).contains("Body::Empty"));
assert!(format!("{:?}", Body::Bytes(Bytes::from_static(b"1"))).contains('1'));
}
@@ -252,7 +252,7 @@ mod tests {
#[actix_rt::test]
async fn test_to_bytes() {
let body = Body::Empty;
let body = Body::empty();
let bytes = to_bytes(body).await.unwrap();
assert!(bytes.is_empty());

View File

@@ -6,14 +6,9 @@ pub enum BodySize {
/// Will skip writing Content-Length header.
None,
/// Zero size body.
///
/// Will write `Content-Length: 0` header.
Empty,
/// Known size body.
///
/// Will write `Content-Length: N` header. `Sized(0)` is treated the same as `Empty`.
/// Will write `Content-Length: N` header.
Sized(u64),
/// Unknown size body.
@@ -25,16 +20,17 @@ pub enum BodySize {
impl BodySize {
/// Returns true if size hint indicates no or empty body.
///
/// Streams will return false because it cannot be known without reading the stream.
///
/// ```
/// # use actix_http::body::BodySize;
/// assert!(BodySize::None.is_eof());
/// assert!(BodySize::Empty.is_eof());
/// assert!(BodySize::Sized(0).is_eof());
///
/// assert!(!BodySize::Sized(64).is_eof());
/// assert!(!BodySize::Stream.is_eof());
/// ```
pub fn is_eof(&self) -> bool {
matches!(self, BodySize::None | BodySize::Empty | BodySize::Sized(0))
matches!(self, BodySize::None | BodySize::Sized(0))
}
}