mirror of
https://github.com/fluencelabs/marine.git
synced 2024-12-12 06:45:32 +00:00
Print Aqua-compatible types (#86)
This commit is contained in:
parent
c51b5982d6
commit
c62a278897
171
Cargo.lock
generated
171
Cargo.lock
generated
@ -2,6 +2,16 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "Inflector"
|
||||
version = "0.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.15.1"
|
||||
@ -713,6 +723,8 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "fluence-app-service"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba3b1d2c199d6bc140c9ec5ffa323ebd34ac134fb37828bbfd7aeed0339cab78"
|
||||
dependencies = [
|
||||
"fluence-faas 0.7.2",
|
||||
"log",
|
||||
@ -726,11 +738,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "fluence-app-service"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba3b1d2c199d6bc140c9ec5ffa323ebd34ac134fb37828bbfd7aeed0339cab78"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"fluence-faas 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fluence-faas 0.7.3",
|
||||
"log",
|
||||
"maplit",
|
||||
"serde",
|
||||
@ -740,32 +750,6 @@ dependencies = [
|
||||
"wasmer-wasi-fl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluence-faas"
|
||||
version = "0.7.2"
|
||||
dependencies = [
|
||||
"cmd_lib",
|
||||
"env_logger 0.7.1",
|
||||
"fluence",
|
||||
"fluence-sdk-main",
|
||||
"itertools 0.9.0",
|
||||
"log",
|
||||
"marine-runtime 0.5.0",
|
||||
"marine-utils 0.2.0",
|
||||
"once_cell",
|
||||
"pretty_assertions",
|
||||
"safe-transmute",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"toml",
|
||||
"wasmer-interface-types-fl",
|
||||
"wasmer-runtime-core-fl",
|
||||
"wasmer-runtime-fl",
|
||||
"wasmer-wasi-fl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluence-faas"
|
||||
version = "0.7.2"
|
||||
@ -791,6 +775,33 @@ dependencies = [
|
||||
"wasmer-wasi-fl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluence-faas"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"cmd_lib",
|
||||
"env_logger 0.7.1",
|
||||
"fluence",
|
||||
"fluence-sdk-main",
|
||||
"itertools 0.9.0",
|
||||
"log",
|
||||
"marine-module-interface",
|
||||
"marine-runtime 0.5.0",
|
||||
"marine-utils 0.2.0",
|
||||
"once_cell",
|
||||
"pretty_assertions",
|
||||
"safe-transmute",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"toml",
|
||||
"wasmer-interface-types-fl",
|
||||
"wasmer-runtime-core-fl",
|
||||
"wasmer-runtime-fl",
|
||||
"wasmer-wasi-fl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluence-it-types"
|
||||
version = "0.3.0"
|
||||
@ -830,11 +841,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "fluence-test"
|
||||
version = "0.1.7"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7be0d7928e5e6a74a8e303b7f539116fdb4043f5788f78e9eaf32c53700c4c18"
|
||||
checksum = "886ac15e0e95754d5d9339b541a5119dc47cc1a8d80101dc4e3e238d06a4b28b"
|
||||
dependencies = [
|
||||
"fluence-app-service 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fluence-app-service 0.7.2",
|
||||
"marine-test-macro",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -994,9 +1005,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
|
||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
@ -1064,8 +1075,8 @@ dependencies = [
|
||||
"http",
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio 1.5.0",
|
||||
"tokio-util 0.6.6",
|
||||
"tokio 1.6.0",
|
||||
"tokio-util 0.6.7",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@ -1200,7 +1211,7 @@ dependencies = [
|
||||
"itoa",
|
||||
"pin-project",
|
||||
"socket2 0.4.0",
|
||||
"tokio 1.5.0",
|
||||
"tokio 1.6.0",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"want",
|
||||
@ -1228,7 +1239,7 @@ dependencies = [
|
||||
"bytes 1.0.1",
|
||||
"hyper 0.14.7",
|
||||
"native-tls",
|
||||
"tokio 1.5.0",
|
||||
"tokio 1.6.0",
|
||||
"tokio-native-tls",
|
||||
]
|
||||
|
||||
@ -1446,14 +1457,15 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||
|
||||
[[package]]
|
||||
name = "marine"
|
||||
version = "0.6.1"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"anyhow",
|
||||
"check-latest",
|
||||
"clap",
|
||||
"exitfailure",
|
||||
"marine-it-generator 0.5.1",
|
||||
"marine-it-parser 0.6.0",
|
||||
"marine-it-generator 0.5.2",
|
||||
"marine-it-parser 0.6.1",
|
||||
"marine-module-info-parser 0.1.0",
|
||||
"semver 0.11.0",
|
||||
"serde",
|
||||
@ -1483,11 +1495,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "marine-it-generator"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
dependencies = [
|
||||
"cargo_toml",
|
||||
"it-lilo",
|
||||
"marine-it-parser 0.6.0",
|
||||
"marine-it-parser 0.6.1",
|
||||
"marine-macro-impl",
|
||||
"once_cell",
|
||||
"serde",
|
||||
@ -1534,10 +1546,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "marine-it-parser"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.10.0",
|
||||
"marine-it-interfaces 0.4.0",
|
||||
"marine-module-interface",
|
||||
"nom",
|
||||
"semver 0.11.0",
|
||||
"serde",
|
||||
@ -1600,6 +1614,22 @@ dependencies = [
|
||||
"wasmer-runtime-core-fl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "marine-module-interface"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.10.0",
|
||||
"marine-it-interfaces 0.4.0",
|
||||
"nom",
|
||||
"semver 0.11.0",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"walrus",
|
||||
"wasmer-interface-types-fl",
|
||||
"wasmer-runtime-core-fl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "marine-runtime"
|
||||
version = "0.5.0"
|
||||
@ -1609,10 +1639,11 @@ dependencies = [
|
||||
"bytes 0.5.6",
|
||||
"it-lilo",
|
||||
"log",
|
||||
"marine-it-generator 0.5.1",
|
||||
"marine-it-generator 0.5.2",
|
||||
"marine-it-interfaces 0.4.0",
|
||||
"marine-it-parser 0.6.0",
|
||||
"marine-it-parser 0.6.1",
|
||||
"marine-module-info-parser 0.1.0",
|
||||
"marine-module-interface",
|
||||
"marine-utils 0.2.0",
|
||||
"multimap",
|
||||
"once_cell",
|
||||
@ -1670,9 +1701,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "marine-test-macro"
|
||||
version = "0.1.6"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "709eebc4ee6c8e6aa49066ab066c9f137d9cf164f298f578a67bfb11a0508f65"
|
||||
checksum = "089a1d98ebee2fa24928e23019b477222562beda663f8625d3d490dce290e532"
|
||||
dependencies = [
|
||||
"marine-test-macro-impl",
|
||||
"proc-macro-error",
|
||||
@ -1683,12 +1714,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "marine-test-macro-impl"
|
||||
version = "0.1.5"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2432fd5233a088981c79324668b76f3ee2ae6d313d4522b5490226e5e7827ce"
|
||||
checksum = "b6e79cfbde74677cbeb60fe5944c345617739aae37dc5ac5ef5f12d487472071"
|
||||
dependencies = [
|
||||
"darling 0.12.4",
|
||||
"fluence-app-service 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fluence-app-service 0.7.2",
|
||||
"marine-it-parser 0.5.0",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
@ -1829,13 +1860,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mrepl"
|
||||
version = "0.7.2"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"check-latest",
|
||||
"clap",
|
||||
"env_logger 0.7.1",
|
||||
"fluence-app-service 0.7.2",
|
||||
"fluence-app-service 0.7.3",
|
||||
"fluence-sdk-main",
|
||||
"itertools 0.9.0",
|
||||
"log",
|
||||
@ -2181,9 +2212,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.26"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
|
||||
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
@ -2242,7 +2273,7 @@ version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
|
||||
dependencies = [
|
||||
"getrandom 0.2.2",
|
||||
"getrandom 0.2.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2267,9 +2298,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
|
||||
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"crossbeam-deque",
|
||||
@ -2279,9 +2310,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.9.0"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
|
||||
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
@ -2355,7 +2386,7 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
|
||||
dependencies = [
|
||||
"getrandom 0.2.2",
|
||||
"getrandom 0.2.3",
|
||||
"redox_syscall 0.2.8",
|
||||
]
|
||||
|
||||
@ -2446,7 +2477,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio 1.5.0",
|
||||
"tokio 1.6.0",
|
||||
"tokio-native-tls",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
@ -2934,9 +2965,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.5.0"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83f0c8e7c0addab50b663055baf787d0af7f413a46e6e7fb9559a4e4db7137a5"
|
||||
checksum = "bd3076b5c8cc18138b8f8814895c11eb4de37114a5d127bafdc5e55798ceef37"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes 1.0.1",
|
||||
@ -2965,7 +2996,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
|
||||
dependencies = [
|
||||
"native-tls",
|
||||
"tokio 1.5.0",
|
||||
"tokio 1.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2994,16 +3025,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.6.6"
|
||||
version = "0.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "940a12c99365c31ea8dd9ba04ec1be183ffe4920102bb7122c2f515437601e8e"
|
||||
checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592"
|
||||
dependencies = [
|
||||
"bytes 1.0.1",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"log",
|
||||
"pin-project-lite 0.2.6",
|
||||
"tokio 1.5.0",
|
||||
"tokio 1.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3183,7 +3214,7 @@ version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||
dependencies = [
|
||||
"getrandom 0.2.2",
|
||||
"getrandom 0.2.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4,6 +4,7 @@ members = [
|
||||
"crates/it-interfaces",
|
||||
"crates/it-parser",
|
||||
"crates/module-info-parser",
|
||||
"crates/module-interface",
|
||||
"crates/utils",
|
||||
"examples/call_parameters",
|
||||
"examples/greeting",
|
||||
|
@ -148,7 +148,7 @@ fn generate_it_instructions<'f>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn generate_raw_args<'f>(signature: &FnSignature) -> Rc<Vec<IFunctionArg>> {
|
||||
pub(crate) fn generate_raw_args(signature: &FnSignature) -> Rc<Vec<IFunctionArg>> {
|
||||
let raw_inputs = signature
|
||||
.arguments
|
||||
.iter()
|
||||
@ -159,7 +159,7 @@ pub(crate) fn generate_raw_args<'f>(signature: &FnSignature) -> Rc<Vec<IFunction
|
||||
Rc::new(raw_inputs)
|
||||
}
|
||||
|
||||
pub(crate) fn generate_raw_output_type<'f>(signature: &FnSignature) -> Rc<Vec<IType>> {
|
||||
pub(crate) fn generate_raw_output_type(signature: &FnSignature) -> Rc<Vec<IType>> {
|
||||
let raw_outputs = signature
|
||||
.output_types
|
||||
.iter()
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "marine-it-parser"
|
||||
description = "Fluence Marine interface types parser"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
authors = ["Fluence Labs"]
|
||||
license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
@ -12,6 +12,7 @@ path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
marine-it-interfaces = { path = "../it-interfaces", version = "0.4.0" }
|
||||
marine-module-interface = { path = "../module-interface", version = "0.1.0" }
|
||||
|
||||
anyhow = "1.0.31"
|
||||
walrus = "0.18.0"
|
||||
@ -19,6 +20,7 @@ wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0"}
|
||||
wasmer-it = { package = "wasmer-interface-types-fl", version = "0.20.0" }
|
||||
nom = "5.1"
|
||||
|
||||
itertools = "0.10.0"
|
||||
semver = "0.11.0"
|
||||
serde = "=1.0.118"
|
||||
thiserror = "1.0.24"
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use super::custom::ITCustomSection;
|
||||
use super::errors::ITParserError;
|
||||
use crate::Result;
|
||||
use crate::ParserResult;
|
||||
|
||||
use walrus::ModuleConfig;
|
||||
use wasmer_it::{
|
||||
@ -28,7 +28,7 @@ use wasmer_it::ToBytes;
|
||||
use std::path::Path;
|
||||
|
||||
/// Embed provided IT to a Wasm file by path.
|
||||
pub fn embed_text_it<I, O>(in_wasm_path: I, out_wasm_path: O, it: &str) -> Result<()>
|
||||
pub fn embed_text_it<I, O>(in_wasm_path: I, out_wasm_path: O, it: &str) -> ParserResult<()>
|
||||
where
|
||||
I: AsRef<Path>,
|
||||
O: AsRef<Path>,
|
||||
|
@ -14,6 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use marine_module_interface::interface::InterfaceError;
|
||||
use marine_module_interface::it_interface::ITInterfaceError;
|
||||
|
||||
use wasmer_it::decoders::wat::Error as WATError;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
@ -45,6 +48,14 @@ pub enum ITParserError {
|
||||
#[error("{0}")]
|
||||
IncorrectITFormat(String),
|
||||
|
||||
/// An error occurred while processing module interface.
|
||||
#[error("{0}")]
|
||||
ModuleInterfaceError(#[from] InterfaceError),
|
||||
|
||||
/// An error occurred while processing module IT interface.
|
||||
#[error("{0}")]
|
||||
ModuleITInterfaceError(#[from] ITInterfaceError),
|
||||
|
||||
/// An error occurred while parsing file in Wat format.
|
||||
#[error("provided file with IT definitions is corrupted: {0}")]
|
||||
CorruptedITFile(#[from] WATError),
|
||||
|
@ -14,38 +14,41 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
mod functions;
|
||||
mod it;
|
||||
|
||||
pub use functions::*;
|
||||
pub use it::*;
|
||||
|
||||
use crate::Result;
|
||||
use crate::interface::ModuleInterface;
|
||||
use crate::it_interface::IModuleInterface;
|
||||
use crate::ParserResult;
|
||||
use crate::ITParserError;
|
||||
|
||||
use marine_module_interface::it_interface;
|
||||
use marine_module_interface::interface;
|
||||
use marine_it_interfaces::MITInterfaces;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn module_interface<P>(module_path: P) -> Result<ServiceInterface>
|
||||
pub fn module_interface<P>(module_path: P) -> ParserResult<ModuleInterface>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
create_mit_with(module_path, |it| get_interface(&it))
|
||||
create_mit_with(module_path, |it| interface::get_interface(&it))
|
||||
}
|
||||
|
||||
pub fn module_raw_interface<P>(module_path: P) -> Result<MModuleInterface>
|
||||
pub fn module_it_interface<P>(module_path: P) -> ParserResult<IModuleInterface>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
create_mit_with(module_path, |it| get_raw_interface(&it))
|
||||
create_mit_with(module_path, |it| it_interface::get_interface(&it))
|
||||
}
|
||||
|
||||
fn create_mit_with<P, T>(
|
||||
fn create_mit_with<P, T, E>(
|
||||
module_path: P,
|
||||
transformer: impl FnOnce(MITInterfaces<'_>) -> Result<T>,
|
||||
) -> Result<T>
|
||||
transformer: impl FnOnce(MITInterfaces<'_>) -> std::result::Result<T, E>,
|
||||
) -> ParserResult<T>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
ITParserError: From<E>,
|
||||
{
|
||||
let module = walrus::ModuleConfig::new()
|
||||
.parse_file(module_path)
|
||||
@ -56,5 +59,5 @@ where
|
||||
|
||||
let mit = MITInterfaces::new(it);
|
||||
|
||||
transformer(mit)
|
||||
transformer(mit).map_err(Into::into)
|
||||
}
|
||||
|
@ -1,213 +0,0 @@
|
||||
/*
|
||||
* 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::Result;
|
||||
use crate::ITParserError;
|
||||
use marine_it_interfaces::MITInterfaces;
|
||||
|
||||
use wasmer_it::IRecordType;
|
||||
use wasmer_it::ast::FunctionArg as IFunctionArg;
|
||||
use wasmer_it::IType;
|
||||
use serde::Serialize;
|
||||
use serde::Deserialize;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type MRecordTypes = HashMap<u64, Rc<IRecordType>>;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub struct MFunctionSignature {
|
||||
pub name: Rc<String>,
|
||||
pub arguments: Rc<Vec<IFunctionArg>>,
|
||||
pub outputs: Rc<Vec<IType>>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Serialize)]
|
||||
pub struct MModuleInterface {
|
||||
pub record_types: MRecordTypes,
|
||||
pub function_signatures: Vec<MFunctionSignature>,
|
||||
}
|
||||
|
||||
pub fn get_interface(mit: &MITInterfaces<'_>) -> Result<ServiceInterface> {
|
||||
let marine_interface = get_raw_interface(mit)?;
|
||||
let service_interface = into_service_interface(marine_interface);
|
||||
|
||||
Ok(service_interface)
|
||||
}
|
||||
|
||||
pub fn get_raw_interface(mit: &MITInterfaces<'_>) -> Result<MModuleInterface> {
|
||||
let function_signatures = get_exports(mit)?;
|
||||
let record_types = extract_record_types(mit);
|
||||
|
||||
let mm_interface = MModuleInterface {
|
||||
record_types,
|
||||
function_signatures,
|
||||
};
|
||||
|
||||
Ok(mm_interface)
|
||||
}
|
||||
|
||||
fn get_exports(it: &MITInterfaces<'_>) -> Result<Vec<MFunctionSignature>> {
|
||||
use marine_it_interfaces::ITAstType;
|
||||
|
||||
it.implementations()
|
||||
.filter_map(|(adapter_function_type, core_function_type)| {
|
||||
it.exports_by_type(*core_function_type)
|
||||
.map(|export_function_name| (adapter_function_type, export_function_name))
|
||||
})
|
||||
.map(|(adapter_function_type, export_function_names)| {
|
||||
export_function_names
|
||||
.iter()
|
||||
.map(move |export_function_name| (*adapter_function_type, export_function_name))
|
||||
})
|
||||
.flatten()
|
||||
.map(|(adapter_function_type, export_function_name)| {
|
||||
let it_type = it.type_by_idx_r(adapter_function_type).unwrap();
|
||||
|
||||
match it_type {
|
||||
ITAstType::Function {
|
||||
arguments,
|
||||
output_types,
|
||||
} => {
|
||||
let signature = MFunctionSignature {
|
||||
name: Rc::new(export_function_name.to_string()),
|
||||
arguments: arguments.clone(),
|
||||
outputs: output_types.clone(),
|
||||
};
|
||||
Ok(signature)
|
||||
}
|
||||
_ => Err(ITParserError::IncorrectITFormat(format!(
|
||||
"type with idx = {} isn't a function type",
|
||||
adapter_function_type
|
||||
))),
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<MFunctionSignature>>>()
|
||||
}
|
||||
|
||||
fn extract_record_types(it: &MITInterfaces<'_>) -> MRecordTypes {
|
||||
use marine_it_interfaces::ITAstType;
|
||||
|
||||
let (record_types_by_id, _) = it.types().fold(
|
||||
(HashMap::new(), 0u64),
|
||||
|(mut record_types_by_id, id), ty| {
|
||||
match ty {
|
||||
ITAstType::Record(record_type) => {
|
||||
record_types_by_id.insert(id, record_type.clone());
|
||||
}
|
||||
ITAstType::Function { .. } => {}
|
||||
};
|
||||
(record_types_by_id, id + 1)
|
||||
},
|
||||
);
|
||||
|
||||
record_types_by_id
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct FunctionSignature {
|
||||
pub name: String,
|
||||
pub arguments: Vec<(String, String)>,
|
||||
pub output_types: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct RecordType {
|
||||
pub name: String,
|
||||
pub id: u64,
|
||||
pub fields: Vec<(String, String)>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct ServiceInterface {
|
||||
pub function_signatures: Vec<FunctionSignature>,
|
||||
pub record_types: Vec<RecordType>,
|
||||
}
|
||||
|
||||
pub(crate) fn into_service_interface(mm_interface: MModuleInterface) -> ServiceInterface {
|
||||
let record_types = mm_interface.record_types;
|
||||
|
||||
let function_signatures = mm_interface
|
||||
.function_signatures
|
||||
.into_iter()
|
||||
.map(|sign| serialize_function_signature(sign, &record_types))
|
||||
.collect();
|
||||
|
||||
let record_types = record_types
|
||||
.iter()
|
||||
.map(|(id, record)| serialize_record_type(*id, record.clone(), &record_types))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
ServiceInterface {
|
||||
function_signatures,
|
||||
record_types,
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_function_signature(
|
||||
signature: MFunctionSignature,
|
||||
record_types: &MRecordTypes,
|
||||
) -> FunctionSignature {
|
||||
let arguments = signature
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|arg| (arg.name.clone(), itype_text_view(&arg.ty, record_types)))
|
||||
.collect();
|
||||
|
||||
let output_types = signature
|
||||
.outputs
|
||||
.iter()
|
||||
.map(|itype| itype_text_view(itype, record_types))
|
||||
.collect();
|
||||
|
||||
FunctionSignature {
|
||||
name: signature.name.to_string(),
|
||||
arguments,
|
||||
output_types,
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_record_type(
|
||||
id: u64,
|
||||
record: Rc<IRecordType>,
|
||||
record_types: &MRecordTypes,
|
||||
) -> RecordType {
|
||||
let fields = record
|
||||
.fields
|
||||
.iter()
|
||||
.map(|field| (field.name.clone(), itype_text_view(&field.ty, record_types)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
RecordType {
|
||||
name: record.name.clone(),
|
||||
id,
|
||||
fields,
|
||||
}
|
||||
}
|
||||
|
||||
fn itype_text_view(arg_ty: &IType, record_types: &MRecordTypes) -> String {
|
||||
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 = record_types.get(record_type_id).unwrap();
|
||||
record.name.clone()
|
||||
}
|
||||
IType::Array(array_ty) => format!("Array<{}>", itype_text_view(array_ty, record_types)),
|
||||
t => format!("{:?}", t),
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
|
||||
use crate::custom::IT_SECTION_NAME;
|
||||
use crate::errors::ITParserError;
|
||||
use crate::Result;
|
||||
use crate::ParserResult;
|
||||
|
||||
use walrus::IdsToIndices;
|
||||
use wasmer_it::ast::Interfaces;
|
||||
@ -26,7 +26,7 @@ use std::borrow::Cow;
|
||||
use std::path::Path;
|
||||
|
||||
/// Extracts IT section of provided Wasm binary and converts it to a string.
|
||||
pub fn extract_text_it<P>(wasm_file_path: P) -> Result<String>
|
||||
pub fn extract_text_it<P>(wasm_file_path: P) -> ParserResult<String>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
@ -42,7 +42,7 @@ where
|
||||
}
|
||||
|
||||
/// Extracts IT section of provided Wasm binary and converts it to a MITInterfaces.
|
||||
pub fn extract_it_from_module(wasmer_module: &WasmerModule) -> Result<Interfaces<'_>> {
|
||||
pub fn extract_it_from_module(wasmer_module: &WasmerModule) -> ParserResult<Interfaces<'_>> {
|
||||
let wit_sections = wasmer_module
|
||||
.custom_sections(IT_SECTION_NAME)
|
||||
.ok_or(ITParserError::NoITSection)?;
|
||||
@ -54,7 +54,7 @@ pub fn extract_it_from_module(wasmer_module: &WasmerModule) -> Result<Interfaces
|
||||
extract_it_from_bytes(&wit_sections[0])
|
||||
}
|
||||
|
||||
pub fn extract_version_from_module(module: &walrus::Module) -> Result<semver::Version> {
|
||||
pub fn extract_version_from_module(module: &walrus::Module) -> ParserResult<semver::Version> {
|
||||
let raw_custom_section = extract_custom_section(&module)?;
|
||||
let wit_section_bytes = raw_custom_section.as_ref();
|
||||
let it = extract_it_from_bytes(wit_section_bytes)?;
|
||||
@ -62,7 +62,7 @@ pub fn extract_version_from_module(module: &walrus::Module) -> Result<semver::Ve
|
||||
Ok(it.version)
|
||||
}
|
||||
|
||||
pub(crate) fn extract_it_from_bytes(wit_section_bytes: &[u8]) -> Result<Interfaces<'_>> {
|
||||
pub(crate) fn extract_it_from_bytes(wit_section_bytes: &[u8]) -> ParserResult<Interfaces<'_>> {
|
||||
match wasmer_it::decoders::binary::parse::<(&[u8], nom::error::ErrorKind)>(wit_section_bytes) {
|
||||
Ok((remainder, it)) if remainder.is_empty() => Ok(it),
|
||||
Ok(_) => Err(ITParserError::ITRemainderNotEmpty),
|
||||
@ -70,7 +70,7 @@ pub(crate) fn extract_it_from_bytes(wit_section_bytes: &[u8]) -> Result<Interfac
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn extract_custom_section(module: &walrus::Module) -> Result<Cow<'_, [u8]>> {
|
||||
pub(crate) fn extract_custom_section(module: &walrus::Module) -> ParserResult<Cow<'_, [u8]>> {
|
||||
let sections = module
|
||||
.customs
|
||||
.iter()
|
||||
|
@ -42,16 +42,20 @@ pub use extractor::extract_it_from_module;
|
||||
pub use extractor::extract_version_from_module;
|
||||
pub use extractor::extract_text_it;
|
||||
pub use extractor::module_interface;
|
||||
pub use extractor::module_raw_interface;
|
||||
pub use extractor::module_it_interface;
|
||||
|
||||
pub mod interface {
|
||||
pub use crate::extractor::ServiceInterface;
|
||||
pub use crate::extractor::RecordType;
|
||||
pub use crate::extractor::FunctionSignature;
|
||||
pub use marine_module_interface::interface::ModuleInterface;
|
||||
pub use marine_module_interface::interface::RecordType;
|
||||
pub use marine_module_interface::interface::RecordField;
|
||||
pub use marine_module_interface::interface::FunctionSignature;
|
||||
}
|
||||
|
||||
pub mod it_interface {
|
||||
pub use marine_module_interface::it_interface::IModuleInterface;
|
||||
pub use marine_module_interface::it_interface::IRecordTypes;
|
||||
pub use marine_module_interface::it_interface::IFunctionSignature;
|
||||
|
||||
pub use crate::extractor::MModuleInterface;
|
||||
pub use crate::extractor::MRecordTypes;
|
||||
pub use crate::extractor::MFunctionSignature;
|
||||
pub mod it {
|
||||
pub use wasmer_it::IType;
|
||||
pub use wasmer_it::ast::FunctionArg as IFunctionArg;
|
||||
@ -60,4 +64,4 @@ pub mod interface {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type Result<T> = std::result::Result<T, ITParserError>;
|
||||
pub(crate) type ParserResult<T> = std::result::Result<T, ITParserError>;
|
||||
|
26
crates/module-interface/Cargo.toml
Normal file
26
crates/module-interface/Cargo.toml
Normal file
@ -0,0 +1,26 @@
|
||||
[package]
|
||||
name = "marine-module-interface"
|
||||
description = "Fluence Marine module interface"
|
||||
version = "0.1.0"
|
||||
authors = ["Fluence Labs"]
|
||||
license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "marine_module_interface"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
marine-it-interfaces = { path = "../it-interfaces", version = "0.4.0" }
|
||||
#marine-it-generator = { path = "../it-generator", verision = "0.5.2"}
|
||||
|
||||
anyhow = "1.0.31"
|
||||
walrus = "0.18.0"
|
||||
wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0"}
|
||||
wasmer-it = { package = "wasmer-interface-types-fl", version = "0.20.0" }
|
||||
nom = "5.1"
|
||||
|
||||
itertools = "0.10.0"
|
||||
semver = "0.11.0"
|
||||
serde = "=1.0.118"
|
||||
thiserror = "1.0.24"
|
27
crates/module-interface/src/interface/errors.rs
Normal file
27
crates/module-interface/src/interface/errors.rs
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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::it_interface::ITInterfaceError;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum InterfaceError {
|
||||
#[error("record type with type id {0} not found")]
|
||||
NotFoundRecordTypeId(u64),
|
||||
|
||||
#[error("{0}")]
|
||||
ITInterfaceError(#[from] ITInterfaceError),
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2021 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 super::ModuleInterface;
|
||||
use super::InterfaceResult;
|
||||
use super::FunctionSignature;
|
||||
use super::records_transformer::RecordsTransformer;
|
||||
use crate::it_interface::IModuleInterface;
|
||||
use crate::it_interface::IFunctionSignature;
|
||||
use crate::it_interface::IRecordTypes;
|
||||
|
||||
pub fn it_to_module_interface(mm_interface: IModuleInterface) -> InterfaceResult<ModuleInterface> {
|
||||
let record_types = mm_interface.export_record_types;
|
||||
|
||||
let function_signatures = mm_interface
|
||||
.function_signatures
|
||||
.into_iter()
|
||||
.map(|sign| serialize_function_signature(sign, &record_types))
|
||||
.collect();
|
||||
|
||||
let record_types = RecordsTransformer::transform(&record_types)?;
|
||||
|
||||
let interface = ModuleInterface {
|
||||
function_signatures,
|
||||
record_types,
|
||||
};
|
||||
|
||||
Ok(interface)
|
||||
}
|
||||
|
||||
fn serialize_function_signature(
|
||||
signature: IFunctionSignature,
|
||||
record_types: &IRecordTypes,
|
||||
) -> FunctionSignature {
|
||||
use super::itype_text_view;
|
||||
|
||||
let arguments = signature
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|arg| (arg.name.clone(), itype_text_view(&arg.ty, record_types)))
|
||||
.collect();
|
||||
|
||||
let output_types = signature
|
||||
.outputs
|
||||
.iter()
|
||||
.map(|itype| itype_text_view(itype, record_types))
|
||||
.collect();
|
||||
|
||||
FunctionSignature {
|
||||
name: signature.name.to_string(),
|
||||
arguments,
|
||||
output_types,
|
||||
}
|
||||
}
|
50
crates/module-interface/src/interface/itype_to_text.rs
Normal file
50
crates/module-interface/src/interface/itype_to_text.rs
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2021 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::it_interface::IRecordTypes;
|
||||
|
||||
use wasmer_it::IType;
|
||||
|
||||
/// Converts the supplied IType to a Aqua0compatible text representation.
|
||||
///
|
||||
/// SAFETY:
|
||||
/// It's assumed that arguments are well-formed and all records have a corresponded type in
|
||||
/// record_types.
|
||||
pub fn itype_text_view(arg_ty: &IType, record_types: &IRecordTypes) -> String {
|
||||
match arg_ty {
|
||||
IType::Record(record_type_id) => {
|
||||
// assumed that this functions called with well-formed args
|
||||
let record = record_types.get(record_type_id).unwrap();
|
||||
record.name.clone()
|
||||
}
|
||||
IType::Array(array_ty) => format!("[]{}", itype_text_view(array_ty, record_types)),
|
||||
IType::Boolean => "bool".to_string(),
|
||||
IType::S8 => "i8".to_string(),
|
||||
IType::S16 => "i16".to_string(),
|
||||
IType::S32 => "i32".to_string(),
|
||||
IType::S64 => "i64".to_string(),
|
||||
IType::U8 => "u8".to_string(),
|
||||
IType::U16 => "u16".to_string(),
|
||||
IType::U32 => "u32".to_string(),
|
||||
IType::U64 => "u64".to_string(),
|
||||
IType::F32 => "f32".to_string(),
|
||||
IType::F64 => "f64".to_string(),
|
||||
IType::String => "string".to_string(),
|
||||
IType::ByteArray => "[]u8".to_string(),
|
||||
IType::I32 => "i32".to_string(),
|
||||
IType::I64 => "i64".to_string(),
|
||||
}
|
||||
}
|
38
crates/module-interface/src/interface/mod.rs
Normal file
38
crates/module-interface/src/interface/mod.rs
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2021 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.
|
||||
*/
|
||||
|
||||
mod errors;
|
||||
mod interface_transformer;
|
||||
mod itype_to_text;
|
||||
mod module_interface;
|
||||
mod records_transformer;
|
||||
|
||||
pub use errors::InterfaceError;
|
||||
pub use interface_transformer::it_to_module_interface;
|
||||
pub use itype_to_text::*;
|
||||
pub use module_interface::*;
|
||||
|
||||
pub type InterfaceResult<T> = std::result::Result<T, InterfaceError>;
|
||||
|
||||
use marine_it_interfaces::MITInterfaces;
|
||||
|
||||
/// Returns interface of a Marine module.
|
||||
pub fn get_interface(mit: &MITInterfaces<'_>) -> InterfaceResult<ModuleInterface> {
|
||||
let it_interface = crate::it_interface::get_interface(mit)?;
|
||||
let interface = it_to_module_interface(it_interface)?;
|
||||
|
||||
Ok(interface)
|
||||
}
|
78
crates/module-interface/src/interface/module_interface.rs
Normal file
78
crates/module-interface/src/interface/module_interface.rs
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2021 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 serde::Serialize;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub struct FunctionSignature {
|
||||
pub name: String,
|
||||
pub arguments: Vec<(String, String)>,
|
||||
pub output_types: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub struct RecordField {
|
||||
pub name: String,
|
||||
pub ty: String,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub struct RecordType {
|
||||
pub name: String,
|
||||
pub id: u64,
|
||||
pub fields: Vec<RecordField>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub struct ModuleInterface {
|
||||
pub function_signatures: Vec<FunctionSignature>,
|
||||
// record types are guaranteed to be topological sorted
|
||||
pub record_types: Vec<RecordType>,
|
||||
}
|
||||
|
||||
use std::fmt;
|
||||
|
||||
impl fmt::Display for FunctionSignature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use itertools::Itertools;
|
||||
|
||||
let output = match self.output_types.len() {
|
||||
0 => "()",
|
||||
1 => &self.output_types[0],
|
||||
_ => unimplemented!("more than 1 output type is unsupported"),
|
||||
};
|
||||
|
||||
if self.arguments.is_empty() {
|
||||
writeln!(f, "{}: -> {}", self.name, output)
|
||||
} else {
|
||||
let args = self.arguments.iter().map(|(_, ty)| ty).format(",");
|
||||
writeln!(f, "{}: {} -> {}", self.name, args, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RecordType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "data {}:", self.name)?;
|
||||
|
||||
for field in self.fields.iter() {
|
||||
writeln!(f, " {}: {}", field.name, field.ty)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
128
crates/module-interface/src/interface/records_transformer.rs
Normal file
128
crates/module-interface/src/interface/records_transformer.rs
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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 super::RecordType;
|
||||
use super::RecordField;
|
||||
use super::InterfaceResult;
|
||||
use super::InterfaceError;
|
||||
use crate::it_interface::IRecordTypes;
|
||||
|
||||
use wasmer_it::IRecordType;
|
||||
use wasmer_it::IType;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub(crate) struct RecordsTransformer {
|
||||
used: HashSet<u64>,
|
||||
sorted_order: Vec<u64>,
|
||||
}
|
||||
|
||||
impl RecordsTransformer {
|
||||
pub(crate) fn transform(record_types: &IRecordTypes) -> InterfaceResult<Vec<RecordType>> {
|
||||
let records_count = record_types.len();
|
||||
|
||||
let mut transformer = Self {
|
||||
used: HashSet::with_capacity(records_count),
|
||||
sorted_order: Vec::with_capacity(records_count),
|
||||
};
|
||||
|
||||
// TODO: check for cycles
|
||||
transformer.topological_sort(record_types)?;
|
||||
let record_types = transformer.into_transformed_records(record_types);
|
||||
|
||||
Ok(record_types)
|
||||
}
|
||||
|
||||
fn topological_sort(&mut self, exported_records: &IRecordTypes) -> InterfaceResult<()> {
|
||||
for (id, record) in exported_records {
|
||||
self.dfs(*id, record, exported_records)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dfs(
|
||||
&mut self,
|
||||
record_id: u64,
|
||||
record: &Rc<IRecordType>,
|
||||
exported_records: &IRecordTypes,
|
||||
) -> InterfaceResult<()> {
|
||||
if !self.used.insert(record_id) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
for field in (&record.fields).iter() {
|
||||
self.type_dfs(&field.ty, exported_records)?;
|
||||
}
|
||||
|
||||
self.sorted_order.push(record_id);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn type_dfs(
|
||||
&mut self,
|
||||
field_ty: &IType,
|
||||
exported_records: &IRecordTypes,
|
||||
) -> InterfaceResult<()> {
|
||||
match field_ty {
|
||||
IType::Record(type_id) => {
|
||||
let child_record = exported_records
|
||||
.get(type_id)
|
||||
.ok_or(InterfaceError::NotFoundRecordTypeId(*type_id))?;
|
||||
|
||||
self.dfs(*type_id, child_record, exported_records)
|
||||
}
|
||||
IType::Array(ty) => self.type_dfs(ty, exported_records),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn into_transformed_records(self, record_types: &IRecordTypes) -> Vec<RecordType> {
|
||||
self.sorted_order
|
||||
.into_iter()
|
||||
.map(|id| {
|
||||
// unwrap is safe here because sorted_order is constructed based on record_types
|
||||
let record = record_types.get(&id).unwrap();
|
||||
Self::convert_record(id, record, &record_types)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn convert_record(
|
||||
id: u64,
|
||||
record: &Rc<IRecordType>,
|
||||
record_types: &IRecordTypes,
|
||||
) -> RecordType {
|
||||
use super::itype_text_view;
|
||||
|
||||
let fields = record
|
||||
.fields
|
||||
.iter()
|
||||
.map(|field| RecordField {
|
||||
name: field.name.clone(),
|
||||
ty: itype_text_view(&field.ty, record_types),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
RecordType {
|
||||
name: record.name.clone(),
|
||||
id,
|
||||
fields,
|
||||
}
|
||||
}
|
||||
}
|
33
crates/module-interface/src/it_interface/errors.rs
Normal file
33
crates/module-interface/src/it_interface/errors.rs
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 marine_it_interfaces::MITInterfacesError;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum ITInterfaceError {
|
||||
#[error("type with idx = {0} isn't a function type")]
|
||||
ITTypeNotFunction(u32),
|
||||
|
||||
#[error("record type with type id {0} not found")]
|
||||
NotFoundRecordTypeId(u64),
|
||||
|
||||
#[error("mailformed module: a record contains more recursion level then allowed")]
|
||||
TooManyRecursionLevels,
|
||||
|
||||
#[error("{0}")]
|
||||
MITInterfacesError(#[from] MITInterfacesError),
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2021 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 super::IFunctionSignature;
|
||||
use super::ITInterfaceError;
|
||||
use super::RIResult;
|
||||
|
||||
use marine_it_interfaces::MITInterfaces;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct ITExportFuncDescriptor<'n> {
|
||||
pub adapter_function_type: u32,
|
||||
pub name: &'n str,
|
||||
}
|
||||
|
||||
/// Returns all exported IT functions descriptors.
|
||||
pub fn get_export_funcs_descriptors<'i>(
|
||||
mit: &'i MITInterfaces<'_>,
|
||||
) -> Vec<ITExportFuncDescriptor<'i>> {
|
||||
// An IT function is exported if it lies in export functions and have implementation.
|
||||
// An export IT function without implementation is a hack and used to call core function from
|
||||
// a Wasm module. This hack is needed because there is only one call instruction in the
|
||||
// interface-types crates and it's needed to distinguish somehow between calling export IT or
|
||||
// core functions. This scheme is a kind of mess and it needs to be refactored one day.
|
||||
mit.implementations()
|
||||
.filter_map(|(adapter_function_type, core_function_type)| {
|
||||
mit.exports_by_type(*core_function_type)
|
||||
.map(|export_function_name| (adapter_function_type, export_function_name))
|
||||
})
|
||||
.map(|(&adapter_function_type, export_function_names)| {
|
||||
export_function_names
|
||||
.iter()
|
||||
.map(move |name| ITExportFuncDescriptor {
|
||||
adapter_function_type,
|
||||
name,
|
||||
})
|
||||
})
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
/// Returns all exported IT functions.
|
||||
pub fn get_export_funcs(mit: &MITInterfaces<'_>) -> RIResult<Vec<IFunctionSignature>> {
|
||||
use marine_it_interfaces::ITAstType;
|
||||
|
||||
let funcs_descriptors = get_export_funcs_descriptors(mit);
|
||||
|
||||
funcs_descriptors
|
||||
.into_iter()
|
||||
.map(|descriptor| {
|
||||
let it_type = mit.type_by_idx_r(descriptor.adapter_function_type)?;
|
||||
|
||||
match it_type {
|
||||
ITAstType::Function {
|
||||
arguments,
|
||||
output_types,
|
||||
} => {
|
||||
let signature = IFunctionSignature {
|
||||
name: Rc::new(descriptor.name.to_string()),
|
||||
arguments: arguments.clone(),
|
||||
outputs: output_types.clone(),
|
||||
adapter_function_type: descriptor.adapter_function_type,
|
||||
};
|
||||
Ok(signature)
|
||||
}
|
||||
_ => Err(ITInterfaceError::ITTypeNotFunction(
|
||||
descriptor.adapter_function_type,
|
||||
)),
|
||||
}
|
||||
})
|
||||
.collect::<RIResult<Vec<IFunctionSignature>>>()
|
||||
}
|
129
crates/module-interface/src/it_interface/export_it_records.rs
Normal file
129
crates/module-interface/src/it_interface/export_it_records.rs
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright 2021 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 super::IRecordTypes;
|
||||
use super::RIResult;
|
||||
use super::ITInterfaceError;
|
||||
use super::IFunctionSignature;
|
||||
|
||||
use marine_it_interfaces::MITInterfaces;
|
||||
use wasmer_it::IType;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
const TYPE_RESOLVE_RECURSION_LIMIT: u32 = 1024;
|
||||
|
||||
pub struct FullRecordTypes {
|
||||
pub record_types: IRecordTypes,
|
||||
pub export_record_types: IRecordTypes,
|
||||
}
|
||||
|
||||
pub fn get_record_types<'f>(
|
||||
mit: &MITInterfaces<'_>,
|
||||
export_funcs: impl ExactSizeIterator<Item = &'f IFunctionSignature>,
|
||||
) -> RIResult<FullRecordTypes> {
|
||||
let all_record_types = get_all_records(mit);
|
||||
let mut export_record_types = HashMap::new();
|
||||
|
||||
let itypes = export_funcs.flat_map(|s| {
|
||||
s.arguments
|
||||
.as_ref()
|
||||
.iter()
|
||||
.map(|a| &a.ty)
|
||||
.chain(s.outputs.as_ref().iter())
|
||||
});
|
||||
|
||||
for itype in itypes {
|
||||
handle_itype(itype, &all_record_types, &mut export_record_types, 0)?;
|
||||
}
|
||||
|
||||
let full_record_types = FullRecordTypes {
|
||||
record_types: all_record_types,
|
||||
export_record_types,
|
||||
};
|
||||
|
||||
Ok(full_record_types)
|
||||
}
|
||||
|
||||
fn handle_itype(
|
||||
itype: &IType,
|
||||
all_record_types: &IRecordTypes,
|
||||
export_record_types: &mut IRecordTypes,
|
||||
recursion_level: u32,
|
||||
) -> RIResult<()> {
|
||||
if recursion_level > TYPE_RESOLVE_RECURSION_LIMIT {
|
||||
return Err(ITInterfaceError::TooManyRecursionLevels);
|
||||
}
|
||||
|
||||
match itype {
|
||||
IType::Record(record_type_id) => handle_record_type(
|
||||
*record_type_id,
|
||||
all_record_types,
|
||||
export_record_types,
|
||||
recursion_level + 1,
|
||||
)?,
|
||||
IType::Array(array_ty) => handle_itype(
|
||||
array_ty,
|
||||
all_record_types,
|
||||
export_record_types,
|
||||
recursion_level + 1,
|
||||
)?,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_record_type(
|
||||
record_type_id: u64,
|
||||
all_record_types: &IRecordTypes,
|
||||
export_record_types: &mut IRecordTypes,
|
||||
recursion_level: u32,
|
||||
) -> RIResult<()> {
|
||||
let record_type = all_record_types
|
||||
.get(&record_type_id)
|
||||
.ok_or(ITInterfaceError::NotFoundRecordTypeId(record_type_id))?;
|
||||
|
||||
export_record_types.insert(record_type_id, record_type.clone());
|
||||
|
||||
for field in record_type.fields.iter() {
|
||||
handle_itype(
|
||||
&field.ty,
|
||||
all_record_types,
|
||||
export_record_types,
|
||||
recursion_level + 1,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_all_records(mit: &MITInterfaces<'_>) -> IRecordTypes {
|
||||
use marine_it_interfaces::ITAstType;
|
||||
|
||||
mit.types()
|
||||
.enumerate()
|
||||
.fold(HashMap::new(), |mut record_types_by_id, (id, ty)| {
|
||||
match ty {
|
||||
ITAstType::Record(record_type) => {
|
||||
record_types_by_id.insert(id as u64, record_type.clone());
|
||||
}
|
||||
ITAstType::Function { .. } => {}
|
||||
};
|
||||
|
||||
record_types_by_id
|
||||
})
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2021 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 wasmer_it::IType;
|
||||
use wasmer_it::ast::FunctionArg as IFunctionArg;
|
||||
use wasmer_it::IRecordType;
|
||||
|
||||
use serde::Serialize;
|
||||
use serde::Deserialize;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type IRecordTypes = HashMap<u64, Rc<IRecordType>>;
|
||||
|
||||
/// Represent a function type inside Marine module.
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub struct IFunctionSignature {
|
||||
pub name: Rc<String>,
|
||||
pub arguments: Rc<Vec<IFunctionArg>>,
|
||||
pub outputs: Rc<Vec<IType>>,
|
||||
pub adapter_function_type: u32,
|
||||
}
|
||||
|
||||
/// Represent an interface of a Wasm module.
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct IModuleInterface {
|
||||
pub export_record_types: IRecordTypes,
|
||||
pub record_types: IRecordTypes,
|
||||
pub function_signatures: Vec<IFunctionSignature>,
|
||||
}
|
46
crates/module-interface/src/it_interface/mod.rs
Normal file
46
crates/module-interface/src/it_interface/mod.rs
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2021 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.
|
||||
*/
|
||||
|
||||
mod errors;
|
||||
mod export_it_functions;
|
||||
mod export_it_records;
|
||||
mod it_module_interface;
|
||||
|
||||
pub use errors::*;
|
||||
pub use export_it_functions::*;
|
||||
pub use export_it_records::*;
|
||||
pub use it_module_interface::*;
|
||||
|
||||
pub type RIResult<T> = std::result::Result<T, ITInterfaceError>;
|
||||
|
||||
use marine_it_interfaces::MITInterfaces;
|
||||
|
||||
/// Returns Marine module interface that includes both export and all record types.
|
||||
pub fn get_interface(mit: &MITInterfaces<'_>) -> RIResult<IModuleInterface> {
|
||||
let function_signatures = get_export_funcs(mit)?;
|
||||
let FullRecordTypes {
|
||||
record_types,
|
||||
export_record_types,
|
||||
} = get_record_types(mit, function_signatures.iter())?;
|
||||
|
||||
let mm_interface = IModuleInterface {
|
||||
record_types,
|
||||
export_record_types,
|
||||
function_signatures,
|
||||
};
|
||||
|
||||
Ok(mm_interface)
|
||||
}
|
29
crates/module-interface/src/lib.rs
Normal file
29
crates/module-interface/src/lib.rs
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2021 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.
|
||||
*/
|
||||
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![deny(
|
||||
dead_code,
|
||||
nonstandard_style,
|
||||
unused_imports,
|
||||
unused_mut,
|
||||
unused_variables,
|
||||
unused_unsafe,
|
||||
unreachable_patterns
|
||||
)]
|
||||
|
||||
pub mod interface;
|
||||
pub mod it_interface;
|
@ -1,13 +1,13 @@
|
||||
[package]
|
||||
name = "fluence-app-service"
|
||||
description = "Fluence Application Service"
|
||||
version = "0.7.2"
|
||||
version = "0.7.3"
|
||||
authors = ["Fluence Labs"]
|
||||
license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
fluence-faas = { path = "../fluence-faas", version = "0.7.2" }
|
||||
fluence-faas = { path = "../fluence-faas", version = "0.7.3" }
|
||||
|
||||
maplit = "1.0.2"
|
||||
log = "0.4.8"
|
||||
|
@ -17,7 +17,7 @@
|
||||
use fluence_faas::FaaSModuleInterface;
|
||||
use fluence_faas::FaaSFunctionSignature;
|
||||
use fluence_faas::IRecordType;
|
||||
use fluence_faas::RecordTypes;
|
||||
use fluence_faas::MRecordTypes;
|
||||
use fluence_faas::itype_text_view;
|
||||
|
||||
use serde::Serialize;
|
||||
@ -66,7 +66,7 @@ pub(crate) fn into_service_interface(faas_interface: FaaSModuleInterface<'_>) ->
|
||||
|
||||
fn serialize_function_signature(
|
||||
signature: FaaSFunctionSignature,
|
||||
record_types: &RecordTypes,
|
||||
record_types: &MRecordTypes,
|
||||
) -> FunctionSignature {
|
||||
let arguments = signature
|
||||
.arguments
|
||||
@ -90,7 +90,7 @@ fn serialize_function_signature(
|
||||
fn serialize_record_type(
|
||||
id: u64,
|
||||
record: Rc<IRecordType>,
|
||||
record_types: &RecordTypes,
|
||||
record_types: &MRecordTypes,
|
||||
) -> RecordType {
|
||||
let fields = record
|
||||
.fields
|
||||
|
@ -1,13 +1,14 @@
|
||||
[package]
|
||||
name = "fluence-faas"
|
||||
description = "Fluence FaaS"
|
||||
version = "0.7.2"
|
||||
version = "0.7.3"
|
||||
authors = ["Fluence Labs"]
|
||||
license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
marine-runtime = { path = "../runtime", version = "0.5.0" }
|
||||
marine-module-interface = { path = "../crates/module-interface", version = "0.1.0" }
|
||||
marine-utils = { path = "../crates/utils", version = "0.2.0" }
|
||||
fluence-sdk-main = { version = "0.6.9", features = ["logger"] }
|
||||
fluence = { version = "0.6.3", features = ["logger"] }
|
||||
|
@ -28,7 +28,7 @@ use crate::host_imports::logger::WASM_LOG_ENV_NAME;
|
||||
use marine::Marine;
|
||||
use marine::IFunctionArg;
|
||||
use marine_utils::SharedString;
|
||||
use marine::RecordTypes;
|
||||
use marine::MRecordTypes;
|
||||
use fluence::CallParameters;
|
||||
|
||||
use serde_json::Value as JValue;
|
||||
@ -39,7 +39,7 @@ use std::rc::Rc;
|
||||
|
||||
struct ModuleInterface {
|
||||
function_signatures: HashMap<SharedString, (Rc<Vec<IFunctionArg>>, Rc<Vec<IType>>)>,
|
||||
record_types: Rc<RecordTypes>,
|
||||
record_types: Rc<MRecordTypes>,
|
||||
}
|
||||
|
||||
// TODO: remove and use mutex instead
|
||||
@ -186,7 +186,7 @@ impl FluenceFaaS {
|
||||
&'faas mut self,
|
||||
module_name: &str,
|
||||
func_name: &str,
|
||||
) -> Result<(Rc<Vec<IFunctionArg>>, Rc<Vec<IType>>, Rc<RecordTypes>)> {
|
||||
) -> Result<(Rc<Vec<IFunctionArg>>, Rc<Vec<IType>>, Rc<MRecordTypes>)> {
|
||||
use FaaSError::NoSuchModule;
|
||||
use FaaSError::MissingFunctionError;
|
||||
|
||||
|
@ -14,17 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use super::IType;
|
||||
use super::IRecordType;
|
||||
use super::itype_text_view;
|
||||
use crate::FaaSModuleInterface;
|
||||
|
||||
use marine::RecordTypes;
|
||||
use itertools::Itertools;
|
||||
use serde::Serialize;
|
||||
|
||||
use std::fmt;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize)]
|
||||
pub struct FaaSInterface<'a> {
|
||||
@ -33,78 +31,80 @@ pub struct FaaSInterface<'a> {
|
||||
|
||||
impl<'a> fmt::Display for FaaSInterface<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut printed_record_types: HashSet<&IRecordType> = HashSet::new();
|
||||
|
||||
for (_, module_interface) in self.modules.iter() {
|
||||
for (_, record_type) in module_interface.record_types.iter() {
|
||||
if !printed_record_types.insert(record_type) {
|
||||
// do not print record if it has been already printed
|
||||
continue;
|
||||
}
|
||||
|
||||
writeln!(f, "{} {{", record_type.name)?;
|
||||
|
||||
for field in record_type.fields.iter() {
|
||||
writeln!(
|
||||
f,
|
||||
" {}: {}",
|
||||
field.name,
|
||||
itype_text_view(&field.ty, &module_interface.record_types)
|
||||
)?;
|
||||
}
|
||||
|
||||
writeln!(f, "}}")?;
|
||||
}
|
||||
}
|
||||
|
||||
for (name, module_interface) in self.modules.iter() {
|
||||
writeln!(f, "\n{}:", *name)?;
|
||||
|
||||
for function_signature in module_interface.function_signatures.iter() {
|
||||
write!(f, " fn {}(", function_signature.name)?;
|
||||
|
||||
let args = function_signature
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
format!(
|
||||
"{}: {}",
|
||||
arg.name,
|
||||
itype_text_view(&arg.ty, &module_interface.record_types)
|
||||
)
|
||||
})
|
||||
.join(", ");
|
||||
|
||||
let outputs = &function_signature.outputs;
|
||||
if outputs.is_empty() {
|
||||
writeln!(f, "{})", args)?;
|
||||
} else if outputs.len() == 1 {
|
||||
writeln!(
|
||||
f,
|
||||
"{}) -> {}",
|
||||
args,
|
||||
itype_text_view(&outputs[0], &module_interface.record_types)
|
||||
)?;
|
||||
} else {
|
||||
// At now, multi values aren't supported - only one output type is possible
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
print_record_types(self.modules.values(), f)?;
|
||||
print_functions_sign(self.modules.iter(), f)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn itype_text_view(arg_ty: &IType, record_types: &RecordTypes) -> String {
|
||||
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 = record_types.get(record_type_id).unwrap();
|
||||
record.name.clone()
|
||||
fn print_record_types<'r>(
|
||||
modules: impl Iterator<Item = &'r FaaSModuleInterface<'r>>,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
use std::collections::HashSet;
|
||||
|
||||
let mut printed_record_types: HashSet<&IRecordType> = HashSet::new();
|
||||
|
||||
for module in modules {
|
||||
for (_, record_type) in module.record_types.iter() {
|
||||
if !printed_record_types.insert(record_type) {
|
||||
// do not print record if it has been already printed
|
||||
continue;
|
||||
}
|
||||
|
||||
writeln!(f, "data {}:", record_type.name)?;
|
||||
|
||||
for field in record_type.fields.iter() {
|
||||
writeln!(
|
||||
f,
|
||||
" {}: {}",
|
||||
field.name,
|
||||
itype_text_view(&field.ty, &module.record_types)
|
||||
)?;
|
||||
}
|
||||
}
|
||||
IType::Array(array_ty) => format!("Array<{}>", itype_text_view(array_ty, record_types)),
|
||||
t => format!("{:?}", t),
|
||||
}
|
||||
|
||||
writeln!(f)
|
||||
}
|
||||
|
||||
fn print_functions_sign<'r>(
|
||||
modules: impl Iterator<Item = (&'r &'r str, &'r FaaSModuleInterface<'r>)>,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
for (name, module_interface) in modules {
|
||||
writeln!(f, "{}:", *name)?;
|
||||
|
||||
for function_signature in module_interface.function_signatures.iter() {
|
||||
write!(f, " fn {}(", function_signature.name)?;
|
||||
|
||||
let args = function_signature
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
format!(
|
||||
"{}: {}",
|
||||
arg.name,
|
||||
itype_text_view(&arg.ty, &module_interface.record_types)
|
||||
)
|
||||
})
|
||||
.join(", ");
|
||||
|
||||
let outputs = &function_signature.outputs;
|
||||
if outputs.is_empty() {
|
||||
writeln!(f, "{})", args)?;
|
||||
} else if outputs.len() == 1 {
|
||||
writeln!(
|
||||
f,
|
||||
"{}) -> {}",
|
||||
args,
|
||||
itype_text_view(&outputs[0], &module_interface.record_types)
|
||||
)?;
|
||||
} else {
|
||||
// At now, multi values aren't supported - only one output type is possible
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -19,13 +19,13 @@ use crate::IType;
|
||||
use crate::Result;
|
||||
use crate::errors::FaaSError::JsonOutputSerializationError as OutputDeError;
|
||||
|
||||
use marine::RecordTypes;
|
||||
use marine::MRecordTypes;
|
||||
use serde_json::Value as JValue;
|
||||
|
||||
pub(crate) fn ivalues_to_json(
|
||||
mut ivalues: Vec<IValue>,
|
||||
outputs: &[IType],
|
||||
record_types: &RecordTypes,
|
||||
record_types: &MRecordTypes,
|
||||
) -> Result<JValue> {
|
||||
if outputs.len() != ivalues.len() {
|
||||
return Err(OutputDeError(format!(
|
||||
@ -42,7 +42,7 @@ pub(crate) fn ivalues_to_json(
|
||||
}
|
||||
}
|
||||
|
||||
fn ivalue_to_json(ivalue: IValue, output: &IType, record_types: &RecordTypes) -> Result<JValue> {
|
||||
fn ivalue_to_json(ivalue: IValue, output: &IType, record_types: &MRecordTypes) -> Result<JValue> {
|
||||
use serde_json::json;
|
||||
|
||||
// clone here needed because binding by-value and by-ref in the same pattern in unstable
|
||||
|
@ -19,7 +19,7 @@ use crate::IType;
|
||||
use crate::Result;
|
||||
use crate::FaaSError::JsonArgumentsDeserializationError as ArgDeError;
|
||||
|
||||
use marine::RecordTypes;
|
||||
use marine::MRecordTypes;
|
||||
use serde_json::Value as JValue;
|
||||
use wasmer_it::NEVec;
|
||||
|
||||
@ -30,7 +30,7 @@ use std::iter::ExactSizeIterator;
|
||||
pub(crate) fn json_to_ivalues<'a, 'b>(
|
||||
json_args: JValue,
|
||||
arg_types: impl Iterator<Item = (&'a String, &'a IType)> + ExactSizeIterator,
|
||||
record_types: &'b RecordTypes,
|
||||
record_types: &'b MRecordTypes,
|
||||
) -> Result<Vec<IValue>> {
|
||||
let ivalues = match json_args {
|
||||
JValue::Object(json_map) => json_map_to_ivalues(json_map, arg_types, &record_types)?,
|
||||
@ -48,7 +48,7 @@ pub(crate) fn json_to_ivalues<'a, 'b>(
|
||||
fn json_map_to_ivalues<'a, 'b>(
|
||||
mut json_map: serde_json::Map<String, JValue>,
|
||||
arg_types: impl Iterator<Item = (&'a String, &'a IType)>,
|
||||
record_types: &'b RecordTypes,
|
||||
record_types: &'b MRecordTypes,
|
||||
) -> Result<Vec<IValue>> {
|
||||
let mut iargs = Vec::new();
|
||||
|
||||
@ -75,7 +75,7 @@ fn json_map_to_ivalues<'a, 'b>(
|
||||
fn json_array_to_ivalues<'a, 'b>(
|
||||
json_array: Vec<JValue>,
|
||||
arg_types: impl Iterator<Item = &'a IType> + ExactSizeIterator,
|
||||
record_types: &'b RecordTypes,
|
||||
record_types: &'b MRecordTypes,
|
||||
) -> Result<Vec<IValue>> {
|
||||
if json_array.len() != arg_types.len() {
|
||||
return Err(ArgDeError(format!(
|
||||
@ -129,7 +129,7 @@ fn json_null_to_ivalues<'a>(
|
||||
}
|
||||
|
||||
/// Convert one JValue to an array of ivalues according to the supplied argument type.
|
||||
fn jvalue_to_ivalue(jvalue: JValue, ty: &IType, record_types: &RecordTypes) -> Result<IValue> {
|
||||
fn jvalue_to_ivalue(jvalue: JValue, ty: &IType, record_types: &MRecordTypes) -> Result<IValue> {
|
||||
macro_rules! to_ivalue(
|
||||
($json_value:expr, $ty:ident) => {
|
||||
{
|
||||
@ -211,7 +211,7 @@ fn jvalue_to_ivalue(jvalue: JValue, ty: &IType, record_types: &RecordTypes) -> R
|
||||
fn json_record_type_to_ivalue(
|
||||
json_value: JValue,
|
||||
record_type_id: &u64,
|
||||
record_types: &RecordTypes,
|
||||
record_types: &MRecordTypes,
|
||||
) -> Result<NEVec<IValue>> {
|
||||
let record_type = record_types.get(record_type_id).ok_or_else(|| {
|
||||
ArgDeError(format!(
|
||||
|
@ -36,7 +36,6 @@ pub(crate) type Result<T> = std::result::Result<T, FaaSError>;
|
||||
|
||||
pub use faas::FluenceFaaS;
|
||||
pub use faas_interface::FaaSInterface;
|
||||
pub use faas_interface::itype_text_view;
|
||||
|
||||
pub use config::FaaSConfig;
|
||||
pub use config::FaaSModuleConfig;
|
||||
@ -57,7 +56,7 @@ pub use marine::IFunctionArg;
|
||||
pub use marine::IType;
|
||||
pub use marine::MModuleInterface as FaaSModuleInterface;
|
||||
pub use marine::MFunctionSignature as FaaSFunctionSignature;
|
||||
pub use marine::RecordTypes;
|
||||
pub use marine::MRecordTypes;
|
||||
pub use marine::HostExportedFunc;
|
||||
pub use marine::HostImportDescriptor;
|
||||
pub use marine::HostImportError;
|
||||
@ -67,6 +66,8 @@ pub use marine::ne_vec;
|
||||
pub use marine::min_sdk_version;
|
||||
pub use marine::min_it_version;
|
||||
|
||||
pub use marine_module_interface::interface::itype_text_view;
|
||||
|
||||
pub use fluence::CallParameters;
|
||||
pub use fluence::SecurityTetraplet;
|
||||
|
||||
|
@ -15,6 +15,7 @@ marine-module-info-parser = { path = "../crates/module-info-parser", version = "
|
||||
marine-it-interfaces = { path = "../crates/it-interfaces", version = "0.4.0" }
|
||||
marine-it-parser = { path = "../crates/it-parser", version = "0.6.0" }
|
||||
marine-it-generator = { path = "../crates/it-generator", version = "0.5.0" }
|
||||
marine-module-interface = { path = "../crates/module-interface", version = "0.1.0" }
|
||||
marine-utils = { path = "../crates/utils", version = "0.2.0" }
|
||||
|
||||
wasmer-runtime = { package = "wasmer-runtime-fl", version = "0.17.0" }
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use super::*;
|
||||
use crate::module::MModule;
|
||||
use crate::module::RecordTypes;
|
||||
use crate::module::MRecordTypes;
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
@ -27,7 +27,7 @@ use std::rc::Rc;
|
||||
/// Represent Marine module interface.
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Serialize)]
|
||||
pub struct MModuleInterface<'a> {
|
||||
pub record_types: &'a RecordTypes,
|
||||
pub record_types: &'a MRecordTypes,
|
||||
pub function_signatures: Vec<MFunctionSignature>,
|
||||
}
|
||||
|
||||
@ -119,7 +119,7 @@ impl Marine {
|
||||
}
|
||||
|
||||
/// Return record types exported by module with given name.
|
||||
pub fn module_record_types<S: AsRef<str>>(&self, module_name: S) -> Option<&RecordTypes> {
|
||||
pub fn module_record_types<S: AsRef<str>>(&self, module_name: S) -> Option<&MRecordTypes> {
|
||||
self.modules
|
||||
.get(module_name.as_ref())
|
||||
.map(|module| module.export_record_types())
|
||||
|
@ -18,6 +18,7 @@ use crate::HostImportError;
|
||||
use marine_it_interfaces::MITInterfacesError;
|
||||
use marine_it_parser::ITParserError;
|
||||
use marine_module_info_parser::ModuleInfoError;
|
||||
use marine_module_interface::it_interface::ITInterfaceError;
|
||||
|
||||
use wasmer_runtime::error as wasmer_error;
|
||||
|
||||
@ -63,6 +64,10 @@ pub enum MError {
|
||||
#[error("{0}")]
|
||||
WASIPrepareError(String),
|
||||
|
||||
/// Errors occurred inside marine-module-interface crate.
|
||||
#[error("{0}")]
|
||||
ModuleInterfaceError(#[from] ITInterfaceError),
|
||||
|
||||
/// Error arisen during execution of Wasm modules (especially, interface types).
|
||||
#[error("Execution error: {0}")]
|
||||
ITInstructionError(#[from] wasmer_it::errors::InstructionError),
|
||||
|
@ -22,7 +22,7 @@ use super::lowering::LoHelper;
|
||||
use super::utils::itypes_args_to_wtypes;
|
||||
use super::utils::itypes_output_to_wtypes;
|
||||
|
||||
use crate::RecordTypes;
|
||||
use crate::MRecordTypes;
|
||||
use crate::init_wasm_func_once;
|
||||
use crate::call_wasm_func;
|
||||
use crate::HostImportDescriptor;
|
||||
@ -41,7 +41,7 @@ use std::ops::Deref;
|
||||
|
||||
pub(crate) fn create_host_import_func(
|
||||
descriptor: HostImportDescriptor,
|
||||
record_types: Rc<RecordTypes>,
|
||||
record_types: Rc<MRecordTypes>,
|
||||
) -> DynamicFunc<'static> {
|
||||
let allocate_func: AllocateFunc = Box::new(RefCell::new(None));
|
||||
let set_result_ptr_func: SetResultPtrFunc = Box::new(RefCell::new(None));
|
||||
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::RecordTypes;
|
||||
use crate::MRecordTypes;
|
||||
use crate::IRecordType;
|
||||
use it_lilo::traits::RecordResolvable;
|
||||
use it_lilo::traits::RecordResolvableError;
|
||||
@ -22,11 +22,11 @@ use it_lilo::traits::RecordResolvableError;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub(crate) struct LiHelper {
|
||||
record_types: Rc<RecordTypes>,
|
||||
record_types: Rc<MRecordTypes>,
|
||||
}
|
||||
|
||||
impl LiHelper {
|
||||
pub(crate) fn new(record_types: Rc<RecordTypes>) -> Self {
|
||||
pub(crate) fn new(record_types: Rc<MRecordTypes>) -> Self {
|
||||
Self { record_types }
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ pub use module::IValue;
|
||||
pub use module::IRecordType;
|
||||
pub use module::IFunctionArg;
|
||||
pub use module::IType;
|
||||
pub use module::RecordTypes;
|
||||
pub use module::MRecordTypes;
|
||||
pub use module::MFunctionSignature;
|
||||
pub use module::from_interface_values;
|
||||
pub use module::to_interface_value;
|
||||
|
@ -15,8 +15,9 @@
|
||||
*/
|
||||
|
||||
use super::wit_prelude::*;
|
||||
use super::MFunctionSignature;
|
||||
use super::MRecordTypes;
|
||||
use super::{IType, IRecordType, IFunctionArg, IValue, WValue};
|
||||
use super::RecordTypes;
|
||||
use crate::MResult;
|
||||
use crate::MModuleConfig;
|
||||
|
||||
@ -29,9 +30,6 @@ use wasmer_runtime::compile;
|
||||
use wasmer_runtime::ImportObject;
|
||||
use wasmer_it::interpreter::Interpreter;
|
||||
|
||||
use serde::Serialize;
|
||||
use serde::Deserialize;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
use std::mem::MaybeUninit;
|
||||
@ -48,18 +46,10 @@ pub(super) struct ITModuleFunc {
|
||||
pub(super) output_types: Rc<Vec<IType>>,
|
||||
}
|
||||
|
||||
/// Represent a function type inside Marine module.
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub struct MFunctionSignature {
|
||||
pub name: Rc<String>,
|
||||
pub arguments: Rc<Vec<IFunctionArg>>,
|
||||
pub outputs: Rc<Vec<IType>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(super) struct Callable {
|
||||
pub(super) wit_instance: Arc<ITInstance>,
|
||||
pub(super) wit_module_func: ITModuleFunc,
|
||||
pub(super) it_instance: Arc<ITInstance>,
|
||||
pub(super) it_module_func: ITModuleFunc,
|
||||
}
|
||||
|
||||
impl Callable {
|
||||
@ -67,9 +57,9 @@ impl Callable {
|
||||
use wasmer_it::interpreter::stack::Stackable;
|
||||
|
||||
let result = self
|
||||
.wit_module_func
|
||||
.it_module_func
|
||||
.interpreter
|
||||
.run(args, Arc::make_mut(&mut self.wit_instance))?
|
||||
.run(args, Arc::make_mut(&mut self.it_instance))?
|
||||
.as_slice()
|
||||
.to_owned();
|
||||
|
||||
@ -105,7 +95,7 @@ pub(crate) struct MModule {
|
||||
|
||||
// TODO: save refs instead copying of a record types HashMap.
|
||||
/// Record types used in exported functions as arguments or return values.
|
||||
export_record_types: RecordTypes,
|
||||
export_record_types: MRecordTypes,
|
||||
}
|
||||
|
||||
impl MModule {
|
||||
@ -130,7 +120,7 @@ impl MModule {
|
||||
Self::create_import_objects(config, &mit, wit_import_object.clone())?;
|
||||
|
||||
let wasmer_instance = wasmer_module.instantiate(&wasi_import_object)?;
|
||||
let wit_instance = unsafe {
|
||||
let it_instance = unsafe {
|
||||
// get_mut_unchecked here is safe because currently only this modules have reference to
|
||||
// it and the environment is single-threaded
|
||||
*Arc::get_mut_unchecked(&mut wit_instance) =
|
||||
@ -138,8 +128,7 @@ impl MModule {
|
||||
std::mem::transmute::<_, Arc<ITInstance>>(wit_instance)
|
||||
};
|
||||
|
||||
let export_funcs = Self::instantiate_wit_exports(&wit_instance, &mit)?;
|
||||
let export_record_types = Self::extract_export_record_types(&export_funcs, &wit_instance)?;
|
||||
let (export_funcs, export_record_types) = Self::instantiate_exports(&it_instance, &mit)?;
|
||||
|
||||
// call _start to populate the WASI state of the module
|
||||
#[rustfmt::skip]
|
||||
@ -179,12 +168,12 @@ impl MModule {
|
||||
.iter()
|
||||
.map(|(func_name, func)| MFunctionSignature {
|
||||
name: func_name.0.clone(),
|
||||
arguments: func.wit_module_func.arguments.clone(),
|
||||
outputs: func.wit_module_func.output_types.clone(),
|
||||
arguments: func.it_module_func.arguments.clone(),
|
||||
outputs: func.it_module_func.output_types.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn export_record_types(&self) -> &RecordTypes {
|
||||
pub(crate) fn export_record_types(&self) -> &MRecordTypes {
|
||||
&self.export_record_types
|
||||
}
|
||||
|
||||
@ -260,54 +249,36 @@ impl MModule {
|
||||
Ok((wasi_import_object, host_closures_import_object))
|
||||
}
|
||||
|
||||
fn instantiate_wit_exports(
|
||||
wit_instance: &Arc<ITInstance>,
|
||||
wit: &MITInterfaces<'_>,
|
||||
) -> MResult<ExportFunctions> {
|
||||
use marine_it_interfaces::ITAstType;
|
||||
fn instantiate_exports(
|
||||
it_instance: &Arc<ITInstance>,
|
||||
mit: &MITInterfaces<'_>,
|
||||
) -> MResult<(ExportFunctions, MRecordTypes)> {
|
||||
let module_interface = marine_module_interface::it_interface::get_interface(mit)?;
|
||||
|
||||
wit.implementations()
|
||||
.filter_map(|(adapter_function_type, core_function_type)| {
|
||||
wit.exports_by_type(*core_function_type)
|
||||
.map(|export_function_name| (adapter_function_type, export_function_name))
|
||||
let export_funcs = module_interface
|
||||
.function_signatures
|
||||
.into_iter()
|
||||
.map(|sign| {
|
||||
let adapter_instructions = mit.adapter_by_type_r(sign.adapter_function_type)?;
|
||||
|
||||
let interpreter: ITInterpreter = adapter_instructions.clone().try_into()?;
|
||||
let it_module_func = ITModuleFunc {
|
||||
interpreter: Arc::new(interpreter),
|
||||
arguments: sign.arguments.clone(),
|
||||
output_types: sign.outputs.clone(),
|
||||
};
|
||||
|
||||
let shared_string = SharedString(sign.name);
|
||||
let callable = Rc::new(Callable {
|
||||
it_instance: it_instance.clone(),
|
||||
it_module_func,
|
||||
});
|
||||
|
||||
Ok((shared_string, callable))
|
||||
})
|
||||
.map(|(adapter_function_type, export_function_names)| {
|
||||
export_function_names
|
||||
.iter()
|
||||
.map(move |export_function_name| (*adapter_function_type, export_function_name))
|
||||
})
|
||||
.flatten()
|
||||
.map(|(adapter_function_type, export_function_name)| {
|
||||
let adapter_instructions = wit.adapter_by_type_r(adapter_function_type)?;
|
||||
let wit_type = wit.type_by_idx_r(adapter_function_type)?;
|
||||
.collect::<MResult<ExportFunctions>>()?;
|
||||
|
||||
match wit_type {
|
||||
ITAstType::Function {
|
||||
arguments,
|
||||
output_types,
|
||||
} => {
|
||||
let interpreter: ITInterpreter = adapter_instructions.clone().try_into()?;
|
||||
let wit_module_func = ITModuleFunc {
|
||||
interpreter: Arc::new(interpreter),
|
||||
arguments: arguments.clone(),
|
||||
output_types: output_types.clone(),
|
||||
};
|
||||
|
||||
let shared_string = SharedString(Rc::new(export_function_name.to_string()));
|
||||
let callable = Rc::new(Callable {
|
||||
wit_instance: wit_instance.clone(),
|
||||
wit_module_func,
|
||||
});
|
||||
|
||||
Ok((shared_string, callable))
|
||||
}
|
||||
_ => Err(MError::IncorrectWIT(format!(
|
||||
"type with idx = {} isn't a function type",
|
||||
adapter_function_type
|
||||
))),
|
||||
}
|
||||
})
|
||||
.collect::<MResult<ExportFunctions>>()
|
||||
Ok((export_funcs, module_interface.export_record_types))
|
||||
}
|
||||
|
||||
// this function deals only with import functions that have an adaptor implementation
|
||||
@ -442,92 +413,4 @@ impl MModule {
|
||||
|
||||
Ok(import_object)
|
||||
}
|
||||
|
||||
// TODO : move it to a separate crate
|
||||
fn extract_export_record_types(
|
||||
export_funcs: &ExportFunctions,
|
||||
wit_instance: &Arc<ITInstance>,
|
||||
) -> MResult<RecordTypes> {
|
||||
use marine_it_generator::TYPE_RESOLVE_RECURSION_LIMIT;
|
||||
use MError::RecordResolveError;
|
||||
|
||||
fn handle_itype(
|
||||
itype: &IType,
|
||||
wit_instance: &Arc<ITInstance>,
|
||||
export_record_types: &mut RecordTypes,
|
||||
recursion_level: u32,
|
||||
) -> MResult<()> {
|
||||
use wasmer_it::interpreter::wasm::structures::Instance;
|
||||
|
||||
if recursion_level > TYPE_RESOLVE_RECURSION_LIMIT {
|
||||
return Err(RecordResolveError(String::from(
|
||||
"mailformed module: a record contains more recursion level then allowed",
|
||||
)));
|
||||
}
|
||||
|
||||
fn handle_record_type(
|
||||
record_type_id: u64,
|
||||
wit_instance: &Arc<ITInstance>,
|
||||
export_record_types: &mut RecordTypes,
|
||||
recursion_level: u32,
|
||||
) -> MResult<()> {
|
||||
let record_type =
|
||||
wit_instance
|
||||
.wit_record_by_id(record_type_id)
|
||||
.ok_or_else(|| {
|
||||
RecordResolveError(format!(
|
||||
"record type with type id {} not found",
|
||||
record_type_id
|
||||
))
|
||||
})?;
|
||||
export_record_types.insert(record_type_id, record_type.clone());
|
||||
|
||||
for field in record_type.fields.iter() {
|
||||
handle_itype(
|
||||
&field.ty,
|
||||
wit_instance,
|
||||
export_record_types,
|
||||
recursion_level + 1,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
match itype {
|
||||
IType::Record(record_type_id) => handle_record_type(
|
||||
*record_type_id,
|
||||
wit_instance,
|
||||
export_record_types,
|
||||
recursion_level + 1,
|
||||
)?,
|
||||
IType::Array(array_ty) => handle_itype(
|
||||
array_ty,
|
||||
wit_instance,
|
||||
export_record_types,
|
||||
recursion_level + 1,
|
||||
)?,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let mut export_record_types = HashMap::new();
|
||||
|
||||
let itypes = 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())
|
||||
});
|
||||
|
||||
for itype in itypes {
|
||||
handle_itype(itype, wit_instance, &mut export_record_types, 0)?;
|
||||
}
|
||||
|
||||
Ok(export_record_types)
|
||||
}
|
||||
}
|
||||
|
@ -21,16 +21,26 @@ mod wit_function;
|
||||
mod wit_instance;
|
||||
mod type_converters;
|
||||
|
||||
pub use wit_instance::RecordTypes;
|
||||
|
||||
pub use wit_instance::MRecordTypes;
|
||||
pub use wasmer_it::IType;
|
||||
pub use wasmer_it::IRecordType;
|
||||
pub use wasmer_it::ast::FunctionArg as IFunctionArg;
|
||||
pub use wasmer_it::IValue;
|
||||
pub use marine_module::MFunctionSignature;
|
||||
pub use wasmer_it::from_interface_values;
|
||||
pub use wasmer_it::to_interface_value;
|
||||
|
||||
use serde::Serialize;
|
||||
use serde::Deserialize;
|
||||
use std::rc::Rc;
|
||||
|
||||
/// Represent a function type inside Marine module.
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub struct MFunctionSignature {
|
||||
pub name: Rc<String>,
|
||||
pub arguments: Rc<Vec<IFunctionArg>>,
|
||||
pub outputs: Rc<Vec<IType>>,
|
||||
}
|
||||
|
||||
pub(crate) use marine_module::MModule;
|
||||
pub(self) use wasmer_core::types::Type as WType;
|
||||
pub(self) use wasmer_core::types::Value as WValue;
|
||||
|
@ -29,7 +29,7 @@ use std::collections::HashMap;
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type RecordTypes = HashMap<u64, Rc<IRecordType>>;
|
||||
pub type MRecordTypes = HashMap<u64, Rc<IRecordType>>;
|
||||
|
||||
/// Contains all import and export functions that could be called from IT context by call-core.
|
||||
#[derive(Clone)]
|
||||
@ -41,7 +41,7 @@ pub(super) struct ITInstance {
|
||||
memories: Vec<WITMemory>,
|
||||
|
||||
/// All record types that instance contains.
|
||||
record_types_by_id: RecordTypes,
|
||||
record_types_by_id: MRecordTypes,
|
||||
}
|
||||
|
||||
impl ITInstance {
|
||||
@ -158,7 +158,7 @@ impl ITInstance {
|
||||
memories
|
||||
}
|
||||
|
||||
fn extract_record_types(wit: &MITInterfaces<'_>) -> RecordTypes {
|
||||
fn extract_record_types(wit: &MITInterfaces<'_>) -> MRecordTypes {
|
||||
let (record_types_by_id, _) = wit.types().fold(
|
||||
(HashMap::new(), 0u64),
|
||||
|(mut record_types_by_id, id), ty| {
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "marine"
|
||||
description = "Fluence Marine command line tool"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
authors = ["Fluence Labs"]
|
||||
repository = "https://github.com/fluencelabs/marine/tools/cli"
|
||||
license = "Apache-2.0"
|
||||
@ -13,11 +13,12 @@ path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
marine-it-generator = { path = "../../crates/it-generator", version = "0.5.1" }
|
||||
marine-it-parser = { path = "../../crates/it-parser", version = "0.6.0" }
|
||||
marine-it-parser = { path = "../../crates/it-parser", version = "0.6.1" }
|
||||
marine-module-info-parser = { path = "../../crates/module-info-parser", version = "0.1.0" }
|
||||
|
||||
semver = "0.11.0"
|
||||
walrus = "0.18.0"
|
||||
Inflector = "0.11.4"
|
||||
|
||||
thiserror = "1.0.24"
|
||||
anyhow = "1.0.31"
|
||||
|
@ -23,9 +23,27 @@ pub const DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION");
|
||||
pub const IN_WASM_PATH: &str = "in-wasm-path";
|
||||
pub const IT_PATH: &str = "it-path";
|
||||
pub const OUT_WASM_PATH: &str = "out-wasm-path";
|
||||
pub const SERVICE_NAME: &str = "service-name";
|
||||
|
||||
pub const SDK_VERSION: &str = "sdk-version";
|
||||
|
||||
pub fn aqua<'a, 'b>() -> App<'a, 'b> {
|
||||
SubCommand::with_name("aqua")
|
||||
.about("Shows data types of provided module in a format suitable for Aqua")
|
||||
.args(&[
|
||||
Arg::with_name(IN_WASM_PATH)
|
||||
.required(true)
|
||||
.takes_value(true)
|
||||
.index(1)
|
||||
.help("a path to a Wasm file"),
|
||||
Arg::with_name(SERVICE_NAME)
|
||||
.required(false)
|
||||
.takes_value(true)
|
||||
.short("s")
|
||||
.help("optional service name"),
|
||||
])
|
||||
}
|
||||
|
||||
pub fn build<'a, 'b>() -> App<'a, 'b> {
|
||||
SubCommand::with_name("build")
|
||||
.about("Builds provided Rust project to Wasm")
|
||||
|
@ -25,13 +25,13 @@
|
||||
unreachable_patterns
|
||||
)]
|
||||
|
||||
use marine_module_info_parser::manifest;
|
||||
use marine_module_info_parser::sdk_version;
|
||||
|
||||
mod args;
|
||||
mod build;
|
||||
mod errors;
|
||||
|
||||
use marine_module_info_parser::manifest;
|
||||
use marine_module_info_parser::sdk_version;
|
||||
|
||||
pub(crate) type CLIResult<T> = std::result::Result<T, crate::errors::CLIError>;
|
||||
|
||||
pub fn main() -> Result<(), anyhow::Error> {
|
||||
@ -39,6 +39,7 @@ pub fn main() -> Result<(), anyhow::Error> {
|
||||
.version(args::VERSION)
|
||||
.author(args::AUTHORS)
|
||||
.setting(clap::AppSettings::ArgRequiredElseHelp)
|
||||
.subcommand(args::aqua())
|
||||
.subcommand(args::build())
|
||||
.subcommand(args::set())
|
||||
.subcommand(args::show_manifest())
|
||||
@ -47,6 +48,7 @@ pub fn main() -> Result<(), anyhow::Error> {
|
||||
let arg_matches = app.get_matches();
|
||||
|
||||
match arg_matches.subcommand() {
|
||||
("aqua", Some(args)) => aqua(args),
|
||||
("build", Some(args)) => build(args),
|
||||
("set", Some(args)) => set(args),
|
||||
("it", Some(args)) => it(args),
|
||||
@ -76,6 +78,36 @@ pub fn main() -> Result<(), anyhow::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn aqua(args: &clap::ArgMatches<'_>) -> Result<(), anyhow::Error> {
|
||||
use inflector::Inflector;
|
||||
|
||||
let wasm_path = args.value_of(args::IN_WASM_PATH).unwrap();
|
||||
let wasm_path = std::path::Path::new(wasm_path);
|
||||
|
||||
let module_interface = marine_it_parser::module_interface(wasm_path)?;
|
||||
for record in module_interface.record_types.iter() {
|
||||
println!("{}", record);
|
||||
}
|
||||
|
||||
match args.value_of(args::SERVICE_NAME) {
|
||||
Some(service_name) => println!("service {}:", service_name.to_title_case()),
|
||||
None => {
|
||||
let service_name = wasm_path
|
||||
.file_stem()
|
||||
.ok_or(anyhow::Error::msg("provided path isn't a path to a file"))?;
|
||||
let service_name = service_name.to_string_lossy().to_title_case();
|
||||
|
||||
println!("service {}:", service_name);
|
||||
}
|
||||
}
|
||||
|
||||
for sign in module_interface.function_signatures {
|
||||
println!(" {}", sign);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build(args: &clap::ArgMatches<'_>) -> Result<(), anyhow::Error> {
|
||||
let trailing_args: Vec<&str> = args.values_of("optional").unwrap_or_default().collect();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "mrepl"
|
||||
description = "Fluence Marine REPL intended for testing purposes"
|
||||
version = "0.7.2"
|
||||
version = "0.7.3"
|
||||
authors = ["Fluence Labs"]
|
||||
repository = "https://github.com/fluencelabs/marine/tools/repl"
|
||||
license = "Apache-2.0"
|
||||
@ -12,7 +12,7 @@ name = "mrepl"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
fluence-app-service = { path = "../../fluence-app-service", version = "0.7.1", features = ["raw-module-api"] }
|
||||
fluence-app-service = { path = "../../fluence-app-service", version = "0.7.2", features = ["raw-module-api"] }
|
||||
fluence-sdk-main = { version = "0.6.9", features = ["logger"] }
|
||||
|
||||
anyhow = "1.0.31"
|
||||
|
Loading…
Reference in New Issue
Block a user