1 use crate::{Body, SizeHint}; 2 use bytes::{Buf, Bytes}; 3 use http::HeaderMap; 4 use pin_project_lite::pin_project; 5 use std::borrow::Cow; 6 use std::convert::{Infallible, TryFrom}; 7 use std::pin::Pin; 8 use std::task::{Context, Poll}; 9 10 pin_project! { 11 /// A body that consists of a single chunk. 12 #[derive(Clone, Copy, Debug)] 13 pub struct Full<D> { 14 data: Option<D>, 15 } 16 } 17 18 impl<D> Full<D> 19 where 20 D: Buf, 21 { 22 /// Create a new `Full`. new(data: D) -> Self23 pub fn new(data: D) -> Self { 24 let data = if data.has_remaining() { 25 Some(data) 26 } else { 27 None 28 }; 29 Full { data } 30 } 31 } 32 33 impl<D> Body for Full<D> 34 where 35 D: Buf, 36 { 37 type Data = D; 38 type Error = Infallible; 39 poll_data( mut self: Pin<&mut Self>, _cx: &mut Context<'_>, ) -> Poll<Option<Result<D, Self::Error>>>40 fn poll_data( 41 mut self: Pin<&mut Self>, 42 _cx: &mut Context<'_>, 43 ) -> Poll<Option<Result<D, Self::Error>>> { 44 Poll::Ready(self.data.take().map(Ok)) 45 } 46 poll_trailers( self: Pin<&mut Self>, _cx: &mut Context<'_>, ) -> Poll<Result<Option<HeaderMap>, Self::Error>>47 fn poll_trailers( 48 self: Pin<&mut Self>, 49 _cx: &mut Context<'_>, 50 ) -> Poll<Result<Option<HeaderMap>, Self::Error>> { 51 Poll::Ready(Ok(None)) 52 } 53 is_end_stream(&self) -> bool54 fn is_end_stream(&self) -> bool { 55 self.data.is_none() 56 } 57 size_hint(&self) -> SizeHint58 fn size_hint(&self) -> SizeHint { 59 self.data 60 .as_ref() 61 .map(|data| SizeHint::with_exact(u64::try_from(data.remaining()).unwrap())) 62 .unwrap_or_else(|| SizeHint::with_exact(0)) 63 } 64 } 65 66 impl<D> Default for Full<D> 67 where 68 D: Buf, 69 { 70 /// Create an empty `Full`. default() -> Self71 fn default() -> Self { 72 Full { data: None } 73 } 74 } 75 76 impl<D> From<Bytes> for Full<D> 77 where 78 D: Buf + From<Bytes>, 79 { from(bytes: Bytes) -> Self80 fn from(bytes: Bytes) -> Self { 81 Full::new(D::from(bytes)) 82 } 83 } 84 85 impl<D> From<Vec<u8>> for Full<D> 86 where 87 D: Buf + From<Vec<u8>>, 88 { from(vec: Vec<u8>) -> Self89 fn from(vec: Vec<u8>) -> Self { 90 Full::new(D::from(vec)) 91 } 92 } 93 94 impl<D> From<&'static [u8]> for Full<D> 95 where 96 D: Buf + From<&'static [u8]>, 97 { from(slice: &'static [u8]) -> Self98 fn from(slice: &'static [u8]) -> Self { 99 Full::new(D::from(slice)) 100 } 101 } 102 103 impl<D, B> From<Cow<'static, B>> for Full<D> 104 where 105 D: Buf + From<&'static B> + From<B::Owned>, 106 B: ToOwned + ?Sized, 107 { from(cow: Cow<'static, B>) -> Self108 fn from(cow: Cow<'static, B>) -> Self { 109 match cow { 110 Cow::Borrowed(b) => Full::new(D::from(b)), 111 Cow::Owned(o) => Full::new(D::from(o)), 112 } 113 } 114 } 115 116 impl<D> From<String> for Full<D> 117 where 118 D: Buf + From<String>, 119 { from(s: String) -> Self120 fn from(s: String) -> Self { 121 Full::new(D::from(s)) 122 } 123 } 124 125 impl<D> From<&'static str> for Full<D> 126 where 127 D: Buf + From<&'static str>, 128 { from(slice: &'static str) -> Self129 fn from(slice: &'static str) -> Self { 130 Full::new(D::from(slice)) 131 } 132 } 133 134 #[cfg(test)] 135 mod tests { 136 use super::*; 137 138 #[tokio::test] full_returns_some()139 async fn full_returns_some() { 140 let mut full = Full::new(&b"hello"[..]); 141 assert_eq!(full.size_hint().exact(), Some(b"hello".len() as u64)); 142 assert_eq!(full.data().await, Some(Ok(&b"hello"[..]))); 143 assert!(full.data().await.is_none()); 144 } 145 146 #[tokio::test] empty_full_returns_none()147 async fn empty_full_returns_none() { 148 assert!(Full::<&[u8]>::default().data().await.is_none()); 149 assert!(Full::new(&b""[..]).data().await.is_none()); 150 } 151 } 152