diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2018-08-13 19:55:10 -0400 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2018-08-16 08:40:11 -0400 |
commit | 36d82374cf54be5df23e570bd2c6865e223d5d76 (patch) | |
tree | 0885b628d43cd452981c278b9c02ee45042442e5 /src/handlers.rs | |
parent | d770cc18f80257b520c2cf9cdc5ddea707b38680 (diff) |
Implement deno_handle_msg_from_js in Rust
Fixes #419, #414.
Diffstat (limited to 'src/handlers.rs')
-rw-r--r-- | src/handlers.rs | 154 |
1 files changed, 98 insertions, 56 deletions
diff --git a/src/handlers.rs b/src/handlers.rs index 6f2bc8c8e..401c25144 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -6,28 +6,97 @@ use from_c; use fs; use futures; use futures::sync::oneshot; -use libc::c_char; use msg_generated::deno as msg; -use std::ffi::CStr; +use std; use std::path::Path; -// Help. Is there a way to do this without macros? -// Want: fn str_from_ptr(*const c_char) -> &str -macro_rules! str_from_ptr { - ($ptr:expr) => {{ - let cstr = unsafe { CStr::from_ptr($ptr as *const i8) }; - cstr.to_str().unwrap() - }}; +pub extern "C" fn msg_from_js(d: *const DenoC, buf: deno_buf) { + let bytes = unsafe { std::slice::from_raw_parts(buf.data_ptr, buf.data_len) }; + let base = msg::GetRootAsBase(bytes); + let msg_type = base.msg_type(); + match msg_type { + msg::Any::Start => { + reply_start(d); + } + msg::Any::CodeFetch => { + // TODO base.msg_as_CodeFetch(); + let msg = msg::CodeFetch::init_from_table(base.msg().unwrap()); + let module_specifier = msg.module_specifier().unwrap(); + let containing_file = msg.containing_file().unwrap(); + handle_code_fetch(d, module_specifier, containing_file); + } + msg::Any::CodeCache => { + // TODO base.msg_as_CodeCache(); + let msg = msg::CodeCache::init_from_table(base.msg().unwrap()); + let filename = msg.filename().unwrap(); + let source_code = msg.source_code().unwrap(); + let output_code = msg.output_code().unwrap(); + handle_code_cache(d, filename, source_code, output_code); + } + msg::Any::TimerStart => { + // TODO base.msg_as_TimerStart(); + let msg = msg::TimerStart::init_from_table(base.msg().unwrap()); + handle_timer_start(d, msg.id(), msg.interval(), msg.delay()); + } + msg::Any::TimerClear => { + // TODO base.msg_as_TimerClear(); + let msg = msg::TimerClear::init_from_table(base.msg().unwrap()); + handle_timer_clear(d, msg.id()); + } + msg::Any::Exit => { + // TODO base.msg_as_Exit(); + let msg = msg::Exit::init_from_table(base.msg().unwrap()); + std::process::exit(msg.code()); + } + msg::Any::ReadFileSync => { + // TODO base.msg_as_ReadFileSync(); + let msg = msg::ReadFileSync::init_from_table(base.msg().unwrap()); + let filename = msg.filename().unwrap(); + handle_read_file_sync(d, filename); + } + msg::Any::NONE => { + assert!(false, "Got message with msg_type == Any_NONE"); + } + _ => { + assert!( + false, + format!("Unhandled message {}", msg::EnumNameAny(msg_type)) + ); + } + } } -/* -// reply_start partially implemented here https://gist.github.com/ry/297c83e0ac8722c045db1b097cdb6afc -pub fn deno_handle_msg_from_js(d: *const DenoC, buf: deno_buf) { - let s = std::slice::from_raw_parts(buf.data_ptr, buf.data_len); - buf.data_ptr - get_root() +fn reply_start(d: *const DenoC) { + let deno = from_c(d); + + let mut builder = flatbuffers::FlatBufferBuilder::new(); + + let argv = deno.argv.iter().map(|s| s.as_str()).collect::<Vec<_>>(); + let argv_off = builder.create_vector_of_strings(argv.as_slice()); + + let cwd_path = std::env::current_dir().unwrap(); + let cwd_off = builder.create_string(cwd_path.to_str().unwrap()); + + let msg = msg::CreateStartRes( + &mut builder, + &msg::StartResArgs { + cwd: Some(cwd_off), + argv: Some(argv_off), + debug_flag: false, + ..Default::default() + }, + ); + + set_response_base( + d, + &mut builder, + &msg::BaseArgs { + msg: Some(flatbuffers::Offset::new(msg.value())), + msg_type: msg::Any::StartRes, + ..Default::default() + }, + ) } -*/ // TODO(ry) Use Deno instead of DenoC as first arg. fn reply_error(d: *const DenoC, cmd_id: u32, msg: &String) { @@ -81,16 +150,11 @@ fn send_base( } // https://github.com/denoland/deno/blob/golang/os.go#L100-L154 -#[no_mangle] -pub extern "C" fn handle_code_fetch( +fn handle_code_fetch( d: *const DenoC, - cmd_id: u32, - module_specifier_: *const c_char, - containing_file_: *const c_char, + module_specifier: &str, + containing_file: &str, ) { - let module_specifier = str_from_ptr!(module_specifier_); - let containing_file = str_from_ptr!(containing_file_); - let deno = from_c(d); assert!(deno.dir.root.join("gen") == deno.dir.gen, "Sanity check"); @@ -100,7 +164,7 @@ pub extern "C" fn handle_code_fetch( .code_fetch(module_specifier, containing_file) .map_err(|err| { let errmsg = format!("{}", err); - reply_error(d, cmd_id, &errmsg); + reply_error(d, 0, &errmsg); }); if result.is_err() { return; @@ -122,7 +186,6 @@ pub extern "C" fn handle_code_fetch( }; let msg = msg::CreateCodeFetchRes(&mut builder, &msg_args); let args = msg::BaseArgs { - cmdId: cmd_id, msg: Some(flatbuffers::Offset::new(msg.value())), msg_type: msg::Any::CodeFetchRes, ..Default::default() @@ -131,23 +194,18 @@ pub extern "C" fn handle_code_fetch( } // https://github.com/denoland/deno/blob/golang/os.go#L156-L169 -#[no_mangle] -pub extern "C" fn handle_code_cache( +fn handle_code_cache( d: *const DenoC, - cmd_id: u32, - filename_: *const c_char, - source_code_: *const c_char, - output_code_: *const c_char, + filename: &str, + source_code: &str, + output_code: &str, ) { let deno = from_c(d); - let filename = str_from_ptr!(filename_); - let source_code = str_from_ptr!(source_code_); - let output_code = str_from_ptr!(output_code_); let result = deno.dir.code_cache(filename, source_code, output_code); if result.is_err() { let err = result.unwrap_err(); let errmsg = format!("{}", err); - reply_error(d, cmd_id, &errmsg); + reply_error(d, 0, &errmsg); } // null response indicates success. } @@ -227,20 +285,13 @@ fn send_timer_ready(d: *const DenoC, timer_id: u32, done: bool) { } // Prototype https://github.com/denoland/deno/blob/golang/os.go#L171-L184 -#[no_mangle] -pub extern "C" fn handle_read_file_sync( - d: *const DenoC, - cmd_id: u32, - filename: *const c_char, -) { - let filename = str_from_ptr!(filename); - +fn handle_read_file_sync(d: *const DenoC, filename: &str) { debug!("handle_read_file_sync {}", filename); let result = fs::read_file_sync(Path::new(filename)); if result.is_err() { let err = result.unwrap_err(); let errmsg = format!("{}", err); - reply_error(d, cmd_id, &errmsg); + reply_error(d, 0, &errmsg); return; } @@ -277,15 +328,12 @@ use std::time::{Duration, Instant}; use tokio::prelude::*; use tokio::timer::{Delay, Interval}; // Prototype: https://github.com/ry/deno/blob/golang/timers.go#L25-L39 -#[no_mangle] -pub extern "C" fn handle_timer_start( +fn handle_timer_start( d: *const DenoC, - cmd_id: u32, timer_id: u32, interval: bool, delay: u32, ) { - assert!(cmd_id == 0); debug!("handle_timer_start"); let deno = from_c(d); @@ -314,13 +362,7 @@ pub extern "C" fn handle_timer_start( } // Prototype: https://github.com/ry/deno/blob/golang/timers.go#L40-L43 -#[no_mangle] -pub extern "C" fn handle_timer_clear( - d: *const DenoC, - cmd_id: u32, - timer_id: u32, -) { - assert!(cmd_id == 0); +fn handle_timer_clear(d: *const DenoC, timer_id: u32) { debug!("handle_timer_clear"); remove_timer(d, timer_id); } |