1use http_body::{Body as HttpBody, Frame, SizeHint};
5use std::{
6 convert::Infallible,
7 pin::Pin,
8 task::{Context, Poll},
9};
10
11#[derive(Debug)]
17pub struct Body<'a> {
18 data: Option<&'a [u8]>,
20}
21impl<'a> Body<'a> {
22 pub fn new(data: &'a [u8]) -> Self {
24 let data = if !data.is_empty() { Some(data) } else { None };
25 Self { data }
26 }
27
28 pub fn empty() -> Self {
30 let data = None;
31 Self { data }
32 }
33
34 pub fn data(&self) -> &'a [u8] {
39 self.data.unwrap_or(b"")
40 }
41}
42impl<'a> HttpBody for Body<'a> {
43 type Data = &'a [u8];
44 type Error = Infallible;
45
46 fn poll_frame(
47 self: Pin<&mut Self>,
48 _cx: &mut Context<'_>,
49 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
50 let self_ = unsafe { self.get_unchecked_mut() };
51 let data = self_.data.take();
52
53 match data {
54 Some(data) => Poll::Ready(Some(Ok(Frame::data(data)))),
55 None => Poll::Ready(None),
56 }
57 }
58
59 fn is_end_stream(&self) -> bool {
60 self.data.is_none()
61 }
62
63 fn size_hint(&self) -> SizeHint {
64 match self.data {
65 Some(data) => SizeHint::with_exact(data.len() as u64),
66 None => SizeHint::with_exact(0),
67 }
68 }
69}
70
71#[cfg(test)]
72mod test_body {
73 use super::Body as Body_;
74 use http_body::Body;
75 use http_body_util::combinators::BoxBody;
76
77 #[test]
79 fn body_converts_to_box_body() {
80 let body = Body_::new(b"foo");
81 let box_body = BoxBody::new(body);
82
83 assert_eq!(box_body.size_hint().lower(), 3);
84 }
85}