Introduce call parameters (#21)

This commit is contained in:
vms 2020-08-25 19:26:21 +03:00 committed by GitHub
parent 9cdb91c8d3
commit 5632d684ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 267 additions and 63 deletions

View File

@ -10,7 +10,7 @@ jobs:
- checkout
- restore_cache:
keys:
- fce01-{{ checksum "Cargo.lock" }}-{{ checksum "examples/greeting/artifacts/greeting.wasm" }}-{{ checksum "examples/records/artifacts/pure.wasm" }}-{{ checksum "examples/records/artifacts/effector.wasm" }}
- fce01-{{ checksum "Cargo.lock" }}
- run: |
rustup toolchain install nightly
rustup component add rustfmt
@ -25,7 +25,7 @@ jobs:
paths:
- ~/.cargo
- ~/.rustup
key: fce01-{{ checksum "Cargo.lock" }}-{{ checksum "examples/greeting/artifacts/greeting.wasm" }}-{{ checksum "examples/records/artifacts/pure.wasm" }}-{{ checksum "examples/records/artifacts/effector.wasm" }}
key: fce01-{{ checksum "Cargo.lock" }}
examples:
docker:

6
.gitignore vendored
View File

@ -16,6 +16,6 @@ target/
/examples/ipfs_node/wasm/artifacts/ipfs_rpc_file
# Allowed Wasm files for examples
!/examples/greeting/artifacts/greeting.wasm
!/examples/ipfs_node/artifacts/wasm_modules/*
!/examples/records/artifacts/wasm_modules/*
!/examples/greeting/artifacts/*.wasm
!/examples/ipfs_node/artifacts/wasm_modules/*.wasm
!/examples/records/artifacts/wasm_modules/*.wasm

55
Cargo.lock generated
View File

@ -295,6 +295,16 @@ dependencies = [
"target-lexicon",
]
[[package]]
name = "crossbeam-channel"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ee0cc8804d5393478d743b035099520087a5186f3b93fa58cec08fa62407b6"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.7.3"
@ -321,17 +331,6 @@ dependencies = [
"scopeguard",
]
[[package]]
name = "crossbeam-queue"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570"
dependencies = [
"cfg-if",
"crossbeam-utils",
"maybe-uninit",
]
[[package]]
name = "crossbeam-utils"
version = "0.7.2"
@ -487,9 +486,9 @@ checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f"
[[package]]
name = "encoding_rs"
version = "0.8.23"
version = "0.8.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8ac63f94732332f44fe654443c46f6375d1939684c17b0afb6cb56b0456e171"
checksum = "a51b8cf747471cb9499b6d59e59b0444f4c90eba8968c4e44874e92b5b64ace2"
dependencies = [
"cfg-if",
]
@ -638,7 +637,7 @@ dependencies = [
[[package]]
name = "fluence"
version = "0.2.0"
source = "git+https://github.com/fluencelabs/rust-sdk#55f965f9b88b1a8bbceaee3fc9fb6b1e5f3aa63f"
source = "git+https://github.com/fluencelabs/rust-sdk#d0db9a365f68046e3fe8d2ae19badb988c68ea3f"
dependencies = [
"fluence-sdk-macro",
"fluence-sdk-main",
@ -661,7 +660,9 @@ version = "0.1.0"
dependencies = [
"cmd_lib",
"fce",
"fluence-sdk-main",
"log",
"safe-transmute",
"serde",
"serde_derive",
"serde_json",
@ -675,7 +676,7 @@ dependencies = [
[[package]]
name = "fluence-sdk-macro"
version = "0.2.0"
source = "git+https://github.com/fluencelabs/rust-sdk#55f965f9b88b1a8bbceaee3fc9fb6b1e5f3aa63f"
source = "git+https://github.com/fluencelabs/rust-sdk#d0db9a365f68046e3fe8d2ae19badb988c68ea3f"
dependencies = [
"fluence-sdk-wit 0.2.0 (git+https://github.com/fluencelabs/rust-sdk)",
]
@ -683,15 +684,17 @@ dependencies = [
[[package]]
name = "fluence-sdk-main"
version = "0.2.0"
source = "git+https://github.com/fluencelabs/rust-sdk#55f965f9b88b1a8bbceaee3fc9fb6b1e5f3aa63f"
source = "git+https://github.com/fluencelabs/rust-sdk#d0db9a365f68046e3fe8d2ae19badb988c68ea3f"
dependencies = [
"fluence-sdk-macro",
"log",
"serde",
]
[[package]]
name = "fluence-sdk-wit"
version = "0.2.0"
source = "git+https://github.com/fluencelabs/rust-sdk#55f965f9b88b1a8bbceaee3fc9fb6b1e5f3aa63f"
source = "git+https://github.com/fluencelabs/rust-sdk#d0db9a365f68046e3fe8d2ae19badb988c68ea3f"
dependencies = [
"proc-macro2",
"quote",
@ -1608,9 +1611,9 @@ dependencies = [
[[package]]
name = "rayon"
version = "1.3.1"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f02856753d04e03e26929f820d0a0a337ebe71f849801eea335d464b349080"
checksum = "cfd016f0c045ad38b5251be2c9c0ab806917f82da4d36b2a327e5166adad9270"
dependencies = [
"autocfg",
"crossbeam-deque",
@ -1620,12 +1623,12 @@ dependencies = [
[[package]]
name = "rayon-core"
version = "1.7.1"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e92e15d89083484e11353891f1af602cc661426deb9564c298b270c726973280"
checksum = "91739a34c4355b5434ce54c9086c5895604a9c278586d1f1aa95e04f66b525a0"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-queue",
"crossbeam-utils",
"lazy_static",
"num_cpus",
@ -2210,9 +2213,9 @@ dependencies = [
[[package]]
name = "tracing-core"
version = "0.1.14"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db63662723c316b43ca36d833707cc93dff82a02ba3d7e354f342682cc8b3545"
checksum = "4f0e00789804e99b20f12bc7003ca416309d28a6f495d6af58d1e2c2842461b5"
dependencies = [
"lazy_static",
]
@ -2548,9 +2551,9 @@ dependencies = [
[[package]]
name = "wasmer-interface-types-fl"
version = "0.17.1"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7ea6479fe1487fc529af1d59f33f2ba89f1f50c5c89614ce8385f7915c8fbcb"
checksum = "7b12519a2a53ea1b2166ff47e56c6b57a3f7d714a2d34d26a6b04bdf22c37a41"
dependencies = [
"nom",
"safe-transmute",

View File

@ -15,6 +15,6 @@ fce-wit-parser = { path = "../wit-parser", version = "0.1.1"}
walrus = "0.17.0"
fluence-sdk-wit = "0.2.0"
once_cell = "1.4.0"
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.1", features = ["serde"] }
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.0", features = ["serde"] }
serde = { version = "1.0.110", features = ["derive"] }
serde_json = "1.0.56"

View File

@ -11,5 +11,5 @@ name = "fce_wit_interfaces"
path = "src/lib.rs"
[dependencies]
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.1"}
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.0"}
multimap = "0.8.1"

View File

@ -13,7 +13,7 @@ path = "src/lib.rs"
[dependencies]
walrus = "0.17.0"
wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0"}
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.1"}
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.0"}
fce-wit-interfaces = { path = "../wit-interfaces", version = "0.1.0" }
anyhow = "1.0.31"

View File

@ -17,7 +17,7 @@ fce-wit-parser = { path = "../crates/wit-parser", version = "0.1.2" }
wasmer-runtime = { package = "wasmer-runtime-fl", version = "0.17.0" }
# dynamicfunc-fat-closures allows using state inside DynamicFunc
wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0", features = ["dynamicfunc-fat-closures"] }
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.1", features = ["serde"] }
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.0", features = ["serde"] }
wasmer-wasi = { package = "wasmer-wasi-fl", version = "0.17.0" }
serde = { version = "1.0.114", default-features = false, features = [ "derive" ] }

View File

@ -8,5 +8,9 @@ edition = "2018"
name = "greeting"
path = "src/main.rs"
[[bin]]
name = "greeting_cp"
path = "src/main_cp.rs"
[dependencies]
fluence = { git = "https://github.com/fluencelabs/rust-sdk" }

View File

@ -0,0 +1,6 @@
modules_dir = "artifacts/"
[[module]]
name = "greeting_cp"
mem_pages_count = 1
logger_enabled = false

Binary file not shown.

View File

@ -0,0 +1,24 @@
/*
* Copyright 2020 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pub fn main() {}
#[fluence::fce]
#[cfg(target_arch = "wasm32")]
pub fn greeting() -> String {
let name = fluence::get_call_parameters().user_name;
format!("Hi, {}", name)
}

View File

@ -32,6 +32,7 @@ pub(crate) type Result<T> = std::result::Result<T, AppServiceError>;
pub use errors::AppServiceError;
pub use service::AppService;
pub use fluence_faas::CallParameters;
pub use fluence_faas::IValue;
pub use fluence_faas::IType;
pub use fluence_faas::FaaSInterface;

View File

@ -60,11 +60,12 @@ impl AppService {
module_name: MN,
func_name: FN,
arguments: serde_json::Value,
call_parameters: crate::CallParameters,
) -> Result<Vec<IValue>> {
let arguments = Self::json_to_ivalue(arguments)?;
self.faas
.call(module_name, func_name, &arguments)
.call(module_name, func_name, &arguments, call_parameters)
.map_err(Into::into)
}

View File

@ -8,6 +8,7 @@ edition = "2018"
[dependencies]
fce = { path = "../engine", version = "0.1.1" }
fluence-sdk-main = { git = "https://github.com/fluencelabs/rust-sdk" }
wasmer-runtime = { package = "wasmer-runtime-fl", version = "0.17.0" }
# dynamicfunc-fat-closures allows using state inside DynamicFunc
@ -20,9 +21,10 @@ serde_json = "1.0.53"
serde_derive = "1.0.111"
cmd_lib = "0.7.8"
log = "0.4.8"
safe-transmute = "0.11.0"
[dev-dependencies]
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.1"}
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.0"}
[features]
raw-module-api = []

View File

@ -22,12 +22,16 @@ use crate::Result;
use crate::IValue;
use fce::FCE;
use fluence_sdk_main::CallParameters;
use std::cell::RefCell;
use std::convert::TryInto;
use std::collections::HashSet;
use std::collections::HashMap;
use std::rc::Rc;
use std::fs;
use std::path::{PathBuf, Path};
use std::path::PathBuf;
use std::path::Path;
// TODO: remove and use mutex instead
unsafe impl Send for FluenceFaaS {}
@ -92,7 +96,11 @@ impl<'a> ModulesLoadStrategy<'a> {
}
pub struct FluenceFaaS {
/// The Fluence Compute Engine instance.
fce: FCE,
/// Parameters of call accessible by Wasm modules.
call_parameters: Rc<RefCell<CallParameters>>,
}
impl FluenceFaaS {
@ -127,6 +135,7 @@ impl FluenceFaaS {
{
let mut fce = FCE::new();
let config = config.try_into()?;
let call_parameters = Rc::new(RefCell::new(<_>::default()));
for (module_name, module_config) in config.modules_config {
let module_bytes = modules.remove(&module_name).ok_or_else(|| {
@ -135,11 +144,15 @@ impl FluenceFaaS {
module_name
))
})?;
let fce_module_config = crate::misc::make_fce_config(Some(module_config))?;
let fce_module_config =
crate::misc::make_fce_config(Some(module_config), call_parameters.clone())?;
fce.load_module(module_name, &module_bytes, fce_module_config)?;
}
Ok(Self { fce })
Ok(Self {
fce,
call_parameters,
})
}
/// Searches for modules in `config.modules_dir`, loads only those in the `names` set
@ -215,7 +228,10 @@ impl FluenceFaaS {
module_name: MN,
func_name: FN,
args: &[IValue],
call_parameters: fluence_sdk_main::CallParameters,
) -> Result<Vec<IValue>> {
self.call_parameters.replace(call_parameters);
self.fce
.call(module_name, func_name, args)
.map_err(Into::into)
@ -258,7 +274,7 @@ impl FluenceFaaS {
{
let config = config.map(|c| c.try_into()).transpose()?;
let fce_module_config = crate::misc::make_fce_config(config)?;
let fce_module_config = crate::misc::make_fce_config(config, self.call_parameters.clone())?;
self.fce
.load_module(name, &wasm_bytes, fce_module_config)
.map_err(Into::into)

View File

@ -22,12 +22,12 @@ use serde::Serializer;
use std::fmt;
use std::collections::HashMap;
#[derive(Debug)]
#[derive(Debug, PartialEq, Clone)]
pub struct FaaSInterface<'a> {
pub modules: HashMap<&'a str, HashMap<&'a str, FaaSFunctionSignature<'a>>>,
}
#[derive(Debug, Serialize)]
#[derive(Debug, PartialEq, Clone)]
pub struct FaaSFunctionSignature<'a> {
pub input_types: &'a Vec<IType>,
pub output_types: &'a Vec<IType>,

View File

@ -38,8 +38,11 @@ pub use fce::IType;
pub use fce::to_interface_value;
pub use fce::from_interface_values;
pub use fluence_sdk_main::CallParameters;
pub use faas::FluenceFaaS;
pub use faas_interface::FaaSInterface;
pub use faas_interface::FaaSFunctionSignature;
pub use misc::RawModulesConfig;
pub use misc::RawModuleConfig;

View File

@ -23,6 +23,9 @@ use wasmer_core::types::Value;
use wasmer_core::types::Type;
use wasmer_core::types::FuncSig;
use std::cell::RefCell;
use std::rc::Rc;
const ALLOCATE_FUNC_NAME: &str = "allocate";
const SET_PTR_FUNC_NAME: &str = "set_result_ptr";
const SET_SIZE_FUNC_NAME: &str = "set_result_size";
@ -33,19 +36,17 @@ pub(super) fn log_utf8_string(ctx: &mut Ctx, offset: i32, size: i32) {
let wasm_ptr = WasmPtr::<u8, Array>::new(offset as _);
match wasm_ptr.get_utf8_string(ctx.memory(0), size as _) {
Some(msg) => log::info!("{}", msg),
None => log::warn!("ipfs node logger: incorrect UTF8 string's been supplied to logger"),
None => log::warn!("logger: incorrect UTF8 string's been supplied to logger"),
}
}
fn write_to_mem(context: &mut Ctx, address: usize, value: &[u8]) {
let memory = context.memory(0);
for (byte_id, cell) in memory.view::<u8>()[address as usize..(address + value.len())]
memory.view::<u8>()[address..(address + value.len())]
.iter()
.enumerate()
{
cell.set(value[byte_id]);
}
.zip(value.iter())
.for_each(|(cell, byte)| cell.set(*byte));
}
pub(super) fn create_host_import_func<S>(host_cmd: S) -> DynamicFunc<'static>
@ -53,9 +54,7 @@ where
S: Into<String>,
{
use wasmer_core::Func;
use std::cell::RefCell;
//#[rustfmt:skip]
let allocate_func: Box<RefCell<Option<Func<'static, i32, i32>>>> = Box::new(RefCell::new(None));
let set_result_ptr_func: Box<RefCell<Option<Func<'static, i32, ()>>>> =
Box::new(RefCell::new(None));
@ -75,7 +74,7 @@ where
let wasm_ptr = WasmPtr::<u8, Array>::new(array_ptr as _);
let result = match wasm_ptr.get_utf8_string(ctx.memory(0), array_size as _) {
Some(arg_value) => cmd_lib::run_fun!("{} {}", host_cmd, arg_value).unwrap(),
None => return vec![Value::I32(1)],
None => return vec![],
};
unsafe {
@ -88,7 +87,7 @@ where
call_wasm_func!(set_result_ptr_func, mem_address);
call_wasm_func!(set_result_size_func, result.len() as i32);
vec![Value::I32(0)]
vec![]
}
};
@ -97,3 +96,70 @@ where
func,
)
}
pub(super) fn create_get_call_parameters_func(
call_parameters: Rc<RefCell<crate::CallParameters>>,
) -> DynamicFunc<'static> {
use wasmer_core::Func;
let allocate_func: Box<RefCell<Option<Func<'static, i32, i32>>>> = Box::new(RefCell::new(None));
// TODO: refactor this approach after switching to the new Wasmer
let func = move |ctx: &mut Ctx, _inputs: &[Value]| -> Vec<Value> {
unsafe {
init_wasm_func_once!(allocate_func, ctx, i32, i32, ALLOCATE_FUNC_NAME, 2);
let call_id_ptr =
call_wasm_func!(allocate_func, call_parameters.borrow().call_id.len() as i32);
let user_name_ptr = call_wasm_func!(
allocate_func,
call_parameters.borrow().user_name.len() as i32
);
let application_id_ptr = call_wasm_func!(
allocate_func,
call_parameters.borrow().application_id.len() as i32
);
write_to_mem(
ctx,
call_id_ptr as usize,
call_parameters.borrow().call_id.as_bytes(),
);
write_to_mem(
ctx,
user_name_ptr as usize,
call_parameters.borrow().user_name.as_bytes(),
);
write_to_mem(
ctx,
application_id_ptr as usize,
call_parameters.borrow().application_id.as_bytes(),
);
let mut serialized_call_parameters = Vec::new();
serialized_call_parameters.push(call_id_ptr as u64);
serialized_call_parameters.push(call_parameters.borrow().call_id.len() as u64);
serialized_call_parameters.push(user_name_ptr as u64);
serialized_call_parameters.push(call_parameters.borrow().user_name.len() as u64);
serialized_call_parameters.push(application_id_ptr as u64);
serialized_call_parameters.push(call_parameters.borrow().application_id.len() as u64);
let serialized_call_parameters_ptr =
call_wasm_func!(allocate_func, serialized_call_parameters.len() as i32);
let serialized_call_parameters_bytes =
safe_transmute::transmute_to_bytes::<u64>(&serialized_call_parameters);
write_to_mem(
ctx,
serialized_call_parameters_ptr as usize,
serialized_call_parameters_bytes,
);
vec![Value::I32(serialized_call_parameters_ptr as _)]
}
};
DynamicFunc::new(
std::sync::Arc::new(FuncSig::new(vec![], vec![Type::I32])),
func,
)
}

View File

@ -102,8 +102,10 @@ where
/// Make FCE config based on parsed config.
pub(crate) fn make_fce_config(
module_config: Option<ModuleConfig>,
call_parameters: std::rc::Rc<std::cell::RefCell<fluence_sdk_main::CallParameters>>,
) -> crate::Result<FCEModuleConfig> {
use super::imports::create_host_import_func;
use super::imports::create_get_call_parameters_func;
use super::imports::log_utf8_string;
use wasmer_core::import::Namespace;
use std::path::PathBuf;
@ -159,6 +161,10 @@ pub(crate) fn make_fce_config(
namespace.insert(import_name, host_import);
}
}
namespace.insert(
"get_call_parameters",
create_get_call_parameters_func(call_parameters),
);
let mut import_object = ImportObject::new();
import_object.register("host", namespace);
@ -181,7 +187,7 @@ macro_rules! init_wasm_func_once {
};
// assumed that this function will be used only in the context of closure
// linked to a corresponding Wasm import - os it is safe to make is static
// linked to a corresponding Wasm import, so it is safe to make is static
let raw_func = std::mem::transmute::<Func<'_, _, _>, Func<'static, _, _>>(raw_func);
*$func.borrow_mut() = Some(raw_func);

View File

@ -36,13 +36,80 @@ pub fn greeting() {
"greeting",
"greeting",
&[IValue::String(String::from("Fluence"))],
<_>::default(),
)
.unwrap_or_else(|e| panic!("can't invoke greeting: {:?}", e));
let result2 = faas
.call("greeting", "greeting", &[IValue::String(String::from(""))])
.call(
"greeting",
"greeting",
&[IValue::String(String::from(""))],
<_>::default(),
)
.unwrap_or_else(|e| panic!("can't invoke greeting: {:?}", e));
assert_eq!(result1, vec![IValue::String(String::from("Hi, Fluence"))]);
assert_eq!(result2, vec![IValue::String(String::from("Hi, "))]);
}
#[test]
pub fn get_interfaces() {
let greeting_config_path = "../examples/greeting/Config.toml";
let greeting_config_raw = std::fs::read(greeting_config_path)
.expect("../examples/greeting/Config.toml should presence");
let mut greeting_config: fluence_faas::RawModulesConfig =
toml::from_slice(&greeting_config_raw).expect("greeting config should be well-formed");
greeting_config.modules_dir = Some(String::from("../examples/greeting/artifacts"));
let faas = FluenceFaaS::with_raw_config(greeting_config)
.unwrap_or_else(|e| panic!("can't crate Fluence FaaS instance: {:?}", e));
let interface = faas.get_interface();
let string_type_params = vec![fluence_faas::IType::String];
let greeting_sign = fluence_faas::FaaSFunctionSignature {
input_types: &string_type_params,
output_types: &string_type_params,
};
let mut functions = std::collections::HashMap::new();
functions.insert("greeting", greeting_sign);
let mut modules = std::collections::HashMap::new();
modules.insert("greeting", functions);
assert_eq!(interface, fluence_faas::FaaSInterface { modules });
}
#[test]
pub fn call_parameters() {
let greeting_config_path = "../examples/greeting/Config_cp.toml";
let greeting_config_raw = std::fs::read(greeting_config_path)
.expect("../examples/greeting/Config_cp.toml should presence");
let mut greeting_config: fluence_faas::RawModulesConfig =
toml::from_slice(&greeting_config_raw).expect("greeting config should be well-formed");
greeting_config.modules_dir = Some(String::from("../examples/greeting/artifacts"));
let mut faas = FluenceFaaS::with_raw_config(greeting_config)
.unwrap_or_else(|e| panic!("can't crate Fluence FaaS instance: {:?}", e));
let result = faas
.call(
"greeting_cp",
"greeting",
&[],
fluence_sdk_main::CallParameters {
call_id: "0x1337".to_string(),
user_name: "root".to_string(),
application_id: "0x31337".to_string(),
},
)
.unwrap_or_else(|e| panic!("can't invoke greeting_cp: {:?}", e));
assert_eq!(result, vec![IValue::String(String::from("Hi, root"))]);
}

View File

@ -33,7 +33,7 @@ pub fn records() {
.unwrap_or_else(|e| panic!("can't crate Fluence FaaS instance: {:?}", e));
let result = faas
.call("pure", "invoke", &[])
.call("pure", "invoke", &[], <_>::default())
.unwrap_or_else(|e| panic!("can't invoke pure: {:?}", e));
assert_eq!(

View File

@ -110,13 +110,18 @@ impl REPL {
};
let start = Instant::now();
let result = match self.app_service.call(module_name, func_name, module_arg) {
Ok(result) => {
let elapsed_time = start.elapsed();
format!("result: {:?}\n elapsed time: {:?}", result, elapsed_time)
}
Err(e) => format!("execution failed with {:?}", e),
};
// TODO: add support of call parameters
let result =
match self
.app_service
.call(module_name, func_name, module_arg, <_>::default())
{
Ok(result) => {
let elapsed_time = start.elapsed();
format!("result: {:?}\n elapsed time: {:?}", result, elapsed_time)
}
Err(e) => format!("execution failed with {:?}", e),
};
println!("{}", result);
}
Some("envs") => {