#![crate_name = "rustful"]
#![crate_type = "rlib"]
#![doc(html_root_url = "http://ogeon.github.io/docs/rustful/master/")]
#![cfg_attr(test, cfg_attr(feature = "benchmark", feature(test)))]
#[cfg(test)]
#[cfg(feature = "benchmark")]
extern crate test;
#[cfg(test)]
extern crate tempdir;
#[cfg(feature = "rustc-serialize")]
extern crate rustc_serialize;
extern crate url;
extern crate time;
extern crate hyper;
extern crate anymap;
extern crate unicase as uni;
extern crate phf;
pub use hyper::mime;
pub use hyper::method::Method;
pub use hyper::status::StatusCode;
pub use hyper::header;
pub use hyper::Result as HttpResult;
pub use hyper::Error as HttpError;
pub use hyper::version::HttpVersion;
pub use uni as unicase;
pub use self::server::Server;
pub use self::context::Context;
pub use self::response::Response;
pub use self::response::Error;
pub use self::handler::Handler;
pub use self::router::Router;
pub use self::log::Log;
pub use self::router::TreeRouter;
mod utils;
#[macro_use]
#[doc(hidden)]
pub mod macros;
pub mod server;
pub mod router;
pub mod handler;
pub mod context;
pub mod response;
pub mod filter;
pub mod log;
pub mod file;
use std::path::Path;
use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6, Ipv4Addr};
use std::str::FromStr;
use std::any::TypeId;
use anymap::Map;
use anymap::any::{Any, UncheckedAnyExt};
pub enum Scheme<'a> {
Http,
Https {
cert: &'a Path,
key: &'a Path
}
}
#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy)]
pub struct Host(SocketAddr);
impl Host {
pub fn any_v4(port: u16) -> Host {
Host(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), port)))
}
pub fn port(&mut self, port: u16) {
self.0 = match self.0 {
SocketAddr::V4(addr) => SocketAddr::V4(SocketAddrV4::new(addr.ip().clone(), port)),
SocketAddr::V6(addr) => {
SocketAddr::V6(SocketAddrV6::new(addr.ip().clone(), port, addr.flowinfo(), addr.scope_id()))
}
};
}
}
impl From<Host> for SocketAddr {
fn from(host: Host) -> SocketAddr {
host.0
}
}
impl From<u16> for Host {
fn from(port: u16) -> Host {
Host::any_v4(port)
}
}
impl From<SocketAddr> for Host {
fn from(addr: SocketAddr) -> Host {
Host(addr)
}
}
impl From<SocketAddrV4> for Host {
fn from(addr: SocketAddrV4) -> Host {
Host(SocketAddr::V4(addr))
}
}
impl From<SocketAddrV6> for Host {
fn from(addr: SocketAddrV6) -> Host {
Host(SocketAddr::V6(addr))
}
}
impl From<(Ipv4Addr, u16)> for Host {
fn from((ip, port): (Ipv4Addr, u16)) -> Host {
Host(SocketAddr::V4(SocketAddrV4::new(ip, port)))
}
}
impl FromStr for Host {
type Err = <SocketAddr as FromStr>::Err;
fn from_str(s: &str) -> Result<Host, Self::Err> {
s.parse().map(|s| Host(s))
}
}
pub struct Global(GlobalState);
impl Global {
pub fn get<T: Any + Send + Sync>(&self) -> Option<&T> {
match self.0 {
GlobalState::None => None,
GlobalState::One(id, ref a) => if id == TypeId::of::<T>() {
unsafe { Some(a.downcast_ref_unchecked()) }
} else {
None
},
GlobalState::Many(ref map) => map.get()
}
}
pub fn insert<T: Any + Send + Sync>(&mut self, value: T) -> Option<T> {
match self.0 {
GlobalState::None => {
*self = Box::new(value).into();
None
},
GlobalState::One(id, _) => if id == TypeId::of::<T>() {
if let GlobalState::One(_, ref mut previous_value) = self.0 {
let mut v = Box::new(value) as Box<Any + Send + Sync>;
std::mem::swap(previous_value, &mut v);
Some(unsafe { *v.downcast_unchecked() })
} else {
unreachable!()
}
} else {
let mut other = GlobalState::Many(Map::new());
std::mem::swap(&mut self.0, &mut other);
if let GlobalState::Many(ref mut map) = self.0 {
if let GlobalState::One(id, previous_value) = other {
let mut raw = map.as_mut();
unsafe { raw.insert(id, previous_value); }
}
map.insert(value)
} else {
unreachable!()
}
},
GlobalState::Many(ref mut map) => {
map.insert(value)
}
}
}
}
impl<T: Any + Send + Sync> From<Box<T>> for Global {
fn from(data: Box<T>) -> Global {
Global(GlobalState::One(TypeId::of::<T>(), data))
}
}
macro_rules! from_tuple {
($first: ident, $($t: ident),+) => (
impl<$first: Any + Send + Sync, $($t: Any + Send + Sync),+> From<($first, $($t),+)> for Global {
#[allow(non_snake_case)]
fn from(tuple: ($first, $($t),+))-> Global {
let ($first, $($t),+) = tuple;
let mut map = Map::new();
map.insert($first);
$(
map.insert($t);
)+
Global(GlobalState::Many(map))
}
}
from_tuple!($($t),+);
);
($ty: ident) => (
impl<$ty: Any + Send + Sync> From<($ty,)> for Global {
fn from(tuple: ($ty,)) -> Global {
Box::new(tuple.0).into()
}
}
);
}
impl From<()> for Global {
fn from(_: ()) -> Global {
Global(GlobalState::None)
}
}
from_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
impl Default for Global {
fn default() -> Global {
Global(GlobalState::None)
}
}
enum GlobalState {
None,
One(TypeId, Box<Any + Send + Sync>),
Many(Map<Any + Send + Sync>),
}