Further restructure langserver::io for WebAssembly

This commit is contained in:
Tad Hardesty 2019-04-02 18:29:14 -07:00
parent 28de01e74d
commit d79d42e10a
4 changed files with 73 additions and 65 deletions

15
src/langserver/io/mod.rs Normal file
View file

@ -0,0 +1,15 @@
//! Pluggable backends for input/output handling.
pub trait RequestRead {
fn read(&self) -> Option<String>;
}
pub trait ResponseWrite {
fn write(&self, output: String);
}
#[cfg_attr(target_arch="wasm32", path="wasm.rs")]
#[cfg_attr(not(target_arch="wasm32"), path="stdio.rs")]
mod system;
pub use self::system::*;

View file

@ -1,16 +1,22 @@
// Based loosely on RLS's input/output code
//! I/O backend for standard targets.
//!
//! JSON-RPC over stdin/stdout with Content-Length headers.
use Engine;
use io::{RequestRead, ResponseWrite};
use std::io::{self, Read, Write};
pub trait RequestRead {
fn read(&self) -> Option<String>;
pub fn io_main() {
let stdio = StdIo;
let context = Default::default();
let mut engine = Engine::new(&stdio, &context);
loop {
let message = stdio.read().expect("request bad read");
engine.handle_input(&message);
}
}
pub trait ResponseWrite {
fn write(&self, output: String);
}
pub struct StdIo;
struct StdIo;
impl RequestRead for StdIo {
fn read(&self) -> Option<String> {
@ -62,44 +68,3 @@ impl ResponseWrite for StdIo {
stdout_lock.flush().unwrap();
}
}
#[cfg(target_arch="wasm32")]
#[allow(unsafe_code)]
pub mod wasm {
use Engine;
use super::ResponseWrite;
extern {
fn handle_output(ptr: *const u8, len: usize);
}
struct WasmIo;
impl ResponseWrite for WasmIo {
fn write(&self, output: String) {
unsafe {
handle_output(output.as_ptr(), output.len());
}
}
}
static mut ENGINE_PTR: *mut Engine<WasmIo> = 0 as *mut Engine<WasmIo>;
pub fn main() {
let wasmio = Box::leak(Box::new(WasmIo));
let context = Box::leak(Box::new(Default::default()));
let engine = Box::new(Engine::new(wasmio, context));
unsafe {
ENGINE_PTR = Box::into_raw(engine);
}
}
#[no_mangle]
pub unsafe extern fn handle_input(ptr: *const u8, len: usize) {
assert!(!ENGINE_PTR.is_null());
let engine = &mut *ENGINE_PTR;
let slice = std::slice::from_raw_parts(ptr, len);
let text = std::str::from_utf8(slice).expect("input is not utf-8");
engine.handle_input(text);
}
}

42
src/langserver/io/wasm.rs Normal file
View file

@ -0,0 +1,42 @@
//! I/O backend for WebAssembly target.
//!
//! `main()` creates an engine that will respond to calls to `handle_input()`,
//! which will then call `handle_output()` with output messages.
#![allow(unsafe_code)]
use Engine;
use super::ResponseWrite;
pub fn io_main() {
let wasmio = Box::leak(Box::new(WasmIo));
let context = Box::leak(Box::new(Default::default()));
let engine = Box::new(Engine::new(wasmio, context));
unsafe {
ENGINE_PTR = Box::into_raw(engine);
}
}
static mut ENGINE_PTR: *mut Engine<WasmIo> = 0 as *mut Engine<WasmIo>;
#[no_mangle]
pub unsafe extern fn handle_input(ptr: *const u8, len: usize) {
assert!(!ENGINE_PTR.is_null());
let engine = &mut *ENGINE_PTR;
let slice = std::slice::from_raw_parts(ptr, len);
let text = std::str::from_utf8(slice).expect("input is not utf-8");
engine.handle_input(text);
}
struct WasmIo;
impl ResponseWrite for WasmIo {
fn write(&self, output: String) {
unsafe {
handle_output(output.as_ptr(), output.len());
}
}
}
extern {
fn handle_output(ptr: *const u8, len: usize);
}

View file

@ -6,6 +6,7 @@
//! * https://microsoft.github.io/language-server-protocol/specification
//! * https://github.com/rust-lang-nursery/rls
#![deny(unsafe_code)]
#![cfg_attr(not(target_arch="wasm32"), forbid(unsafe_code))]
extern crate url;
extern crate serde;
@ -60,22 +61,7 @@ fn main() {
Err(e) => eprintln!("dir check failure: {}", e),
}
#[cfg(not(target_arch="wasm32"))]
{
let stdio = io::StdIo;
let context = Default::default();
let mut engine = Engine::new(&stdio, &context);
loop {
use io::RequestRead;
let message = stdio.read().expect("request bad read");
engine.handle_input(&message);
}
}
#[cfg(target_arch="wasm32")]
{
io::wasm::main();
}
io::io_main();
}
const VERSION: Option<jsonrpc::Version> = Some(jsonrpc::Version::V2);