use bytes::{BytesMut, BufMut};
use futures::future;
use std::fmt::Write;
use ZapResult;
pub struct Response {
headers: BytesMut,
response: BytesMut,
status: usize,
}
impl Response {
pub fn new() -> Response {
Response {
headers: BytesMut::new(),
response: BytesMut::new(),
status: 200,
}
}
pub fn status(&mut self, code: usize) -> &mut Response {
self.status = code;
self
}
pub fn header(&mut self, name: &str, val: &str) -> &mut Response {
push(&mut self.headers, name.as_bytes());
push(&mut self.headers, b": ");
push(&mut self.headers, val.as_bytes());
push(&mut self.headers, b"\r\n");
self
}
pub fn body(&mut self, s: &str) -> &mut Response {
self.response.write_str(s).unwrap();
self
}
pub fn body_raw(&mut self, s: &[u8]) -> &mut Response {
push(&mut self.response, s);
self
}
pub fn ok(self) -> ZapResult {
future::ok(self)
}
}
pub fn encode(msg: &Response, buf: &mut BytesMut) {
let length = msg.response.len();
push(buf, b"HTTP/1.1 ");
usize_to_bytes(msg.status, buf);
push(buf, b"\r\nContent-Length: ");
usize_to_bytes(length, buf);
push(buf, b"\r\n");
push(buf, msg.headers.as_ref());
push(buf, b"\r\n");
push(buf, msg.response.as_ref());
}
fn push(buf: &mut BytesMut, data: &[u8]) {
buf.reserve(data.len());
unsafe {
buf.bytes_mut()[..data.len()].copy_from_slice(data);
buf.advance_mut(data.len());
}
}
fn usize_to_bytes(s : usize, buf : &mut BytesMut) {
let mut length = s as u32;
let mut data : [u8; 6] = [0; 6];
for i in 0..5 {
let c = 48 + (&length % 10 as u32) as u8;
data[5 - i] = c;
length = (&length / 10 as u32) as u32;
if length <= 9 {
data[4 - i] = 48 + length as u8;
push(buf, &data[(4 - i)..6]);
break;
}
}
}