mirror of
https://github.com/fluencelabs/marine.git
synced 2025-06-24 20:21:39 +00:00
Record refactoring (#19)
This commit is contained in:
@ -10,7 +10,7 @@ jobs:
|
|||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- fce01-{{ checksum "Cargo.lock" }}
|
- fce02-{{ checksum "Cargo.lock" }}
|
||||||
- run: |
|
- run: |
|
||||||
rustup toolchain install nightly
|
rustup toolchain install nightly
|
||||||
rustup component add rustfmt
|
rustup component add rustfmt
|
||||||
@ -25,7 +25,7 @@ jobs:
|
|||||||
paths:
|
paths:
|
||||||
- ~/.cargo
|
- ~/.cargo
|
||||||
- ~/.rustup
|
- ~/.rustup
|
||||||
key: fce01-{{ checksum "Cargo.lock" }}
|
key: fce02-{{ checksum "Cargo.lock" }}
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
docker:
|
docker:
|
||||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -16,3 +16,8 @@ target/
|
|||||||
!/examples/greeting/artifacts/*.wasm
|
!/examples/greeting/artifacts/*.wasm
|
||||||
!/examples/ipfs_node/artifacts/*.wasm
|
!/examples/ipfs_node/artifacts/*.wasm
|
||||||
!/examples/records/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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b"
|
checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arguments-passing-test"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"fluence 0.2.3",
|
||||||
|
"safe-transmute",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
@ -158,7 +166,7 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
|
|||||||
name = "call_parameters"
|
name = "call_parameters"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fluence",
|
"fluence 0.2.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -367,7 +375,7 @@ dependencies = [
|
|||||||
name = "curl"
|
name = "curl"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fluence",
|
"fluence 0.2.3",
|
||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -598,12 +606,12 @@ dependencies = [
|
|||||||
"fce-wit-interfaces",
|
"fce-wit-interfaces",
|
||||||
"fce-wit-parser",
|
"fce-wit-parser",
|
||||||
"log",
|
"log",
|
||||||
|
"multi-map",
|
||||||
"multimap",
|
"multimap",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parity-wasm",
|
"parity-wasm",
|
||||||
"pwasm-utils",
|
"pwasm-utils",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
"wasmer-interface-types-fl",
|
"wasmer-interface-types-fl",
|
||||||
"wasmer-runtime-core-fl",
|
"wasmer-runtime-core-fl",
|
||||||
@ -616,7 +624,7 @@ name = "fce-wit-generator"
|
|||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fce-wit-parser",
|
"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",
|
"once_cell",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -659,10 +667,19 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "fluence"
|
name = "fluence"
|
||||||
version = "0.2.2"
|
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 = [
|
dependencies = [
|
||||||
"fluence-sdk-macro 0.2.2 (git+https://github.com/fluencelabs/rust-sdk)",
|
"fluence-sdk-macro 0.2.2",
|
||||||
"fluence-sdk-main 0.2.2 (git+https://github.com/fluencelabs/rust-sdk)",
|
"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]]
|
[[package]]
|
||||||
@ -681,9 +698,12 @@ name = "fluence-faas"
|
|||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cmd_lib",
|
"cmd_lib",
|
||||||
|
"env_logger 0.7.1",
|
||||||
"fce",
|
"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",
|
"log",
|
||||||
|
"once_cell",
|
||||||
"safe-transmute",
|
"safe-transmute",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
@ -698,37 +718,55 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "fluence-sdk-macro"
|
name = "fluence-sdk-macro"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/fluencelabs/rust-sdk?branch=record_support#9201a824f2ecc4f2668449ea956d9b10a39091e5"
|
||||||
checksum = "21ca1fdcc78a17bc84798cdc2b13c36a07555b1a3dfe9db9a6ec3a3079aaebe6"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fluence-sdk-wit 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fluence-sdk-wit 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fluence-sdk-macro"
|
name = "fluence-sdk-macro"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
source = "git+https://github.com/fluencelabs/rust-sdk#dcb6cfddf95978e777a8a53710bda88aec7d4baf"
|
source = "git+https://github.com/fluencelabs/rust-sdk#04e2538661bab57110a288a3c7d21a2905c377e4"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
name = "fluence-sdk-main"
|
name = "fluence-sdk-main"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/fluencelabs/rust-sdk?branch=record_support#9201a824f2ecc4f2668449ea956d9b10a39091e5"
|
||||||
checksum = "26474b00df6b7ec38cfcaf96c8636bca84f3e504c3e192c3341dc2372e23b30e"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fluence-sdk-macro 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fluence-sdk-macro 0.2.2",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fluence-sdk-main"
|
name = "fluence-sdk-main"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
source = "git+https://github.com/fluencelabs/rust-sdk#dcb6cfddf95978e777a8a53710bda88aec7d4baf"
|
source = "git+https://github.com/fluencelabs/rust-sdk#04e2538661bab57110a288a3c7d21a2905c377e4"
|
||||||
dependencies = [
|
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",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
@ -736,8 +774,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "fluence-sdk-wit"
|
name = "fluence-sdk-wit"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/fluencelabs/rust-sdk?branch=record_support#9201a824f2ecc4f2668449ea956d9b10a39091e5"
|
||||||
checksum = "93c94643121eb234778b7f8f0e12fd29ec7c70ac71d84329ae25daf5d263074d"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -749,8 +786,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fluence-sdk-wit"
|
name = "fluence-sdk-wit"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
source = "git+https://github.com/fluencelabs/rust-sdk#dcb6cfddf95978e777a8a53710bda88aec7d4baf"
|
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 = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1091,6 +1142,14 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inner-records-test"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"fluence 0.2.3",
|
||||||
|
"safe-transmute",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inventory"
|
name = "inventory"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
@ -1126,7 +1185,7 @@ dependencies = [
|
|||||||
name = "ipfs-effector"
|
name = "ipfs-effector"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fluence",
|
"fluence 0.2.3",
|
||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1134,7 +1193,7 @@ dependencies = [
|
|||||||
name = "ipfs-pure"
|
name = "ipfs-pure"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fluence",
|
"fluence 0.2.3",
|
||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1213,7 +1272,7 @@ checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
|
|||||||
name = "local_storage"
|
name = "local_storage"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fluence",
|
"fluence 0.2.3",
|
||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1329,6 +1388,12 @@ dependencies = [
|
|||||||
"ws2_32-sys",
|
"ws2_32-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "multi-map"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bba551d6d795f74a01767577ea8339560bf0a65354e0417b7e915ed608443d46"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "multimap"
|
name = "multimap"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
@ -1696,7 +1761,7 @@ dependencies = [
|
|||||||
name = "record-effector"
|
name = "record-effector"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fluence",
|
"fluence 0.2.3",
|
||||||
"test-record",
|
"test-record",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1704,7 +1769,7 @@ dependencies = [
|
|||||||
name = "record-pure"
|
name = "record-pure"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fluence",
|
"fluence 0.2.3",
|
||||||
"test-record",
|
"test-record",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1989,7 +2054,7 @@ name = "site-storage"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"fluence",
|
"fluence 0.2.2",
|
||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2068,9 +2133,9 @@ checksum = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.40"
|
version = "1.0.41"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350"
|
checksum = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -2133,7 +2198,7 @@ dependencies = [
|
|||||||
name = "test-record"
|
name = "test-record"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fluence",
|
"fluence 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2568,7 +2633,7 @@ checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307"
|
|||||||
name = "wasm-greeting"
|
name = "wasm-greeting"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fluence",
|
"fluence 0.2.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2625,10 +2690,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmer-interface-types-fl"
|
name = "wasmer-interface-types-fl"
|
||||||
version = "0.17.0"
|
version = "0.17.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b12519a2a53ea1b2166ff47e56c6b57a3f7d714a2d34d26a6b04bdf22c37a41"
|
checksum = "486603d8267c5ade7a8c62b4fe4e15a6349e64857f40c7a9ac2a2a28d81569b8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"log",
|
||||||
"nom",
|
"nom",
|
||||||
"safe-transmute",
|
"safe-transmute",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -16,6 +16,8 @@ members = [
|
|||||||
"examples/call_parameters",
|
"examples/call_parameters",
|
||||||
"fluence-app-service",
|
"fluence-app-service",
|
||||||
"fluence-faas",
|
"fluence-faas",
|
||||||
|
"fluence-faas/tests/json_wasm_tests/arguments_passing",
|
||||||
|
"fluence-faas/tests/json_wasm_tests/inner_records",
|
||||||
"tools/cli",
|
"tools/cli",
|
||||||
"tools/repl",
|
"tools/repl",
|
||||||
]
|
]
|
||||||
|
@ -12,9 +12,10 @@ path = "src/lib.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fce-wit-parser = { path = "../wit-parser", version = "0.1.3"}
|
fce-wit-parser = { path = "../wit-parser", version = "0.1.3"}
|
||||||
|
fluence-sdk-wit = "0.2.3"
|
||||||
|
|
||||||
walrus = "0.17.0"
|
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"
|
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 = { version = "1.0.110", features = ["derive"] }
|
||||||
serde_json = "1.0.56"
|
serde_json = "1.0.56"
|
||||||
|
@ -16,20 +16,21 @@
|
|||||||
|
|
||||||
use wasmer_wit::ast::Interfaces;
|
use wasmer_wit::ast::Interfaces;
|
||||||
use wasmer_wit::types::InterfaceType as IType;
|
use wasmer_wit::types::InterfaceType as IType;
|
||||||
|
use wasmer_wit::ast::FunctionArg as IFunctionArg;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
pub(crate) struct ApiExportFuncDescriptor {
|
pub(crate) struct ApiExportFuncDescriptor {
|
||||||
pub(crate) name: &'static str,
|
pub(crate) name: &'static str,
|
||||||
pub(crate) id: u32,
|
pub(crate) id: u32,
|
||||||
pub(crate) input_types: Vec<IType>,
|
pub(crate) arguments: Vec<IFunctionArg>,
|
||||||
pub(crate) output_types: Vec<IType>,
|
pub(crate) output_types: Vec<IType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApiExportFuncDescriptor {
|
impl ApiExportFuncDescriptor {
|
||||||
pub fn update_interfaces(&self, interfaces: &mut Interfaces<'_>) {
|
pub fn update_interfaces(&self, interfaces: &mut Interfaces<'_>) {
|
||||||
let func_type = wasmer_wit::ast::Type::Function {
|
let func_type = wasmer_wit::ast::Type::Function {
|
||||||
inputs: self.input_types.clone(),
|
arguments: self.arguments.clone(),
|
||||||
outputs: self.output_types.clone(),
|
output_types: self.output_types.clone(),
|
||||||
};
|
};
|
||||||
interfaces.types.push(func_type);
|
interfaces.types.push(func_type);
|
||||||
|
|
||||||
@ -45,7 +46,10 @@ pub(crate) static ALLOCATE_FUNC: Lazy<ApiExportFuncDescriptor> =
|
|||||||
Lazy::new(|| ApiExportFuncDescriptor {
|
Lazy::new(|| ApiExportFuncDescriptor {
|
||||||
name: "allocate",
|
name: "allocate",
|
||||||
id: 0,
|
id: 0,
|
||||||
input_types: vec![IType::I32],
|
arguments: vec![IFunctionArg {
|
||||||
|
name: String::from("size"),
|
||||||
|
ty: IType::I32,
|
||||||
|
}],
|
||||||
output_types: vec![IType::I32],
|
output_types: vec![IType::I32],
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -53,7 +57,16 @@ pub(crate) static DEALLOCATE_FUNC: Lazy<ApiExportFuncDescriptor> =
|
|||||||
Lazy::new(|| ApiExportFuncDescriptor {
|
Lazy::new(|| ApiExportFuncDescriptor {
|
||||||
name: "deallocate",
|
name: "deallocate",
|
||||||
id: 1,
|
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![],
|
output_types: vec![],
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -61,7 +74,7 @@ pub(crate) static GET_RESULT_SIZE_FUNC: Lazy<ApiExportFuncDescriptor> =
|
|||||||
Lazy::new(|| ApiExportFuncDescriptor {
|
Lazy::new(|| ApiExportFuncDescriptor {
|
||||||
name: "get_result_size",
|
name: "get_result_size",
|
||||||
id: 2,
|
id: 2,
|
||||||
input_types: vec![],
|
arguments: vec![],
|
||||||
output_types: vec![IType::I32],
|
output_types: vec![IType::I32],
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -69,7 +82,7 @@ pub(crate) static GET_RESULT_PTR_FUNC: Lazy<ApiExportFuncDescriptor> =
|
|||||||
Lazy::new(|| ApiExportFuncDescriptor {
|
Lazy::new(|| ApiExportFuncDescriptor {
|
||||||
name: "get_result_ptr",
|
name: "get_result_ptr",
|
||||||
id: 3,
|
id: 3,
|
||||||
input_types: vec![],
|
arguments: vec![],
|
||||||
output_types: vec![IType::I32],
|
output_types: vec![IType::I32],
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -77,7 +90,10 @@ pub(crate) static SET_RESULT_SIZE_FUNC: Lazy<ApiExportFuncDescriptor> =
|
|||||||
Lazy::new(|| ApiExportFuncDescriptor {
|
Lazy::new(|| ApiExportFuncDescriptor {
|
||||||
name: "set_result_size",
|
name: "set_result_size",
|
||||||
id: 4,
|
id: 4,
|
||||||
input_types: vec![IType::I32],
|
arguments: vec![IFunctionArg {
|
||||||
|
name: String::from("result_size"),
|
||||||
|
ty: IType::I32,
|
||||||
|
}],
|
||||||
output_types: vec![],
|
output_types: vec![],
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -85,6 +101,9 @@ pub(crate) static SET_RESULT_PTR_FUNC: Lazy<ApiExportFuncDescriptor> =
|
|||||||
Lazy::new(|| ApiExportFuncDescriptor {
|
Lazy::new(|| ApiExportFuncDescriptor {
|
||||||
name: "set_result_ptr",
|
name: "set_result_ptr",
|
||||||
id: 5,
|
id: 5,
|
||||||
input_types: vec![IType::I32],
|
arguments: vec![IFunctionArg {
|
||||||
|
name: String::from("result_ptr"),
|
||||||
|
ty: IType::I32,
|
||||||
|
}],
|
||||||
output_types: vec![],
|
output_types: vec![],
|
||||||
});
|
});
|
||||||
|
@ -23,15 +23,17 @@ use crate::Result;
|
|||||||
|
|
||||||
use wasmer_wit::types::InterfaceType as IType;
|
use wasmer_wit::types::InterfaceType as IType;
|
||||||
use wasmer_wit::ast::Interfaces;
|
use wasmer_wit::ast::Interfaces;
|
||||||
|
use wasmer_wit::types::RecordType;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Default)]
|
#[derive(PartialEq, Debug, Default)]
|
||||||
pub(crate) struct WITResolver<'a> {
|
pub(crate) struct WITResolver<'a> {
|
||||||
pub(crate) types: std::collections::HashMap<String, u32>,
|
types: std::collections::HashMap<String, usize>,
|
||||||
pub(crate) interfaces: Interfaces<'a>,
|
pub(crate) interfaces: Interfaces<'a>,
|
||||||
|
not_resolved_types_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> WITResolver<'a> {
|
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) {
|
match self.types.get(record_name) {
|
||||||
Some(type_index) => Ok(*type_index),
|
Some(type_index) => Ok(*type_index),
|
||||||
None => Err(crate::errors::WITGeneratorError::CorruptedRecord(format!(
|
None => Err(crate::errors::WITGeneratorError::CorruptedRecord(format!(
|
||||||
@ -41,22 +43,63 @@ 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(
|
pub(crate) fn get_record_type(
|
||||||
&self,
|
&self,
|
||||||
record_name: &str,
|
record_type_id: u64,
|
||||||
) -> Result<wasmer_wit::types::RecordType> {
|
) -> Result<&wasmer_wit::types::RecordType> {
|
||||||
match self.types.get(record_name) {
|
if record_type_id >= self.interfaces.types.len() as u64 {
|
||||||
Some(type_index) => match &self.interfaces.types[*type_index as usize] {
|
return Err(crate::errors::WITGeneratorError::CorruptedRecord(format!(
|
||||||
wasmer_wit::ast::Type::Function { .. } => {
|
"Can't find record with id {}, don't you forget to wrap it with #[fce]",
|
||||||
panic!("internal error inside WITResolver")
|
record_type_id
|
||||||
}
|
)));
|
||||||
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
|
|
||||||
))),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match &self.interfaces.types[record_type_id as usize] {
|
||||||
|
wasmer_wit::ast::Type::Function { .. } => {
|
||||||
|
panic!("internal error inside WITResolver: interfaces AST type should be record not record")
|
||||||
|
}
|
||||||
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,39 +16,48 @@
|
|||||||
|
|
||||||
use super::WITGenerator;
|
use super::WITGenerator;
|
||||||
use super::WITResolver;
|
use super::WITResolver;
|
||||||
use super::utils::ptype_to_itype;
|
use super::utils::ptype_to_itype_checked;
|
||||||
use crate::default_export_api_config::*;
|
use crate::default_export_api_config::*;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
use fluence_sdk_wit::AstFunctionItem;
|
use fluence_sdk_wit::AstFunctionItem;
|
||||||
use fluence_sdk_wit::ParsedType;
|
use fluence_sdk_wit::ParsedType;
|
||||||
use wasmer_wit::interpreter::Instruction;
|
use wasmer_wit::interpreter::Instruction;
|
||||||
|
use wasmer_wit::ast::FunctionArg as IFunctionArg;
|
||||||
|
|
||||||
impl WITGenerator for AstFunctionItem {
|
impl WITGenerator for AstFunctionItem {
|
||||||
fn generate_wit<'a>(&'a self, wit_resolver: &mut WITResolver<'a>) -> Result<()> {
|
fn generate_wit<'a>(&'a self, wit_resolver: &mut WITResolver<'a>) -> Result<()> {
|
||||||
use wasmer_wit::ast::Type;
|
use wasmer_wit::ast::Type;
|
||||||
use wasmer_wit::ast::Adapter;
|
use wasmer_wit::ast::Adapter;
|
||||||
|
|
||||||
let inputs = self
|
let arguments = self
|
||||||
.signature
|
.signature
|
||||||
.input_types
|
.arguments
|
||||||
.iter()
|
.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<_>>>()?;
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
let outputs = match self.signature.output_type {
|
let output_types = match self.signature.output_type {
|
||||||
Some(ref output_type) => vec![ptype_to_itype(output_type, wit_resolver)?],
|
Some(ref output_type) => vec![ptype_to_itype_checked(output_type, wit_resolver)?],
|
||||||
None => vec![],
|
None => vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let interfaces = &mut wit_resolver.interfaces;
|
let interfaces = &mut wit_resolver.interfaces;
|
||||||
interfaces.types.push(Type::Function {
|
interfaces.types.push(Type::Function {
|
||||||
inputs: inputs.clone(),
|
arguments: arguments.clone(),
|
||||||
outputs: outputs.clone(),
|
output_types: output_types.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: replace with Wasm types
|
// 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 adapter_idx = (interfaces.types.len() - 2) as u32;
|
||||||
let export_idx = (interfaces.types.len() - 1) as u32;
|
let export_idx = (interfaces.types.len() - 1) as u32;
|
||||||
@ -60,16 +69,19 @@ impl WITGenerator for AstFunctionItem {
|
|||||||
|
|
||||||
let mut instructions = self
|
let mut instructions = self
|
||||||
.signature
|
.signature
|
||||||
.input_types
|
.arguments
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.try_fold::<_, _, Result<_>>(Vec::new(), |mut instructions, (arg_id, input_type)| {
|
.try_fold::<_, _, Result<_>>(
|
||||||
let mut new_instructions =
|
Vec::new(),
|
||||||
input_type.generate_instructions_for_input_type(arg_id as _, wit_resolver)?;
|
|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);
|
instructions.append(&mut new_instructions);
|
||||||
Ok(instructions)
|
Ok(instructions)
|
||||||
})?;
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
let export_function_index = (wit_resolver.interfaces.exports.len() - 1) as u32;
|
let export_function_index = (wit_resolver.interfaces.exports.len() - 1) as u32;
|
||||||
instructions.push(Instruction::CallCore {
|
instructions.push(Instruction::CallCore {
|
||||||
@ -119,8 +131,8 @@ impl FnInstructionGenerator for ParsedType {
|
|||||||
ParsedType::Boolean => vec![Instruction::ArgumentGet { index }],
|
ParsedType::Boolean => vec![Instruction::ArgumentGet { index }],
|
||||||
ParsedType::I8 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS8],
|
ParsedType::I8 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS8],
|
||||||
ParsedType::I16 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS16],
|
ParsedType::I16 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS16],
|
||||||
ParsedType::I32 => vec![Instruction::ArgumentGet { index }],
|
ParsedType::I32 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS32],
|
||||||
ParsedType::I64 => vec![Instruction::ArgumentGet { index }],
|
ParsedType::I64 => vec![Instruction::ArgumentGet { index }, Instruction::I64FromS64],
|
||||||
ParsedType::U8 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU8],
|
ParsedType::U8 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU8],
|
||||||
ParsedType::U16 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU16],
|
ParsedType::U16 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU16],
|
||||||
ParsedType::U32 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU32],
|
ParsedType::U32 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU32],
|
||||||
@ -142,11 +154,11 @@ impl FnInstructionGenerator for ParsedType {
|
|||||||
Instruction::ByteArrayLowerMemory,
|
Instruction::ByteArrayLowerMemory,
|
||||||
],
|
],
|
||||||
ParsedType::Record(record_name) => {
|
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! [
|
vec! [
|
||||||
Instruction::ArgumentGet { index },
|
Instruction::ArgumentGet { index },
|
||||||
Instruction::RecordLowerMemory { type_index },
|
Instruction::RecordLowerMemory { record_type_id },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -160,8 +172,8 @@ impl FnInstructionGenerator for ParsedType {
|
|||||||
ParsedType::Boolean => vec![],
|
ParsedType::Boolean => vec![],
|
||||||
ParsedType::I8 => vec![Instruction::S8FromI32],
|
ParsedType::I8 => vec![Instruction::S8FromI32],
|
||||||
ParsedType::I16 => vec![Instruction::S16FromI32],
|
ParsedType::I16 => vec![Instruction::S16FromI32],
|
||||||
ParsedType::I32 => vec![],
|
ParsedType::I32 => vec![Instruction::S32FromI32],
|
||||||
ParsedType::I64 => vec![],
|
ParsedType::I64 => vec![Instruction::S64FromI64],
|
||||||
ParsedType::U8 => vec![Instruction::U8FromI32],
|
ParsedType::U8 => vec![Instruction::U8FromI32],
|
||||||
ParsedType::U16 => vec![Instruction::U16FromI32],
|
ParsedType::U16 => vec![Instruction::U16FromI32],
|
||||||
ParsedType::U32 => vec![Instruction::U32FromI32],
|
ParsedType::U32 => vec![Instruction::U32FromI32],
|
||||||
@ -185,11 +197,11 @@ impl FnInstructionGenerator for ParsedType {
|
|||||||
Instruction::CallCore { function_index: DEALLOCATE_FUNC.id },
|
Instruction::CallCore { function_index: DEALLOCATE_FUNC.id },
|
||||||
],
|
],
|
||||||
ParsedType::Record(record_name) => {
|
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! [
|
vec! [
|
||||||
Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id },
|
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::WITGenerator;
|
||||||
use super::WITResolver;
|
use super::WITResolver;
|
||||||
use super::utils::ptype_to_itype;
|
use super::utils::ptype_to_itype_checked;
|
||||||
use crate::default_export_api_config::*;
|
use crate::default_export_api_config::*;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
use fluence_sdk_wit::AstExternModItem;
|
use fluence_sdk_wit::AstExternModItem;
|
||||||
use fluence_sdk_wit::AstExternFnItem;
|
use fluence_sdk_wit::AstExternFnItem;
|
||||||
use fluence_sdk_wit::ParsedType;
|
use fluence_sdk_wit::ParsedType;
|
||||||
|
use wasmer_wit::ast::FunctionArg as IFunctionArg;
|
||||||
use wasmer_wit::interpreter::Instruction;
|
use wasmer_wit::interpreter::Instruction;
|
||||||
use crate::instructions_generator::utils::wtype_to_itype;
|
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::Type;
|
||||||
use wasmer_wit::ast::Adapter;
|
use wasmer_wit::ast::Adapter;
|
||||||
|
|
||||||
let inputs = import
|
let arguments = import
|
||||||
.signature
|
.signature
|
||||||
.input_types
|
.arguments
|
||||||
.iter()
|
.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<_>>>()?;
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
let outputs = match import.signature.output_type {
|
let output_types = match import.signature.output_type {
|
||||||
Some(ref output_type) => vec![ptype_to_itype(output_type, wit_resolver)?],
|
Some(ref output_type) => vec![ptype_to_itype_checked(output_type, wit_resolver)?],
|
||||||
None => vec![],
|
None => vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let interfaces = &mut wit_resolver.interfaces;
|
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
|
let raw_inputs = import
|
||||||
.signature
|
.signature
|
||||||
.input_types
|
.arguments
|
||||||
.iter()
|
.iter()
|
||||||
.map(to_raw_input_types)
|
.map(to_raw_input_types)
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|wt| wtype_to_itype(&wt))
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let raw_outputs = match import.signature.output_type {
|
let raw_outputs = match import.signature.output_type {
|
||||||
@ -84,13 +92,13 @@ fn generate_wit_for_import<'a>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
interfaces.types.push(Type::Function {
|
interfaces.types.push(Type::Function {
|
||||||
inputs: raw_inputs.clone(),
|
arguments: raw_inputs.clone(),
|
||||||
outputs: raw_outputs.clone(),
|
output_types: raw_outputs.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
interfaces.types.push(Type::Function {
|
interfaces.types.push(Type::Function {
|
||||||
inputs: raw_inputs,
|
arguments: raw_inputs,
|
||||||
outputs: raw_outputs,
|
output_types: raw_outputs,
|
||||||
});
|
});
|
||||||
|
|
||||||
let adapter_idx = (interfaces.types.len() - 2) as u32;
|
let adapter_idx = (interfaces.types.len() - 2) as u32;
|
||||||
@ -116,15 +124,18 @@ fn generate_wit_for_import<'a>(
|
|||||||
|
|
||||||
let mut instructions = import
|
let mut instructions = import
|
||||||
.signature
|
.signature
|
||||||
.input_types
|
.arguments
|
||||||
.iter()
|
.iter()
|
||||||
.try_fold::<_, _, Result<_>>((0, Vec::new()), |(arg_id, mut instructions), input_type| {
|
.try_fold::<_, _, Result<_>>(
|
||||||
let (mut new_instructions, shift) =
|
(0, Vec::new()),
|
||||||
input_type.generate_instructions_for_input_type(arg_id as _, wit_resolver)?;
|
|(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);
|
instructions.append(&mut new_instructions);
|
||||||
Ok((arg_id + shift, instructions))
|
Ok((arg_id + shift, instructions))
|
||||||
})?
|
},
|
||||||
|
)?
|
||||||
.1;
|
.1;
|
||||||
|
|
||||||
// TODO: refactor
|
// TODO: refactor
|
||||||
@ -180,8 +191,8 @@ impl ForeignModInstructionGenerator for ParsedType {
|
|||||||
ParsedType::Boolean => (vec![Instruction::ArgumentGet { index }], 1),
|
ParsedType::Boolean => (vec![Instruction::ArgumentGet { index }], 1),
|
||||||
ParsedType::I8 => (vec![Instruction::ArgumentGet { index }, Instruction::S8FromI32], 1),
|
ParsedType::I8 => (vec![Instruction::ArgumentGet { index }, Instruction::S8FromI32], 1),
|
||||||
ParsedType::I16 => (vec![Instruction::ArgumentGet { index }, Instruction::S16FromI32], 1),
|
ParsedType::I16 => (vec![Instruction::ArgumentGet { index }, Instruction::S16FromI32], 1),
|
||||||
ParsedType::I32 => (vec![Instruction::ArgumentGet { index }], 1),
|
ParsedType::I32 => (vec![Instruction::ArgumentGet { index }, Instruction::S32FromI32], 1),
|
||||||
ParsedType::I64 => (vec![Instruction::ArgumentGet { index }], 1),
|
ParsedType::I64 => (vec![Instruction::ArgumentGet { index }, Instruction::S64FromI64], 1),
|
||||||
ParsedType::U8 => (vec![Instruction::ArgumentGet { index }, Instruction::U8FromI32], 1),
|
ParsedType::U8 => (vec![Instruction::ArgumentGet { index }, Instruction::U8FromI32], 1),
|
||||||
ParsedType::U16 => (vec![Instruction::ArgumentGet { index }, Instruction::U16FromI32], 1),
|
ParsedType::U16 => (vec![Instruction::ArgumentGet { index }, Instruction::U16FromI32], 1),
|
||||||
ParsedType::U32 => (vec![Instruction::ArgumentGet { index }, Instruction::U32FromI32], 1),
|
ParsedType::U32 => (vec![Instruction::ArgumentGet { index }, Instruction::U32FromI32], 1),
|
||||||
@ -199,11 +210,11 @@ impl ForeignModInstructionGenerator for ParsedType {
|
|||||||
Instruction::ByteArrayLiftMemory,
|
Instruction::ByteArrayLiftMemory,
|
||||||
], 2),
|
], 2),
|
||||||
ParsedType::Record(record_name) => {
|
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![
|
(vec![
|
||||||
Instruction::ArgumentGet { index },
|
Instruction::ArgumentGet { index },
|
||||||
Instruction::RecordLiftMemory { type_index },
|
Instruction::RecordLiftMemory { record_type_id },
|
||||||
], 1)
|
], 1)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -217,8 +228,8 @@ impl ForeignModInstructionGenerator for ParsedType {
|
|||||||
ParsedType::Boolean => vec![],
|
ParsedType::Boolean => vec![],
|
||||||
ParsedType::I8 => vec![Instruction::I32FromS8],
|
ParsedType::I8 => vec![Instruction::I32FromS8],
|
||||||
ParsedType::I16 => vec![Instruction::I32FromS16],
|
ParsedType::I16 => vec![Instruction::I32FromS16],
|
||||||
ParsedType::I32 => vec![],
|
ParsedType::I32 => vec![Instruction::I32FromS32],
|
||||||
ParsedType::I64 => vec![],
|
ParsedType::I64 => vec![Instruction::I64FromS64],
|
||||||
ParsedType::U8 => vec![Instruction::I32FromU8],
|
ParsedType::U8 => vec![Instruction::I32FromU8],
|
||||||
ParsedType::U16 => vec![Instruction::I32FromU16],
|
ParsedType::U16 => vec![Instruction::I32FromU16],
|
||||||
ParsedType::U32 => vec![Instruction::I32FromU32],
|
ParsedType::U32 => vec![Instruction::I32FromU32],
|
||||||
@ -244,10 +255,10 @@ impl ForeignModInstructionGenerator for ParsedType {
|
|||||||
Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.id },
|
Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.id },
|
||||||
],
|
],
|
||||||
ParsedType::Record(record_name) => {
|
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![
|
vec![
|
||||||
Instruction::RecordLowerMemory {type_index},
|
Instruction::RecordLowerMemory { record_type_id },
|
||||||
Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.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> {
|
pub fn to_raw_input_types(arg: &(String, ParsedType)) -> Vec<IFunctionArg> {
|
||||||
match ty {
|
match arg.1 {
|
||||||
ParsedType::Boolean
|
ParsedType::Boolean
|
||||||
| ParsedType::I8
|
| ParsedType::I8
|
||||||
| ParsedType::I16
|
| ParsedType::I16
|
||||||
@ -268,15 +280,36 @@ pub fn to_raw_input_types(ty: &ParsedType) -> Vec<WasmType> {
|
|||||||
| ParsedType::U8
|
| ParsedType::U8
|
||||||
| ParsedType::U16
|
| ParsedType::U16
|
||||||
| ParsedType::U32
|
| ParsedType::U32
|
||||||
| ParsedType::Record(_) => vec![WasmType::I32],
|
| ParsedType::Record(_) => vec![IFunctionArg {
|
||||||
ParsedType::I64 | ParsedType::U64 => vec![WasmType::I64],
|
name: arg.0.clone(),
|
||||||
ParsedType::F32 => vec![WasmType::F32],
|
ty: IType::I32,
|
||||||
ParsedType::F64 => vec![WasmType::F64],
|
}],
|
||||||
ParsedType::Utf8String | ParsedType::ByteVector => vec![WasmType::I32, WasmType::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 {
|
match ty {
|
||||||
ParsedType::Boolean
|
ParsedType::Boolean
|
||||||
| ParsedType::I8
|
| ParsedType::I8
|
||||||
@ -284,10 +317,10 @@ pub fn to_raw_output_type(ty: &ParsedType) -> Vec<WasmType> {
|
|||||||
| ParsedType::I32
|
| ParsedType::I32
|
||||||
| ParsedType::U8
|
| ParsedType::U8
|
||||||
| ParsedType::U16
|
| ParsedType::U16
|
||||||
| ParsedType::U32 => vec![WasmType::I32],
|
| ParsedType::U32 => vec![RustType::I32],
|
||||||
ParsedType::I64 | ParsedType::U64 => vec![WasmType::I64],
|
ParsedType::I64 | ParsedType::U64 => vec![RustType::I64],
|
||||||
ParsedType::F32 => vec![WasmType::F32],
|
ParsedType::F32 => vec![RustType::F32],
|
||||||
ParsedType::F64 => vec![WasmType::F64],
|
ParsedType::F64 => vec![RustType::F64],
|
||||||
ParsedType::Utf8String | ParsedType::ByteVector | ParsedType::Record(_) => vec![],
|
ParsedType::Utf8String | ParsedType::ByteVector | ParsedType::Record(_) => vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ use crate::Result;
|
|||||||
|
|
||||||
use fluence_sdk_wit::AstRecordItem;
|
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::types::RecordType;
|
||||||
use wasmer_wit::vec1::Vec1;
|
use wasmer_wit::vec1::Vec1;
|
||||||
|
|
||||||
@ -29,8 +29,11 @@ impl WITGenerator for AstRecordItem {
|
|||||||
let fields = self
|
let fields = self
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|field| super::utils::ptype_to_itype(&field.ty, wit_resolver))
|
.map(|field| IRecordFieldType {
|
||||||
.collect::<Result<Vec<_>>>()?;
|
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(|_| {
|
let fields = Vec1::new(fields).map_err(|_| {
|
||||||
crate::errors::WITGeneratorError::CorruptedRecord(format!(
|
crate::errors::WITGeneratorError::CorruptedRecord(format!(
|
||||||
@ -39,15 +42,12 @@ impl WITGenerator for AstRecordItem {
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
wit_resolver
|
let new_record_type = RecordType {
|
||||||
.interfaces
|
name: self.name.clone(),
|
||||||
.types
|
fields,
|
||||||
.push(Type::Record(RecordType { fields }));
|
};
|
||||||
|
|
||||||
wit_resolver.types.insert(
|
wit_resolver.insert_record_type(new_record_type);
|
||||||
self.name.clone(),
|
|
||||||
(wit_resolver.interfaces.types.len() - 1) as _,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -19,34 +19,55 @@ use crate::instructions_generator::WITResolver;
|
|||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
use fluence_sdk_wit::ParsedType;
|
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 {
|
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) => {
|
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 {
|
match pty {
|
||||||
WasmType::I32 => IType::I32,
|
RustType::I8 => IType::S8,
|
||||||
WasmType::I64 => IType::I64,
|
RustType::I16 => IType::S16,
|
||||||
WasmType::F32 => IType::F32,
|
RustType::I32 => IType::S32,
|
||||||
WasmType::F64 => IType::F64,
|
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::default_export_api_config::*;
|
||||||
use crate::errors::WITGeneratorError;
|
use crate::errors::WITGeneratorError;
|
||||||
use crate::instructions_generator::WITGenerator;
|
use crate::instructions_generator::WITGenerator;
|
||||||
|
use crate::instructions_generator::WITResolver;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
pub use fluence_sdk_wit::FCEAst;
|
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<'_>> {
|
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);
|
generate_default_export_api(&mut wit_resolver.interfaces);
|
||||||
|
|
||||||
for record in &module_ast.records {
|
for record in &module_ast.records {
|
||||||
record.generate_wit(&mut wit_resolver)?;
|
record.generate_wit(&mut wit_resolver)?;
|
||||||
}
|
}
|
||||||
|
validate_records(&wit_resolver)?;
|
||||||
|
|
||||||
for function in &module_ast.functions {
|
for function in &module_ast.functions {
|
||||||
function.generate_wit(&mut wit_resolver)?;
|
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_SIZE_FUNC.update_interfaces(interfaces);
|
||||||
SET_RESULT_PTR_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"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[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"
|
multimap = "0.8.1"
|
||||||
|
@ -13,7 +13,7 @@ path = "src/lib.rs"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
walrus = "0.17.0"
|
walrus = "0.17.0"
|
||||||
wasmer-core = { package = "wasmer-runtime-core-fl", version = "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" }
|
fce-wit-interfaces = { path = "../wit-interfaces", version = "0.1.1" }
|
||||||
|
|
||||||
anyhow = "1.0.31"
|
anyhow = "1.0.31"
|
||||||
|
@ -32,9 +32,9 @@ mod extractor;
|
|||||||
|
|
||||||
pub use errors::WITParserError;
|
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;
|
||||||
pub use deleter::delete_wit_section_from_file;
|
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_wit;
|
||||||
pub use extractor::extract_text_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" }
|
wasmer-runtime = { package = "wasmer-runtime-fl", version = "0.17.0" }
|
||||||
# dynamicfunc-fat-closures allows using state inside DynamicFunc
|
# dynamicfunc-fat-closures allows using state inside DynamicFunc
|
||||||
wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0", features = ["dynamicfunc-fat-closures"] }
|
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" }
|
wasmer-wasi = { package = "wasmer-wasi-fl", version = "0.17.0" }
|
||||||
serde = { version = "1.0.114", default-features = false, features = [ "derive" ] }
|
|
||||||
|
|
||||||
multimap = "0.8.1"
|
multimap = "0.8.1"
|
||||||
|
multi-map = "1.3.0"
|
||||||
boolinator = "2.4.0"
|
boolinator = "2.4.0"
|
||||||
parity-wasm = "0.41.0"
|
parity-wasm = "0.41.0"
|
||||||
pwasm-utils = "0.12.0"
|
pwasm-utils = "0.12.0"
|
||||||
|
@ -21,10 +21,10 @@ use std::collections::hash_map::Entry;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
/// Represent a function type inside FCE.
|
/// Represent a function type inside FCE.
|
||||||
#[derive(Debug, serde::Serialize)]
|
#[derive(Debug)]
|
||||||
pub struct FCEFunctionSignature<'a> {
|
pub struct FCEFunctionSignature<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub input_types: &'a Vec<IType>,
|
pub arguments: &'a Vec<IFunctionArg>,
|
||||||
pub output_types: &'a Vec<IType>,
|
pub output_types: &'a Vec<IType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ impl FCE {
|
|||||||
self.modules.iter().map(|(module_name, module)| {
|
self.modules.iter().map(|(module_name, module)| {
|
||||||
(
|
(
|
||||||
module_name.as_str(),
|
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>>(
|
pub fn module_interface<S: AsRef<str>>(
|
||||||
&self,
|
&self,
|
||||||
module_name: S,
|
module_name: S,
|
||||||
) -> Result<Vec<FCEFunctionSignature<'_>>> {
|
) -> Result<impl Iterator<Item = FCEFunctionSignature<'_>>> {
|
||||||
match self.modules.get(module_name.as_ref()) {
|
match self.modules.get(module_name.as_ref()) {
|
||||||
Some(module) => Ok(Self::get_module_function_signatures(module)),
|
Some(module) => Ok(Self::get_module_function_signatures(module)),
|
||||||
None => Err(FCEError::NoSuchModule(module_name.as_ref().to_string())),
|
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
|
module
|
||||||
.get_exports_signatures()
|
.get_exports_signatures()
|
||||||
.map(|(name, input_types, output_types)| FCEFunctionSignature {
|
.map(|(name, arguments, output_types)| FCEFunctionSignature {
|
||||||
name,
|
name,
|
||||||
input_types,
|
arguments,
|
||||||
output_types,
|
output_types,
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
@ -38,8 +38,12 @@ pub use engine::FCE;
|
|||||||
pub use engine::FCEFunctionSignature;
|
pub use engine::FCEFunctionSignature;
|
||||||
pub use errors::FCEError;
|
pub use errors::FCEError;
|
||||||
pub use module::IValue;
|
pub use module::IValue;
|
||||||
|
pub use module::IRecordType;
|
||||||
|
pub use module::IFunctionArg;
|
||||||
pub use module::IType;
|
pub use module::IType;
|
||||||
pub use module::from_interface_values;
|
pub use module::from_interface_values;
|
||||||
pub use module::to_interface_value;
|
pub use module::to_interface_value;
|
||||||
|
|
||||||
|
pub use wasmer_wit::types::RecordFieldType as IRecordFieldType;
|
||||||
|
|
||||||
pub(crate) type Result<T> = std::result::Result<T, FCEError>;
|
pub(crate) type Result<T> = std::result::Result<T, FCEError>;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
use super::IValue;
|
use super::IValue;
|
||||||
use super::IType;
|
use super::IType;
|
||||||
|
use super::IFunctionArg;
|
||||||
use wasmer_wit::interpreter::wasm;
|
use wasmer_wit::interpreter::wasm;
|
||||||
|
|
||||||
// In current implementation export simply does nothing, because there is no more
|
// 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.
|
// but explicit Exports is still required by wasmer-interface-types::Interpreter.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct WITExport {
|
pub(crate) struct WITExport {
|
||||||
inputs: Vec<IType>,
|
arguments: Vec<IFunctionArg>,
|
||||||
outputs: Vec<IType>,
|
outputs: Vec<IType>,
|
||||||
function: fn(arguments: &[IValue]) -> Result<Vec<IValue>, ()>,
|
function: fn(arguments: &[IValue]) -> Result<Vec<IValue>, ()>,
|
||||||
}
|
}
|
||||||
@ -32,7 +33,7 @@ impl WITExport {
|
|||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub(crate) fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
inputs: vec![],
|
arguments: vec![],
|
||||||
outputs: vec![],
|
outputs: vec![],
|
||||||
function: |_| -> _ { Ok(vec![]) },
|
function: |_| -> _ { Ok(vec![]) },
|
||||||
}
|
}
|
||||||
@ -41,15 +42,15 @@ impl WITExport {
|
|||||||
|
|
||||||
impl wasm::structures::Export for WITExport {
|
impl wasm::structures::Export for WITExport {
|
||||||
fn inputs_cardinality(&self) -> usize {
|
fn inputs_cardinality(&self) -> usize {
|
||||||
self.inputs.len() as usize
|
self.arguments.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn outputs_cardinality(&self) -> usize {
|
fn outputs_cardinality(&self) -> usize {
|
||||||
self.outputs.len()
|
self.outputs.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inputs(&self) -> &[IType] {
|
fn arguments(&self) -> &[IFunctionArg] {
|
||||||
&self.inputs
|
&self.arguments
|
||||||
}
|
}
|
||||||
|
|
||||||
fn outputs(&self) -> &[IType] {
|
fn outputs(&self) -> &[IType] {
|
||||||
|
@ -15,17 +15,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use super::wit_prelude::*;
|
use super::wit_prelude::*;
|
||||||
use super::{IType, IValue, WValue};
|
use super::{IType, IRecordType, IFunctionArg, IValue, WValue};
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use crate::FCEModuleConfig;
|
use crate::FCEModuleConfig;
|
||||||
|
|
||||||
use fce_wit_interfaces::FCEWITInterfaces;
|
use fce_wit_interfaces::FCEWITInterfaces;
|
||||||
|
use fce_wit_parser::extract_wit;
|
||||||
use wasmer_core::Instance as WasmerInstance;
|
use wasmer_core::Instance as WasmerInstance;
|
||||||
use wasmer_core::import::Namespace;
|
use wasmer_core::import::Namespace;
|
||||||
use wasmer_runtime::compile;
|
use wasmer_runtime::compile;
|
||||||
use wasmer_runtime::ImportObject;
|
use wasmer_runtime::ImportObject;
|
||||||
use wasmer_wit::interpreter::Interpreter;
|
use wasmer_wit::interpreter::Interpreter;
|
||||||
use fce_wit_parser::extract_wit;
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
@ -38,8 +38,8 @@ type WITInterpreter =
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(super) struct WITModuleFunc {
|
pub(super) struct WITModuleFunc {
|
||||||
interpreter: Arc<WITInterpreter>,
|
interpreter: Arc<WITInterpreter>,
|
||||||
pub(super) inputs: Vec<IType>,
|
pub(super) arguments: Vec<IFunctionArg>,
|
||||||
pub(super) outputs: Vec<IType>,
|
pub(super) output_types: Vec<IType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -65,7 +65,7 @@ impl Callable {
|
|||||||
|
|
||||||
pub(crate) struct FCEModule {
|
pub(crate) struct FCEModule {
|
||||||
// wasmer_instance is needed because WITInstance contains dynamic functions
|
// wasmer_instance is needed because WITInstance contains dynamic functions
|
||||||
// that internally keep pointer to Wasmer instance.
|
// that internally keep pointer to it.
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
wasmer_instance: Box<WasmerInstance>,
|
wasmer_instance: Box<WasmerInstance>,
|
||||||
|
|
||||||
@ -80,7 +80,10 @@ pub(crate) struct FCEModule {
|
|||||||
host_import_object: ImportObject,
|
host_import_object: ImportObject,
|
||||||
|
|
||||||
// TODO: replace with dyn Trait
|
// 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 {
|
impl FCEModule {
|
||||||
@ -116,7 +119,8 @@ impl FCEModule {
|
|||||||
std::mem::transmute::<_, Arc<WITInstance>>(wit_instance)
|
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
|
// call _start to populate the WASI state of the module
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
@ -128,12 +132,13 @@ impl FCEModule {
|
|||||||
wasmer_instance: Box::new(wasmer_instance),
|
wasmer_instance: Box::new(wasmer_instance),
|
||||||
import_object,
|
import_object,
|
||||||
host_import_object: config.imports,
|
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>> {
|
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),
|
Some(func) => Arc::make_mut(func).call(args),
|
||||||
None => Err(FCEError::NoSuchFunction(format!(
|
None => Err(FCEError::NoSuchFunction(format!(
|
||||||
"{} hasn't been found while calling",
|
"{} hasn't been found while calling",
|
||||||
@ -144,23 +149,27 @@ impl FCEModule {
|
|||||||
|
|
||||||
pub(crate) fn get_exports_signatures(
|
pub(crate) fn get_exports_signatures(
|
||||||
&self,
|
&self,
|
||||||
) -> impl Iterator<Item = (&String, &Vec<IType>, &Vec<IType>)> {
|
) -> impl Iterator<Item = (&String, &Vec<IFunctionArg>, &Vec<IType>)> {
|
||||||
self.exports_funcs.iter().map(|(func_name, func)| {
|
self.export_funcs.iter().map(|(func_name, func)| {
|
||||||
(
|
(
|
||||||
func_name,
|
func_name,
|
||||||
&func.wit_module_func.inputs,
|
&func.wit_module_func.arguments,
|
||||||
&func.wit_module_func.outputs,
|
&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 {
|
pub(crate) fn get_wasi_state(&mut self) -> &wasmer_wasi::state::WasiState {
|
||||||
unsafe { wasmer_wasi::state::get_wasi_state(self.wasmer_instance.context_mut()) }
|
unsafe { wasmer_wasi::state::get_wasi_state(self.wasmer_instance.context_mut()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: change the cloning Callable behaviour after changes of Wasmer API
|
// TODO: change the cloning Callable behaviour after changes of Wasmer API
|
||||||
pub(super) fn get_callable(&self, function_name: &str) -> Result<Arc<Callable>> {
|
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()),
|
Some(func) => Ok(func.clone()),
|
||||||
None => Err(FCEError::NoSuchFunction(format!(
|
None => Err(FCEError::NoSuchFunction(format!(
|
||||||
"{} hasn't been found while calling",
|
"{} hasn't been found while calling",
|
||||||
@ -170,7 +179,7 @@ impl FCEModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn instantiate_wit_exports(
|
fn instantiate_wit_exports(
|
||||||
wit_instance: Arc<WITInstance>,
|
wit_instance: &Arc<WITInstance>,
|
||||||
wit: &FCEWITInterfaces<'_>,
|
wit: &FCEWITInterfaces<'_>,
|
||||||
) -> Result<HashMap<String, Arc<Callable>>> {
|
) -> Result<HashMap<String, Arc<Callable>>> {
|
||||||
use fce_wit_interfaces::WITAstType;
|
use fce_wit_interfaces::WITAstType;
|
||||||
@ -197,13 +206,14 @@ impl FCEModule {
|
|||||||
|
|
||||||
match wit_type {
|
match wit_type {
|
||||||
WITAstType::Function {
|
WITAstType::Function {
|
||||||
inputs, outputs, ..
|
arguments,
|
||||||
|
output_types,
|
||||||
} => {
|
} => {
|
||||||
let interpreter: WITInterpreter = adapter_instructions.try_into()?;
|
let interpreter: WITInterpreter = adapter_instructions.try_into()?;
|
||||||
let wit_module_func = WITModuleFunc {
|
let wit_module_func = WITModuleFunc {
|
||||||
interpreter: Arc::new(interpreter),
|
interpreter: Arc::new(interpreter),
|
||||||
inputs: inputs.clone(),
|
arguments: arguments.clone(),
|
||||||
outputs: outputs.clone(),
|
output_types: output_types.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
@ -233,9 +243,9 @@ impl FCEModule {
|
|||||||
use wasmer_core::vm::Ctx;
|
use wasmer_core::vm::Ctx;
|
||||||
|
|
||||||
// returns function that will be called from imports of Wasmer module
|
// returns function that will be called from imports of Wasmer module
|
||||||
fn dyn_func_from_raw_import<F>(
|
fn dyn_func_from_raw_import<'a, 'b, F>(
|
||||||
inputs: Vec<IType>,
|
inputs: impl Iterator<Item = &'a IType>,
|
||||||
outputs: Vec<IType>,
|
outputs: impl Iterator<Item = &'b IType>,
|
||||||
raw_import: F,
|
raw_import: F,
|
||||||
) -> DynamicFunc<'static>
|
) -> DynamicFunc<'static>
|
||||||
where
|
where
|
||||||
@ -244,8 +254,8 @@ impl FCEModule {
|
|||||||
use wasmer_core::types::FuncSig;
|
use wasmer_core::types::FuncSig;
|
||||||
use super::type_converters::itype_to_wtype;
|
use super::type_converters::itype_to_wtype;
|
||||||
|
|
||||||
let inputs = inputs.iter().map(itype_to_wtype).collect::<Vec<_>>();
|
let inputs = inputs.map(itype_to_wtype).collect::<Vec<_>>();
|
||||||
let outputs = outputs.iter().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)
|
DynamicFunc::new(Arc::new(FuncSig::new(inputs, outputs)), raw_import)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,7 +267,10 @@ impl FCEModule {
|
|||||||
import_name: String,
|
import_name: String,
|
||||||
) -> impl Fn(&mut Ctx, &[WValue]) -> Vec<WValue> + 'static {
|
) -> impl Fn(&mut Ctx, &[WValue]) -> Vec<WValue> + 'static {
|
||||||
move |_: &mut Ctx, inputs: &[WValue]| -> Vec<WValue> {
|
move |_: &mut Ctx, inputs: &[WValue]| -> Vec<WValue> {
|
||||||
|
use wasmer_wit::interpreter::stack::Stackable;
|
||||||
|
|
||||||
use super::type_converters::wval_to_ival;
|
use super::type_converters::wval_to_ival;
|
||||||
|
use super::type_converters::ival_to_wval;
|
||||||
|
|
||||||
log::trace!(
|
log::trace!(
|
||||||
"raw import for {}.{} called with {:?}\n",
|
"raw import for {}.{} called with {:?}\n",
|
||||||
@ -269,13 +282,13 @@ impl FCEModule {
|
|||||||
// copy here because otherwise wit_instance will be consumed by the closure
|
// copy here because otherwise wit_instance will be consumed by the closure
|
||||||
let wit_instance_callable = wit_instance.clone();
|
let wit_instance_callable = wit_instance.clone();
|
||||||
let wit_inputs = inputs.iter().map(wval_to_ival).collect::<Vec<_>>();
|
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
|
// error here will be propagated by the special error instruction
|
||||||
let _ = interpreter.run(
|
interpreter.run(
|
||||||
&wit_inputs,
|
&wit_inputs,
|
||||||
Arc::make_mut(&mut wit_instance_callable.assume_init()),
|
Arc::make_mut(&mut wit_instance_callable.assume_init()),
|
||||||
);
|
)
|
||||||
}
|
};
|
||||||
|
|
||||||
log::trace!(
|
log::trace!(
|
||||||
"\nraw import for {}.{} finished",
|
"\nraw import for {}.{} finished",
|
||||||
@ -283,9 +296,13 @@ impl FCEModule {
|
|||||||
import_name
|
import_name
|
||||||
);
|
);
|
||||||
|
|
||||||
// wit import functions should only change the stack state -
|
// TODO: optimize by prevent copying stack values
|
||||||
// the result will be returned by an export function
|
outputs
|
||||||
vec![]
|
.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)?;
|
let wit_type = wit.type_by_idx_r(adapter_function_type)?;
|
||||||
|
|
||||||
match wit_type {
|
match wit_type {
|
||||||
WITAstType::Function { inputs, outputs } => {
|
WITAstType::Function {
|
||||||
|
arguments,
|
||||||
|
output_types,
|
||||||
|
} => {
|
||||||
let interpreter: WITInterpreter = adapter_instructions.try_into()?;
|
let interpreter: WITInterpreter = adapter_instructions.try_into()?;
|
||||||
|
|
||||||
let raw_import = create_raw_import(
|
let raw_import = create_raw_import(
|
||||||
@ -318,8 +338,12 @@ impl FCEModule {
|
|||||||
import_namespace.to_string(),
|
import_namespace.to_string(),
|
||||||
import_name.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)))
|
Ok((import_namespace.to_string(), (*import_name, wit_import)))
|
||||||
}
|
}
|
||||||
@ -344,4 +368,57 @@ impl FCEModule {
|
|||||||
|
|
||||||
Ok(import_object)
|
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;
|
mod fce_module;
|
||||||
|
|
||||||
pub use wasmer_wit::types::InterfaceType as IType;
|
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::InterfaceValue as IValue;
|
||||||
pub use wasmer_wit::values::from_interface_values;
|
pub use wasmer_wit::values::from_interface_values;
|
||||||
pub use wasmer_wit::values::to_interface_value;
|
pub use wasmer_wit::values::to_interface_value;
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use super::fce_module::FCEModule;
|
use super::fce_module::FCEModule;
|
||||||
use super::{IType, IValue, WValue};
|
use super::{IType, IFunctionArg, IValue, WValue};
|
||||||
use super::fce_module::Callable;
|
use super::fce_module::Callable;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ use std::sync::Arc;
|
|||||||
enum WITFunctionInner {
|
enum WITFunctionInner {
|
||||||
Export {
|
Export {
|
||||||
func: Arc<DynFunc<'static>>,
|
func: Arc<DynFunc<'static>>,
|
||||||
inputs: Vec<IType>,
|
arguments: Vec<IFunctionArg>,
|
||||||
outputs: Vec<IType>,
|
outputs: Vec<IType>,
|
||||||
},
|
},
|
||||||
Import {
|
Import {
|
||||||
@ -49,10 +49,14 @@ impl WITFunction {
|
|||||||
use super::type_converters::wtype_to_itype;
|
use super::type_converters::wtype_to_itype;
|
||||||
|
|
||||||
let signature = dyn_func.signature();
|
let signature = dyn_func.signature();
|
||||||
let inputs = signature
|
let arguments = signature
|
||||||
.params()
|
.params()
|
||||||
.iter()
|
.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<_>>();
|
.collect::<Vec<_>>();
|
||||||
let outputs = signature
|
let outputs = signature
|
||||||
.returns()
|
.returns()
|
||||||
@ -62,7 +66,7 @@ impl WITFunction {
|
|||||||
|
|
||||||
let inner = WITFunctionInner::Export {
|
let inner = WITFunctionInner::Export {
|
||||||
func: Arc::new(dyn_func),
|
func: Arc::new(dyn_func),
|
||||||
inputs,
|
arguments,
|
||||||
outputs,
|
outputs,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -82,29 +86,31 @@ impl WITFunction {
|
|||||||
impl wasm::structures::LocalImport for WITFunction {
|
impl wasm::structures::LocalImport for WITFunction {
|
||||||
fn inputs_cardinality(&self) -> usize {
|
fn inputs_cardinality(&self) -> usize {
|
||||||
match &self.inner {
|
match &self.inner {
|
||||||
WITFunctionInner::Export { ref inputs, .. } => inputs.len(),
|
WITFunctionInner::Export { arguments, .. } => arguments.len(),
|
||||||
WITFunctionInner::Import { ref callable, .. } => callable.wit_module_func.inputs.len(),
|
WITFunctionInner::Import { callable, .. } => callable.wit_module_func.arguments.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn outputs_cardinality(&self) -> usize {
|
fn outputs_cardinality(&self) -> usize {
|
||||||
match &self.inner {
|
match &self.inner {
|
||||||
WITFunctionInner::Export { ref outputs, .. } => outputs.len(),
|
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 {
|
match &self.inner {
|
||||||
WITFunctionInner::Export { ref inputs, .. } => inputs,
|
WITFunctionInner::Export { ref arguments, .. } => arguments,
|
||||||
WITFunctionInner::Import { ref callable, .. } => &callable.wit_module_func.inputs,
|
WITFunctionInner::Import { ref callable, .. } => &callable.wit_module_func.arguments,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn outputs(&self) -> &[IType] {
|
fn outputs(&self) -> &[IType] {
|
||||||
match &self.inner {
|
match &self.inner {
|
||||||
WITFunctionInner::Export { ref outputs, .. } => outputs,
|
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::wit_prelude::*;
|
||||||
use super::fce_module::FCEModule;
|
use super::fce_module::FCEModule;
|
||||||
|
use super::IRecordType;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
use fce_wit_interfaces::FCEWITInterfaces;
|
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.
|
/// Contains all import and export functions that could be called from WIT context by call-core.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(super) struct WITInstance {
|
pub(super) struct WITInstance {
|
||||||
|
/// WIT functions indexed by id.
|
||||||
funcs: HashMap<usize, WITFunction>,
|
funcs: HashMap<usize, WITFunction>,
|
||||||
|
|
||||||
|
/// WIT memories.
|
||||||
memories: Vec<WITMemory>,
|
memories: Vec<WITMemory>,
|
||||||
record_types: HashMap<u32, WITAstType>,
|
|
||||||
|
record_types_by_id: HashMap<u64, IRecordType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WITInstance {
|
impl WITInstance {
|
||||||
@ -47,12 +52,12 @@ impl WITInstance {
|
|||||||
exports.extend(imports);
|
exports.extend(imports);
|
||||||
let funcs = exports;
|
let funcs = exports;
|
||||||
|
|
||||||
let record_types = Self::extract_record_types(wit);
|
let record_types_by_id = Self::extract_record_types(wit);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
funcs,
|
funcs,
|
||||||
memories,
|
memories,
|
||||||
record_types,
|
record_types_by_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,14 +126,21 @@ impl WITInstance {
|
|||||||
memories
|
memories
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_record_types(wit: &FCEWITInterfaces<'_>) -> HashMap<u32, WITAstType> {
|
fn extract_record_types(wit: &FCEWITInterfaces<'_>) -> HashMap<u64, IRecordType> {
|
||||||
wit.types()
|
let record_types_by_id = wit.types().fold(
|
||||||
.enumerate()
|
(HashMap::new(), 0u64),
|
||||||
.filter_map(|(id, ty)| match ty {
|
|(mut record_types_by_id, id), ty| {
|
||||||
WITAstType::Record(_) => Some((id as u32, ty.clone())),
|
match ty {
|
||||||
_ => None,
|
WITAstType::Record(record_type) => {
|
||||||
})
|
record_types_by_id.insert(id, record_type.clone());
|
||||||
.collect::<HashMap<_, _>>()
|
}
|
||||||
|
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
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn local_or_import<I: TypedIndex + LocalImportIndex>(
|
fn local_or_import<I: TypedIndex + LocalImportIndex>(&self, index: I) -> Option<&WITFunction> {
|
||||||
&mut self,
|
|
||||||
index: I,
|
|
||||||
) -> Option<&WITFunction> {
|
|
||||||
self.funcs.get(&index.index())
|
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> {
|
fn wit_record_by_id(&self, index: u64) -> Option<&IRecordType> {
|
||||||
self.record_types.get(&index)
|
self.record_types_by_id.get(&index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,26 +18,25 @@ use fce::FCE;
|
|||||||
use fce::IValue;
|
use fce::IValue;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
pub fn records() {
|
pub fn records() {
|
||||||
let effector_wasm_bytes = std::fs::read("../examples/records/artifacts/wasm_modules/effector")
|
let effector_wasm_bytes = std::fs::read("../examples/records/artifacts/records_effector.wasm")
|
||||||
.expect("../examples/records/artifacts/wasm_modules/effector.wasm should presence");
|
.expect("../examples/records/artifacts/records_effector.wasm should presence");
|
||||||
|
|
||||||
let pure_wasm_bytes = std::fs::read("../examples/records/artifacts/wasm_modules/pure")
|
let pure_wasm_bytes = std::fs::read("../examples/records/artifacts/records_pure.wasm")
|
||||||
.expect("../examples/records/artifacts/wasm_modules/pure.wasm should presence");
|
.expect("../examples/records/artifacts/records_pure.wasm should presence");
|
||||||
|
|
||||||
let mut fce = FCE::new();
|
let mut fce = FCE::new();
|
||||||
let load_result = fce.load_module("pure", &pure_wasm_bytes, <_>::default());
|
let load_result = fce.load_module("pure", &pure_wasm_bytes, <_>::default());
|
||||||
assert!(load_result.is_err());
|
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));
|
.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));
|
.unwrap_or_else(|e| panic!("can't load a module into FCE: {:?}", e));
|
||||||
|
|
||||||
let result = fce
|
let result = fce
|
||||||
.call("pure", "invoke", &[])
|
.call("records_pure", "invoke", &[])
|
||||||
.unwrap_or_else(|e| panic!("can't invoke pure: {:?}", e));
|
.unwrap_or_else(|e| panic!("can't invoke pure: {:?}", e));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -32,6 +32,7 @@ pub async fn download(url: &str) -> bytes::Bytes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
#[ignore]
|
||||||
async fn redis() {
|
async fn redis() {
|
||||||
let wasm_bytes = download(REDIS_DOWNLOAD_URL).await;
|
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/
|
@ -9,5 +9,5 @@ name = "ipfs_effector"
|
|||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["logger"] }
|
fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["logger"]}
|
||||||
log = "0.4.11"
|
log = "0.4.11"
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
modules_dir = "artifacts/"
|
modules_dir = "artifacts/"
|
||||||
|
|
||||||
[[module]]
|
[[module]]
|
||||||
name = "effector"
|
name = "records_effector"
|
||||||
mem_pages_count = 1
|
mem_pages_count = 1
|
||||||
logger_enabled = true
|
logger_enabled = true
|
||||||
|
|
||||||
[[module]]
|
[[module]]
|
||||||
name = "pure"
|
name = "records_pure"
|
||||||
mem_pages_count = 1
|
mem_pages_count = 1
|
||||||
logger_enabled = true
|
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"
|
edition = "2018"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "effector"
|
name = "records_effector"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fluence = { git = "https://github.com/fluencelabs/rust-sdk" }
|
fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["logger"] }
|
||||||
test-record = { path = "../test-record" }
|
test-record = { path = "../test-record" }
|
@ -20,7 +20,7 @@ use test_record::TestRecord;
|
|||||||
pub fn main() {}
|
pub fn main() {}
|
||||||
|
|
||||||
#[fce]
|
#[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_0 = true;
|
||||||
test_record.field_1 = 1;
|
test_record.field_1 = 1;
|
||||||
test_record.field_2 = 2;
|
test_record.field_2 = 2;
|
||||||
|
@ -5,9 +5,9 @@ authors = ["Fluence Labs"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "pure"
|
name = "records_pure"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fluence = { git = "https://github.com/fluencelabs/rust-sdk" }
|
fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["logger"] }
|
||||||
test-record = { path = "../test-record" }
|
test-record = { path = "../test-record" }
|
||||||
|
@ -41,7 +41,7 @@ pub fn invoke() -> TestRecord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[fce]
|
#[fce]
|
||||||
#[link(wasm_import_module = "effector")]
|
#[link(wasm_import_module = "records_effector")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn mutate_struct(test_record: TestRecord) -> TestRecord;
|
pub fn mutate_struct(test_record: TestRecord) -> TestRecord;
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,4 @@ name = "test_record"
|
|||||||
path = "src/test_record.rs"
|
path = "src/test_record.rs"
|
||||||
|
|
||||||
[dependencies]
|
[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"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[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"
|
anyhow = "1.0.31"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
|
@ -62,10 +62,8 @@ impl AppService {
|
|||||||
arguments: serde_json::Value,
|
arguments: serde_json::Value,
|
||||||
call_parameters: crate::CallParameters,
|
call_parameters: crate::CallParameters,
|
||||||
) -> Result<Vec<IValue>> {
|
) -> Result<Vec<IValue>> {
|
||||||
let arguments = Self::json_to_ivalue(arguments)?;
|
|
||||||
|
|
||||||
self.faas
|
self.faas
|
||||||
.call(module_name, func_name, &arguments, call_parameters)
|
.call_with_json(module_name, func_name, arguments, call_parameters)
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,33 +130,6 @@ impl AppService {
|
|||||||
|
|
||||||
Ok(config)
|
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)
|
// This API is intended for testing purposes (mostly in FCE REPL)
|
||||||
|
@ -8,23 +8,27 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fce = { path = "../engine", version = "0.1.3" }
|
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" }
|
wasmer-runtime = { package = "wasmer-runtime-fl", version = "0.17.0" }
|
||||||
# dynamicfunc-fat-closures allows using state inside DynamicFunc
|
# dynamicfunc-fat-closures allows using state inside DynamicFunc
|
||||||
wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0", features = ["dynamicfunc-fat-closures"] }
|
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-wasi = { package = "wasmer-wasi-fl", version = "0.17.0" }
|
||||||
|
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.5" }
|
||||||
|
|
||||||
toml = "0.5.6"
|
toml = "0.5.6"
|
||||||
serde = { version = "1.0.111", features = ["derive"] }
|
serde = { version = "1.0.111", features = ["derive"] }
|
||||||
serde_json = "1.0.53"
|
serde_json = "1.0.53"
|
||||||
serde_derive = "1.0.111"
|
serde_derive = "1.0.111"
|
||||||
|
itertools = "0.9.0"
|
||||||
cmd_lib = "0.7.8"
|
cmd_lib = "0.7.8"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
safe-transmute = "0.11.0"
|
safe-transmute = "0.11.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[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]
|
[features]
|
||||||
raw-module-api = []
|
raw-module-api = []
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
use fce::FCEError;
|
use fce::FCEError;
|
||||||
|
|
||||||
|
use serde_json::error::Error as SerdeError;
|
||||||
|
|
||||||
use std::io::Error as IOError;
|
use std::io::Error as IOError;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
@ -30,6 +32,18 @@ pub enum FaaSError {
|
|||||||
/// Various errors related to file i/o.
|
/// Various errors related to file i/o.
|
||||||
IOError(String),
|
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.
|
/// FCE errors.
|
||||||
EngineError(FCEError),
|
EngineError(FCEError),
|
||||||
}
|
}
|
||||||
@ -41,6 +55,14 @@ impl std::fmt::Display for FaaSError {
|
|||||||
match self {
|
match self {
|
||||||
FaaSError::ConfigParseError(err_msg) => write!(f, "{}", err_msg),
|
FaaSError::ConfigParseError(err_msg) => write!(f, "{}", err_msg),
|
||||||
FaaSError::InstantiationError(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::IOError(err_msg) => write!(f, "{}", err_msg),
|
||||||
FaaSError::EngineError(err) => write!(f, "{}", err),
|
FaaSError::EngineError(err) => write!(f, "{}", err),
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::misc::ModulesConfig;
|
use crate::misc::ModulesConfig;
|
||||||
|
use crate::misc::ModulesLoadStrategy;
|
||||||
use crate::faas_interface::FaaSFunctionSignature;
|
use crate::faas_interface::FaaSFunctionSignature;
|
||||||
use crate::faas_interface::FaaSInterface;
|
use crate::faas_interface::FaaSInterface;
|
||||||
use crate::FaaSError;
|
use crate::FaaSError;
|
||||||
@ -31,70 +32,10 @@ use std::collections::HashMap;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
// TODO: remove and use mutex instead
|
// TODO: remove and use mutex instead
|
||||||
unsafe impl Send for FluenceFaaS {}
|
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 {
|
pub struct FluenceFaaS {
|
||||||
/// The Fluence Compute Engine instance.
|
/// The Fluence Compute Engine instance.
|
||||||
fce: FCE,
|
fce: FCE,
|
||||||
@ -223,7 +164,7 @@ impl FluenceFaaS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Call a specified function of loaded on a startup module by its name.
|
/// 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,
|
&mut self,
|
||||||
module_name: MN,
|
module_name: MN,
|
||||||
func_name: FN,
|
func_name: FN,
|
||||||
@ -237,8 +178,50 @@ impl FluenceFaaS {
|
|||||||
.map_err(Into::into)
|
.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.
|
/// Return all export functions (name and signatures) of loaded modules.
|
||||||
pub fn get_interface(&self) -> FaaSInterface<'_> {
|
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
|
let modules = self
|
||||||
.fce
|
.fce
|
||||||
.interface()
|
.interface()
|
||||||
@ -249,7 +232,7 @@ impl FluenceFaaS {
|
|||||||
(
|
(
|
||||||
f.name,
|
f.name,
|
||||||
FaaSFunctionSignature {
|
FaaSFunctionSignature {
|
||||||
input_types: f.input_types,
|
arguments: f.arguments,
|
||||||
output_types: f.output_types,
|
output_types: f.output_types,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -259,7 +242,10 @@ impl FluenceFaaS {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
FaaSInterface { modules }
|
FaaSInterface {
|
||||||
|
record_types,
|
||||||
|
modules,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use super::IType;
|
use super::IType;
|
||||||
|
use super::IRecordType;
|
||||||
|
use super::IFunctionArg;
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde::Serializer;
|
use serde::Serializer;
|
||||||
@ -24,27 +26,63 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct FaaSInterface<'a> {
|
pub struct FaaSInterface<'a> {
|
||||||
|
pub record_types: HashMap<u64, &'a IRecordType>,
|
||||||
pub modules: HashMap<&'a str, HashMap<&'a str, FaaSFunctionSignature<'a>>>,
|
pub modules: HashMap<&'a str, HashMap<&'a str, FaaSFunctionSignature<'a>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct FaaSFunctionSignature<'a> {
|
pub struct FaaSFunctionSignature<'a> {
|
||||||
pub input_types: &'a Vec<IType>,
|
pub arguments: &'a Vec<IFunctionArg>,
|
||||||
pub output_types: &'a Vec<IType>,
|
pub output_types: &'a Vec<IType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> fmt::Display for FaaSInterface<'a> {
|
impl<'a> fmt::Display for FaaSInterface<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
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() {
|
for (name, functions) in self.modules.iter() {
|
||||||
writeln!(f, "{}", *name)?;
|
writeln!(f, "{}:", *name)?;
|
||||||
|
|
||||||
for (name, signature) in functions.iter() {
|
for (name, signature) in functions.iter() {
|
||||||
writeln!(
|
write!(f, " pub fn {}(", name)?;
|
||||||
f,
|
|
||||||
" pub fn {}({:?}) -> {:?}",
|
for arg in signature.arguments {
|
||||||
name, signature.input_types, signature.output_types
|
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(())
|
Ok(())
|
||||||
@ -59,10 +97,17 @@ impl<'a> Serialize for FaaSInterface<'a> {
|
|||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct Function<'a> {
|
pub struct Function<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub input_types: &'a Vec<IType>,
|
pub arguments: Vec<(&'a String, &'a IType)>,
|
||||||
pub output_types: &'a Vec<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)]
|
#[derive(Serialize)]
|
||||||
pub struct Module<'a> {
|
pub struct Module<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
@ -71,9 +116,27 @@ impl<'a> Serialize for FaaSInterface<'a> {
|
|||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct Interface<'a> {
|
pub struct Interface<'a> {
|
||||||
|
pub record_types: Vec<RecordType<'a>>,
|
||||||
pub modules: Vec<Module<'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
|
let modules: Vec<_> = self
|
||||||
.modules
|
.modules
|
||||||
.iter()
|
.iter()
|
||||||
@ -84,13 +147,15 @@ impl<'a> Serialize for FaaSInterface<'a> {
|
|||||||
|(
|
|(
|
||||||
name,
|
name,
|
||||||
FaaSFunctionSignature {
|
FaaSFunctionSignature {
|
||||||
input_types,
|
arguments,
|
||||||
output_types,
|
output_types,
|
||||||
},
|
},
|
||||||
)| {
|
)| {
|
||||||
|
let arguments =
|
||||||
|
arguments.iter().map(|arg| (&arg.name, &arg.ty)).collect();
|
||||||
Function {
|
Function {
|
||||||
name,
|
name,
|
||||||
input_types,
|
arguments,
|
||||||
output_types,
|
output_types,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -100,6 +165,10 @@ impl<'a> Serialize for FaaSInterface<'a> {
|
|||||||
})
|
})
|
||||||
.collect();
|
.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 errors::FaaSError;
|
||||||
|
|
||||||
pub use fce::IValue;
|
pub use fce::IValue;
|
||||||
|
pub use fce::IRecordType;
|
||||||
|
pub use fce::IFunctionArg;
|
||||||
pub use fce::IType;
|
pub use fce::IType;
|
||||||
pub use fce::to_interface_value;
|
pub use fce::to_interface_value;
|
||||||
pub use fce::from_interface_values;
|
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;
|
* Copyright 2020 Fluence Labs Limited
|
||||||
mod config;
|
*
|
||||||
|
* 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;
|
mod config;
|
||||||
pub(crate) use config::load_config;
|
mod imports;
|
||||||
|
mod json_to_ivalues;
|
||||||
|
mod modules_load_strategy;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
pub use config::RawModulesConfig;
|
pub use config::RawModulesConfig;
|
||||||
pub use config::RawModuleConfig;
|
pub use config::RawModuleConfig;
|
||||||
pub use config::ModulesConfig;
|
pub use config::ModulesConfig;
|
||||||
pub use config::ModuleConfig;
|
pub use config::ModuleConfig;
|
||||||
pub use config::WASIConfig;
|
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 application_id = "0x31337";
|
||||||
|
|
||||||
let result = faas
|
let result = faas
|
||||||
.call(
|
.call_with_ivalues(
|
||||||
"call_parameters",
|
"call_parameters",
|
||||||
"call_parameters",
|
"call_parameters",
|
||||||
&[],
|
&[],
|
||||||
|
@ -32,7 +32,7 @@ pub fn greeting() {
|
|||||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||||
|
|
||||||
let result1 = faas
|
let result1 = faas
|
||||||
.call(
|
.call_with_ivalues(
|
||||||
"greeting",
|
"greeting",
|
||||||
"greeting",
|
"greeting",
|
||||||
&[IValue::String(String::from("Fluence"))],
|
&[IValue::String(String::from("Fluence"))],
|
||||||
@ -41,7 +41,7 @@ pub fn greeting() {
|
|||||||
.unwrap_or_else(|e| panic!("can't invoke greeting: {:?}", e));
|
.unwrap_or_else(|e| panic!("can't invoke greeting: {:?}", e));
|
||||||
|
|
||||||
let result2 = faas
|
let result2 = faas
|
||||||
.call(
|
.call_with_ivalues(
|
||||||
"greeting",
|
"greeting",
|
||||||
"greeting",
|
"greeting",
|
||||||
&[IValue::String(String::from(""))],
|
&[IValue::String(String::from(""))],
|
||||||
@ -69,10 +69,15 @@ pub fn get_interfaces() {
|
|||||||
|
|
||||||
let interface = faas.get_interface();
|
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 {
|
let greeting_sign = fluence_faas::FaaSFunctionSignature {
|
||||||
input_types: &string_type_params,
|
arguments: &arguments,
|
||||||
output_types: &string_type_params,
|
output_types: &output_types,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut functions = std::collections::HashMap::new();
|
let mut functions = std::collections::HashMap::new();
|
||||||
@ -81,5 +86,11 @@ pub fn get_interfaces() {
|
|||||||
let mut modules = std::collections::HashMap::new();
|
let mut modules = std::collections::HashMap::new();
|
||||||
modules.insert("greeting", functions);
|
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::FluenceFaaS;
|
||||||
use fluence_faas::IValue;
|
use fluence_faas::IValue;
|
||||||
|
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
pub fn records() {
|
pub fn records() {
|
||||||
let records_config_path = "../examples/records/Config.toml";
|
let records_config_path = "../examples/records/Config.toml";
|
||||||
|
|
||||||
@ -27,17 +28,176 @@ pub fn records() {
|
|||||||
|
|
||||||
let mut records_config: fluence_faas::RawModulesConfig =
|
let mut records_config: fluence_faas::RawModulesConfig =
|
||||||
toml::from_slice(&records_config_raw).expect("records config should be well-formed");
|
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)
|
let mut faas = FluenceFaaS::with_raw_config(records_config)
|
||||||
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {:?}", e));
|
||||||
|
|
||||||
let result = faas
|
let result1 = faas
|
||||||
.call("pure", "invoke", &[], <_>::default())
|
.call_with_ivalues("records_pure", "invoke", &[], <_>::default())
|
||||||
.unwrap_or_else(|e| panic!("can't invoke pure: {:?}", e));
|
.unwrap_or_else(|e| panic!("can't invoke pure: {:?}", e));
|
||||||
|
|
||||||
assert_eq!(
|
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(
|
vec![IValue::Record(
|
||||||
wasmer_wit::vec1::Vec1::new(vec![
|
wasmer_wit::vec1::Vec1::new(vec![
|
||||||
IValue::I32(1),
|
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") => {
|
Some("interface") => {
|
||||||
let interface = self.app_service.get_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 => {
|
Some("h") | Some("help") | None => {
|
||||||
println!(
|
println!(
|
||||||
|
Reference in New Issue
Block a user