use crate::*;
extern "C" {
fn _wasmesh_recall_request(ctx_id: i64, offset: i32);
fn _wasmesh_send_response(ctx_id: i64, offset: i32, size: i32);
fn _wasmesh_send_request(ctx_id: i64, offset: i32, size: i32) -> i32;
fn _wasmesh_recall_response(ctx_id: i64, offset: i32);
}
pub fn handle_request<F>(ctx_id: i64, size: i32, handler: F)
where
F: Fn(i64, Request) -> Option<Response>,
{
let mut buffer = vec![0u8; size as usize];
let req = {
if size == 0 {
Request::default()
} else {
unsafe { _wasmesh_recall_request(ctx_id, buffer.as_ptr() as i32) };
Request::parse_from_bytes(buffer.as_slice())
.unwrap_or_else(|e| {
eprintln!("receive request parse_from_bytes error: {}", e);
Request::default()
})
}
};
let is_oneway = req.method == Method::ONEWAY;
let resp = handler(ctx_id, req);
if let Some(resp) = resp {
let size = resp.compute_size() as usize;
if size > buffer.capacity() {
buffer.resize(size, 0);
} else {
unsafe { buffer.set_len(size) };
}
let mut os = CodedOutputStream::bytes(&mut buffer);
resp.write_to_with_cached_sizes(&mut os)
.or_else(|e| Err(format!("{}", e))).unwrap();
os.flush().unwrap();
unsafe { _wasmesh_send_response(ctx_id, buffer.as_ptr() as i32, buffer.len() as i32) };
} else if !is_oneway {
unsafe { _wasmesh_send_response(ctx_id, 0i32, 0 as i32) };
}
}
pub fn do_request(ctx_id: i64, req: Request) -> Option<Response> {
let mut buffer = req.write_to_bytes().unwrap();
let size = unsafe { _wasmesh_send_request(ctx_id, buffer.as_ptr() as i32, buffer.len() as i32) };
if size <= 0 || req.get_method() == Method::ONEWAY {
return None
}
buffer.resize(size as usize, 0);
unsafe { _wasmesh_recall_response(ctx_id, buffer.as_ptr() as i32) };
Some(Response::parse_from_bytes(buffer.as_slice())
.unwrap_or_else(|e| {
eprintln!("receive response parse_from_bytes error: {}", e);
Response::default()
}))
}