use std::sync::Arc;
use std::marker::PhantomData;
use std::collections::hash_map::Entry;
use std::io::{Error, Result, ErrorKind};
use https::Method;
use regex::{RegexSetBuilder, RegexSet, RegexBuilder, Regex};
use pi_hash::XHashMap;
use pi_atom::Atom;
use tcp::Socket;
use crate::{service::HttpService,
middleware::Middleware};
const DOT_CHAR: &str = r".";
const SINGLE_STAR_CHAR: &str = r"*";
const DOUBLE_STAR_CHAR: &str = r"**";
const REPLACED_DOT: &str = r"\.";
const REPLACED_SINGLE_STAR: &str = r"([\w \.-])+";
const REPLACED_DOUBLE_STAR: &str = r"/?([\w \.-]/?)+";
struct WildcardRouter<S: Socket, Context: Send + Sync + 'static, Handler: Middleware<S, Context>> {
matchor: Option<RegexSet>, route: Arc<Vec<Atom>>, handlers: Arc<Vec<Arc<Handler>>>, marker: PhantomData<(S, Context)>,
}
impl<S: Socket, Context: Send + Sync + 'static, Handler: Middleware<S, Context>> Clone for WildcardRouter<S, Context, Handler> {
fn clone(&self) -> Self {
WildcardRouter {
matchor: self.matchor.clone(), route: self.route.clone(),
handlers: self.handlers.clone(),
marker: PhantomData,
}
}
}
impl<S: Socket, Context: Send + Sync + 'static, Handler: Middleware<S, Context>> WildcardRouter<S, Context, Handler> {
pub fn new() -> Self {
WildcardRouter {
matchor: None,
route: Arc::new(Vec::new()),
handlers: Arc::new(Vec::new()),
marker: PhantomData,
}
}
pub fn with_capacity(capacity: usize) -> Self {
WildcardRouter {
matchor: None,
route: Arc::new(Vec::with_capacity(capacity)),
handlers: Arc::new(Vec::with_capacity(capacity)),
marker: PhantomData,
}
}
pub fn len(&self) -> usize {
self.route.len()
}
pub fn add(&mut self, route: Atom, handler: Handler) {
if let Some(vec) = Arc::get_mut(&mut self.route) {
vec.push(route);
} else {
panic!("Add wildcard route error, get mut ref failed");
}
if let Some(vec) = Arc::get_mut(&mut self.handlers) {
vec.push(Arc::new(handler));
} else {
panic!("Add wildcard route handler error, get mut ref failed");
}
}
pub fn finish(&mut self) -> Result<()> {
let route: Vec<&str> = self.route.iter().map(|r| {
r.as_ref()
}).collect();
match RegexSetBuilder::new(route.as_slice()).build() {
Err(e) => {
Err(Error::new(ErrorKind::Other,
format!("Finish wildcard router failed, reason: {:?}",
e)))
},
Ok(set) => {
self.matchor = Some(set);
Ok(())
}
}
}
pub fn is_match(&self, path: &str) -> bool {
if let Some(matchor) = &self.matchor {
return matchor.is_match(path);
}
false
}
pub fn match_route(&self, path: &str) -> Option<Arc<Handler>> {
if let Some(matchor) = &self.matchor {
let indexes: Vec<usize> = matchor.matches(path).into_iter().collect();
let len = indexes.len();
if len > 0 {
return Some(self.handlers[indexes[len - 1]].clone());
}
}
None
}
}
struct Router<S: Socket,Context: Send + Sync + 'static, Handler: Middleware<S, Context>> {
fixed: Arc<XHashMap<Atom, Arc<Handler>>>, single_wildcard: WildcardRouter<S, Context, Handler>, mutil_wildcard: WildcardRouter<S, Context, Handler>, filter: Arc<Regex>, }
impl<S: Socket, Context: Send + Sync + 'static, Handler: Middleware<S, Context>> Clone for Router<S, Context, Handler> {
fn clone(&self) -> Self {
Router {
fixed: self.fixed.clone(),
single_wildcard: self.single_wildcard.clone(),
mutil_wildcard: self.mutil_wildcard.clone(),
filter: self.filter.clone(),
}
}
}
impl<S: Socket, Context: Send + Sync + 'static, Handler: Middleware<S, Context>> Router<S, Context, Handler> {
pub fn new() -> Self {
Router {
fixed: Arc::new(XHashMap::default()),
single_wildcard: WildcardRouter::new(),
mutil_wildcard: WildcardRouter::new(),
filter: Arc::new(RegexBuilder::new(r"^([^\*])+[\.\*]$").build().ok().unwrap()),
}
}
pub fn with(route: String, handler: Handler) -> Self {
let mut router = Self::new();
router.add(route, handler);
router
}
pub fn len(&self) -> usize {
self.fixed.len() + self.single_wildcard.len() + self.mutil_wildcard.len()
}
pub fn add(&mut self, mut route: String, handler: Handler) {
if self.filter.is_match(&route) {
route = route.replace(".*", "");
}
if route.contains(DOUBLE_STAR_CHAR) {
let atom = Atom::from(route.replace(DOT_CHAR, REPLACED_DOT)
.replace(DOUBLE_STAR_CHAR, REPLACED_DOUBLE_STAR)
.replace(SINGLE_STAR_CHAR, REPLACED_SINGLE_STAR));
self.mutil_wildcard.add(atom, handler);
} else if route.contains(SINGLE_STAR_CHAR) {
let atom = Atom::from(route.replace(DOT_CHAR, REPLACED_DOT)
.replace(SINGLE_STAR_CHAR, REPLACED_SINGLE_STAR));
self.single_wildcard.add(atom, handler);
} else {
if let Some(map) = Arc::get_mut(&mut self.fixed) {
let atom = Atom::from(route);
map.insert(atom.clone(), Arc::new(handler));
} else {
panic!("Add route error, get mut ref failed");
}
}
}
pub fn finish(&mut self) -> Result<()> {
if let Err(e) = self.single_wildcard.finish() {
return Err(e);
}
if let Err(e) = self.mutil_wildcard.finish() {
return Err(e);
}
Ok(())
}
pub fn is_match(&self, path: &str) -> bool {
if !self.fixed.contains_key(&Atom::from(path)) {
if !self.single_wildcard.is_match(path) {
return self.mutil_wildcard.is_match(path);
}
}
true
}
pub fn match_route(&self, path: &str) -> Option<Arc<Handler>> {
if let Some(handler) = self.fixed.get(&Atom::from(path)) {
return Some(handler.clone());
}
if let Some(handler) = self.single_wildcard.match_route(path) {
return Some(handler);
}
if let Some(handler) = self.mutil_wildcard.match_route(path) {
return Some(handler);
}
None
}
}
pub struct RouterTab<S: Socket, Context: Send + Sync + 'static, Handler: Middleware<S, Context>> {
map: XHashMap<Method, Router<S, Context, Handler>>, }
impl<S: Socket, Context: Send + Sync + 'static, Handler: Middleware<S, Context>> Clone for RouterTab<S, Context, Handler> {
fn clone(&self) -> Self {
RouterTab {
map: self.map.clone(),
}
}
}
impl<S: Socket, Context: Send + Sync + 'static, Handler: Middleware<S, Context>> RouterTab<S, Context, Handler> {
pub fn new() -> Self {
RouterTab {
map: XHashMap::default(),
}
}
pub fn len(&self) -> usize {
self.map.iter().map(|(_, router)| {
router.len()
}).collect::<Vec<usize>>().iter().sum()
}
pub fn add(&mut self, route: String, method: Method, handler: Handler) {
match self.map.entry(method) {
Entry::Vacant(v) => {
v.insert(Router::with(route, handler));
},
Entry::Occupied(mut o) => {
o.get_mut().add(route, handler);
},
}
}
pub fn finish(&mut self) -> Result<()> {
for router in self.map.values_mut() {
if let Err(e) = router.finish() {
return Err(e);
}
}
Ok(())
}
pub fn is_match(&self, method: &Method, path: &str) -> bool {
if let Some(router) = self.map.get(method) {
return router.is_match(path);
}
false
}
pub fn match_route(&self, method: &Method, path: &str) -> Option<Arc<Handler>> {
if let Some(router) = self.map.get(method) {
return router.match_route(path);
}
None
}
}
pub struct HttpRoute<S: Socket, Context: Send + Sync + 'static, Handler: Middleware<S, Context>> {
tab: RouterTab<S, Context, Handler>, path: String, }
impl<S: Socket, Context: Send + Sync + 'static, Handler: Middleware<S, Context>> From<HttpRoute<S, Context, Handler>> for RouterTab<S, Context, Handler> {
fn from(route: HttpRoute<S, Context, Handler>) -> Self {
let mut tab = route.tab;
tab.finish();
tab
}
}
impl<S: Socket, Context: Send + Sync + 'static, Handler: Middleware<S, Context>> HttpRoute<S, Context, Handler> {
pub fn new() -> Self {
HttpRoute {
tab: RouterTab::new(),
path: String::default(),
}
}
pub fn at(&mut self, path: &str) -> &mut Self {
self.path = path.to_string();
self
}
pub fn method(&mut self, method: Method, handler: Handler) -> &mut Self {
self.tab.add(self.path.clone(), method, handler);
self
}
pub fn options(&mut self, handler: Handler) -> &mut Self {
self.method(Method::OPTIONS, handler);
self
}
pub fn head(&mut self, handler: Handler) -> &mut Self {
self.method(Method::HEAD, handler);
self
}
pub fn get(&mut self, handler: Handler) -> &mut Self {
self.method(Method::GET, handler);
self
}
pub fn post(&mut self, handler: Handler) -> &mut Self {
self.method(Method::POST, handler);
self
}
}