feat: can run qjs

This commit is contained in:
2020-11-07 16:12:21 +08:00
parent 5110732561
commit 56b44d1a8f
60 changed files with 91718 additions and 16 deletions

View File

@@ -1,5 +1,46 @@
use std::collections::HashMap;
mod qjs;
mod sig;
pub use qjs::*;
pub use sig::*; // TODO
fn main() {
println!("Hello, world!");
let context = QuickJSContext::new().unwrap();
let mut map = HashMap::new();
map.insert("name", "hatter");
let script = r##"
function __EXPORT(f) { eval('__PUBLIC_' + f + '=' + f); }
function getName() {
console.info("=========================");
for (var i = 0; i < arguments.length; i++) {
console.info(i, ' ----> ', arguments[i]);
}
return 'hatter';
}
function helloAb(a, b) {
console.info("Hello: ", a);
console.info("Hello: ", b);
}
function main(p) {
console.log(p);
return 1;
}
__EXPORT('getName');
__EXPORT('helloAb');
"##;
context.init(script).unwrap();
let r = context.run_js(&map);
println!("{:?}", r);
let r = context.call_fn("getName", "[1, 'hatter', 'jiang']");
println!("{:?}", r);
let r = context.call_fn("helloAb", "['hatter', 'jiang']");
println!("{:?}", r);
}

View File

@@ -0,0 +1,65 @@
use quick_js::Context;
use quick_js::JsValue;
use quick_js::console::Level;
use quick_js::console::ConsoleBackend;
use serde::{ Serialize, Deserialize };
use rust_util::XResult;
pub struct QuickJSContext {
context: Context,
}
impl QuickJSContext {
pub fn new() -> XResult<Self> {
Ok(Self{
context: build_default_context()?,
})
}
pub fn init(&self, js: &str) -> XResult<JsValue> {
self.context.eval(js).map_err(|e| e.into())
}
pub fn run_js<T>(&self, p: &T) -> XResult<JsValue> where T: ?Sized + Serialize {
let p_json = match serde_json::to_string(p) {
Err(e) => return Err(e.into()),
Ok(p) => p,
};
self.context.eval(&format!("main({})", p_json)).map_err(|e| e.into())
}
pub fn call_fn(&self, fun: &str, params: &str) -> XResult<JsValue> {
if !params.trim().starts_with("[") {
return Err(rust_util::new_box_error("Params is not JSON array!"));
}
let f: String = fun.chars().map(|c| if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' {
c
} else {
'_'
}).collect();
// TODO check JSON valid
// let v: Option<Vec<EmptyObject>> = serde_json::from_str(params).ok();
// if v.is_none() {
// return Err(rust_util::new_box_error("Params is not valid JSON array!"));
// }
self.context.eval(&format!("__PUBLIC_{}.apply(null, {})", f, params)).map_err(|e| e.into())
}
}
#[derive(Serialize, Deserialize)]
struct EmptyObject {}
struct ConsoleBackendImpl;
impl ConsoleBackend for ConsoleBackendImpl {
fn log(&self, level: Level, values: Vec<JsValue>) {
println!("[{:>5}] - {:?}", format!("{:?}", level).to_uppercase(), values);
}
}
fn build_default_context() -> XResult<Context> {
Context::builder().memory_limit(16 * 1024 * 1024)
.console(ConsoleBackendImpl{})
.build()
.map_err(|e| e.into())
}

View File

@@ -3,8 +3,8 @@ use std::io::{ Write, Read };
use serde::{ Deserialize, Serialize };
use ring::{
signature::{ KeyPair, Ed25519KeyPair, UnparsedPublicKey, ED25519 },
hmac, rand, error::Unspecified,
digest,
rand,
// hmac, digest, error::Unspecified,
};
use rust_util::XResult;
@@ -14,7 +14,7 @@ pub struct SigningKeyPair {
}
impl SigningKeyPair {
fn new() -> Self {
pub fn new() -> Self {
let rng = rand::SystemRandom::new();
let pkcs8 = Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); // TODO ...
SigningKeyPair{
@@ -22,19 +22,19 @@ impl SigningKeyPair {
}
}
fn parse(&self) -> Ed25519KeyPair {
pub fn key_pair(&self) -> Ed25519KeyPair {
Ed25519KeyPair::from_pkcs8(&self.key_pair).unwrap() // TODO ...
}
fn public_key(&self) -> Vec<u8> {
self.parse().public_key().as_ref().to_vec()
pub fn public_key(&self) -> Vec<u8> {
self.key_pair().public_key().as_ref().to_vec()
}
fn unparsed_public_key(&self) -> UnparsedPublicKey<Vec<u8>> {
pub fn unparsed_public_key(&self) -> UnparsedPublicKey<Vec<u8>> {
UnparsedPublicKey::new(&ED25519, self.public_key())
}
fn read_from_file(file: &str) -> XResult<Self> {
pub fn read_from_file(file: &str) -> XResult<Self> {
match File::open(file) {
Err(e) => Err(rust_util::new_box_ioerror(&format!("Read from file failed: {}", e))),
Ok(mut f) => {
@@ -53,7 +53,7 @@ impl SigningKeyPair {
}
}
fn write_to_file(&self, file: &str) -> XResult<()> {
pub fn write_to_file(&self, file: &str) -> XResult<()> {
if File::open(file).is_ok() {
return Err(rust_util::new_box_ioerror(&format!("File exists: {}", file)));
}
@@ -90,7 +90,7 @@ impl SignedMessage {
}
pub fn sign(&mut self, key_pair: &SigningKeyPair) {
let sig = key_pair.parse().sign(&self.msg);
let sig = key_pair.key_pair().sign(&self.msg);
self.sig = Some(sig.as_ref().to_vec());
}
@@ -113,4 +113,4 @@ fn test_sign() {
);
signed_message.sign(&signing_key_pair);
assert!(signed_message.verify(&signing_key_pair.public_key()))
}
}