titan_http/
body.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use std::{
  convert::Infallible,
  pin::{pin, Pin},
  task::Poll,
};

use bytes::Bytes;
use futures_core::Stream;
use http_body::{Frame, SizeHint};

pub enum Body {
  Full(Box<[u8]>),
  Stream(Pin<Box<dyn Stream<Item = Vec<u8>> + Send>>),
}

impl http_body::Body for Body {
  type Data = Bytes;
  type Error = Infallible;

  fn size_hint(&self) -> http_body::SizeHint {
    match self {
      Body::Full(value) => SizeHint::with_exact(value.len() as u64),
      Body::Stream(body) => {
        let (lower, higher) = body.size_hint();
        let mut size_hint = SizeHint::default();
        size_hint.set_lower(lower as u64);
        if let Some(higher) = higher {
          size_hint.set_upper(higher as u64);
        }
        size_hint
      }
    }
  }

  fn poll_frame(
    self: Pin<&mut Self>,
    cx: &mut std::task::Context<'_>,
  ) -> std::task::Poll<Option<Result<http_body::Frame<Self::Data>, Self::Error>>>
  {
    match self.get_mut() {
      Body::Full(body) => {
        Poll::Ready(Some(Ok(Frame::data(Bytes::from(body.clone())))))
      }
      Body::Stream(body) => {
        let value = pin!(body);
        let value = match value.poll_next(cx) {
          Poll::Pending => return Poll::Pending,
          Poll::Ready(value) => match value {
            None => return Poll::Ready(None),
            Some(value) => value,
          },
        };

        let frame = Frame::data(Bytes::from(value));
        Poll::Ready(Some(Ok(frame)))
      }
    }
  }

  fn is_end_stream(&self) -> bool {
    // TODO
    true
  }
}

impl From<String> for Body {
  fn from(value: String) -> Self {
    Self::Full(value.as_bytes().into())
  }
}

impl From<()> for Body {
  fn from(_: ()) -> Self {
    Self::Full([].into())
  }
}

impl<'a> From<&'a str> for Body {
  fn from(value: &'a str) -> Self {
    Self::Full(value.as_bytes().into())
  }
}

impl From<Box<[u8]>> for Body {
  fn from(value: Box<[u8]>) -> Self {
    Self::Full(value)
  }
}

impl From<Vec<u8>> for Body {
  fn from(value: Vec<u8>) -> Self {
    Self::Full(value.into())
  }
}

impl From<&'_ [u8]> for Body {
  fn from(value: &'_ [u8]) -> Self {
    Self::Full(value.into())
  }
}

//impl From<StatusCode> for Body {
//  fn from(value: StatusCode) -> Self {
//    match value {
//      StatusCode::OK => "Ok",
//      StatusCode::BAD_REQUEST => "Bad Request",
//      _ => panic!("no"),
//    }
//    .into()
//  }
//}

//impl From<Body> for String {
//  fn from(value: Body) -> Self {
//    match value {
//      Body::Full(bytes) => unsafe {
//        String::from_utf8_unchecked(bytes.to_vec())
//      },
//    }
//  }
//}

macro_rules! impl_tostring {
  ($( $type:ident )*) => {
    $(impl From<$type> for Body {
          fn from(value: $type) -> Self {
            let body_str = value.to_string();
            Self::Full(body_str.as_bytes().into())
          }
    })*
  };
}

impl_tostring! { usize i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 }