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
use view::{ ViewResult, ViewResultEnum };
use std::any::Any;
use hyper::server::{ Server as HyperServer, Request as HyperRequest, Response as HyperResponse, Listening };
use std::marker::{ Send, Sync };

use server::Request;
use std::error::Error;

pub struct Server {
	server: Listening
}

impl Server {
	pub fn create<
		THost: ToString,
		TControllerCallback: Send + Sync + 'static + Fn(&mut Request) -> (&'static str, ViewResult),
		TViewCallback: Send + Sync + 'static + Fn(String) -> Option<String>,
		TViewModelCallback: Send + Sync + 'static + Fn(String, Box<Any>) -> Option<String>
	>(host: THost, port: u16, controller_callback: TControllerCallback, view_callback: TViewCallback, view_model_callback: TViewModelCallback) -> Server {
		let addr = format!("{}:{}", host.to_string(), port);
		Server {
			server: HyperServer::http(addr.as_str()).unwrap().handle(move |req: HyperRequest, res: HyperResponse| {
				let url = format!("{}", req.uri);
				let mut request = Request::new(url.clone());

				let result = controller_callback(&mut request);
				let result = (result.0, match result.1 {
					Err(e) => {
						res.send(e.description().as_bytes()).unwrap();
						return;
					},
					Ok(r) => r
				});

				let view_result = match result.1 {
					ViewResultEnum::CurrentView => view_callback(result.0.to_string()),
					ViewResultEnum::CurrentViewWithModel(model) => view_model_callback(result.0.to_string(), model),
					ViewResultEnum::SpecificView(view) => view_callback(view),
					ViewResultEnum::SpecificViewWithModel(view, model) => view_model_callback(view, model),
				};
				
				match view_result {
					Some(r) => res.send(r.as_bytes()).unwrap(),
					None => res.send(b"<html><body><h1>Page not found</h1></body></html>").unwrap()
				};
			}).unwrap()
		}
	}

	#[allow(dead_code)]
	pub fn close(&mut self) {
		self.server.close().unwrap();
	}
}