use std::os::raw::{c_char, c_void};
use std::ffi::CStr;
use std::ptr::null;
use std::rc::Rc;
use ::servlet::{Unimplemented, AsyncServlet, SyncServlet, ServletMode, ServletFuncResult, Bootstrap, AsyncTaskHandle, fail, BootstrapResult};
use ::protocol::{TypeModelObject, TypeInstanceObject, Untyped, ProtocolModel, DataModel};
impl SyncServlet for Unimplemented {
type ProtocolType = Untyped;
type DataModelType = Untyped;
fn init(&mut self, _args:&[&str],
_type_inst : &mut Untyped) -> ServletFuncResult
{
return fail();
}
fn exec(&mut self, _ti : Untyped) -> ServletFuncResult
{
return fail();
}
fn cleanup(&mut self) -> ServletFuncResult
{
return fail();
}
}
impl AsyncServlet for Unimplemented {
type ProtocolType = ();
type DataModelType = ();
type AsyncTaskData = ();
fn init(&mut self, _args:&[&str],
_type_inst:&mut ()) -> ServletFuncResult
{
return fail();
}
fn async_init(&mut self,
_handle:&AsyncTaskHandle,
_ti:()) -> Option<Box<()>>
{
return None;
}
fn async_exec(_handle:&AsyncTaskHandle,
_task_data:&mut Self::AsyncTaskData) -> ServletFuncResult
{
return fail();
}
fn async_cleanup(&mut self,
_handle:&AsyncTaskHandle,
_task_data:&mut Self::AsyncTaskData,
_ti:()) -> ServletFuncResult
{
return fail();
}
fn cleanup(&mut self) -> ServletFuncResult
{
return fail();
}
}
struct SyncServletObject<BT:Bootstrap> {
protocol_model : Rc<<BT::SyncServletType as SyncServlet>::ProtocolType>,
servlet_context: BT::SyncServletType
}
struct AsyncServletObject<BT:Bootstrap> {
protocol_model : Rc<<BT::AsyncServletType as AsyncServlet>::ProtocolType>,
servlet_context: BT::AsyncServletType
}
enum ServletObject<BT:Bootstrap> {
SYNC(SyncServletObject<BT>),
ASYNC(AsyncServletObject<BT>)
}
fn create_servlet_object<BT:Bootstrap>(bs_result:ServletMode<BT::AsyncServletType, BT::SyncServletType>,
type_model_obj: TypeModelObject) -> ServletObject<BT>
{
match bs_result {
ServletMode::SyncMode(servlet) => {
let protocol_model = <BT::SyncServletType as SyncServlet>::ProtocolType::new_protocol_model(type_model_obj);
return ServletObject::SYNC(SyncServletObject {
protocol_model : Rc::new(protocol_model),
servlet_context: servlet
});
},
ServletMode::AsyncMode(servlet) => {
let protocol_model = <BT::AsyncServletType as AsyncServlet>::ProtocolType::new_protocol_model(type_model_obj);
return ServletObject::ASYNC(AsyncServletObject {
protocol_model : Rc::new(protocol_model),
servlet_context: servlet
});
}
}
}
unsafe fn make_argument_list<'a>(argc: u32, argv: *const *const c_char) -> Option<Vec<&'a str>>
{
let mut args = Vec::new();
for idx in 0..argc
{
let current = argv.offset(idx as isize);
let c_str = CStr::from_ptr(*current);
if let Ok(str_obj) = c_str.to_str()
{
args.push(str_obj);
}
else
{
return None;
}
}
return Some(args);
}
unsafe fn unpack<'a, T>(ptr : *mut c_void) -> &'a mut T
{
return Box::leak(Box::<T>::from_raw(ptr as *mut T));
}
unsafe fn dispose<T>(ptr : *mut c_void)
{
Box::from_raw(ptr as *mut T);
}
unsafe fn unpack_servlet_object<'a, BT:Bootstrap>(obj_ptr : *mut c_void) -> &'a mut ServletObject<BT>
{
unpack(obj_ptr)
}
unsafe fn dispose_servlet_object<BT:Bootstrap>(obj_ptr : *mut c_void)
{
dispose::<ServletObject<BT>>(obj_ptr);
}
unsafe fn unpack_async_handle<'a>(handle_ptr : *mut c_void) -> &'a AsyncTaskHandle
{
unpack(handle_ptr)
}
unsafe fn unpack_async_task_data<'a, BT:Bootstrap>(data_ptr : *mut c_void) -> &'a mut <<BT as Bootstrap>::AsyncServletType as AsyncServlet>::AsyncTaskData
{
unpack(data_ptr)
}
unsafe fn dispose_async_task_data<BT:Bootstrap>(obj_ptr : *mut c_void)
{
dispose::<<<BT as Bootstrap>::AsyncServletType as AsyncServlet>::AsyncTaskData>(obj_ptr);
}
pub unsafe fn call_bootstrap_obj<T:Bootstrap>(argc: u32, argv: *const *const c_char, type_model_ptr:*mut c_void) -> *mut c_void
{
if let Some(type_model) = TypeModelObject::from_raw(type_model_ptr as *mut c_void)
{
if let Some(args) = make_argument_list(argc, argv)
{
if let BootstrapResult::Success(servlet_mode) = T::get(&args[0..])
{
let result_obj = Box::new(create_servlet_object::<T>(servlet_mode, type_model));
return Box::into_raw(result_obj) as *mut c_void;
}
}
}
return null::<c_void>() as *mut c_void;
}
pub fn invoke_servlet_init<BT:Bootstrap>(obj_ptr : *mut c_void, argc: u32, argv: *const *const c_char) -> i32
{
if let Some(args) = unsafe{ make_argument_list(argc, argv) }
{
match unsafe { unpack_servlet_object::<BT>(obj_ptr) }
{
ServletObject::SYNC(ref mut servlet) => {
if let Some(pm_ref) = Rc::get_mut(&mut servlet.protocol_model)
{
if let Ok(_) = servlet.servlet_context.init(&args[0..], pm_ref)
{
return 0;
}
}
},
ServletObject::ASYNC(ref mut servlet) => {
if let Some(pm_ref) = Rc::get_mut(&mut servlet.protocol_model)
{
if let Ok(_) = servlet.servlet_context.init(&args[0..], pm_ref)
{
return 1;
}
}
}
}
}
return -1;
}
pub fn invoke_servlet_sync_exec<BT:Bootstrap>(obj_ptr : *mut c_void, type_inst : *mut c_void) -> i32
{
if let Some(type_inst_obj) = TypeInstanceObject::from_raw(type_inst)
{
if let ServletObject::SYNC(ref mut servlet) = unsafe { unpack_servlet_object::<BT>(obj_ptr) }
{
let accessor = <BT::SyncServletType as SyncServlet>::DataModelType::new_data_model(Rc::clone(&servlet.protocol_model), type_inst_obj);
if let Ok(_) = servlet.servlet_context.exec(accessor)
{
return 0;
}
}
}
return -1;
}
pub fn invoke_servlet_cleanup<BT:Bootstrap>(obj_ptr : *mut c_void) -> i32
{
let mut ret = -1;
match unsafe { unpack_servlet_object::<BT>(obj_ptr) }
{
ServletObject::SYNC(ref mut servlet) => {
if let Ok(_) = servlet.servlet_context.cleanup()
{
ret = 0;
}
},
ServletObject::ASYNC(ref mut servlet) => {
if let Ok(_) = servlet.servlet_context.cleanup()
{
ret = 0;
}
}
}
unsafe { dispose_servlet_object::<BT>(obj_ptr) };
return ret;
}
pub fn invoke_servlet_async_init<BT:Bootstrap>(obj_ptr : *mut c_void, handle_ptr : *mut c_void, type_inst : *mut c_void) -> *mut c_void
{
if let Some(type_inst_obj) = TypeInstanceObject::from_raw(type_inst)
{
if let ServletObject::ASYNC(ref mut servlet) = unsafe { unpack_servlet_object::<BT>(obj_ptr) }
{
let handle = unsafe{unpack_async_handle(handle_ptr)};
let accessor = <BT::AsyncServletType as AsyncServlet>::DataModelType::new_data_model(Rc::clone(&servlet.protocol_model), type_inst_obj);
if let Some(task_data) = servlet.servlet_context.async_init(handle, accessor)
{
return Box::into_raw(task_data) as *mut c_void;
}
}
}
return null::<c_void>() as *mut c_void;
}
pub fn invoke_servlet_async_exec<BT:Bootstrap>(handle_ptr : *mut c_void, task_data_ptr : *mut c_void) -> i32
{
let handle = unsafe { unpack_async_handle(handle_ptr) };
let task_data = unsafe { unpack_async_task_data::<BT>(task_data_ptr) };
if let Ok(_) = BT::AsyncServletType::async_exec(handle, task_data)
{
return 0;
}
return -1;
}
pub fn invoke_servlet_async_cleanup<BT:Bootstrap>(obj_ptr : *mut c_void, handle_ptr: *mut c_void, task_data_ptr : *mut c_void, type_inst: *mut c_void) -> i32
{
if let Some(type_inst_obj) = TypeInstanceObject::from_raw(type_inst)
{
if let ServletObject::ASYNC(ref mut servlet) = unsafe { unpack_servlet_object::<BT>(obj_ptr) }
{
let handle = unsafe{ unpack_async_handle(handle_ptr) };
let task_data = unsafe { unpack_async_task_data::<BT>(task_data_ptr) };
let accessor = <BT::AsyncServletType as AsyncServlet>::DataModelType::new_data_model(Rc::clone(&servlet.protocol_model), type_inst_obj);
if let Ok(_) = servlet.servlet_context.async_cleanup(handle, task_data, accessor)
{
return 0;
}
}
}
unsafe { dispose_async_task_data::<BT>(task_data_ptr) };
return -1;
}