mirror of
https://github.com/fluencelabs/marine.git
synced 2025-06-26 05:01:38 +00:00
Record refactoring (#19)
This commit is contained in:
@ -10,7 +10,7 @@ jobs:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- fce01-{{ checksum "Cargo.lock" }}
|
||||
- fce02-{{ 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" }}
|
||||
key: fce02-{{ checksum "Cargo.lock" }}
|
||||
|
||||
examples:
|
||||
docker:
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -16,3 +16,8 @@ target/
|
||||
!/examples/greeting/artifacts/*.wasm
|
||||
!/examples/ipfs_node/artifacts/*.wasm
|
||||
!/examples/records/artifacts/*.wasm
|
||||
|
||||
# Allowed Wasm files for test
|
||||
!/fluence-faas/tests/json_wasm_tests/arguments_passing/artifacts/effector.wasm
|
||||
!/fluence-faas/tests/json_wasm_tests/arguments_passing/artifacts/pure.wasm
|
||||
!/fluence-faas/tests/json_wasm_tests/inner_records/artifacts/inner_records_pure.wasm
|
||||
|
138
Cargo.lock
generated
138
Cargo.lock
generated
@ -39,6 +39,14 @@ version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b"
|
||||
|
||||
[[package]]
|
||||
name = "arguments-passing-test"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fluence 0.2.3",
|
||||
"safe-transmute",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.6"
|
||||
@ -158,7 +166,7 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
|
||||
name = "call_parameters"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fluence",
|
||||
"fluence 0.2.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -367,7 +375,7 @@ dependencies = [
|
||||
name = "curl"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fluence",
|
||||
"fluence 0.2.3",
|
||||
"log",
|
||||
]
|
||||
|
||||
@ -598,12 +606,12 @@ dependencies = [
|
||||
"fce-wit-interfaces",
|
||||
"fce-wit-parser",
|
||||
"log",
|
||||
"multi-map",
|
||||
"multimap",
|
||||
"once_cell",
|
||||
"parity-wasm",
|
||||
"pwasm-utils",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"tokio",
|
||||
"wasmer-interface-types-fl",
|
||||
"wasmer-runtime-core-fl",
|
||||
@ -616,7 +624,7 @@ name = "fce-wit-generator"
|
||||
version = "0.1.4"
|
||||
dependencies = [
|
||||
"fce-wit-parser",
|
||||
"fluence-sdk-wit 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fluence-sdk-wit 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -659,10 +667,19 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "fluence"
|
||||
version = "0.2.2"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#dcb6cfddf95978e777a8a53710bda88aec7d4baf"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk?branch=record_support#9201a824f2ecc4f2668449ea956d9b10a39091e5"
|
||||
dependencies = [
|
||||
"fluence-sdk-macro 0.2.2 (git+https://github.com/fluencelabs/rust-sdk)",
|
||||
"fluence-sdk-main 0.2.2 (git+https://github.com/fluencelabs/rust-sdk)",
|
||||
"fluence-sdk-macro 0.2.2",
|
||||
"fluence-sdk-main 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluence"
|
||||
version = "0.2.3"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#04e2538661bab57110a288a3c7d21a2905c377e4"
|
||||
dependencies = [
|
||||
"fluence-sdk-macro 0.2.3 (git+https://github.com/fluencelabs/rust-sdk)",
|
||||
"fluence-sdk-main 0.2.3 (git+https://github.com/fluencelabs/rust-sdk)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -681,9 +698,12 @@ name = "fluence-faas"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"cmd_lib",
|
||||
"env_logger 0.7.1",
|
||||
"fce",
|
||||
"fluence-sdk-main 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fluence-sdk-main 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools",
|
||||
"log",
|
||||
"once_cell",
|
||||
"safe-transmute",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
@ -698,37 +718,55 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "fluence-sdk-macro"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21ca1fdcc78a17bc84798cdc2b13c36a07555b1a3dfe9db9a6ec3a3079aaebe6"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk?branch=record_support#9201a824f2ecc4f2668449ea956d9b10a39091e5"
|
||||
dependencies = [
|
||||
"fluence-sdk-wit 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fluence-sdk-wit 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluence-sdk-macro"
|
||||
version = "0.2.2"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#dcb6cfddf95978e777a8a53710bda88aec7d4baf"
|
||||
version = "0.2.3"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#04e2538661bab57110a288a3c7d21a2905c377e4"
|
||||
dependencies = [
|
||||
"fluence-sdk-wit 0.2.2 (git+https://github.com/fluencelabs/rust-sdk)",
|
||||
"fluence-sdk-wit 0.2.3 (git+https://github.com/fluencelabs/rust-sdk)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluence-sdk-macro"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c326f99a17dccf48e9cceadb7f19df184142d023f74ccb76634b8f99ac2dac1b"
|
||||
dependencies = [
|
||||
"fluence-sdk-wit 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluence-sdk-main"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26474b00df6b7ec38cfcaf96c8636bca84f3e504c3e192c3341dc2372e23b30e"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk?branch=record_support#9201a824f2ecc4f2668449ea956d9b10a39091e5"
|
||||
dependencies = [
|
||||
"fluence-sdk-macro 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fluence-sdk-macro 0.2.2",
|
||||
"log",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluence-sdk-main"
|
||||
version = "0.2.2"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#dcb6cfddf95978e777a8a53710bda88aec7d4baf"
|
||||
version = "0.2.3"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#04e2538661bab57110a288a3c7d21a2905c377e4"
|
||||
dependencies = [
|
||||
"fluence-sdk-macro 0.2.2 (git+https://github.com/fluencelabs/rust-sdk)",
|
||||
"fluence-sdk-macro 0.2.3 (git+https://github.com/fluencelabs/rust-sdk)",
|
||||
"log",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluence-sdk-main"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8377076746dede55b132c745c5058630f164d9977d7f7dc4e414a837300cd9cc"
|
||||
dependencies = [
|
||||
"fluence-sdk-macro 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log",
|
||||
"serde",
|
||||
]
|
||||
@ -736,8 +774,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "fluence-sdk-wit"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93c94643121eb234778b7f8f0e12fd29ec7c70ac71d84329ae25daf5d263074d"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk?branch=record_support#9201a824f2ecc4f2668449ea956d9b10a39091e5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -749,8 +786,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "fluence-sdk-wit"
|
||||
version = "0.2.2"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#dcb6cfddf95978e777a8a53710bda88aec7d4baf"
|
||||
version = "0.2.3"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#04e2538661bab57110a288a3c7d21a2905c377e4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluence-sdk-wit"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cb9034a9a196c94b12d650d07398c7e63ff83e98c120397f411da44156ab93a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1091,6 +1142,14 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inner-records-test"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fluence 0.2.3",
|
||||
"safe-transmute",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inventory"
|
||||
version = "0.1.9"
|
||||
@ -1126,7 +1185,7 @@ dependencies = [
|
||||
name = "ipfs-effector"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fluence",
|
||||
"fluence 0.2.3",
|
||||
"log",
|
||||
]
|
||||
|
||||
@ -1134,7 +1193,7 @@ dependencies = [
|
||||
name = "ipfs-pure"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fluence",
|
||||
"fluence 0.2.3",
|
||||
"log",
|
||||
]
|
||||
|
||||
@ -1213,7 +1272,7 @@ checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
|
||||
name = "local_storage"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fluence",
|
||||
"fluence 0.2.3",
|
||||
"log",
|
||||
]
|
||||
|
||||
@ -1329,6 +1388,12 @@ dependencies = [
|
||||
"ws2_32-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multi-map"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bba551d6d795f74a01767577ea8339560bf0a65354e0417b7e915ed608443d46"
|
||||
|
||||
[[package]]
|
||||
name = "multimap"
|
||||
version = "0.8.2"
|
||||
@ -1696,7 +1761,7 @@ dependencies = [
|
||||
name = "record-effector"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fluence",
|
||||
"fluence 0.2.3",
|
||||
"test-record",
|
||||
]
|
||||
|
||||
@ -1704,7 +1769,7 @@ dependencies = [
|
||||
name = "record-pure"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fluence",
|
||||
"fluence 0.2.3",
|
||||
"test-record",
|
||||
]
|
||||
|
||||
@ -1989,7 +2054,7 @@ name = "site-storage"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"fluence",
|
||||
"fluence 0.2.2",
|
||||
"log",
|
||||
]
|
||||
|
||||
@ -2068,9 +2133,9 @@ checksum = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.40"
|
||||
version = "1.0.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350"
|
||||
checksum = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -2133,7 +2198,7 @@ dependencies = [
|
||||
name = "test-record"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fluence",
|
||||
"fluence 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2568,7 +2633,7 @@ checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307"
|
||||
name = "wasm-greeting"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fluence",
|
||||
"fluence 0.2.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2625,10 +2690,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-interface-types-fl"
|
||||
version = "0.17.0"
|
||||
version = "0.17.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b12519a2a53ea1b2166ff47e56c6b57a3f7d714a2d34d26a6b04bdf22c37a41"
|
||||
checksum = "486603d8267c5ade7a8c62b4fe4e15a6349e64857f40c7a9ac2a2a28d81569b8"
|
||||
dependencies = [
|
||||
"log",
|
||||
"nom",
|
||||
"safe-transmute",
|
||||
"serde",
|
||||
|
@ -16,6 +16,8 @@ members = [
|
||||
"examples/call_parameters",
|
||||
"fluence-app-service",
|
||||
"fluence-faas",
|
||||
"fluence-faas/tests/json_wasm_tests/arguments_passing",
|
||||
"fluence-faas/tests/json_wasm_tests/inner_records",
|
||||
"tools/cli",
|
||||
"tools/repl",
|
||||
]
|
||||
|
@ -12,9 +12,10 @@ path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
fce-wit-parser = { path = "../wit-parser", version = "0.1.3"}
|
||||
fluence-sdk-wit = "0.2.3"
|
||||
|
||||
walrus = "0.17.0"
|
||||
fluence-sdk-wit = "0.2.0"
|
||||
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.5" }
|
||||
once_cell = "1.4.0"
|
||||
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"
|
||||
|
@ -16,20 +16,21 @@
|
||||
|
||||
use wasmer_wit::ast::Interfaces;
|
||||
use wasmer_wit::types::InterfaceType as IType;
|
||||
use wasmer_wit::ast::FunctionArg as IFunctionArg;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
pub(crate) struct ApiExportFuncDescriptor {
|
||||
pub(crate) name: &'static str,
|
||||
pub(crate) id: u32,
|
||||
pub(crate) input_types: Vec<IType>,
|
||||
pub(crate) arguments: Vec<IFunctionArg>,
|
||||
pub(crate) output_types: Vec<IType>,
|
||||
}
|
||||
|
||||
impl ApiExportFuncDescriptor {
|
||||
pub fn update_interfaces(&self, interfaces: &mut Interfaces<'_>) {
|
||||
let func_type = wasmer_wit::ast::Type::Function {
|
||||
inputs: self.input_types.clone(),
|
||||
outputs: self.output_types.clone(),
|
||||
arguments: self.arguments.clone(),
|
||||
output_types: self.output_types.clone(),
|
||||
};
|
||||
interfaces.types.push(func_type);
|
||||
|
||||
@ -45,7 +46,10 @@ pub(crate) static ALLOCATE_FUNC: Lazy<ApiExportFuncDescriptor> =
|
||||
Lazy::new(|| ApiExportFuncDescriptor {
|
||||
name: "allocate",
|
||||
id: 0,
|
||||
input_types: vec![IType::I32],
|
||||
arguments: vec![IFunctionArg {
|
||||
name: String::from("size"),
|
||||
ty: IType::I32,
|
||||
}],
|
||||
output_types: vec![IType::I32],
|
||||
});
|
||||
|
||||
@ -53,7 +57,16 @@ pub(crate) static DEALLOCATE_FUNC: Lazy<ApiExportFuncDescriptor> =
|
||||
Lazy::new(|| ApiExportFuncDescriptor {
|
||||
name: "deallocate",
|
||||
id: 1,
|
||||
input_types: vec![IType::I32, IType::I32],
|
||||
arguments: vec![
|
||||
IFunctionArg {
|
||||
name: String::from("pointer"),
|
||||
ty: IType::I32,
|
||||
},
|
||||
IFunctionArg {
|
||||
name: String::from("size"),
|
||||
ty: IType::I32,
|
||||
},
|
||||
],
|
||||
output_types: vec![],
|
||||
});
|
||||
|
||||
@ -61,7 +74,7 @@ pub(crate) static GET_RESULT_SIZE_FUNC: Lazy<ApiExportFuncDescriptor> =
|
||||
Lazy::new(|| ApiExportFuncDescriptor {
|
||||
name: "get_result_size",
|
||||
id: 2,
|
||||
input_types: vec![],
|
||||
arguments: vec![],
|
||||
output_types: vec![IType::I32],
|
||||
});
|
||||
|
||||
@ -69,7 +82,7 @@ pub(crate) static GET_RESULT_PTR_FUNC: Lazy<ApiExportFuncDescriptor> =
|
||||
Lazy::new(|| ApiExportFuncDescriptor {
|
||||
name: "get_result_ptr",
|
||||
id: 3,
|
||||
input_types: vec![],
|
||||
arguments: vec![],
|
||||
output_types: vec![IType::I32],
|
||||
});
|
||||
|
||||
@ -77,7 +90,10 @@ pub(crate) static SET_RESULT_SIZE_FUNC: Lazy<ApiExportFuncDescriptor> =
|
||||
Lazy::new(|| ApiExportFuncDescriptor {
|
||||
name: "set_result_size",
|
||||
id: 4,
|
||||
input_types: vec![IType::I32],
|
||||
arguments: vec![IFunctionArg {
|
||||
name: String::from("result_size"),
|
||||
ty: IType::I32,
|
||||
}],
|
||||
output_types: vec![],
|
||||
});
|
||||
|
||||
@ -85,6 +101,9 @@ pub(crate) static SET_RESULT_PTR_FUNC: Lazy<ApiExportFuncDescriptor> =
|
||||
Lazy::new(|| ApiExportFuncDescriptor {
|
||||
name: "set_result_ptr",
|
||||
id: 5,
|
||||
input_types: vec![IType::I32],
|
||||
arguments: vec![IFunctionArg {
|
||||
name: String::from("result_ptr"),
|
||||
ty: IType::I32,
|
||||
}],
|
||||
output_types: vec![],
|
||||
});
|
||||
|
@ -23,15 +23,17 @@ use crate::Result;
|
||||
|
||||
use wasmer_wit::types::InterfaceType as IType;
|
||||
use wasmer_wit::ast::Interfaces;
|
||||
use wasmer_wit::types::RecordType;
|
||||
|
||||
#[derive(PartialEq, Debug, Default)]
|
||||
pub(crate) struct WITResolver<'a> {
|
||||
pub(crate) types: std::collections::HashMap<String, u32>,
|
||||
types: std::collections::HashMap<String, usize>,
|
||||
pub(crate) interfaces: Interfaces<'a>,
|
||||
not_resolved_types_count: usize,
|
||||
}
|
||||
|
||||
impl<'a> WITResolver<'a> {
|
||||
pub(crate) fn get_record_type_id(&self, record_name: &str) -> Result<u32> {
|
||||
pub(crate) fn get_record_type_id(&self, record_name: &str) -> Result<usize> {
|
||||
match self.types.get(record_name) {
|
||||
Some(type_index) => Ok(*type_index),
|
||||
None => Err(crate::errors::WITGeneratorError::CorruptedRecord(format!(
|
||||
@ -41,23 +43,64 @@ impl<'a> WITResolver<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// adds a stub for type with such a name if it wasn't found
|
||||
pub(crate) fn get_record_type_id_unchecked(&mut self, record_name: &str) -> usize {
|
||||
use wasmer_wit::ast::Type;
|
||||
|
||||
match self.types.get(record_name) {
|
||||
Some(type_index) => *type_index,
|
||||
None => {
|
||||
self.types
|
||||
.insert(record_name.to_string(), self.interfaces.types.len());
|
||||
self.interfaces
|
||||
.types
|
||||
.push(Type::Record(RecordType::default()));
|
||||
|
||||
self.not_resolved_types_count += 1;
|
||||
self.interfaces.types.len()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_record_type(
|
||||
&self,
|
||||
record_name: &str,
|
||||
) -> Result<wasmer_wit::types::RecordType> {
|
||||
match self.types.get(record_name) {
|
||||
Some(type_index) => match &self.interfaces.types[*type_index as usize] {
|
||||
record_type_id: u64,
|
||||
) -> Result<&wasmer_wit::types::RecordType> {
|
||||
if record_type_id >= self.interfaces.types.len() as u64 {
|
||||
return Err(crate::errors::WITGeneratorError::CorruptedRecord(format!(
|
||||
"Can't find record with id {}, don't you forget to wrap it with #[fce]",
|
||||
record_type_id
|
||||
)));
|
||||
}
|
||||
|
||||
match &self.interfaces.types[record_type_id as usize] {
|
||||
wasmer_wit::ast::Type::Function { .. } => {
|
||||
panic!("internal error inside WITResolver")
|
||||
panic!("internal error inside WITResolver: interfaces AST type should be record not record")
|
||||
}
|
||||
wasmer_wit::ast::Type::Record(record_type) => Ok(record_type.clone()),
|
||||
},
|
||||
None => Err(crate::errors::WITGeneratorError::CorruptedRecord(format!(
|
||||
"Can't find record with name='{}', don't you forget to wrap it with #[fce]",
|
||||
record_name
|
||||
))),
|
||||
wasmer_wit::ast::Type::Record(record_type) => Ok(record_type),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn insert_record_type(&mut self, record: RecordType) {
|
||||
use wasmer_wit::ast::Type;
|
||||
|
||||
match self.types.get(&record.name) {
|
||||
Some(pos) => {
|
||||
self.interfaces.types[*pos] = Type::Record(record);
|
||||
self.not_resolved_types_count -= 1;
|
||||
}
|
||||
None => {
|
||||
self.types
|
||||
.insert(record.name.clone(), self.interfaces.types.len());
|
||||
|
||||
self.interfaces.types.push(Type::Record(record));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn unresolved_types_count(&self) -> usize {
|
||||
self.not_resolved_types_count
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait WITGenerator {
|
||||
|
@ -16,39 +16,48 @@
|
||||
|
||||
use super::WITGenerator;
|
||||
use super::WITResolver;
|
||||
use super::utils::ptype_to_itype;
|
||||
use super::utils::ptype_to_itype_checked;
|
||||
use crate::default_export_api_config::*;
|
||||
use crate::Result;
|
||||
|
||||
use fluence_sdk_wit::AstFunctionItem;
|
||||
use fluence_sdk_wit::ParsedType;
|
||||
use wasmer_wit::interpreter::Instruction;
|
||||
use wasmer_wit::ast::FunctionArg as IFunctionArg;
|
||||
|
||||
impl WITGenerator for AstFunctionItem {
|
||||
fn generate_wit<'a>(&'a self, wit_resolver: &mut WITResolver<'a>) -> Result<()> {
|
||||
use wasmer_wit::ast::Type;
|
||||
use wasmer_wit::ast::Adapter;
|
||||
|
||||
let inputs = self
|
||||
let arguments = self
|
||||
.signature
|
||||
.input_types
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|input_type| ptype_to_itype(input_type, wit_resolver))
|
||||
.map(|(arg_name, arg_type)| -> Result<IFunctionArg> {
|
||||
Ok(IFunctionArg {
|
||||
name: arg_name.clone(),
|
||||
ty: ptype_to_itype_checked(arg_type, wit_resolver)?,
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
let outputs = match self.signature.output_type {
|
||||
Some(ref output_type) => vec![ptype_to_itype(output_type, wit_resolver)?],
|
||||
let output_types = match self.signature.output_type {
|
||||
Some(ref output_type) => vec![ptype_to_itype_checked(output_type, wit_resolver)?],
|
||||
None => vec![],
|
||||
};
|
||||
|
||||
let interfaces = &mut wit_resolver.interfaces;
|
||||
interfaces.types.push(Type::Function {
|
||||
inputs: inputs.clone(),
|
||||
outputs: outputs.clone(),
|
||||
arguments: arguments.clone(),
|
||||
output_types: output_types.clone(),
|
||||
});
|
||||
|
||||
// TODO: replace with Wasm types
|
||||
interfaces.types.push(Type::Function { inputs, outputs });
|
||||
interfaces.types.push(Type::Function {
|
||||
arguments,
|
||||
output_types,
|
||||
});
|
||||
|
||||
let adapter_idx = (interfaces.types.len() - 2) as u32;
|
||||
let export_idx = (interfaces.types.len() - 1) as u32;
|
||||
@ -60,16 +69,19 @@ impl WITGenerator for AstFunctionItem {
|
||||
|
||||
let mut instructions = self
|
||||
.signature
|
||||
.input_types
|
||||
.arguments
|
||||
.iter()
|
||||
.enumerate()
|
||||
.try_fold::<_, _, Result<_>>(Vec::new(), |mut instructions, (arg_id, input_type)| {
|
||||
let mut new_instructions =
|
||||
input_type.generate_instructions_for_input_type(arg_id as _, wit_resolver)?;
|
||||
.try_fold::<_, _, Result<_>>(
|
||||
Vec::new(),
|
||||
|mut instructions, (arg_id, (_, input_type))| {
|
||||
let mut new_instructions = input_type
|
||||
.generate_instructions_for_input_type(arg_id as _, wit_resolver)?;
|
||||
|
||||
instructions.append(&mut new_instructions);
|
||||
Ok(instructions)
|
||||
})?;
|
||||
},
|
||||
)?;
|
||||
|
||||
let export_function_index = (wit_resolver.interfaces.exports.len() - 1) as u32;
|
||||
instructions.push(Instruction::CallCore {
|
||||
@ -119,8 +131,8 @@ impl FnInstructionGenerator for ParsedType {
|
||||
ParsedType::Boolean => vec![Instruction::ArgumentGet { index }],
|
||||
ParsedType::I8 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS8],
|
||||
ParsedType::I16 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS16],
|
||||
ParsedType::I32 => vec![Instruction::ArgumentGet { index }],
|
||||
ParsedType::I64 => vec![Instruction::ArgumentGet { index }],
|
||||
ParsedType::I32 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS32],
|
||||
ParsedType::I64 => vec![Instruction::ArgumentGet { index }, Instruction::I64FromS64],
|
||||
ParsedType::U8 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU8],
|
||||
ParsedType::U16 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU16],
|
||||
ParsedType::U32 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU32],
|
||||
@ -142,11 +154,11 @@ impl FnInstructionGenerator for ParsedType {
|
||||
Instruction::ByteArrayLowerMemory,
|
||||
],
|
||||
ParsedType::Record(record_name) => {
|
||||
let type_index = wit_resolver.get_record_type_id(record_name)?;
|
||||
let record_type_id = wit_resolver.get_record_type_id(record_name)? as u32;
|
||||
|
||||
vec! [
|
||||
Instruction::ArgumentGet { index },
|
||||
Instruction::RecordLowerMemory { type_index },
|
||||
Instruction::RecordLowerMemory { record_type_id },
|
||||
]
|
||||
},
|
||||
};
|
||||
@ -160,8 +172,8 @@ impl FnInstructionGenerator for ParsedType {
|
||||
ParsedType::Boolean => vec![],
|
||||
ParsedType::I8 => vec![Instruction::S8FromI32],
|
||||
ParsedType::I16 => vec![Instruction::S16FromI32],
|
||||
ParsedType::I32 => vec![],
|
||||
ParsedType::I64 => vec![],
|
||||
ParsedType::I32 => vec![Instruction::S32FromI32],
|
||||
ParsedType::I64 => vec![Instruction::S64FromI64],
|
||||
ParsedType::U8 => vec![Instruction::U8FromI32],
|
||||
ParsedType::U16 => vec![Instruction::U16FromI32],
|
||||
ParsedType::U32 => vec![Instruction::U32FromI32],
|
||||
@ -185,11 +197,11 @@ impl FnInstructionGenerator for ParsedType {
|
||||
Instruction::CallCore { function_index: DEALLOCATE_FUNC.id },
|
||||
],
|
||||
ParsedType::Record(record_name) => {
|
||||
let type_index = wit_resolver.get_record_type_id(record_name)?;
|
||||
let record_type_id = wit_resolver.get_record_type_id(record_name)? as u32;
|
||||
|
||||
vec! [
|
||||
Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id },
|
||||
Instruction::RecordLiftMemory { type_index },
|
||||
Instruction::RecordLiftMemory { record_type_id },
|
||||
]
|
||||
},
|
||||
};
|
||||
|
@ -16,13 +16,14 @@
|
||||
|
||||
use super::WITGenerator;
|
||||
use super::WITResolver;
|
||||
use super::utils::ptype_to_itype;
|
||||
use super::utils::ptype_to_itype_checked;
|
||||
use crate::default_export_api_config::*;
|
||||
use crate::Result;
|
||||
|
||||
use fluence_sdk_wit::AstExternModItem;
|
||||
use fluence_sdk_wit::AstExternFnItem;
|
||||
use fluence_sdk_wit::ParsedType;
|
||||
use wasmer_wit::ast::FunctionArg as IFunctionArg;
|
||||
use wasmer_wit::interpreter::Instruction;
|
||||
use crate::instructions_generator::utils::wtype_to_itype;
|
||||
|
||||
@ -51,28 +52,35 @@ fn generate_wit_for_import<'a>(
|
||||
use wasmer_wit::ast::Type;
|
||||
use wasmer_wit::ast::Adapter;
|
||||
|
||||
let inputs = import
|
||||
let arguments = import
|
||||
.signature
|
||||
.input_types
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|input_type| ptype_to_itype(input_type, wit_resolver))
|
||||
.map(|(arg_name, arg_type)| -> Result<IFunctionArg> {
|
||||
Ok(IFunctionArg {
|
||||
name: arg_name.clone(),
|
||||
ty: ptype_to_itype_checked(arg_type, wit_resolver)?,
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
let outputs = match import.signature.output_type {
|
||||
Some(ref output_type) => vec![ptype_to_itype(output_type, wit_resolver)?],
|
||||
let output_types = match import.signature.output_type {
|
||||
Some(ref output_type) => vec![ptype_to_itype_checked(output_type, wit_resolver)?],
|
||||
None => vec![],
|
||||
};
|
||||
|
||||
let interfaces = &mut wit_resolver.interfaces;
|
||||
interfaces.types.push(Type::Function { inputs, outputs });
|
||||
interfaces.types.push(Type::Function {
|
||||
arguments,
|
||||
output_types,
|
||||
});
|
||||
|
||||
let raw_inputs = import
|
||||
.signature
|
||||
.input_types
|
||||
.arguments
|
||||
.iter()
|
||||
.map(to_raw_input_types)
|
||||
.flatten()
|
||||
.map(|wt| wtype_to_itype(&wt))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let raw_outputs = match import.signature.output_type {
|
||||
@ -84,13 +92,13 @@ fn generate_wit_for_import<'a>(
|
||||
};
|
||||
|
||||
interfaces.types.push(Type::Function {
|
||||
inputs: raw_inputs.clone(),
|
||||
outputs: raw_outputs.clone(),
|
||||
arguments: raw_inputs.clone(),
|
||||
output_types: raw_outputs.clone(),
|
||||
});
|
||||
|
||||
interfaces.types.push(Type::Function {
|
||||
inputs: raw_inputs,
|
||||
outputs: raw_outputs,
|
||||
arguments: raw_inputs,
|
||||
output_types: raw_outputs,
|
||||
});
|
||||
|
||||
let adapter_idx = (interfaces.types.len() - 2) as u32;
|
||||
@ -116,15 +124,18 @@ fn generate_wit_for_import<'a>(
|
||||
|
||||
let mut instructions = import
|
||||
.signature
|
||||
.input_types
|
||||
.arguments
|
||||
.iter()
|
||||
.try_fold::<_, _, Result<_>>((0, Vec::new()), |(arg_id, mut instructions), input_type| {
|
||||
.try_fold::<_, _, Result<_>>(
|
||||
(0, Vec::new()),
|
||||
|(arg_id, mut instructions), (_, input_type)| {
|
||||
let (mut new_instructions, shift) =
|
||||
input_type.generate_instructions_for_input_type(arg_id as _, wit_resolver)?;
|
||||
|
||||
instructions.append(&mut new_instructions);
|
||||
Ok((arg_id + shift, instructions))
|
||||
})?
|
||||
},
|
||||
)?
|
||||
.1;
|
||||
|
||||
// TODO: refactor
|
||||
@ -180,8 +191,8 @@ impl ForeignModInstructionGenerator for ParsedType {
|
||||
ParsedType::Boolean => (vec![Instruction::ArgumentGet { index }], 1),
|
||||
ParsedType::I8 => (vec![Instruction::ArgumentGet { index }, Instruction::S8FromI32], 1),
|
||||
ParsedType::I16 => (vec![Instruction::ArgumentGet { index }, Instruction::S16FromI32], 1),
|
||||
ParsedType::I32 => (vec![Instruction::ArgumentGet { index }], 1),
|
||||
ParsedType::I64 => (vec![Instruction::ArgumentGet { index }], 1),
|
||||
ParsedType::I32 => (vec![Instruction::ArgumentGet { index }, Instruction::S32FromI32], 1),
|
||||
ParsedType::I64 => (vec![Instruction::ArgumentGet { index }, Instruction::S64FromI64], 1),
|
||||
ParsedType::U8 => (vec![Instruction::ArgumentGet { index }, Instruction::U8FromI32], 1),
|
||||
ParsedType::U16 => (vec![Instruction::ArgumentGet { index }, Instruction::U16FromI32], 1),
|
||||
ParsedType::U32 => (vec![Instruction::ArgumentGet { index }, Instruction::U32FromI32], 1),
|
||||
@ -199,11 +210,11 @@ impl ForeignModInstructionGenerator for ParsedType {
|
||||
Instruction::ByteArrayLiftMemory,
|
||||
], 2),
|
||||
ParsedType::Record(record_name) => {
|
||||
let type_index = wit_resolver.get_record_type_id(record_name)?;
|
||||
let record_type_id = wit_resolver.get_record_type_id(record_name)? as u32;
|
||||
|
||||
(vec![
|
||||
Instruction::ArgumentGet { index },
|
||||
Instruction::RecordLiftMemory { type_index },
|
||||
Instruction::RecordLiftMemory { record_type_id },
|
||||
], 1)
|
||||
}
|
||||
};
|
||||
@ -217,8 +228,8 @@ impl ForeignModInstructionGenerator for ParsedType {
|
||||
ParsedType::Boolean => vec![],
|
||||
ParsedType::I8 => vec![Instruction::I32FromS8],
|
||||
ParsedType::I16 => vec![Instruction::I32FromS16],
|
||||
ParsedType::I32 => vec![],
|
||||
ParsedType::I64 => vec![],
|
||||
ParsedType::I32 => vec![Instruction::I32FromS32],
|
||||
ParsedType::I64 => vec![Instruction::I64FromS64],
|
||||
ParsedType::U8 => vec![Instruction::I32FromU8],
|
||||
ParsedType::U16 => vec![Instruction::I32FromU16],
|
||||
ParsedType::U32 => vec![Instruction::I32FromU32],
|
||||
@ -244,10 +255,10 @@ impl ForeignModInstructionGenerator for ParsedType {
|
||||
Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.id },
|
||||
],
|
||||
ParsedType::Record(record_name) => {
|
||||
let type_index = wit_resolver.get_record_type_id(record_name)?;
|
||||
let record_type_id = wit_resolver.get_record_type_id(record_name)? as u32;
|
||||
|
||||
vec![
|
||||
Instruction::RecordLowerMemory {type_index},
|
||||
Instruction::RecordLowerMemory { record_type_id },
|
||||
Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.id },
|
||||
]
|
||||
},
|
||||
@ -257,10 +268,11 @@ impl ForeignModInstructionGenerator for ParsedType {
|
||||
}
|
||||
}
|
||||
|
||||
use fluence_sdk_wit::WasmType;
|
||||
use fluence_sdk_wit::RustType;
|
||||
use wasmer_wit::types::InterfaceType as IType;
|
||||
|
||||
pub fn to_raw_input_types(ty: &ParsedType) -> Vec<WasmType> {
|
||||
match ty {
|
||||
pub fn to_raw_input_types(arg: &(String, ParsedType)) -> Vec<IFunctionArg> {
|
||||
match arg.1 {
|
||||
ParsedType::Boolean
|
||||
| ParsedType::I8
|
||||
| ParsedType::I16
|
||||
@ -268,15 +280,36 @@ pub fn to_raw_input_types(ty: &ParsedType) -> Vec<WasmType> {
|
||||
| ParsedType::U8
|
||||
| ParsedType::U16
|
||||
| ParsedType::U32
|
||||
| ParsedType::Record(_) => vec![WasmType::I32],
|
||||
ParsedType::I64 | ParsedType::U64 => vec![WasmType::I64],
|
||||
ParsedType::F32 => vec![WasmType::F32],
|
||||
ParsedType::F64 => vec![WasmType::F64],
|
||||
ParsedType::Utf8String | ParsedType::ByteVector => vec![WasmType::I32, WasmType::I32],
|
||||
| ParsedType::Record(_) => vec![IFunctionArg {
|
||||
name: arg.0.clone(),
|
||||
ty: IType::I32,
|
||||
}],
|
||||
ParsedType::I64 | ParsedType::U64 => vec![IFunctionArg {
|
||||
name: arg.0.clone(),
|
||||
ty: IType::I64,
|
||||
}],
|
||||
ParsedType::F32 => vec![IFunctionArg {
|
||||
name: arg.0.clone(),
|
||||
ty: IType::F32,
|
||||
}],
|
||||
ParsedType::F64 => vec![IFunctionArg {
|
||||
name: arg.0.clone(),
|
||||
ty: IType::F64,
|
||||
}],
|
||||
ParsedType::Utf8String | ParsedType::ByteVector => vec![
|
||||
IFunctionArg {
|
||||
name: format!("{}_ptr", arg.0),
|
||||
ty: IType::I32,
|
||||
},
|
||||
IFunctionArg {
|
||||
name: format!("{}_ptr", arg.0),
|
||||
ty: IType::I32,
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_raw_output_type(ty: &ParsedType) -> Vec<WasmType> {
|
||||
pub fn to_raw_output_type(ty: &ParsedType) -> Vec<RustType> {
|
||||
match ty {
|
||||
ParsedType::Boolean
|
||||
| ParsedType::I8
|
||||
@ -284,10 +317,10 @@ pub fn to_raw_output_type(ty: &ParsedType) -> Vec<WasmType> {
|
||||
| ParsedType::I32
|
||||
| ParsedType::U8
|
||||
| ParsedType::U16
|
||||
| ParsedType::U32 => vec![WasmType::I32],
|
||||
ParsedType::I64 | ParsedType::U64 => vec![WasmType::I64],
|
||||
ParsedType::F32 => vec![WasmType::F32],
|
||||
ParsedType::F64 => vec![WasmType::F64],
|
||||
| ParsedType::U32 => vec![RustType::I32],
|
||||
ParsedType::I64 | ParsedType::U64 => vec![RustType::I64],
|
||||
ParsedType::F32 => vec![RustType::F32],
|
||||
ParsedType::F64 => vec![RustType::F64],
|
||||
ParsedType::Utf8String | ParsedType::ByteVector | ParsedType::Record(_) => vec![],
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ use crate::Result;
|
||||
|
||||
use fluence_sdk_wit::AstRecordItem;
|
||||
|
||||
use wasmer_wit::ast::Type;
|
||||
use wasmer_wit::types::RecordFieldType as IRecordFieldType;
|
||||
use wasmer_wit::types::RecordType;
|
||||
use wasmer_wit::vec1::Vec1;
|
||||
|
||||
@ -29,8 +29,11 @@ impl WITGenerator for AstRecordItem {
|
||||
let fields = self
|
||||
.fields
|
||||
.iter()
|
||||
.map(|field| super::utils::ptype_to_itype(&field.ty, wit_resolver))
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
.map(|field| IRecordFieldType {
|
||||
name: field.name.clone().unwrap_or_default(),
|
||||
ty: super::utils::ptype_to_itype_unchecked(&field.ty, wit_resolver),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let fields = Vec1::new(fields).map_err(|_| {
|
||||
crate::errors::WITGeneratorError::CorruptedRecord(format!(
|
||||
@ -39,15 +42,12 @@ impl WITGenerator for AstRecordItem {
|
||||
))
|
||||
})?;
|
||||
|
||||
wit_resolver
|
||||
.interfaces
|
||||
.types
|
||||
.push(Type::Record(RecordType { fields }));
|
||||
let new_record_type = RecordType {
|
||||
name: self.name.clone(),
|
||||
fields,
|
||||
};
|
||||
|
||||
wit_resolver.types.insert(
|
||||
self.name.clone(),
|
||||
(wit_resolver.interfaces.types.len() - 1) as _,
|
||||
);
|
||||
wit_resolver.insert_record_type(new_record_type);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -19,34 +19,55 @@ use crate::instructions_generator::WITResolver;
|
||||
use crate::Result;
|
||||
|
||||
use fluence_sdk_wit::ParsedType;
|
||||
use fluence_sdk_wit::WasmType;
|
||||
use fluence_sdk_wit::RustType;
|
||||
|
||||
pub(crate) fn ptype_to_itype(pty: &ParsedType, wit_resolver: &WITResolver) -> Result<IType> {
|
||||
// return error if there is no record with such name
|
||||
pub(crate) fn ptype_to_itype_checked(
|
||||
pty: &ParsedType,
|
||||
wit_resolver: &mut WITResolver,
|
||||
) -> Result<IType> {
|
||||
match pty {
|
||||
ParsedType::I8 => Ok(IType::S8),
|
||||
ParsedType::I16 => Ok(IType::S16),
|
||||
ParsedType::I32 => Ok(IType::S32),
|
||||
ParsedType::I64 => Ok(IType::S64),
|
||||
ParsedType::U8 => Ok(IType::U8),
|
||||
ParsedType::U16 => Ok(IType::U16),
|
||||
ParsedType::U32 => Ok(IType::U32),
|
||||
ParsedType::U64 => Ok(IType::U64),
|
||||
ParsedType::F32 => Ok(IType::F32),
|
||||
ParsedType::F64 => Ok(IType::F64),
|
||||
ParsedType::Boolean => Ok(IType::I32),
|
||||
ParsedType::Utf8String => Ok(IType::String),
|
||||
ParsedType::ByteVector => Ok(IType::ByteArray),
|
||||
ParsedType::Record(record_name) => {
|
||||
Ok(IType::Record(wit_resolver.get_record_type(record_name)?))
|
||||
let record_type_id = wit_resolver.get_record_type_id(record_name)?;
|
||||
Ok(IType::Record(record_type_id as _))
|
||||
}
|
||||
_ => Ok(ptype_to_itype_unchecked(pty, wit_resolver)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn ptype_to_itype_unchecked(pty: &ParsedType, wit_resolver: &mut WITResolver) -> IType {
|
||||
match pty {
|
||||
ParsedType::I8 => IType::S8,
|
||||
ParsedType::I16 => IType::S16,
|
||||
ParsedType::I32 => IType::S32,
|
||||
ParsedType::I64 => IType::S64,
|
||||
ParsedType::U8 => IType::U8,
|
||||
ParsedType::U16 => IType::U16,
|
||||
ParsedType::U32 => IType::U32,
|
||||
ParsedType::U64 => IType::U64,
|
||||
ParsedType::F32 => IType::F32,
|
||||
ParsedType::F64 => IType::F64,
|
||||
ParsedType::Boolean => IType::I32,
|
||||
ParsedType::Utf8String => IType::String,
|
||||
ParsedType::ByteVector => IType::ByteArray,
|
||||
ParsedType::Record(record_name) => {
|
||||
let record_type_id = wit_resolver.get_record_type_id_unchecked(record_name);
|
||||
IType::Record(record_type_id as _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn wtype_to_itype(pty: &WasmType) -> IType {
|
||||
pub(crate) fn wtype_to_itype(pty: &RustType) -> IType {
|
||||
match pty {
|
||||
WasmType::I32 => IType::I32,
|
||||
WasmType::I64 => IType::I64,
|
||||
WasmType::F32 => IType::F32,
|
||||
WasmType::F64 => IType::F64,
|
||||
RustType::I8 => IType::S8,
|
||||
RustType::I16 => IType::S16,
|
||||
RustType::I32 => IType::S32,
|
||||
RustType::I64 => IType::S64,
|
||||
RustType::U8 => IType::U8,
|
||||
RustType::U16 => IType::U16,
|
||||
RustType::U32 => IType::U32,
|
||||
RustType::U64 => IType::U64,
|
||||
RustType::F32 => IType::F32,
|
||||
RustType::F64 => IType::F64,
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
use crate::default_export_api_config::*;
|
||||
use crate::errors::WITGeneratorError;
|
||||
use crate::instructions_generator::WITGenerator;
|
||||
use crate::instructions_generator::WITResolver;
|
||||
use crate::Result;
|
||||
|
||||
pub use fluence_sdk_wit::FCEAst;
|
||||
@ -77,12 +78,14 @@ fn wasm_ast_extractor(wasm_module: &walrus::Module) -> Result<ModuleAST> {
|
||||
}
|
||||
|
||||
fn generate_interfaces(module_ast: &ModuleAST) -> Result<Interfaces<'_>> {
|
||||
let mut wit_resolver = crate::instructions_generator::WITResolver::default();
|
||||
let mut wit_resolver = WITResolver::default();
|
||||
generate_default_export_api(&mut wit_resolver.interfaces);
|
||||
|
||||
for record in &module_ast.records {
|
||||
record.generate_wit(&mut wit_resolver)?;
|
||||
}
|
||||
validate_records(&wit_resolver)?;
|
||||
|
||||
for function in &module_ast.functions {
|
||||
function.generate_wit(&mut wit_resolver)?;
|
||||
}
|
||||
@ -102,3 +105,49 @@ fn generate_default_export_api(interfaces: &mut Interfaces) {
|
||||
SET_RESULT_SIZE_FUNC.update_interfaces(interfaces);
|
||||
SET_RESULT_PTR_FUNC.update_interfaces(interfaces);
|
||||
}
|
||||
|
||||
fn validate_records(wit_resolver: &WITResolver) -> Result<()> {
|
||||
const TYPE_RESOLVE_RECURSION_LIMIT: u32 = 1024;
|
||||
|
||||
fn validate_record_type(
|
||||
record_type: &wasmer_wit::types::RecordType,
|
||||
recursion_level: u32,
|
||||
wit_resolver: &WITResolver,
|
||||
) -> Result<()> {
|
||||
if recursion_level >= TYPE_RESOLVE_RECURSION_LIMIT {
|
||||
return Err(WITGeneratorError::CorruptedRecord(String::from(
|
||||
"too many inner structures level",
|
||||
)));
|
||||
}
|
||||
|
||||
for field in record_type.fields.iter() {
|
||||
match &field.ty {
|
||||
wasmer_wit::types::InterfaceType::Record(record_type_id) => {
|
||||
let inner_record_type = wit_resolver.get_record_type(*record_type_id)?;
|
||||
validate_record_type(&inner_record_type, recursion_level + 1, wit_resolver)?;
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
if wit_resolver.unresolved_types_count() != 0 {
|
||||
return Err(WITGeneratorError::CorruptedRecord(format!(
|
||||
"{} types unresolved",
|
||||
wit_resolver.unresolved_types_count()
|
||||
)));
|
||||
}
|
||||
|
||||
for ty in wit_resolver.interfaces.types.iter() {
|
||||
let record_type = match ty {
|
||||
wasmer_wit::ast::Type::Record(ty) => ty,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
validate_record_type(record_type, 0, wit_resolver)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -11,5 +11,5 @@ name = "fce_wit_interfaces"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.0"}
|
||||
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.5" }
|
||||
multimap = "0.8.1"
|
||||
|
@ -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.0"}
|
||||
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.5" }
|
||||
fce-wit-interfaces = { path = "../wit-interfaces", version = "0.1.1" }
|
||||
|
||||
anyhow = "1.0.31"
|
||||
|
@ -32,9 +32,9 @@ mod extractor;
|
||||
|
||||
pub use errors::WITParserError;
|
||||
|
||||
pub use embedder::embed_wit;
|
||||
pub use embedder::embed_text_wit;
|
||||
pub use deleter::delete_wit_section;
|
||||
pub use deleter::delete_wit_section_from_file;
|
||||
pub use embedder::embed_wit;
|
||||
pub use embedder::embed_text_wit;
|
||||
pub use extractor::extract_wit;
|
||||
pub use extractor::extract_text_wit;
|
||||
|
@ -17,11 +17,11 @@ fce-wit-parser = { path = "../crates/wit-parser", version = "0.1.3" }
|
||||
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.0", features = ["serde"] }
|
||||
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.5" }
|
||||
wasmer-wasi = { package = "wasmer-wasi-fl", version = "0.17.0" }
|
||||
serde = { version = "1.0.114", default-features = false, features = [ "derive" ] }
|
||||
|
||||
multimap = "0.8.1"
|
||||
multi-map = "1.3.0"
|
||||
boolinator = "2.4.0"
|
||||
parity-wasm = "0.41.0"
|
||||
pwasm-utils = "0.12.0"
|
||||
|
@ -21,10 +21,10 @@ use std::collections::hash_map::Entry;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Represent a function type inside FCE.
|
||||
#[derive(Debug, serde::Serialize)]
|
||||
#[derive(Debug)]
|
||||
pub struct FCEFunctionSignature<'a> {
|
||||
pub name: &'a str,
|
||||
pub input_types: &'a Vec<IType>,
|
||||
pub arguments: &'a Vec<IFunctionArg>,
|
||||
pub output_types: &'a Vec<IType>,
|
||||
}
|
||||
|
||||
@ -125,7 +125,7 @@ impl FCE {
|
||||
self.modules.iter().map(|(module_name, module)| {
|
||||
(
|
||||
module_name.as_str(),
|
||||
Self::get_module_function_signatures(module),
|
||||
Self::get_module_function_signatures(module).collect::<Vec<_>>(),
|
||||
)
|
||||
})
|
||||
}
|
||||
@ -134,22 +134,41 @@ impl FCE {
|
||||
pub fn module_interface<S: AsRef<str>>(
|
||||
&self,
|
||||
module_name: S,
|
||||
) -> Result<Vec<FCEFunctionSignature<'_>>> {
|
||||
) -> Result<impl Iterator<Item = FCEFunctionSignature<'_>>> {
|
||||
match self.modules.get(module_name.as_ref()) {
|
||||
Some(module) => Ok(Self::get_module_function_signatures(module)),
|
||||
None => Err(FCEError::NoSuchModule(module_name.as_ref().to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_module_function_signatures(module: &FCEModule) -> Vec<FCEFunctionSignature<'_>> {
|
||||
/// Return record types of export functions of all loaded info FCE modules.
|
||||
pub fn record_types(&self) -> impl Iterator<Item = &(u64, IRecordType)> {
|
||||
self.modules
|
||||
.iter()
|
||||
.flat_map(|(_, module)| module.get_export_record_types())
|
||||
}
|
||||
|
||||
/// Return record types exported by module with given name.
|
||||
pub fn module_record_types<S: AsRef<str>>(
|
||||
&self,
|
||||
module_name: S,
|
||||
) -> Result<impl Iterator<Item = &(u64, IRecordType)>> {
|
||||
match self.modules.get(module_name.as_ref()) {
|
||||
Some(module) => Ok(module.get_export_record_types()),
|
||||
None => Err(FCEError::NoSuchModule(module_name.as_ref().to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_module_function_signatures(
|
||||
module: &FCEModule,
|
||||
) -> impl Iterator<Item = FCEFunctionSignature<'_>> {
|
||||
module
|
||||
.get_exports_signatures()
|
||||
.map(|(name, input_types, output_types)| FCEFunctionSignature {
|
||||
.map(|(name, arguments, output_types)| FCEFunctionSignature {
|
||||
name,
|
||||
input_types,
|
||||
arguments,
|
||||
output_types,
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
|
@ -38,8 +38,12 @@ pub use engine::FCE;
|
||||
pub use engine::FCEFunctionSignature;
|
||||
pub use errors::FCEError;
|
||||
pub use module::IValue;
|
||||
pub use module::IRecordType;
|
||||
pub use module::IFunctionArg;
|
||||
pub use module::IType;
|
||||
pub use module::from_interface_values;
|
||||
pub use module::to_interface_value;
|
||||
|
||||
pub use wasmer_wit::types::RecordFieldType as IRecordFieldType;
|
||||
|
||||
pub(crate) type Result<T> = std::result::Result<T, FCEError>;
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
use super::IValue;
|
||||
use super::IType;
|
||||
use super::IFunctionArg;
|
||||
use wasmer_wit::interpreter::wasm;
|
||||
|
||||
// In current implementation export simply does nothing, because there is no more
|
||||
@ -23,7 +24,7 @@ use wasmer_wit::interpreter::wasm;
|
||||
// but explicit Exports is still required by wasmer-interface-types::Interpreter.
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct WITExport {
|
||||
inputs: Vec<IType>,
|
||||
arguments: Vec<IFunctionArg>,
|
||||
outputs: Vec<IType>,
|
||||
function: fn(arguments: &[IValue]) -> Result<Vec<IValue>, ()>,
|
||||
}
|
||||
@ -32,7 +33,7 @@ impl WITExport {
|
||||
#[allow(unused)]
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
inputs: vec![],
|
||||
arguments: vec![],
|
||||
outputs: vec![],
|
||||
function: |_| -> _ { Ok(vec![]) },
|
||||
}
|
||||
@ -41,15 +42,15 @@ impl WITExport {
|
||||
|
||||
impl wasm::structures::Export for WITExport {
|
||||
fn inputs_cardinality(&self) -> usize {
|
||||
self.inputs.len() as usize
|
||||
self.arguments.len()
|
||||
}
|
||||
|
||||
fn outputs_cardinality(&self) -> usize {
|
||||
self.outputs.len()
|
||||
}
|
||||
|
||||
fn inputs(&self) -> &[IType] {
|
||||
&self.inputs
|
||||
fn arguments(&self) -> &[IFunctionArg] {
|
||||
&self.arguments
|
||||
}
|
||||
|
||||
fn outputs(&self) -> &[IType] {
|
||||
|
@ -15,17 +15,17 @@
|
||||
*/
|
||||
|
||||
use super::wit_prelude::*;
|
||||
use super::{IType, IValue, WValue};
|
||||
use super::{IType, IRecordType, IFunctionArg, IValue, WValue};
|
||||
use crate::Result;
|
||||
use crate::FCEModuleConfig;
|
||||
|
||||
use fce_wit_interfaces::FCEWITInterfaces;
|
||||
use fce_wit_parser::extract_wit;
|
||||
use wasmer_core::Instance as WasmerInstance;
|
||||
use wasmer_core::import::Namespace;
|
||||
use wasmer_runtime::compile;
|
||||
use wasmer_runtime::ImportObject;
|
||||
use wasmer_wit::interpreter::Interpreter;
|
||||
use fce_wit_parser::extract_wit;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
@ -38,8 +38,8 @@ type WITInterpreter =
|
||||
#[derive(Clone)]
|
||||
pub(super) struct WITModuleFunc {
|
||||
interpreter: Arc<WITInterpreter>,
|
||||
pub(super) inputs: Vec<IType>,
|
||||
pub(super) outputs: Vec<IType>,
|
||||
pub(super) arguments: Vec<IFunctionArg>,
|
||||
pub(super) output_types: Vec<IType>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -65,7 +65,7 @@ impl Callable {
|
||||
|
||||
pub(crate) struct FCEModule {
|
||||
// wasmer_instance is needed because WITInstance contains dynamic functions
|
||||
// that internally keep pointer to Wasmer instance.
|
||||
// that internally keep pointer to it.
|
||||
#[allow(unused)]
|
||||
wasmer_instance: Box<WasmerInstance>,
|
||||
|
||||
@ -80,7 +80,10 @@ pub(crate) struct FCEModule {
|
||||
host_import_object: ImportObject,
|
||||
|
||||
// TODO: replace with dyn Trait
|
||||
exports_funcs: HashMap<String, Arc<Callable>>,
|
||||
export_funcs: HashMap<String, Arc<Callable>>,
|
||||
|
||||
// TODO: save refs instead of copies
|
||||
record_types: Vec<(u64, IRecordType)>,
|
||||
}
|
||||
|
||||
impl FCEModule {
|
||||
@ -116,7 +119,8 @@ impl FCEModule {
|
||||
std::mem::transmute::<_, Arc<WITInstance>>(wit_instance)
|
||||
};
|
||||
|
||||
let exports_funcs = Self::instantiate_wit_exports(wit_instance, &fce_wit)?;
|
||||
let export_funcs = Self::instantiate_wit_exports(&wit_instance, &fce_wit)?;
|
||||
let record_types = Self::extract_export_record_types(&export_funcs, &wit_instance)?;
|
||||
|
||||
// call _start to populate the WASI state of the module
|
||||
#[rustfmt::skip]
|
||||
@ -128,12 +132,13 @@ impl FCEModule {
|
||||
wasmer_instance: Box::new(wasmer_instance),
|
||||
import_object,
|
||||
host_import_object: config.imports,
|
||||
exports_funcs,
|
||||
export_funcs,
|
||||
record_types,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn call(&mut self, function_name: &str, args: &[IValue]) -> Result<Vec<IValue>> {
|
||||
match self.exports_funcs.get_mut(function_name) {
|
||||
match self.export_funcs.get_mut(function_name) {
|
||||
Some(func) => Arc::make_mut(func).call(args),
|
||||
None => Err(FCEError::NoSuchFunction(format!(
|
||||
"{} hasn't been found while calling",
|
||||
@ -144,23 +149,27 @@ impl FCEModule {
|
||||
|
||||
pub(crate) fn get_exports_signatures(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (&String, &Vec<IType>, &Vec<IType>)> {
|
||||
self.exports_funcs.iter().map(|(func_name, func)| {
|
||||
) -> impl Iterator<Item = (&String, &Vec<IFunctionArg>, &Vec<IType>)> {
|
||||
self.export_funcs.iter().map(|(func_name, func)| {
|
||||
(
|
||||
func_name,
|
||||
&func.wit_module_func.inputs,
|
||||
&func.wit_module_func.outputs,
|
||||
&func.wit_module_func.arguments,
|
||||
&func.wit_module_func.output_types,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn get_export_record_types(&self) -> impl Iterator<Item = &(u64, IRecordType)> {
|
||||
self.record_types.iter()
|
||||
}
|
||||
|
||||
pub(crate) fn get_wasi_state(&mut self) -> &wasmer_wasi::state::WasiState {
|
||||
unsafe { wasmer_wasi::state::get_wasi_state(self.wasmer_instance.context_mut()) }
|
||||
}
|
||||
|
||||
// TODO: change the cloning Callable behaviour after changes of Wasmer API
|
||||
pub(super) fn get_callable(&self, function_name: &str) -> Result<Arc<Callable>> {
|
||||
match self.exports_funcs.get(function_name) {
|
||||
match self.export_funcs.get(function_name) {
|
||||
Some(func) => Ok(func.clone()),
|
||||
None => Err(FCEError::NoSuchFunction(format!(
|
||||
"{} hasn't been found while calling",
|
||||
@ -170,7 +179,7 @@ impl FCEModule {
|
||||
}
|
||||
|
||||
fn instantiate_wit_exports(
|
||||
wit_instance: Arc<WITInstance>,
|
||||
wit_instance: &Arc<WITInstance>,
|
||||
wit: &FCEWITInterfaces<'_>,
|
||||
) -> Result<HashMap<String, Arc<Callable>>> {
|
||||
use fce_wit_interfaces::WITAstType;
|
||||
@ -197,13 +206,14 @@ impl FCEModule {
|
||||
|
||||
match wit_type {
|
||||
WITAstType::Function {
|
||||
inputs, outputs, ..
|
||||
arguments,
|
||||
output_types,
|
||||
} => {
|
||||
let interpreter: WITInterpreter = adapter_instructions.try_into()?;
|
||||
let wit_module_func = WITModuleFunc {
|
||||
interpreter: Arc::new(interpreter),
|
||||
inputs: inputs.clone(),
|
||||
outputs: outputs.clone(),
|
||||
arguments: arguments.clone(),
|
||||
output_types: output_types.clone(),
|
||||
};
|
||||
|
||||
Ok((
|
||||
@ -233,9 +243,9 @@ impl FCEModule {
|
||||
use wasmer_core::vm::Ctx;
|
||||
|
||||
// returns function that will be called from imports of Wasmer module
|
||||
fn dyn_func_from_raw_import<F>(
|
||||
inputs: Vec<IType>,
|
||||
outputs: Vec<IType>,
|
||||
fn dyn_func_from_raw_import<'a, 'b, F>(
|
||||
inputs: impl Iterator<Item = &'a IType>,
|
||||
outputs: impl Iterator<Item = &'b IType>,
|
||||
raw_import: F,
|
||||
) -> DynamicFunc<'static>
|
||||
where
|
||||
@ -244,8 +254,8 @@ impl FCEModule {
|
||||
use wasmer_core::types::FuncSig;
|
||||
use super::type_converters::itype_to_wtype;
|
||||
|
||||
let inputs = inputs.iter().map(itype_to_wtype).collect::<Vec<_>>();
|
||||
let outputs = outputs.iter().map(itype_to_wtype).collect::<Vec<_>>();
|
||||
let inputs = inputs.map(itype_to_wtype).collect::<Vec<_>>();
|
||||
let outputs = outputs.map(itype_to_wtype).collect::<Vec<_>>();
|
||||
DynamicFunc::new(Arc::new(FuncSig::new(inputs, outputs)), raw_import)
|
||||
}
|
||||
|
||||
@ -257,7 +267,10 @@ impl FCEModule {
|
||||
import_name: String,
|
||||
) -> impl Fn(&mut Ctx, &[WValue]) -> Vec<WValue> + 'static {
|
||||
move |_: &mut Ctx, inputs: &[WValue]| -> Vec<WValue> {
|
||||
use wasmer_wit::interpreter::stack::Stackable;
|
||||
|
||||
use super::type_converters::wval_to_ival;
|
||||
use super::type_converters::ival_to_wval;
|
||||
|
||||
log::trace!(
|
||||
"raw import for {}.{} called with {:?}\n",
|
||||
@ -269,13 +282,13 @@ impl FCEModule {
|
||||
// copy here because otherwise wit_instance will be consumed by the closure
|
||||
let wit_instance_callable = wit_instance.clone();
|
||||
let wit_inputs = inputs.iter().map(wval_to_ival).collect::<Vec<_>>();
|
||||
unsafe {
|
||||
let outputs = unsafe {
|
||||
// error here will be propagated by the special error instruction
|
||||
let _ = interpreter.run(
|
||||
interpreter.run(
|
||||
&wit_inputs,
|
||||
Arc::make_mut(&mut wit_instance_callable.assume_init()),
|
||||
);
|
||||
}
|
||||
)
|
||||
};
|
||||
|
||||
log::trace!(
|
||||
"\nraw import for {}.{} finished",
|
||||
@ -283,9 +296,13 @@ impl FCEModule {
|
||||
import_name
|
||||
);
|
||||
|
||||
// wit import functions should only change the stack state -
|
||||
// the result will be returned by an export function
|
||||
vec![]
|
||||
// TODO: optimize by prevent copying stack values
|
||||
outputs
|
||||
.unwrap_or_default()
|
||||
.as_slice()
|
||||
.iter()
|
||||
.map(ival_to_wval)
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,7 +326,10 @@ impl FCEModule {
|
||||
let wit_type = wit.type_by_idx_r(adapter_function_type)?;
|
||||
|
||||
match wit_type {
|
||||
WITAstType::Function { inputs, outputs } => {
|
||||
WITAstType::Function {
|
||||
arguments,
|
||||
output_types,
|
||||
} => {
|
||||
let interpreter: WITInterpreter = adapter_instructions.try_into()?;
|
||||
|
||||
let raw_import = create_raw_import(
|
||||
@ -318,8 +338,12 @@ impl FCEModule {
|
||||
import_namespace.to_string(),
|
||||
import_name.to_string(),
|
||||
);
|
||||
let wit_import =
|
||||
dyn_func_from_raw_import(inputs.clone(), outputs.clone(), raw_import);
|
||||
|
||||
let wit_import = dyn_func_from_raw_import(
|
||||
arguments.iter().map(|IFunctionArg { ty, .. }| ty),
|
||||
output_types.iter(),
|
||||
raw_import,
|
||||
);
|
||||
|
||||
Ok((import_namespace.to_string(), (*import_name, wit_import)))
|
||||
}
|
||||
@ -344,4 +368,57 @@ impl FCEModule {
|
||||
|
||||
Ok(import_object)
|
||||
}
|
||||
|
||||
fn extract_export_record_types(
|
||||
export_funcs: &HashMap<String, Arc<Callable>>,
|
||||
wit_instance: &Arc<WITInstance>,
|
||||
) -> Result<Vec<(u64, IRecordType)>> {
|
||||
fn handle_record_type(
|
||||
record_type_id: u64,
|
||||
wit_instance: &Arc<WITInstance>,
|
||||
export_record_types: &mut Vec<(u64, IRecordType)>,
|
||||
) -> Result<()> {
|
||||
use wasmer_wit::interpreter::wasm::structures::Instance;
|
||||
|
||||
let record_type = wit_instance
|
||||
.wit_record_by_id(record_type_id)
|
||||
.ok_or_else(|| {
|
||||
FCEError::WasmerResolveError(format!(
|
||||
"record type with type id {} not found",
|
||||
record_type_id
|
||||
))
|
||||
})?;
|
||||
export_record_types.push((record_type_id, record_type.clone()));
|
||||
|
||||
for field in record_type.fields.iter() {
|
||||
if let IType::Record(record_type_id) = &field.ty {
|
||||
handle_record_type(*record_type_id, wit_instance, export_record_types)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let export_record_ids = export_funcs
|
||||
.iter()
|
||||
.flat_map(|(_, ref mut callable)| {
|
||||
callable
|
||||
.wit_module_func
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|arg| &arg.ty)
|
||||
.chain(callable.wit_module_func.output_types.iter())
|
||||
})
|
||||
.filter_map(|itype| match itype {
|
||||
IType::Record(record_type_id) => Some(record_type_id),
|
||||
_ => None,
|
||||
});
|
||||
|
||||
let mut export_record_types = Vec::new();
|
||||
for record_type_id in export_record_ids {
|
||||
handle_record_type(*record_type_id, wit_instance, &mut export_record_types)?;
|
||||
}
|
||||
|
||||
Ok(export_record_types)
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ mod type_converters;
|
||||
mod fce_module;
|
||||
|
||||
pub use wasmer_wit::types::InterfaceType as IType;
|
||||
pub use wasmer_wit::types::RecordType as IRecordType;
|
||||
pub use wasmer_wit::ast::FunctionArg as IFunctionArg;
|
||||
pub use wasmer_wit::values::InterfaceValue as IValue;
|
||||
pub use wasmer_wit::values::from_interface_values;
|
||||
pub use wasmer_wit::values::to_interface_value;
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
use super::fce_module::FCEModule;
|
||||
use super::{IType, IValue, WValue};
|
||||
use super::{IType, IFunctionArg, IValue, WValue};
|
||||
use super::fce_module::Callable;
|
||||
use crate::Result;
|
||||
|
||||
@ -28,7 +28,7 @@ use std::sync::Arc;
|
||||
enum WITFunctionInner {
|
||||
Export {
|
||||
func: Arc<DynFunc<'static>>,
|
||||
inputs: Vec<IType>,
|
||||
arguments: Vec<IFunctionArg>,
|
||||
outputs: Vec<IType>,
|
||||
},
|
||||
Import {
|
||||
@ -49,10 +49,14 @@ impl WITFunction {
|
||||
use super::type_converters::wtype_to_itype;
|
||||
|
||||
let signature = dyn_func.signature();
|
||||
let inputs = signature
|
||||
let arguments = signature
|
||||
.params()
|
||||
.iter()
|
||||
.map(wtype_to_itype)
|
||||
.map(|wtype| IFunctionArg {
|
||||
// here it's considered as an anonymous arguments
|
||||
name: String::new(),
|
||||
ty: wtype_to_itype(wtype),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let outputs = signature
|
||||
.returns()
|
||||
@ -62,7 +66,7 @@ impl WITFunction {
|
||||
|
||||
let inner = WITFunctionInner::Export {
|
||||
func: Arc::new(dyn_func),
|
||||
inputs,
|
||||
arguments,
|
||||
outputs,
|
||||
};
|
||||
|
||||
@ -82,29 +86,31 @@ impl WITFunction {
|
||||
impl wasm::structures::LocalImport for WITFunction {
|
||||
fn inputs_cardinality(&self) -> usize {
|
||||
match &self.inner {
|
||||
WITFunctionInner::Export { ref inputs, .. } => inputs.len(),
|
||||
WITFunctionInner::Import { ref callable, .. } => callable.wit_module_func.inputs.len(),
|
||||
WITFunctionInner::Export { arguments, .. } => arguments.len(),
|
||||
WITFunctionInner::Import { callable, .. } => callable.wit_module_func.arguments.len(),
|
||||
}
|
||||
}
|
||||
|
||||
fn outputs_cardinality(&self) -> usize {
|
||||
match &self.inner {
|
||||
WITFunctionInner::Export { ref outputs, .. } => outputs.len(),
|
||||
WITFunctionInner::Import { ref callable, .. } => callable.wit_module_func.outputs.len(),
|
||||
WITFunctionInner::Import { ref callable, .. } => {
|
||||
callable.wit_module_func.output_types.len()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn inputs(&self) -> &[IType] {
|
||||
fn arguments(&self) -> &[IFunctionArg] {
|
||||
match &self.inner {
|
||||
WITFunctionInner::Export { ref inputs, .. } => inputs,
|
||||
WITFunctionInner::Import { ref callable, .. } => &callable.wit_module_func.inputs,
|
||||
WITFunctionInner::Export { ref arguments, .. } => arguments,
|
||||
WITFunctionInner::Import { ref callable, .. } => &callable.wit_module_func.arguments,
|
||||
}
|
||||
}
|
||||
|
||||
fn outputs(&self) -> &[IType] {
|
||||
match &self.inner {
|
||||
WITFunctionInner::Export { ref outputs, .. } => outputs,
|
||||
WITFunctionInner::Import { ref callable, .. } => &callable.wit_module_func.outputs,
|
||||
WITFunctionInner::Import { ref callable, .. } => &callable.wit_module_func.output_types,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
use super::wit_prelude::*;
|
||||
use super::fce_module::FCEModule;
|
||||
use super::IRecordType;
|
||||
use crate::Result;
|
||||
|
||||
use fce_wit_interfaces::FCEWITInterfaces;
|
||||
@ -29,9 +30,13 @@ use std::collections::HashMap;
|
||||
/// Contains all import and export functions that could be called from WIT context by call-core.
|
||||
#[derive(Clone)]
|
||||
pub(super) struct WITInstance {
|
||||
/// WIT functions indexed by id.
|
||||
funcs: HashMap<usize, WITFunction>,
|
||||
|
||||
/// WIT memories.
|
||||
memories: Vec<WITMemory>,
|
||||
record_types: HashMap<u32, WITAstType>,
|
||||
|
||||
record_types_by_id: HashMap<u64, IRecordType>,
|
||||
}
|
||||
|
||||
impl WITInstance {
|
||||
@ -47,12 +52,12 @@ impl WITInstance {
|
||||
exports.extend(imports);
|
||||
let funcs = exports;
|
||||
|
||||
let record_types = Self::extract_record_types(wit);
|
||||
let record_types_by_id = Self::extract_record_types(wit);
|
||||
|
||||
Ok(Self {
|
||||
funcs,
|
||||
memories,
|
||||
record_types,
|
||||
record_types_by_id,
|
||||
})
|
||||
}
|
||||
|
||||
@ -121,14 +126,21 @@ impl WITInstance {
|
||||
memories
|
||||
}
|
||||
|
||||
fn extract_record_types(wit: &FCEWITInterfaces<'_>) -> HashMap<u32, WITAstType> {
|
||||
wit.types()
|
||||
.enumerate()
|
||||
.filter_map(|(id, ty)| match ty {
|
||||
WITAstType::Record(_) => Some((id as u32, ty.clone())),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<HashMap<_, _>>()
|
||||
fn extract_record_types(wit: &FCEWITInterfaces<'_>) -> HashMap<u64, IRecordType> {
|
||||
let record_types_by_id = wit.types().fold(
|
||||
(HashMap::new(), 0u64),
|
||||
|(mut record_types_by_id, id), ty| {
|
||||
match ty {
|
||||
WITAstType::Record(record_type) => {
|
||||
record_types_by_id.insert(id, record_type.clone());
|
||||
}
|
||||
WITAstType::Function { .. } => {}
|
||||
};
|
||||
(record_types_by_id, id + 1)
|
||||
},
|
||||
);
|
||||
|
||||
record_types_by_id.0
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,10 +152,7 @@ impl wasm::structures::Instance<WITExport, WITFunction, WITMemory, WITMemoryView
|
||||
None
|
||||
}
|
||||
|
||||
fn local_or_import<I: TypedIndex + LocalImportIndex>(
|
||||
&mut self,
|
||||
index: I,
|
||||
) -> Option<&WITFunction> {
|
||||
fn local_or_import<I: TypedIndex + LocalImportIndex>(&self, index: I) -> Option<&WITFunction> {
|
||||
self.funcs.get(&index.index())
|
||||
}
|
||||
|
||||
@ -155,7 +164,7 @@ impl wasm::structures::Instance<WITExport, WITFunction, WITMemory, WITMemoryView
|
||||
}
|
||||
}
|
||||
|
||||
fn wit_type(&self, index: u32) -> Option<&WITAstType> {
|
||||
self.record_types.get(&index)
|
||||
fn wit_record_by_id(&self, index: u64) -> Option<&IRecordType> {
|
||||
self.record_types_by_id.get(&index)
|
||||
}
|
||||
}
|
||||
|
@ -18,26 +18,25 @@ use fce::FCE;
|
||||
use fce::IValue;
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
pub fn records() {
|
||||
let effector_wasm_bytes = std::fs::read("../examples/records/artifacts/wasm_modules/effector")
|
||||
.expect("../examples/records/artifacts/wasm_modules/effector.wasm should presence");
|
||||
let effector_wasm_bytes = std::fs::read("../examples/records/artifacts/records_effector.wasm")
|
||||
.expect("../examples/records/artifacts/records_effector.wasm should presence");
|
||||
|
||||
let pure_wasm_bytes = std::fs::read("../examples/records/artifacts/wasm_modules/pure")
|
||||
.expect("../examples/records/artifacts/wasm_modules/pure.wasm should presence");
|
||||
let pure_wasm_bytes = std::fs::read("../examples/records/artifacts/records_pure.wasm")
|
||||
.expect("../examples/records/artifacts/records_pure.wasm should presence");
|
||||
|
||||
let mut fce = FCE::new();
|
||||
let load_result = fce.load_module("pure", &pure_wasm_bytes, <_>::default());
|
||||
assert!(load_result.is_err());
|
||||
|
||||
fce.load_module("effector", &effector_wasm_bytes, <_>::default())
|
||||
fce.load_module("records_effector", &effector_wasm_bytes, <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't load a module into FCE: {:?}", e));
|
||||
|
||||
fce.load_module("pure", &pure_wasm_bytes, <_>::default())
|
||||
fce.load_module("records_pure", &pure_wasm_bytes, <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't load a module into FCE: {:?}", e));
|
||||
|
||||
let result = fce
|
||||
.call("pure", "invoke", &[])
|
||||
.call("records_pure", "invoke", &[])
|
||||
.unwrap_or_else(|e| panic!("can't invoke pure: {:?}", e));
|
||||
|
||||
assert_eq!(
|
||||
|
@ -32,6 +32,7 @@ pub async fn download(url: &str) -> bytes::Bytes {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn redis() {
|
||||
let wasm_bytes = download(REDIS_DOWNLOAD_URL).await;
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
9
examples/greeting/build.sh
Executable file
9
examples/greeting/build.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This script builds all subprojects and puts all created Wasm modules in one dir
|
||||
cargo update
|
||||
fce build --release
|
||||
|
||||
rm artifacts/*
|
||||
cp ../../target/wasm32-wasi/release/greeting.wasm artifacts/
|
||||
cp ../../target/wasm32-wasi/release/greeting_cp.wasm artifacts/
|
14
examples/ipfs-node/build.sh
Executable file
14
examples/ipfs-node/build.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This script builds all subprojects and puts all created Wasm modules in one dir
|
||||
cd effector
|
||||
cargo update
|
||||
fce build --release
|
||||
cd ../pure
|
||||
cargo update
|
||||
fce build --release
|
||||
|
||||
cd ..
|
||||
rm artifacts/*
|
||||
cp ../../target/wasm32-wasi/release/ipfs_effector.wasm artifacts/
|
||||
cp ../../target/wasm32-wasi/release/ipfs_pure.wasm artifacts/
|
@ -1,11 +1,11 @@
|
||||
modules_dir = "artifacts/"
|
||||
|
||||
[[module]]
|
||||
name = "effector"
|
||||
name = "records_effector"
|
||||
mem_pages_count = 1
|
||||
logger_enabled = true
|
||||
|
||||
[[module]]
|
||||
name = "pure"
|
||||
name = "records_pure"
|
||||
mem_pages_count = 1
|
||||
logger_enabled = true
|
||||
|
Binary file not shown.
Binary file not shown.
14
examples/records/build.sh
Executable file
14
examples/records/build.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This script builds all subprojects and puts all created Wasm modules in one dir
|
||||
cd effector
|
||||
cargo update
|
||||
fce build --release
|
||||
cd ../pure
|
||||
cargo update
|
||||
fce build --release
|
||||
|
||||
cd ..
|
||||
rm artifacts/*
|
||||
cp ../../target/wasm32-wasi/release/records_effector.wasm artifacts/
|
||||
cp ../../target/wasm32-wasi/release/records_pure.wasm artifacts/
|
@ -5,9 +5,9 @@ authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
|
||||
[[bin]]
|
||||
name = "effector"
|
||||
name = "records_effector"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
fluence = { git = "https://github.com/fluencelabs/rust-sdk" }
|
||||
fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["logger"] }
|
||||
test-record = { path = "../test-record" }
|
@ -20,7 +20,7 @@ use test_record::TestRecord;
|
||||
pub fn main() {}
|
||||
|
||||
#[fce]
|
||||
pub fn mutate_struct(mut test_record: TestRecord) -> TestRecord {
|
||||
pub fn mutate_struct(mut test_record: test_record::TestRecord) -> TestRecord {
|
||||
test_record.field_0 = true;
|
||||
test_record.field_1 = 1;
|
||||
test_record.field_2 = 2;
|
||||
|
@ -5,9 +5,9 @@ authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
|
||||
[[bin]]
|
||||
name = "pure"
|
||||
name = "records_pure"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
fluence = { git = "https://github.com/fluencelabs/rust-sdk" }
|
||||
fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["logger"] }
|
||||
test-record = { path = "../test-record" }
|
||||
|
@ -41,7 +41,7 @@ pub fn invoke() -> TestRecord {
|
||||
}
|
||||
|
||||
#[fce]
|
||||
#[link(wasm_import_module = "effector")]
|
||||
#[link(wasm_import_module = "records_effector")]
|
||||
extern "C" {
|
||||
pub fn mutate_struct(test_record: TestRecord) -> TestRecord;
|
||||
}
|
||||
|
@ -9,4 +9,4 @@ name = "test_record"
|
||||
path = "src/test_record.rs"
|
||||
|
||||
[dependencies]
|
||||
fluence = { git = "https://github.com/fluencelabs/rust-sdk" }
|
||||
fluence = { git = "https://github.com/fluencelabs/rust-sdk", branch = "record_support" }
|
||||
|
Binary file not shown.
@ -9,6 +9,6 @@ name = "site-storage"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["logger"] }
|
||||
fluence = { git = "https://github.com/fluencelabs/rust-sdk", branch = "record_support", features = ["logger"] }
|
||||
anyhow = "1.0.31"
|
||||
log = "0.4.8"
|
||||
|
@ -62,10 +62,8 @@ impl AppService {
|
||||
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_parameters)
|
||||
.call_with_json(module_name, func_name, arguments, call_parameters)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
@ -132,33 +130,6 @@ impl AppService {
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
fn json_to_ivalue(arguments: serde_json::Value) -> Result<Vec<IValue>> {
|
||||
// If arguments are on of: null, [] or {}, avoid calling `to_interface_value`
|
||||
let is_null = arguments.is_null();
|
||||
let is_empty_arr = arguments.as_array().map_or(false, |a| a.is_empty());
|
||||
let is_empty_obj = arguments.as_object().map_or(false, |m| m.is_empty());
|
||||
let arguments = if !is_null && !is_empty_arr && !is_empty_obj {
|
||||
Some(fluence_faas::to_interface_value(&arguments).map_err(|e| {
|
||||
AppServiceError::InvalidConfig(format!(
|
||||
"can't parse arguments as array of interface types: {}",
|
||||
e
|
||||
))
|
||||
})?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
match arguments {
|
||||
Some(IValue::Record(arguments)) => Ok(arguments.into_vec()),
|
||||
// Convert null, [] and {} into vec![]
|
||||
None => Ok(vec![]),
|
||||
other => Err(AppServiceError::InvalidConfig(format!(
|
||||
"expected array of interface values: got {:?}",
|
||||
other
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This API is intended for testing purposes (mostly in FCE REPL)
|
||||
|
@ -8,23 +8,27 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
fce = { path = "../engine", version = "0.1.3" }
|
||||
fluence-sdk-main = "=0.2.2"
|
||||
fluence-sdk-main = "=0.2.3"
|
||||
|
||||
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-wasi = { package = "wasmer-wasi-fl", version = "0.17.0" }
|
||||
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.5" }
|
||||
|
||||
toml = "0.5.6"
|
||||
serde = { version = "1.0.111", features = ["derive"] }
|
||||
serde_json = "1.0.53"
|
||||
serde_derive = "1.0.111"
|
||||
itertools = "0.9.0"
|
||||
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.0"}
|
||||
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.5" }
|
||||
once_cell = "1.4.0"
|
||||
env_logger = "0.7.1"
|
||||
|
||||
[features]
|
||||
raw-module-api = []
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
use fce::FCEError;
|
||||
|
||||
use serde_json::error::Error as SerdeError;
|
||||
|
||||
use std::io::Error as IOError;
|
||||
use std::error::Error;
|
||||
|
||||
@ -30,6 +32,18 @@ pub enum FaaSError {
|
||||
/// Various errors related to file i/o.
|
||||
IOError(String),
|
||||
|
||||
/// A function with specified name is missing.
|
||||
MissingFunctionError(String),
|
||||
|
||||
/// An argument with specified name is missing.
|
||||
MissingArgumentError(String),
|
||||
|
||||
/// Not enough arguments provided for FCE call.
|
||||
JsonArgumentsDeserializationError(String),
|
||||
|
||||
/// An error occurred when incorrect json argument is supplied.
|
||||
ArgumentDeserializationError(SerdeError),
|
||||
|
||||
/// FCE errors.
|
||||
EngineError(FCEError),
|
||||
}
|
||||
@ -41,6 +55,14 @@ impl std::fmt::Display for FaaSError {
|
||||
match self {
|
||||
FaaSError::ConfigParseError(err_msg) => write!(f, "{}", err_msg),
|
||||
FaaSError::InstantiationError(err_msg) => write!(f, "{}", err_msg),
|
||||
FaaSError::MissingFunctionError(func_name) => {
|
||||
write!(f, "function with name `{}` is missing", func_name)
|
||||
}
|
||||
FaaSError::MissingArgumentError(arg_name) => {
|
||||
write!(f, "argument with name `{}` is missing", arg_name)
|
||||
}
|
||||
FaaSError::JsonArgumentsDeserializationError(args) => write!(f, "{}", args),
|
||||
FaaSError::ArgumentDeserializationError(err_msg) => write!(f, "{:?}", err_msg),
|
||||
FaaSError::IOError(err_msg) => write!(f, "{}", err_msg),
|
||||
FaaSError::EngineError(err) => write!(f, "{}", err),
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
use crate::misc::ModulesConfig;
|
||||
use crate::misc::ModulesLoadStrategy;
|
||||
use crate::faas_interface::FaaSFunctionSignature;
|
||||
use crate::faas_interface::FaaSInterface;
|
||||
use crate::FaaSError;
|
||||
@ -31,70 +32,10 @@ use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::path::Path;
|
||||
|
||||
// TODO: remove and use mutex instead
|
||||
unsafe impl Send for FluenceFaaS {}
|
||||
|
||||
/// Strategies for module loading.
|
||||
pub enum ModulesLoadStrategy<'a> {
|
||||
/// Try to load all files in a given directory
|
||||
#[allow(dead_code)]
|
||||
All,
|
||||
/// Try to load only files contained in the set
|
||||
Named(&'a HashSet<String>),
|
||||
/// In a given directory, try to load all files ending with .wasm
|
||||
WasmOnly,
|
||||
}
|
||||
|
||||
impl<'a> ModulesLoadStrategy<'a> {
|
||||
#[inline]
|
||||
/// Returns true if `module` should be loaded.
|
||||
pub fn should_load(&self, module: &Path) -> bool {
|
||||
match self {
|
||||
ModulesLoadStrategy::All => true,
|
||||
ModulesLoadStrategy::Named(set) => set.contains(module.to_string_lossy().as_ref()),
|
||||
ModulesLoadStrategy::WasmOnly => module.extension().map_or(false, |e| e == "wasm"),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Returns the number of modules that must be loaded.
|
||||
pub fn required_modules_len(&self) -> usize {
|
||||
match self {
|
||||
ModulesLoadStrategy::Named(set) => set.len(),
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Returns difference between required and loaded modules.
|
||||
pub fn missing_modules<'s>(&self, loaded: impl Iterator<Item = &'s String>) -> Vec<&'s String> {
|
||||
match self {
|
||||
ModulesLoadStrategy::Named(set) => loaded.fold(vec![], |mut vec, module| {
|
||||
if !set.contains(module) {
|
||||
vec.push(module)
|
||||
}
|
||||
vec
|
||||
}),
|
||||
_ => <_>::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn extract_module_name(&self, module: String) -> String {
|
||||
match self {
|
||||
ModulesLoadStrategy::WasmOnly => {
|
||||
let path: &Path = module.as_ref();
|
||||
path.file_stem()
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.unwrap_or(module)
|
||||
}
|
||||
_ => module,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FluenceFaaS {
|
||||
/// The Fluence Compute Engine instance.
|
||||
fce: FCE,
|
||||
@ -223,7 +164,7 @@ impl FluenceFaaS {
|
||||
}
|
||||
|
||||
/// Call a specified function of loaded on a startup module by its name.
|
||||
pub fn call<MN: AsRef<str>, FN: AsRef<str>>(
|
||||
pub fn call_with_ivalues<MN: AsRef<str>, FN: AsRef<str>>(
|
||||
&mut self,
|
||||
module_name: MN,
|
||||
func_name: FN,
|
||||
@ -237,8 +178,50 @@ impl FluenceFaaS {
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Call a specified function of loaded on a startup module by its name.
|
||||
pub fn call_with_json<MN: AsRef<str>, FN: AsRef<str>>(
|
||||
&mut self,
|
||||
module_name: MN,
|
||||
func_name: FN,
|
||||
json_args: serde_json::Value,
|
||||
call_parameters: fluence_sdk_main::CallParameters,
|
||||
) -> Result<Vec<IValue>> {
|
||||
let module_name = module_name.as_ref();
|
||||
let func_name = func_name.as_ref();
|
||||
|
||||
let iargs = {
|
||||
let mut func_signatures = self.fce.module_interface(module_name)?;
|
||||
let func_signature = func_signatures
|
||||
.find(|sign| sign.name == func_name)
|
||||
.ok_or_else(|| FaaSError::MissingFunctionError(func_name.to_string()))?;
|
||||
|
||||
// TODO: cache record types
|
||||
let record_types = self
|
||||
.fce
|
||||
.module_record_types(module_name)?
|
||||
.map(|(type_id, record_type)| (type_id, record_type))
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
crate::misc::json_to_ivalues(json_args, &func_signature, &record_types)?
|
||||
};
|
||||
|
||||
self.call_parameters.replace(call_parameters);
|
||||
self.fce
|
||||
.call(module_name, func_name, &iargs)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Return all export functions (name and signatures) of loaded modules.
|
||||
pub fn get_interface(&self) -> FaaSInterface<'_> {
|
||||
use itertools::Itertools;
|
||||
|
||||
let record_types = self
|
||||
.fce
|
||||
.record_types()
|
||||
.map(|(id, record_type)| (*id, record_type))
|
||||
.unique()
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
let modules = self
|
||||
.fce
|
||||
.interface()
|
||||
@ -249,7 +232,7 @@ impl FluenceFaaS {
|
||||
(
|
||||
f.name,
|
||||
FaaSFunctionSignature {
|
||||
input_types: f.input_types,
|
||||
arguments: f.arguments,
|
||||
output_types: f.output_types,
|
||||
},
|
||||
)
|
||||
@ -259,7 +242,10 @@ impl FluenceFaaS {
|
||||
})
|
||||
.collect();
|
||||
|
||||
FaaSInterface { modules }
|
||||
FaaSInterface {
|
||||
record_types,
|
||||
modules,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
|
||||
use super::IType;
|
||||
use super::IRecordType;
|
||||
use super::IFunctionArg;
|
||||
|
||||
use serde::Serialize;
|
||||
use serde::Serializer;
|
||||
@ -24,27 +26,63 @@ use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct FaaSInterface<'a> {
|
||||
pub record_types: HashMap<u64, &'a IRecordType>,
|
||||
pub modules: HashMap<&'a str, HashMap<&'a str, FaaSFunctionSignature<'a>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct FaaSFunctionSignature<'a> {
|
||||
pub input_types: &'a Vec<IType>,
|
||||
pub arguments: &'a Vec<IFunctionArg>,
|
||||
pub output_types: &'a Vec<IType>,
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for FaaSInterface<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let type_text_view = |arg_ty: &IType| {
|
||||
match arg_ty {
|
||||
IType::Record(record_type_id) => {
|
||||
// unwrap is safe because FaasInterface here is well-formed
|
||||
// (it was checked on the module startup stage)
|
||||
let record = self.record_types.get(record_type_id).unwrap();
|
||||
record.name.clone()
|
||||
}
|
||||
t => format!("{:?}", t),
|
||||
}
|
||||
};
|
||||
|
||||
for (_, record_type) in self.record_types.iter() {
|
||||
writeln!(f, "{} {{", record_type.name)?;
|
||||
|
||||
for field in record_type.fields.iter() {
|
||||
writeln!(f, " {}: {:?}", field.name, type_text_view(&field.ty))?;
|
||||
}
|
||||
writeln!(f, "}}")?;
|
||||
}
|
||||
|
||||
if !self.record_types.is_empty() {
|
||||
writeln!(f)?;
|
||||
}
|
||||
|
||||
for (name, functions) in self.modules.iter() {
|
||||
writeln!(f, "{}", *name)?;
|
||||
writeln!(f, "{}:", *name)?;
|
||||
|
||||
for (name, signature) in functions.iter() {
|
||||
writeln!(
|
||||
f,
|
||||
" pub fn {}({:?}) -> {:?}",
|
||||
name, signature.input_types, signature.output_types
|
||||
)?;
|
||||
write!(f, " pub fn {}(", name)?;
|
||||
|
||||
for arg in signature.arguments {
|
||||
write!(f, "{}: {}", arg.name, type_text_view(&arg.ty))?;
|
||||
}
|
||||
if signature.output_types.is_empty() {
|
||||
write!(f, ")")?;
|
||||
} else if signature.output_types.len() == 1 {
|
||||
write!(f, ") -> {}", type_text_view(&signature.output_types[0]))?;
|
||||
} else {
|
||||
// At now, multi values aren't supported - only one output type is possible
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(f)?
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -59,10 +97,17 @@ impl<'a> Serialize for FaaSInterface<'a> {
|
||||
#[derive(Serialize)]
|
||||
pub struct Function<'a> {
|
||||
pub name: &'a str,
|
||||
pub input_types: &'a Vec<IType>,
|
||||
pub arguments: Vec<(&'a String, &'a IType)>,
|
||||
pub output_types: &'a Vec<IType>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct RecordType<'a> {
|
||||
pub name: &'a str,
|
||||
pub id: u64,
|
||||
pub fields: Vec<(&'a String, &'a IType)>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Module<'a> {
|
||||
pub name: &'a str,
|
||||
@ -71,9 +116,27 @@ impl<'a> Serialize for FaaSInterface<'a> {
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Interface<'a> {
|
||||
pub record_types: Vec<RecordType<'a>>,
|
||||
pub modules: Vec<Module<'a>>,
|
||||
}
|
||||
|
||||
let record_types: Vec<_> = self
|
||||
.record_types
|
||||
.iter()
|
||||
.map(|(id, IRecordType { name, fields })| {
|
||||
let fields = fields
|
||||
.iter()
|
||||
.map(|field| (&field.name, &field.ty))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
RecordType {
|
||||
name: name.as_str(),
|
||||
id: *id,
|
||||
fields,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let modules: Vec<_> = self
|
||||
.modules
|
||||
.iter()
|
||||
@ -84,13 +147,15 @@ impl<'a> Serialize for FaaSInterface<'a> {
|
||||
|(
|
||||
name,
|
||||
FaaSFunctionSignature {
|
||||
input_types,
|
||||
arguments,
|
||||
output_types,
|
||||
},
|
||||
)| {
|
||||
let arguments =
|
||||
arguments.iter().map(|arg| (&arg.name, &arg.ty)).collect();
|
||||
Function {
|
||||
name,
|
||||
input_types,
|
||||
arguments,
|
||||
output_types,
|
||||
}
|
||||
},
|
||||
@ -100,6 +165,10 @@ impl<'a> Serialize for FaaSInterface<'a> {
|
||||
})
|
||||
.collect();
|
||||
|
||||
Interface { modules }.serialize(serializer)
|
||||
Interface {
|
||||
record_types,
|
||||
modules,
|
||||
}
|
||||
.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,8 @@ pub(crate) type Result<T> = std::result::Result<T, FaaSError>;
|
||||
pub use errors::FaaSError;
|
||||
|
||||
pub use fce::IValue;
|
||||
pub use fce::IRecordType;
|
||||
pub use fce::IFunctionArg;
|
||||
pub use fce::IType;
|
||||
pub use fce::to_interface_value;
|
||||
pub use fce::from_interface_values;
|
||||
|
289
fluence-faas/src/misc/json_to_ivalues.rs
Normal file
289
fluence-faas/src/misc/json_to_ivalues.rs
Normal file
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use crate::IValue;
|
||||
use crate::IType;
|
||||
use crate::Result;
|
||||
use crate::FaaSError;
|
||||
|
||||
use serde_json::Value as SerdeValue;
|
||||
use wasmer_wit::vec1::Vec1;
|
||||
use wasmer_wit::types::RecordType;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub(crate) fn json_to_ivalues(
|
||||
json_args: serde_json::Value,
|
||||
func_signature: &fce::FCEFunctionSignature<'_>,
|
||||
record_types: &HashMap<&u64, &RecordType>,
|
||||
) -> Result<Vec<IValue>> {
|
||||
let ivalues = match json_args {
|
||||
SerdeValue::Object(json_map) => json_map_to_ivalues(
|
||||
json_map,
|
||||
func_signature
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|arg| (&arg.name, &arg.ty)),
|
||||
&record_types,
|
||||
)?,
|
||||
SerdeValue::Array(json_array) => json_array_to_ivalues(
|
||||
json_array,
|
||||
func_signature.arguments.iter().map(|arg| &arg.ty),
|
||||
&record_types,
|
||||
)?,
|
||||
SerdeValue::String(json_string) => json_string_to_ivalue(json_string, func_signature)?,
|
||||
json_bool @ SerdeValue::Bool(_) => json_bool_to_ivalue(json_bool, func_signature)?,
|
||||
json_number @ SerdeValue::Number(_) => json_number_to_ivalue(json_number, func_signature)?,
|
||||
SerdeValue::Null => json_null_to_ivalue(func_signature)?,
|
||||
};
|
||||
|
||||
Ok(ivalues)
|
||||
}
|
||||
|
||||
fn json_map_to_ivalues<'a, 'b>(
|
||||
mut json_map: serde_json::Map<String, SerdeValue>,
|
||||
signature: impl Iterator<Item = (&'a String, &'a IType)>,
|
||||
record_types: &'b HashMap<&'b u64, &'b RecordType>,
|
||||
) -> Result<Vec<IValue>> {
|
||||
let mut iargs = Vec::new();
|
||||
|
||||
for (arg_name, arg_type) in signature {
|
||||
let json_value = json_map
|
||||
.remove(arg_name)
|
||||
.ok_or_else(|| FaaSError::MissingArgumentError(arg_name.clone()))?;
|
||||
let iarg = json_value_to_ivalue(json_value, arg_type, record_types)?;
|
||||
iargs.push(iarg);
|
||||
}
|
||||
|
||||
if !json_map.is_empty() {
|
||||
return Err(FaaSError::JsonArgumentsDeserializationError(format!(
|
||||
"function requires {} arguments, {} provided",
|
||||
iargs.len(),
|
||||
iargs.len() + json_map.len()
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(iargs)
|
||||
}
|
||||
|
||||
fn json_array_to_ivalues<'a, 'b>(
|
||||
mut json_array: Vec<SerdeValue>,
|
||||
signature: impl Iterator<Item = &'a IType> + std::iter::ExactSizeIterator,
|
||||
record_types: &'b HashMap<&'b u64, &'b RecordType>,
|
||||
) -> Result<Vec<IValue>> {
|
||||
if json_array.len() != signature.len() {
|
||||
return Err(FaaSError::JsonArgumentsDeserializationError(format!(
|
||||
"function requires {} arguments, {} provided",
|
||||
signature.len(),
|
||||
json_array.len()
|
||||
)));
|
||||
}
|
||||
|
||||
let mut iargs = Vec::with_capacity(signature.len());
|
||||
|
||||
for arg_type in signature {
|
||||
// remove here is safe because we've already checked sizes
|
||||
let json_value = json_array.remove(0);
|
||||
let iarg = json_value_to_ivalue(json_value, arg_type, record_types)?;
|
||||
iargs.push(iarg);
|
||||
}
|
||||
|
||||
Ok(iargs)
|
||||
}
|
||||
|
||||
fn json_string_to_ivalue(
|
||||
json_string: String,
|
||||
func_signature: &fce::FCEFunctionSignature<'_>,
|
||||
) -> Result<Vec<IValue>> {
|
||||
if func_signature.arguments.len() != 1 || func_signature.arguments[0].ty != IType::String {
|
||||
return Err(FaaSError::JsonArgumentsDeserializationError(format!(
|
||||
"the called function has the following signature: {:?}, but only one string argument is provided",
|
||||
func_signature
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(vec![IValue::String(json_string)])
|
||||
}
|
||||
|
||||
fn json_bool_to_ivalue(
|
||||
json_bool: SerdeValue,
|
||||
func_signature: &fce::FCEFunctionSignature<'_>,
|
||||
) -> Result<Vec<IValue>> {
|
||||
if func_signature.arguments.len() != 1 {
|
||||
return Err(FaaSError::JsonArgumentsDeserializationError(format!(
|
||||
"the called function has the following signature: {:?}, but only one bool argument is provided",
|
||||
func_signature
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(vec![json_value_to_ivalue(
|
||||
json_bool,
|
||||
&func_signature.arguments[0].ty,
|
||||
&HashMap::new(),
|
||||
)?])
|
||||
}
|
||||
|
||||
fn json_number_to_ivalue(
|
||||
json_number: SerdeValue,
|
||||
func_signature: &fce::FCEFunctionSignature<'_>,
|
||||
) -> Result<Vec<IValue>> {
|
||||
if func_signature.arguments.len() != 1 {
|
||||
return Err(FaaSError::JsonArgumentsDeserializationError(format!(
|
||||
"the called function has the following signature: {:?}, but only one number argument is provided",
|
||||
func_signature
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(vec![json_value_to_ivalue(
|
||||
json_number,
|
||||
&func_signature.arguments[0].ty,
|
||||
&HashMap::new(),
|
||||
)?])
|
||||
}
|
||||
|
||||
fn json_null_to_ivalue(func_signature: &fce::FCEFunctionSignature<'_>) -> Result<Vec<IValue>> {
|
||||
if !func_signature.arguments.is_empty() {
|
||||
return Err(FaaSError::JsonArgumentsDeserializationError(format!(
|
||||
"the called function has the following signature: {:?}, but no arguments is provided",
|
||||
func_signature
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(vec![])
|
||||
}
|
||||
|
||||
fn json_value_to_ivalue(
|
||||
json_value: SerdeValue,
|
||||
ty: &IType,
|
||||
record_types: &HashMap<&u64, &RecordType>,
|
||||
) -> Result<IValue> {
|
||||
// TODO: get rid of copy-past
|
||||
match ty {
|
||||
IType::S8 => {
|
||||
let value = serde_json::from_value(json_value)
|
||||
.map_err(FaaSError::ArgumentDeserializationError)?;
|
||||
Ok(IValue::S8(value))
|
||||
}
|
||||
IType::S16 => {
|
||||
let value = serde_json::from_value(json_value)
|
||||
.map_err(FaaSError::ArgumentDeserializationError)?;
|
||||
Ok(IValue::S16(value))
|
||||
}
|
||||
IType::S32 => {
|
||||
let value = serde_json::from_value(json_value)
|
||||
.map_err(FaaSError::ArgumentDeserializationError)?;
|
||||
Ok(IValue::S32(value))
|
||||
}
|
||||
IType::S64 => {
|
||||
let value = serde_json::from_value(json_value)
|
||||
.map_err(FaaSError::ArgumentDeserializationError)?;
|
||||
Ok(IValue::S64(value))
|
||||
}
|
||||
IType::U8 => {
|
||||
let value = serde_json::from_value(json_value)
|
||||
.map_err(FaaSError::ArgumentDeserializationError)?;
|
||||
Ok(IValue::U8(value))
|
||||
}
|
||||
IType::U16 => {
|
||||
let value = serde_json::from_value(json_value)
|
||||
.map_err(FaaSError::ArgumentDeserializationError)?;
|
||||
Ok(IValue::U16(value))
|
||||
}
|
||||
IType::U32 => {
|
||||
let value = serde_json::from_value(json_value)
|
||||
.map_err(FaaSError::ArgumentDeserializationError)?;
|
||||
Ok(IValue::U32(value))
|
||||
}
|
||||
IType::U64 => {
|
||||
let value = serde_json::from_value(json_value)
|
||||
.map_err(FaaSError::ArgumentDeserializationError)?;
|
||||
Ok(IValue::U64(value))
|
||||
}
|
||||
IType::F32 => {
|
||||
let value = serde_json::from_value(json_value)
|
||||
.map_err(FaaSError::ArgumentDeserializationError)?;
|
||||
Ok(IValue::F32(value))
|
||||
}
|
||||
IType::F64 => {
|
||||
let value = serde_json::from_value(json_value)
|
||||
.map_err(FaaSError::ArgumentDeserializationError)?;
|
||||
Ok(IValue::F64(value))
|
||||
}
|
||||
IType::String => {
|
||||
let value = serde_json::from_value(json_value)
|
||||
.map_err(FaaSError::ArgumentDeserializationError)?;
|
||||
Ok(IValue::String(value))
|
||||
}
|
||||
IType::ByteArray => {
|
||||
let value = serde_json::from_value(json_value)
|
||||
.map_err(FaaSError::ArgumentDeserializationError)?;
|
||||
Ok(IValue::ByteArray(value))
|
||||
}
|
||||
IType::I32 => {
|
||||
let value = serde_json::from_value(json_value)
|
||||
.map_err(FaaSError::ArgumentDeserializationError)?;
|
||||
Ok(IValue::I32(value))
|
||||
}
|
||||
IType::I64 => {
|
||||
let value = serde_json::from_value(json_value)
|
||||
.map_err(FaaSError::ArgumentDeserializationError)?;
|
||||
Ok(IValue::I64(value))
|
||||
}
|
||||
IType::Record(record_type_id) => {
|
||||
let value = json_record_type_to_ivalue(json_value, record_type_id, &record_types)?;
|
||||
Ok(IValue::Record(value))
|
||||
}
|
||||
IType::Anyref => Err(FaaSError::JsonArgumentsDeserializationError(String::from(
|
||||
"anyref interface-type is unsupported now",
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::ptr_arg)]
|
||||
fn json_record_type_to_ivalue(
|
||||
json_value: SerdeValue,
|
||||
record_type_id: &u64,
|
||||
record_types: &HashMap<&u64, &RecordType>,
|
||||
) -> Result<Vec1<IValue>> {
|
||||
let record_type = record_types.get(record_type_id).ok_or_else(|| {
|
||||
FaaSError::JsonArgumentsDeserializationError(format!(
|
||||
"record with type id `{}` wasn't found",
|
||||
record_type_id
|
||||
))
|
||||
})?;
|
||||
|
||||
match json_value {
|
||||
SerdeValue::Object(json_map) => Ok(Vec1::new(json_map_to_ivalues(
|
||||
json_map,
|
||||
record_type
|
||||
.fields
|
||||
.iter()
|
||||
.map(|field| (&field.name, &field.ty)),
|
||||
record_types,
|
||||
)?)
|
||||
.unwrap()),
|
||||
SerdeValue::Array(json_array) => Ok(Vec1::new(json_array_to_ivalues(
|
||||
json_array,
|
||||
record_type.fields.iter().map(|field| (&field.ty)),
|
||||
record_types,
|
||||
)?)
|
||||
.unwrap()),
|
||||
_ => Err(FaaSError::JsonArgumentsDeserializationError(format!(
|
||||
"record with type id `{}` should be encoded as array or map of fields",
|
||||
record_type_id
|
||||
))),
|
||||
}
|
||||
}
|
@ -1,12 +1,32 @@
|
||||
mod imports;
|
||||
mod utils;
|
||||
mod config;
|
||||
/*
|
||||
* 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(crate) use utils::make_fce_config;
|
||||
pub(crate) use config::load_config;
|
||||
mod config;
|
||||
mod imports;
|
||||
mod json_to_ivalues;
|
||||
mod modules_load_strategy;
|
||||
mod utils;
|
||||
|
||||
pub use config::RawModulesConfig;
|
||||
pub use config::RawModuleConfig;
|
||||
pub use config::ModulesConfig;
|
||||
pub use config::ModuleConfig;
|
||||
pub use config::WASIConfig;
|
||||
|
||||
pub(crate) use config::load_config;
|
||||
pub(crate) use json_to_ivalues::json_to_ivalues;
|
||||
pub(crate) use modules_load_strategy::ModulesLoadStrategy;
|
||||
pub(crate) use utils::make_fce_config;
|
||||
|
77
fluence-faas/src/misc/modules_load_strategy.rs
Normal file
77
fluence-faas/src/misc/modules_load_strategy.rs
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use std::path::Path;
|
||||
use std::collections::HashSet;
|
||||
|
||||
/// Strategies for module loading.
|
||||
pub enum ModulesLoadStrategy<'a> {
|
||||
/// Try to load all files in a given directory
|
||||
#[allow(dead_code)]
|
||||
All,
|
||||
/// Try to load only files contained in the set
|
||||
Named(&'a HashSet<String>),
|
||||
/// In a given directory, try to load all files ending with .wasm
|
||||
WasmOnly,
|
||||
}
|
||||
|
||||
impl<'a> ModulesLoadStrategy<'a> {
|
||||
#[inline]
|
||||
/// Returns true if `module` should be loaded.
|
||||
pub fn should_load(&self, module: &Path) -> bool {
|
||||
match self {
|
||||
ModulesLoadStrategy::All => true,
|
||||
ModulesLoadStrategy::Named(set) => set.contains(module.to_string_lossy().as_ref()),
|
||||
ModulesLoadStrategy::WasmOnly => module.extension().map_or(false, |e| e == "wasm"),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Returns the number of modules that must be loaded.
|
||||
pub fn required_modules_len(&self) -> usize {
|
||||
match self {
|
||||
ModulesLoadStrategy::Named(set) => set.len(),
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Returns difference between required and loaded modules.
|
||||
pub fn missing_modules<'s>(&self, loaded: impl Iterator<Item = &'s String>) -> Vec<&'s String> {
|
||||
match self {
|
||||
ModulesLoadStrategy::Named(set) => loaded.fold(vec![], |mut vec, module| {
|
||||
if !set.contains(module) {
|
||||
vec.push(module)
|
||||
}
|
||||
vec
|
||||
}),
|
||||
_ => <_>::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn extract_module_name(&self, module: String) -> String {
|
||||
match self {
|
||||
ModulesLoadStrategy::WasmOnly => {
|
||||
let path: &Path = module.as_ref();
|
||||
path.file_stem()
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.unwrap_or(module)
|
||||
}
|
||||
_ => module,
|
||||
}
|
||||
}
|
||||
}
|
557
fluence-faas/tests/arguments_passing.rs
Normal file
557
fluence-faas/tests/arguments_passing.rs
Normal file
@ -0,0 +1,557 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use fluence_faas::FluenceFaaS;
|
||||
use fluence_faas::IValue;
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use serde_json::json;
|
||||
|
||||
static ARG_CONFIG: Lazy<fluence_faas::RawModulesConfig> = Lazy::new(|| {
|
||||
let argument_passing_config_raw =
|
||||
std::fs::read("./tests/json_wasm_tests/arguments_passing/Config.toml")
|
||||
.expect("../examples/greeting/artifacts/greeting.wasm should presence");
|
||||
|
||||
let mut arguments_passing_config: fluence_faas::RawModulesConfig =
|
||||
toml::from_slice(&argument_passing_config_raw)
|
||||
.expect("argument passing test config should be well-formed");
|
||||
arguments_passing_config.modules_dir = Some(String::from(
|
||||
"./tests/json_wasm_tests/arguments_passing/artifacts",
|
||||
));
|
||||
|
||||
arguments_passing_config
|
||||
});
|
||||
|
||||
#[test]
|
||||
pub fn get_interfaces() {
|
||||
let faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let interface = faas.get_interface();
|
||||
|
||||
let string_type_arguments = vec![fluence_faas::IFunctionArg {
|
||||
name: String::from("arg"),
|
||||
ty: fluence_faas::IType::String,
|
||||
}];
|
||||
let string_type_output_types = vec![fluence_faas::IType::String];
|
||||
|
||||
let string_type_sign = fluence_faas::FaaSFunctionSignature {
|
||||
arguments: &string_type_arguments,
|
||||
output_types: &string_type_output_types,
|
||||
};
|
||||
|
||||
let bytearray_type_arguments = vec![fluence_faas::IFunctionArg {
|
||||
name: String::from("arg"),
|
||||
ty: fluence_faas::IType::ByteArray,
|
||||
}];
|
||||
let bytearray_type_output_types = vec![fluence_faas::IType::ByteArray];
|
||||
|
||||
let bytearray_type_sign = fluence_faas::FaaSFunctionSignature {
|
||||
arguments: &bytearray_type_arguments,
|
||||
output_types: &bytearray_type_output_types,
|
||||
};
|
||||
|
||||
let i32_type_arguments = vec![fluence_faas::IFunctionArg {
|
||||
name: String::from("arg"),
|
||||
ty: fluence_faas::IType::S32,
|
||||
}];
|
||||
let i32_type_output_types = vec![fluence_faas::IType::S32];
|
||||
|
||||
let i32_type_sign = fluence_faas::FaaSFunctionSignature {
|
||||
arguments: &i32_type_arguments,
|
||||
output_types: &i32_type_output_types,
|
||||
};
|
||||
|
||||
let i64_type_arguments = vec![fluence_faas::IFunctionArg {
|
||||
name: String::from("arg"),
|
||||
ty: fluence_faas::IType::S64,
|
||||
}];
|
||||
|
||||
let i64_type_output_types = vec![fluence_faas::IType::S64];
|
||||
|
||||
let i64_type_sign = fluence_faas::FaaSFunctionSignature {
|
||||
arguments: &i64_type_arguments,
|
||||
output_types: &i64_type_output_types,
|
||||
};
|
||||
|
||||
let u32_type_arguments = vec![fluence_faas::IFunctionArg {
|
||||
name: String::from("arg"),
|
||||
ty: fluence_faas::IType::U32,
|
||||
}];
|
||||
let u32_type_output_types = vec![fluence_faas::IType::U32];
|
||||
|
||||
let u32_type_sign = fluence_faas::FaaSFunctionSignature {
|
||||
arguments: &u32_type_arguments,
|
||||
output_types: &u32_type_output_types,
|
||||
};
|
||||
|
||||
let u64_type_arguments = vec![fluence_faas::IFunctionArg {
|
||||
name: String::from("arg"),
|
||||
ty: fluence_faas::IType::U64,
|
||||
}];
|
||||
let u64_type_output_types = vec![fluence_faas::IType::U64];
|
||||
|
||||
let u64_type_sign = fluence_faas::FaaSFunctionSignature {
|
||||
arguments: &u64_type_arguments,
|
||||
output_types: &u64_type_output_types,
|
||||
};
|
||||
|
||||
let f32_type_arguments = vec![fluence_faas::IFunctionArg {
|
||||
name: String::from("arg"),
|
||||
ty: fluence_faas::IType::F32,
|
||||
}];
|
||||
let f32_type_output_types = vec![fluence_faas::IType::F32];
|
||||
|
||||
let f32_type_sign = fluence_faas::FaaSFunctionSignature {
|
||||
arguments: &f32_type_arguments,
|
||||
output_types: &f32_type_output_types,
|
||||
};
|
||||
|
||||
let f64_type_arguments = vec![fluence_faas::IFunctionArg {
|
||||
name: String::from("arg"),
|
||||
ty: fluence_faas::IType::F64,
|
||||
}];
|
||||
let f64_type_output_types = vec![fluence_faas::IType::F64];
|
||||
|
||||
let f64_type_sign = fluence_faas::FaaSFunctionSignature {
|
||||
arguments: &f64_type_arguments,
|
||||
output_types: &f64_type_output_types,
|
||||
};
|
||||
|
||||
let empty_type_arguments = vec![];
|
||||
let empty_type_output_types = vec![fluence_faas::IType::String];
|
||||
|
||||
let empty_type_sign = fluence_faas::FaaSFunctionSignature {
|
||||
arguments: &empty_type_arguments,
|
||||
output_types: &empty_type_output_types,
|
||||
};
|
||||
|
||||
let bool_type_arguments = vec![fluence_faas::IFunctionArg {
|
||||
name: String::from("arg"),
|
||||
ty: fluence_faas::IType::I32,
|
||||
}];
|
||||
let bool_type_output_types = vec![fluence_faas::IType::I32];
|
||||
|
||||
let bool_type_sign = fluence_faas::FaaSFunctionSignature {
|
||||
arguments: &bool_type_arguments,
|
||||
output_types: &bool_type_output_types,
|
||||
};
|
||||
|
||||
let all_types_arguments = vec![
|
||||
fluence_faas::IFunctionArg {
|
||||
name: String::from("arg_0"),
|
||||
ty: fluence_faas::IType::S8,
|
||||
},
|
||||
fluence_faas::IFunctionArg {
|
||||
name: String::from("arg_1"),
|
||||
ty: fluence_faas::IType::S16,
|
||||
},
|
||||
fluence_faas::IFunctionArg {
|
||||
name: String::from("arg_2"),
|
||||
ty: fluence_faas::IType::S32,
|
||||
},
|
||||
fluence_faas::IFunctionArg {
|
||||
name: String::from("arg_3"),
|
||||
ty: fluence_faas::IType::S64,
|
||||
},
|
||||
fluence_faas::IFunctionArg {
|
||||
name: String::from("arg_4"),
|
||||
ty: fluence_faas::IType::U8,
|
||||
},
|
||||
fluence_faas::IFunctionArg {
|
||||
name: String::from("arg_5"),
|
||||
ty: fluence_faas::IType::U16,
|
||||
},
|
||||
fluence_faas::IFunctionArg {
|
||||
name: String::from("arg_6"),
|
||||
ty: fluence_faas::IType::U32,
|
||||
},
|
||||
fluence_faas::IFunctionArg {
|
||||
name: String::from("arg_7"),
|
||||
ty: fluence_faas::IType::U64,
|
||||
},
|
||||
fluence_faas::IFunctionArg {
|
||||
name: String::from("arg_8"),
|
||||
ty: fluence_faas::IType::F32,
|
||||
},
|
||||
fluence_faas::IFunctionArg {
|
||||
name: String::from("arg_9"),
|
||||
ty: fluence_faas::IType::F64,
|
||||
},
|
||||
fluence_faas::IFunctionArg {
|
||||
name: String::from("arg_10"),
|
||||
ty: fluence_faas::IType::String,
|
||||
},
|
||||
fluence_faas::IFunctionArg {
|
||||
name: String::from("arg_11"),
|
||||
ty: fluence_faas::IType::ByteArray,
|
||||
},
|
||||
];
|
||||
let all_types_output_types = vec![fluence_faas::IType::ByteArray];
|
||||
|
||||
let all_types_sign = fluence_faas::FaaSFunctionSignature {
|
||||
arguments: &all_types_arguments,
|
||||
output_types: &all_types_output_types,
|
||||
};
|
||||
|
||||
let mut functions = std::collections::HashMap::new();
|
||||
functions.insert("string_type", string_type_sign);
|
||||
functions.insert("bytearray_type", bytearray_type_sign);
|
||||
functions.insert("i32_type", i32_type_sign);
|
||||
functions.insert("i64_type", i64_type_sign);
|
||||
functions.insert("u32_type", u32_type_sign);
|
||||
functions.insert("u64_type", u64_type_sign);
|
||||
functions.insert("f32_type", f32_type_sign);
|
||||
functions.insert("f64_type", f64_type_sign);
|
||||
functions.insert("empty_type", empty_type_sign);
|
||||
functions.insert("bool_type", bool_type_sign);
|
||||
functions.insert("all_types", all_types_sign);
|
||||
|
||||
let mut modules = std::collections::HashMap::new();
|
||||
modules.insert("pure", functions.clone());
|
||||
modules.insert("effector", functions);
|
||||
|
||||
assert_eq!(
|
||||
interface,
|
||||
fluence_faas::FaaSInterface {
|
||||
record_types: <_>::default(),
|
||||
modules
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn all_types() {
|
||||
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let result1 = faas.call_with_json("pure", "all_types", json!({}), <_>::default());
|
||||
assert!(result1.is_err());
|
||||
|
||||
let result2 = faas.call_with_json("pure", "all_types", json!([]), <_>::default());
|
||||
assert!(result2.is_err());
|
||||
|
||||
let result3 = faas
|
||||
.call_with_json(
|
||||
"pure",
|
||||
"all_types",
|
||||
json!({
|
||||
"arg_0": 0,
|
||||
"arg_1": 1,
|
||||
"arg_2": 2,
|
||||
"arg_3": 3,
|
||||
"arg_4": 4,
|
||||
"arg_5": 5,
|
||||
"arg_6": 6,
|
||||
"arg_7": 7,
|
||||
"arg_8": 8.1,
|
||||
"arg_9": 9.1,
|
||||
"arg_10": "fluence",
|
||||
"arg_11": vec! [0x13, 0x37],
|
||||
}),
|
||||
<_>::default(),
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("can't invoke all_types: {:?}", e));
|
||||
assert_eq!(
|
||||
result3,
|
||||
vec![IValue::ByteArray(vec![
|
||||
0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 5, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
|
||||
0, 65, 1, 153, 154, 64, 34, 51, 51, 51, 51, 51, 51, 102, 108, 117, 101, 110, 99, 101,
|
||||
19, 55, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 5, 0, 6, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 65, 1, 153, 154, 64, 34, 51, 51, 51, 51, 51, 51, 102, 108, 117, 101, 110,
|
||||
99, 101, 19, 55
|
||||
])]
|
||||
);
|
||||
|
||||
let result4 = faas
|
||||
.call_with_json(
|
||||
"pure",
|
||||
"all_types",
|
||||
json!([
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8.1,
|
||||
9.1,
|
||||
"fluence",
|
||||
vec![0x13, 0x37]
|
||||
]),
|
||||
<_>::default(),
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("can't invoke all_types: {:?}", e));
|
||||
assert_eq!(
|
||||
result4,
|
||||
vec![IValue::ByteArray(vec![
|
||||
0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 5, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
|
||||
0, 65, 1, 153, 154, 64, 34, 51, 51, 51, 51, 51, 51, 102, 108, 117, 101, 110, 99, 101,
|
||||
19, 55, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 5, 0, 6, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 65, 1, 153, 154, 64, 34, 51, 51, 51, 51, 51, 51, 102, 108, 117, 101, 110,
|
||||
99, 101, 19, 55
|
||||
])]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn i32_type() {
|
||||
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let result1 = faas.call_with_json("pure", "i32_type", json!({}), <_>::default());
|
||||
assert!(result1.is_err());
|
||||
|
||||
let result2 = faas.call_with_json("pure", "i32_type", json!([]), <_>::default());
|
||||
assert!(result2.is_err());
|
||||
|
||||
let result3 = faas
|
||||
.call_with_json("pure", "i32_type", json!({ "arg": 1 }), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke i32_type: {:?}", e));
|
||||
assert_eq!(result3, vec![IValue::S32(3)]);
|
||||
|
||||
let result4 = faas
|
||||
.call_with_json("pure", "i32_type", json!(1), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke i32_type: {:?}", e));
|
||||
assert_eq!(result4, vec![IValue::S32(3)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn i64_type() {
|
||||
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let result1 = faas.call_with_json("pure", "i64_type", json!({}), <_>::default());
|
||||
assert!(result1.is_err());
|
||||
|
||||
let result2 = faas.call_with_json("pure", "i64_type", json!([]), <_>::default());
|
||||
assert!(result2.is_err());
|
||||
|
||||
let result3 = faas
|
||||
.call_with_json("pure", "i64_type", json!({ "arg": 1 }), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke i64_type: {:?}", e));
|
||||
assert_eq!(result3, vec![IValue::S64(3)]);
|
||||
|
||||
let result4 = faas
|
||||
.call_with_json("pure", "i64_type", json!(1), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke i64_type: {:?}", e));
|
||||
assert_eq!(result4, vec![IValue::S64(3)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn u32_type() {
|
||||
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let result1 = faas.call_with_json("pure", "u32_type", json!({}), <_>::default());
|
||||
assert!(result1.is_err());
|
||||
|
||||
let result2 = faas.call_with_json("pure", "u32_type", json!([]), <_>::default());
|
||||
assert!(result2.is_err());
|
||||
|
||||
let result3 = faas
|
||||
.call_with_json("pure", "u32_type", json!({ "arg": 1 }), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke u32_type: {:?}", e));
|
||||
assert_eq!(result3, vec![IValue::U32(3)]);
|
||||
|
||||
let result4 = faas
|
||||
.call_with_json("pure", "u32_type", json!(1), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke u32_type: {:?}", e));
|
||||
assert_eq!(result4, vec![IValue::U32(3)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn u64_type() {
|
||||
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let result1 = faas.call_with_json("pure", "u64_type", json!({}), <_>::default());
|
||||
assert!(result1.is_err());
|
||||
|
||||
let result2 = faas.call_with_json("pure", "u64_type", json!([]), <_>::default());
|
||||
assert!(result2.is_err());
|
||||
|
||||
let result3 = faas
|
||||
.call_with_json("pure", "u64_type", json!({ "arg": 1 }), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke u64_type: {:?}", e));
|
||||
assert_eq!(result3, vec![IValue::U64(3)]);
|
||||
|
||||
let result4 = faas
|
||||
.call_with_json("pure", "u64_type", json!(1), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke u64_type: {:?}", e));
|
||||
assert_eq!(result4, vec![IValue::U64(3)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn f32_type() {
|
||||
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let result1 = faas.call_with_json("pure", "f32_type", json!({}), <_>::default());
|
||||
assert!(result1.is_err());
|
||||
|
||||
let result2 = faas.call_with_json("pure", "f32_type", json!([]), <_>::default());
|
||||
assert!(result2.is_err());
|
||||
|
||||
let result3 = faas
|
||||
.call_with_json("pure", "f32_type", json!({ "arg": 1.0 }), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke f32_type: {:?}", e));
|
||||
assert_eq!(result3, vec![IValue::F32(3.0)]);
|
||||
|
||||
let result4 = faas
|
||||
.call_with_json("pure", "f32_type", json!(1.0), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke f32_type: {:?}", e));
|
||||
assert_eq!(result4, vec![IValue::F32(3.0)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn f64_type() {
|
||||
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let result1 = faas.call_with_json("pure", "f64_type", json!({}), <_>::default());
|
||||
assert!(result1.is_err());
|
||||
|
||||
let result2 = faas.call_with_json("pure", "f64_type", json!([]), <_>::default());
|
||||
assert!(result2.is_err());
|
||||
|
||||
let result3 = faas
|
||||
.call_with_json("pure", "f64_type", json!({ "arg": 1.0 }), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke f64_type: {:?}", e));
|
||||
assert_eq!(result3, vec![IValue::F64(3.0)]);
|
||||
|
||||
let result4 = faas
|
||||
.call_with_json("pure", "f64_type", json!(1.0), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke f64_type: {:?}", e));
|
||||
assert_eq!(result4, vec![IValue::F64(3.0)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn string_type() {
|
||||
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let result1 = faas.call_with_json("pure", "string_type", json!({}), <_>::default());
|
||||
assert!(result1.is_err());
|
||||
|
||||
let result2 = faas.call_with_json("pure", "string_type", json!([]), <_>::default());
|
||||
assert!(result2.is_err());
|
||||
|
||||
let result3 = faas
|
||||
.call_with_json(
|
||||
"pure",
|
||||
"string_type",
|
||||
json!({ "arg": "Fluence" }),
|
||||
<_>::default(),
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("can't invoke string_type: {:?}", e));
|
||||
assert_eq!(
|
||||
result3,
|
||||
vec![IValue::String(String::from(
|
||||
"Fluence_Fluence_Fluence_Fluence"
|
||||
))]
|
||||
);
|
||||
|
||||
let result4 = faas
|
||||
.call_with_json("pure", "string_type", json!("Fluence"), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke string_type: {:?}", e));
|
||||
assert_eq!(
|
||||
result4,
|
||||
vec![IValue::String(String::from(
|
||||
"Fluence_Fluence_Fluence_Fluence"
|
||||
))]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn bytearray_type() {
|
||||
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let result1 = faas.call_with_json("pure", "bytearray_type", json!({}), <_>::default());
|
||||
assert!(result1.is_err());
|
||||
|
||||
let result2 = faas.call_with_json("pure", "bytearray_type", json!([]), <_>::default());
|
||||
assert!(result2.is_err());
|
||||
|
||||
let result3 = faas
|
||||
.call_with_json(
|
||||
"pure",
|
||||
"bytearray_type",
|
||||
json!({ "arg": [0x13, 0x37] }),
|
||||
<_>::default(),
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("can't invoke bytearray_type: {:?}", e));
|
||||
assert_eq!(result3, vec![IValue::ByteArray(vec![0x13, 0x37, 0x1, 0x1])]);
|
||||
|
||||
let result4 = faas
|
||||
.call_with_json(
|
||||
"pure",
|
||||
"bytearray_type",
|
||||
json!([[0x13, 0x37]]),
|
||||
<_>::default(),
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("can't invoke bytearray_type: {:?}", e));
|
||||
assert_eq!(result4, vec![IValue::ByteArray(vec![0x13, 0x37, 0x1, 0x1])]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn bool_type() {
|
||||
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let result1 = faas.call_with_json("pure", "bool_type", json!({}), <_>::default());
|
||||
assert!(result1.is_err());
|
||||
|
||||
let result2 = faas.call_with_json("pure", "bool_type", json!([]), <_>::default());
|
||||
assert!(result2.is_err());
|
||||
|
||||
let result3 = faas
|
||||
.call_with_json("pure", "bool_type", json!({ "arg": 0 }), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke bool_type: {:?}", e));
|
||||
assert_eq!(result3, vec![IValue::I32(1)]);
|
||||
|
||||
let result4 = faas
|
||||
.call_with_json("pure", "bool_type", json!(0), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke bool_type: {:?}", e));
|
||||
assert_eq!(result4, vec![IValue::I32(1)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn empty_type() {
|
||||
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let result1 = faas
|
||||
.call_with_json("pure", "empty_type", json!({}), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke empty_type: {:?}", e));
|
||||
assert_eq!(result1, vec![IValue::String(String::from("success"))]);
|
||||
|
||||
let result2 = faas
|
||||
.call_with_json("pure", "empty_type", json!([]), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke empty_type: {:?}", e));
|
||||
assert_eq!(result2, vec![IValue::String(String::from("success"))]);
|
||||
|
||||
let result3 = faas
|
||||
.call_with_json("pure", "empty_type", json!([]), <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke empty_type: {:?}", e));
|
||||
assert_eq!(result3, vec![IValue::String(String::from("success"))]);
|
||||
|
||||
let result4 = faas.call_with_json("pure", "empty_type", json!([1]), <_>::default());
|
||||
assert!(result4.is_err());
|
||||
}
|
@ -38,7 +38,7 @@ pub fn call_parameters() {
|
||||
let application_id = "0x31337";
|
||||
|
||||
let result = faas
|
||||
.call(
|
||||
.call_with_ivalues(
|
||||
"call_parameters",
|
||||
"call_parameters",
|
||||
&[],
|
||||
|
@ -32,7 +32,7 @@ pub fn greeting() {
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let result1 = faas
|
||||
.call(
|
||||
.call_with_ivalues(
|
||||
"greeting",
|
||||
"greeting",
|
||||
&[IValue::String(String::from("Fluence"))],
|
||||
@ -41,7 +41,7 @@ pub fn greeting() {
|
||||
.unwrap_or_else(|e| panic!("can't invoke greeting: {:?}", e));
|
||||
|
||||
let result2 = faas
|
||||
.call(
|
||||
.call_with_ivalues(
|
||||
"greeting",
|
||||
"greeting",
|
||||
&[IValue::String(String::from(""))],
|
||||
@ -69,10 +69,15 @@ pub fn get_interfaces() {
|
||||
|
||||
let interface = faas.get_interface();
|
||||
|
||||
let string_type_params = vec![fluence_faas::IType::String];
|
||||
let arguments = vec![fluence_faas::IFunctionArg {
|
||||
name: String::from("name"),
|
||||
ty: fluence_faas::IType::String,
|
||||
}];
|
||||
let output_types = vec![fluence_faas::IType::String];
|
||||
|
||||
let greeting_sign = fluence_faas::FaaSFunctionSignature {
|
||||
input_types: &string_type_params,
|
||||
output_types: &string_type_params,
|
||||
arguments: &arguments,
|
||||
output_types: &output_types,
|
||||
};
|
||||
|
||||
let mut functions = std::collections::HashMap::new();
|
||||
@ -81,5 +86,11 @@ pub fn get_interfaces() {
|
||||
let mut modules = std::collections::HashMap::new();
|
||||
modules.insert("greeting", functions);
|
||||
|
||||
assert_eq!(interface, fluence_faas::FaaSInterface { modules });
|
||||
assert_eq!(
|
||||
interface,
|
||||
fluence_faas::FaaSInterface {
|
||||
record_types: <_>::default(),
|
||||
modules
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "arguments-passing-test"
|
||||
version = "0.1.0"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
|
||||
[[bin]]
|
||||
name = "pure"
|
||||
path = "src/pure.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "effector"
|
||||
path = "src/effector.rs"
|
||||
|
||||
[dependencies]
|
||||
fluence = { git = "https://github.com/fluencelabs/rust-sdk" }
|
||||
safe-transmute = "0.11.0"
|
@ -0,0 +1,11 @@
|
||||
modules_dir = "./artifacts/"
|
||||
|
||||
[[module]]
|
||||
name = "effector"
|
||||
mem_pages_count = 1
|
||||
logger_enabled = true
|
||||
|
||||
[[module]]
|
||||
name = "pure"
|
||||
mem_pages_count = 1
|
||||
logger_enabled = true
|
BIN
fluence-faas/tests/json_wasm_tests/arguments_passing/artifacts/effector.wasm
Executable file
BIN
fluence-faas/tests/json_wasm_tests/arguments_passing/artifacts/effector.wasm
Executable file
Binary file not shown.
BIN
fluence-faas/tests/json_wasm_tests/arguments_passing/artifacts/pure.wasm
Executable file
BIN
fluence-faas/tests/json_wasm_tests/arguments_passing/artifacts/pure.wasm
Executable file
Binary file not shown.
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use fluence::fce;
|
||||
|
||||
pub fn main() {}
|
||||
|
||||
#[fce]
|
||||
pub fn all_types(
|
||||
arg_0: i8,
|
||||
arg_1: i16,
|
||||
arg_2: i32,
|
||||
arg_3: i64,
|
||||
arg_4: u8,
|
||||
arg_5: u16,
|
||||
arg_6: u32,
|
||||
arg_7: u64,
|
||||
arg_8: f32,
|
||||
arg_9: f64,
|
||||
arg_10: String,
|
||||
arg_11: Vec<u8>,
|
||||
) -> Vec<u8> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
result.push(arg_0 as u8);
|
||||
result.extend(safe_transmute::transmute_one_to_bytes(&arg_1));
|
||||
result.extend(safe_transmute::transmute_one_to_bytes(&arg_2));
|
||||
result.extend(safe_transmute::transmute_one_to_bytes(&arg_3));
|
||||
result.extend(safe_transmute::transmute_one_to_bytes(&arg_4));
|
||||
result.extend(safe_transmute::transmute_one_to_bytes(&arg_5));
|
||||
result.extend(safe_transmute::transmute_one_to_bytes(&arg_6));
|
||||
result.extend(safe_transmute::transmute_one_to_bytes(&arg_7));
|
||||
result.extend(&arg_8.to_be_bytes());
|
||||
result.extend(&arg_9.to_be_bytes());
|
||||
result.extend(arg_10.into_bytes());
|
||||
result.extend(arg_11);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn string_type(arg: String) -> String {
|
||||
format!("{}_{}", arg, arg)
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn bytearray_type(mut arg: Vec<u8>) -> Vec<u8> {
|
||||
arg.push(1);
|
||||
arg
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn bool_type(arg: bool) -> bool {
|
||||
!arg
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn f32_type(arg: f32) -> f32 {
|
||||
arg + 1.0
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn f64_type(arg: f64) -> f64 {
|
||||
arg + 1.0
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn u32_type(arg: u32) -> u32 {
|
||||
arg + 1
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn u64_type(arg: u64) -> u64 {
|
||||
arg + 1
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn i32_type(arg: i32) -> i32 {
|
||||
arg + 1
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn i64_type(arg: i64) -> i64 {
|
||||
arg + 1
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn empty_type() -> String {
|
||||
String::from("success")
|
||||
}
|
167
fluence-faas/tests/json_wasm_tests/arguments_passing/src/pure.rs
Normal file
167
fluence-faas/tests/json_wasm_tests/arguments_passing/src/pure.rs
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use fluence::fce;
|
||||
|
||||
pub fn main() {}
|
||||
|
||||
#[fce]
|
||||
pub fn all_types(
|
||||
arg_0: i8,
|
||||
arg_1: i16,
|
||||
arg_2: i32,
|
||||
arg_3: i64,
|
||||
arg_4: u8,
|
||||
arg_5: u16,
|
||||
arg_6: u32,
|
||||
arg_7: u64,
|
||||
arg_8: f32,
|
||||
arg_9: f64,
|
||||
arg_10: String,
|
||||
arg_11: Vec<u8>,
|
||||
) -> Vec<u8> {
|
||||
let mut result = unsafe {
|
||||
effector::all_types(
|
||||
arg_0,
|
||||
arg_1,
|
||||
arg_2,
|
||||
arg_3,
|
||||
arg_4,
|
||||
arg_5,
|
||||
arg_6,
|
||||
arg_7,
|
||||
arg_8,
|
||||
arg_9,
|
||||
arg_10.clone(),
|
||||
arg_11.clone(),
|
||||
)
|
||||
};
|
||||
|
||||
result.push(arg_0 as u8);
|
||||
result.extend(safe_transmute::transmute_one_to_bytes(&arg_1));
|
||||
result.extend(safe_transmute::transmute_one_to_bytes(&arg_2));
|
||||
result.extend(safe_transmute::transmute_one_to_bytes(&arg_3));
|
||||
result.extend(safe_transmute::transmute_one_to_bytes(&arg_4));
|
||||
result.extend(safe_transmute::transmute_one_to_bytes(&arg_5));
|
||||
result.extend(safe_transmute::transmute_one_to_bytes(&arg_6));
|
||||
result.extend(safe_transmute::transmute_one_to_bytes(&arg_7));
|
||||
result.extend(&arg_8.to_be_bytes());
|
||||
result.extend(&arg_9.to_be_bytes());
|
||||
result.extend(arg_10.into_bytes());
|
||||
result.extend(arg_11);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn string_type(arg: String) -> String {
|
||||
let arg = unsafe { effector::string_type(arg) };
|
||||
|
||||
format!("{}_{}", arg, arg)
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn bytearray_type(arg: Vec<u8>) -> Vec<u8> {
|
||||
let mut arg = unsafe { effector::bytearray_type(arg) };
|
||||
|
||||
arg.push(1);
|
||||
arg
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn bool_type(arg: bool) -> bool {
|
||||
unsafe { effector::bool_type(arg) }
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn f32_type(arg: f32) -> f32 {
|
||||
let arg = unsafe { effector::f32_type(arg) };
|
||||
arg + 1.0
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn f64_type(arg: f64) -> f64 {
|
||||
let arg = unsafe { effector::f64_type(arg) };
|
||||
arg + 1.0
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn u32_type(arg: u32) -> u32 {
|
||||
let arg = unsafe { effector::u32_type(arg) };
|
||||
arg + 1
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn u64_type(arg: u64) -> u64 {
|
||||
let arg = unsafe { effector::u64_type(arg) };
|
||||
arg + 1
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn i32_type(arg: i32) -> i32 {
|
||||
let arg = unsafe { effector::i32_type(arg) };
|
||||
arg + 1
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn i64_type(arg: i64) -> i64 {
|
||||
let arg = unsafe { effector::i64_type(arg) };
|
||||
arg + 1
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn empty_type() -> String {
|
||||
unsafe { effector::empty_type() }
|
||||
}
|
||||
|
||||
mod effector {
|
||||
use fluence::fce;
|
||||
|
||||
#[fce]
|
||||
#[link(wasm_import_module = "effector")]
|
||||
extern "C" {
|
||||
pub fn all_types(
|
||||
arg_0: i8,
|
||||
arg_1: i16,
|
||||
arg_2: i32,
|
||||
arg_3: i64,
|
||||
arg_4: u8,
|
||||
arg_5: u16,
|
||||
arg_6: u32,
|
||||
arg_7: u64,
|
||||
arg_8: f32,
|
||||
arg_9: f64,
|
||||
arg_10: String,
|
||||
arg_11: Vec<u8>,
|
||||
) -> Vec<u8>;
|
||||
|
||||
pub fn string_type(arg: String) -> String;
|
||||
pub fn bytearray_type(arg: Vec<u8>) -> Vec<u8>;
|
||||
|
||||
pub fn bool_type(arg: bool) -> bool;
|
||||
|
||||
pub fn f32_type(arg: f32) -> f32;
|
||||
pub fn f64_type(arg: f64) -> f64;
|
||||
|
||||
pub fn u32_type(arg: u32) -> u32;
|
||||
pub fn u64_type(arg: u64) -> u64;
|
||||
|
||||
pub fn i32_type(arg: i32) -> i32;
|
||||
pub fn i64_type(arg: i64) -> i64;
|
||||
|
||||
pub fn empty_type() -> String;
|
||||
}
|
||||
}
|
13
fluence-faas/tests/json_wasm_tests/inner_records/Cargo.toml
Normal file
13
fluence-faas/tests/json_wasm_tests/inner_records/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "inner-records-test"
|
||||
version = "0.1.0"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
|
||||
[[bin]]
|
||||
name = "inner_records_pure"
|
||||
path = "src/pure.rs"
|
||||
|
||||
[dependencies]
|
||||
fluence = { git = "https://github.com/fluencelabs/rust-sdk" }
|
||||
safe-transmute = "0.11.0"
|
@ -0,0 +1,6 @@
|
||||
modules_dir = "./artifacts/"
|
||||
|
||||
[[module]]
|
||||
name = "inner_records_pure"
|
||||
mem_pages_count = 1
|
||||
logger_enabled = true
|
Binary file not shown.
45
fluence-faas/tests/json_wasm_tests/inner_records/src/pure.rs
Normal file
45
fluence-faas/tests/json_wasm_tests/inner_records/src/pure.rs
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use fluence::fce;
|
||||
|
||||
#[fce]
|
||||
pub struct TestRecord0 {
|
||||
pub field_0: i32,
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub struct TestRecord1 {
|
||||
pub field_0: i32,
|
||||
pub field_1: String,
|
||||
pub field_2: Vec<u8>,
|
||||
pub test_record_0: TestRecord0,
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub struct TestRecord2 {
|
||||
pub test_record_0: TestRecord0,
|
||||
pub test_record_1: TestRecord1,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
#[fce]
|
||||
fn test_record(mut test_record: TestRecord2) -> TestRecord2 {
|
||||
test_record.test_record_0 = TestRecord0 { field_0: 1 };
|
||||
|
||||
test_record
|
||||
}
|
@ -17,8 +17,9 @@
|
||||
use fluence_faas::FluenceFaaS;
|
||||
use fluence_faas::IValue;
|
||||
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
pub fn records() {
|
||||
let records_config_path = "../examples/records/Config.toml";
|
||||
|
||||
@ -27,17 +28,176 @@ pub fn records() {
|
||||
|
||||
let mut records_config: fluence_faas::RawModulesConfig =
|
||||
toml::from_slice(&records_config_raw).expect("records config should be well-formed");
|
||||
records_config.modules_dir = Some(String::from("../examples/records/artifacts/wasm_modules/"));
|
||||
records_config.modules_dir = Some(String::from("../examples/records/artifacts/"));
|
||||
|
||||
let mut faas = FluenceFaaS::with_raw_config(records_config)
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let result = faas
|
||||
.call("pure", "invoke", &[], <_>::default())
|
||||
let result1 = faas
|
||||
.call_with_ivalues("records_pure", "invoke", &[], <_>::default())
|
||||
.unwrap_or_else(|e| panic!("can't invoke pure: {:?}", e));
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
result1,
|
||||
vec![IValue::Record(
|
||||
wasmer_wit::vec1::Vec1::new(vec![
|
||||
IValue::I32(1),
|
||||
IValue::S8(1),
|
||||
IValue::S16(2),
|
||||
IValue::S32(3),
|
||||
IValue::S64(4),
|
||||
IValue::U8(5),
|
||||
IValue::U16(6),
|
||||
IValue::U32(7),
|
||||
IValue::U64(8),
|
||||
IValue::F32(9.0),
|
||||
IValue::F64(10.0),
|
||||
IValue::String(String::from("field_11")),
|
||||
IValue::ByteArray(vec![0x13, 0x37])
|
||||
])
|
||||
.unwrap()
|
||||
)]
|
||||
);
|
||||
|
||||
let result2 = faas
|
||||
.call_with_json(
|
||||
"records_effector",
|
||||
"mutate_struct",
|
||||
json!({
|
||||
"test_record": {
|
||||
"field_0": 0,
|
||||
"field_1": 0,
|
||||
"field_2": 0,
|
||||
"field_3": 0,
|
||||
"field_4": 0,
|
||||
"field_5": 0,
|
||||
"field_6": 0,
|
||||
"field_7": 0,
|
||||
"field_8": 0,
|
||||
"field_9": 0,
|
||||
"field_10": 0,
|
||||
"field_11": "field",
|
||||
"field_12": vec![1],
|
||||
|
||||
}
|
||||
}),
|
||||
<_>::default(),
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("can't invoke pure: {:?}", e));
|
||||
|
||||
assert_eq!(
|
||||
result2,
|
||||
vec![IValue::Record(
|
||||
wasmer_wit::vec1::Vec1::new(vec![
|
||||
IValue::I32(1),
|
||||
IValue::S8(1),
|
||||
IValue::S16(2),
|
||||
IValue::S32(3),
|
||||
IValue::S64(4),
|
||||
IValue::U8(5),
|
||||
IValue::U16(6),
|
||||
IValue::U32(7),
|
||||
IValue::U64(8),
|
||||
IValue::F32(9.0),
|
||||
IValue::F64(10.0),
|
||||
IValue::String(String::from("field_11")),
|
||||
IValue::ByteArray(vec![0x13, 0x37])
|
||||
])
|
||||
.unwrap()
|
||||
)]
|
||||
);
|
||||
|
||||
let result3 = faas
|
||||
.call_with_json(
|
||||
"records_effector",
|
||||
"mutate_struct",
|
||||
json!({
|
||||
"test_record": [0,0,0,0,0,0,0,0,0,0,0,"",[1]]
|
||||
|
||||
}),
|
||||
<_>::default(),
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("can't invoke pure: {:?}", e));
|
||||
|
||||
assert_eq!(
|
||||
result3,
|
||||
vec![IValue::Record(
|
||||
wasmer_wit::vec1::Vec1::new(vec![
|
||||
IValue::I32(1),
|
||||
IValue::S8(1),
|
||||
IValue::S16(2),
|
||||
IValue::S32(3),
|
||||
IValue::S64(4),
|
||||
IValue::U8(5),
|
||||
IValue::U16(6),
|
||||
IValue::U32(7),
|
||||
IValue::U64(8),
|
||||
IValue::F32(9.0),
|
||||
IValue::F64(10.0),
|
||||
IValue::String(String::from("field_11")),
|
||||
IValue::ByteArray(vec![0x13, 0x37])
|
||||
])
|
||||
.unwrap()
|
||||
)]
|
||||
);
|
||||
|
||||
let result4 = faas
|
||||
.call_with_json(
|
||||
"records_effector",
|
||||
"mutate_struct",
|
||||
json!([{
|
||||
"field_0": 0,
|
||||
"field_1": 0,
|
||||
"field_2": 0,
|
||||
"field_3": 0,
|
||||
"field_4": 0,
|
||||
"field_5": 0,
|
||||
"field_6": 0,
|
||||
"field_7": 0,
|
||||
"field_8": 0,
|
||||
"field_9": 0,
|
||||
"field_10": 0,
|
||||
"field_11": "",
|
||||
"field_12": vec![1],
|
||||
}
|
||||
]),
|
||||
<_>::default(),
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("can't invoke pure: {:?}", e));
|
||||
|
||||
assert_eq!(
|
||||
result4,
|
||||
vec![IValue::Record(
|
||||
wasmer_wit::vec1::Vec1::new(vec![
|
||||
IValue::I32(1),
|
||||
IValue::S8(1),
|
||||
IValue::S16(2),
|
||||
IValue::S32(3),
|
||||
IValue::S64(4),
|
||||
IValue::U8(5),
|
||||
IValue::U16(6),
|
||||
IValue::U32(7),
|
||||
IValue::U64(8),
|
||||
IValue::F32(9.0),
|
||||
IValue::F64(10.0),
|
||||
IValue::String(String::from("field_11")),
|
||||
IValue::ByteArray(vec![0x13, 0x37])
|
||||
])
|
||||
.unwrap()
|
||||
)]
|
||||
);
|
||||
|
||||
let result5 = faas
|
||||
.call_with_json(
|
||||
"records_effector",
|
||||
"mutate_struct",
|
||||
json!([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", [1]]]),
|
||||
<_>::default(),
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("can't invoke pure: {:?}", e));
|
||||
|
||||
assert_eq!(
|
||||
result5,
|
||||
vec![IValue::Record(
|
||||
wasmer_wit::vec1::Vec1::new(vec![
|
||||
IValue::I32(1),
|
||||
@ -58,3 +218,63 @@ pub fn records() {
|
||||
)]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inner_records() {
|
||||
let inner_records_config_raw =
|
||||
std::fs::read("./tests/json_wasm_tests/inner_records/Config.toml")
|
||||
.expect("../examples/greeting/artifacts/greeting.wasm should presence");
|
||||
|
||||
let mut inner_records_config: fluence_faas::RawModulesConfig =
|
||||
toml::from_slice(&inner_records_config_raw)
|
||||
.expect("argument passing test config should be well-formed");
|
||||
|
||||
inner_records_config.modules_dir = Some(String::from(
|
||||
"./tests/json_wasm_tests/inner_records/artifacts",
|
||||
));
|
||||
|
||||
let mut faas = FluenceFaaS::with_raw_config(inner_records_config)
|
||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||
|
||||
let result = faas
|
||||
.call_with_json(
|
||||
"inner_records_pure",
|
||||
"test_record",
|
||||
json!({
|
||||
"test_record": {
|
||||
"test_record_0": {
|
||||
"field_0": 0
|
||||
},
|
||||
"test_record_1": {
|
||||
"field_0": 1,
|
||||
"field_1": "",
|
||||
"field_2": vec![1],
|
||||
"test_record_0": {
|
||||
"field_0": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
<_>::default(),
|
||||
)
|
||||
.unwrap_or_else(|e| panic!("can't invoke inner_records_pure: {:?}", e));
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
vec![IValue::Record(
|
||||
wasmer_wit::vec1::Vec1::new(vec![
|
||||
IValue::Record(wasmer_wit::vec1::Vec1::new(vec![IValue::S32(1),]).unwrap()),
|
||||
IValue::Record(
|
||||
wasmer_wit::vec1::Vec1::new(vec![
|
||||
IValue::S32(1),
|
||||
IValue::String(String::new()),
|
||||
IValue::ByteArray(vec![1]),
|
||||
IValue::Record(wasmer_wit::vec1::Vec1::new(vec![IValue::S32(1),]).unwrap())
|
||||
])
|
||||
.unwrap()
|
||||
),
|
||||
])
|
||||
.unwrap()
|
||||
)]
|
||||
);
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ impl REPL {
|
||||
}
|
||||
Some("interface") => {
|
||||
let interface = self.app_service.get_interface();
|
||||
println!("application service interface:\n{}", interface);
|
||||
println!("Application service interface:\n\n{}", interface);
|
||||
}
|
||||
Some("h") | Some("help") | None => {
|
||||
println!(
|
||||
|
Reference in New Issue
Block a user