use std::any::Any;
use std::fmt;
use {Error, Result, HttpTryFrom, Extensions};
use header::{HeaderMap, HeaderName, HeaderValue};
use status::StatusCode;
use version::Version;
pub struct Response<T> {
head: Parts,
body: T,
}
pub struct Parts {
pub status: StatusCode,
pub version: Version,
pub headers: HeaderMap<HeaderValue>,
pub extensions: Extensions,
_priv: (),
}
#[derive(Debug)]
pub struct Builder {
head: Option<Parts>,
err: Option<Error>,
}
impl Response<()> {
#[inline]
pub fn builder() -> Builder {
Builder::new()
}
}
impl<T> Response<T> {
#[inline]
pub fn new(body: T) -> Response<T> {
Response {
head: Parts::new(),
body: body,
}
}
#[inline]
pub fn from_parts(parts: Parts, body: T) -> Response<T> {
Response {
head: parts,
body: body,
}
}
#[inline]
pub fn status(&self) -> StatusCode {
self.head.status
}
#[inline]
pub fn status_mut(&mut self) -> &mut StatusCode {
&mut self.head.status
}
#[inline]
pub fn version(&self) -> Version {
self.head.version
}
#[inline]
pub fn version_mut(&mut self) -> &mut Version {
&mut self.head.version
}
#[inline]
pub fn headers(&self) -> &HeaderMap<HeaderValue> {
&self.head.headers
}
#[inline]
pub fn headers_mut(&mut self) -> &mut HeaderMap<HeaderValue> {
&mut self.head.headers
}
#[inline]
pub fn extensions(&self) -> &Extensions {
&self.head.extensions
}
#[inline]
pub fn extensions_mut(&mut self) -> &mut Extensions {
&mut self.head.extensions
}
#[inline]
pub fn body(&self) -> &T {
&self.body
}
#[inline]
pub fn body_mut(&mut self) -> &mut T {
&mut self.body
}
#[inline]
pub fn into_body(self) -> T {
self.body
}
#[inline]
pub fn into_parts(self) -> (Parts, T) {
(self.head, self.body)
}
#[inline]
pub fn map<F, U>(self, f: F) -> Response<U>
where F: FnOnce(T) -> U
{
Response { body: f(self.body), head: self.head }
}
}
impl<T: Default> Default for Response<T> {
#[inline]
fn default() -> Response<T> {
Response::new(T::default())
}
}
impl<T: fmt::Debug> fmt::Debug for Response<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Response")
.field("status", &self.status())
.field("version", &self.version())
.field("headers", self.headers())
.field("body", self.body())
.finish()
}
}
impl Parts {
fn new() -> Parts {
Parts{
status: StatusCode::default(),
version: Version::default(),
headers: HeaderMap::default(),
extensions: Extensions::default(),
_priv: (),
}
}
}
impl fmt::Debug for Parts {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Parts")
.field("status", &self.status)
.field("version", &self.version)
.field("headers", &self.headers)
.finish()
}
}
impl Builder {
#[inline]
pub fn new() -> Builder {
Builder::default()
}
pub fn status<T>(&mut self, status: T) -> &mut Builder
where StatusCode: HttpTryFrom<T>,
{
if let Some(head) = head(&mut self.head, &self.err) {
match HttpTryFrom::try_from(status) {
Ok(s) => head.status = s,
Err(e) => self.err = Some(e.into()),
}
}
self
}
pub fn version(&mut self, version: Version) -> &mut Builder {
if let Some(head) = head(&mut self.head, &self.err) {
head.version = version;
}
self
}
pub fn header<K, V>(&mut self, key: K, value: V) -> &mut Builder
where HeaderName: HttpTryFrom<K>,
HeaderValue: HttpTryFrom<V>
{
if let Some(head) = head(&mut self.head, &self.err) {
match <HeaderName as HttpTryFrom<K>>::try_from(key) {
Ok(key) => {
match <HeaderValue as HttpTryFrom<V>>::try_from(value) {
Ok(value) => { head.headers.append(key, value); }
Err(e) => self.err = Some(e.into()),
}
},
Err(e) => self.err = Some(e.into()),
};
}
self
}
pub fn headers_ref(&self) -> Option<&HeaderMap<HeaderValue>> {
if self.err.is_some() {
return None;
}
match self.head
{
Some(ref head) => Some(&head.headers),
None => None
}
}
pub fn headers_mut(&mut self) -> Option<&mut HeaderMap<HeaderValue>> {
if self.err.is_some() {
return None;
}
match self.head
{
Some(ref mut head) => Some(&mut head.headers),
None => None
}
}
pub fn extension<T>(&mut self, extension: T) -> &mut Builder
where T: Any + Send + Sync + 'static,
{
if let Some(head) = head(&mut self.head, &self.err) {
head.extensions.insert(extension);
}
self
}
fn take_parts(&mut self) -> Result<Parts> {
let ret = self.head.take().expect("cannot reuse response builder");
if let Some(e) = self.err.take() {
return Err(e)
}
Ok(ret)
}
pub fn body<T>(&mut self, body: T) -> Result<Response<T>> {
Ok(Response {
head: self.take_parts()?,
body: body,
})
}
}
fn head<'a>(head: &'a mut Option<Parts>, err: &Option<Error>)
-> Option<&'a mut Parts>
{
if err.is_some() {
return None
}
head.as_mut()
}
impl Default for Builder {
#[inline]
fn default() -> Builder {
Builder {
head: Some(Parts::new()),
err: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_can_map_a_body_from_one_type_to_another() {
let response = Response::builder().body("some string").unwrap();
let mapped_response = response.map(|s| {
assert_eq!(s, "some string");
123u32
});
assert_eq!(mapped_response.body(), &123u32);
}
}