mirror of
https://github.com/fluencelabs/marine.git
synced 2024-12-12 14:55:32 +00:00
generalize ipfs node service
This commit is contained in:
parent
8c845c9f37
commit
7d5ae2f9b0
30
Cargo.lock
generated
30
Cargo.lock
generated
@ -514,9 +514,20 @@ name = "ipfs_node"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fce",
|
"fce",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
"toml",
|
"toml",
|
||||||
|
"wasmer-runtime",
|
||||||
|
"wasmer-runtime-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@ -806,9 +817,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.110"
|
version = "1.0.111"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c"
|
checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
@ -834,15 +845,26 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.110"
|
version = "1.0.111"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984"
|
checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.53"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
BIN
bin/wit_embedder
Executable file
BIN
bin/wit_embedder
Executable file
Binary file not shown.
@ -35,13 +35,13 @@ pub struct FCEWITInterfaces<'a> {
|
|||||||
types: Vec<WITAstType>,
|
types: Vec<WITAstType>,
|
||||||
|
|
||||||
/// All the imported functions.
|
/// All the imported functions.
|
||||||
imports: HashMap<CoreFunctionType, (ImportName<'a>, ImportNamespace<'a>)>,
|
imports: MultiMap<CoreFunctionType, (ImportName<'a>, ImportNamespace<'a>)>,
|
||||||
|
|
||||||
/// All the adapters.
|
/// All the adapters.
|
||||||
adapters: HashMap<AdapterFunctionType, Vec<Instruction>>,
|
adapters: HashMap<AdapterFunctionType, Vec<Instruction>>,
|
||||||
|
|
||||||
/// All the exported functions.
|
/// All the exported functions.
|
||||||
exports: HashMap<CoreFunctionType, ExportName<'a>>,
|
exports: MultiMap<CoreFunctionType, ExportName<'a>>,
|
||||||
|
|
||||||
/// All the implementations.
|
/// All the implementations.
|
||||||
adapter_type_to_core: MultiMap<AdapterFunctionType, CoreFunctionType>,
|
adapter_type_to_core: MultiMap<AdapterFunctionType, CoreFunctionType>,
|
||||||
@ -54,7 +54,7 @@ impl<'a> FCEWITInterfaces<'a> {
|
|||||||
.imports
|
.imports
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|import| (import.function_type, (import.namespace, import.name)))
|
.map(|import| (import.function_type, (import.namespace, import.name)))
|
||||||
.collect::<HashMap<_, _>>();
|
.collect::<MultiMap<_, _>>();
|
||||||
|
|
||||||
let adapters = interfaces
|
let adapters = interfaces
|
||||||
.adapters
|
.adapters
|
||||||
@ -66,7 +66,7 @@ impl<'a> FCEWITInterfaces<'a> {
|
|||||||
.exports
|
.exports
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|export| (export.function_type, export.name))
|
.map(|export| (export.function_type, export.name))
|
||||||
.collect::<HashMap<_, _>>();
|
.collect::<MultiMap<_, _>>();
|
||||||
|
|
||||||
let adapter_type_to_core = interfaces
|
let adapter_type_to_core = interfaces
|
||||||
.implementations
|
.implementations
|
||||||
@ -120,19 +120,19 @@ impl<'a> FCEWITInterfaces<'a> {
|
|||||||
self.imports.iter()
|
self.imports.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn import_by_type(
|
pub fn imports_by_type(
|
||||||
&self,
|
&self,
|
||||||
import_type: CoreFunctionType,
|
import_type: CoreFunctionType,
|
||||||
) -> Option<&(ImportName<'a>, ImportNamespace<'a>)> {
|
) -> Option<&Vec<(ImportName<'a>, ImportNamespace<'a>)>> {
|
||||||
self.imports.get(&import_type)
|
self.imports.get_vec(&import_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn import_by_type_r(
|
pub fn imports_by_type_r(
|
||||||
&self,
|
&self,
|
||||||
import_type: CoreFunctionType,
|
import_type: CoreFunctionType,
|
||||||
) -> Result<&(ImportName<'a>, ImportNamespace<'a>), FCEWITInterfacesError> {
|
) -> Result<&Vec<(ImportName<'a>, ImportNamespace<'a>)>, FCEWITInterfacesError> {
|
||||||
self.imports
|
self.imports
|
||||||
.get(&import_type)
|
.get_vec(&import_type)
|
||||||
.ok_or_else(|| FCEWITInterfacesError::NoSuchImport(import_type))
|
.ok_or_else(|| FCEWITInterfacesError::NoSuchImport(import_type))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,14 +153,23 @@ impl<'a> FCEWITInterfaces<'a> {
|
|||||||
.ok_or_else(|| FCEWITInterfacesError::NoSuchAdapter(adapter_type))
|
.ok_or_else(|| FCEWITInterfacesError::NoSuchAdapter(adapter_type))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn export_by_type(&self, export_type: u32) -> Option<&ExportName<'a>> {
|
|
||||||
self.exports.get(&export_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn exports(&self) -> impl Iterator<Item = (&CoreFunctionType, &ExportName<'a>)> {
|
pub fn exports(&self) -> impl Iterator<Item = (&CoreFunctionType, &ExportName<'a>)> {
|
||||||
self.exports.iter()
|
self.exports.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exports_by_type(&self, export_type: u32) -> Option<&Vec<ExportName<'a>>> {
|
||||||
|
self.exports.get_vec(&export_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exports_by_type_r(
|
||||||
|
&self,
|
||||||
|
export_type: CoreFunctionType,
|
||||||
|
) -> Result<&Vec<ExportName<'a>>, FCEWITInterfacesError> {
|
||||||
|
self.exports
|
||||||
|
.get_vec(&export_type)
|
||||||
|
.ok_or_else(|| FCEWITInterfacesError::NoSuchImport(export_type))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn implementations(
|
pub fn implementations(
|
||||||
&self,
|
&self,
|
||||||
) -> impl Iterator<Item = (&AdapterFunctionType, &CoreFunctionType)> {
|
) -> impl Iterator<Item = (&AdapterFunctionType, &CoreFunctionType)> {
|
||||||
|
@ -6,4 +6,11 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fce = { path = "../../fce" }
|
fce = { path = "../../fce" }
|
||||||
|
|
||||||
|
wasmer-core = { package = "wasmer-runtime-core", version = "0.17.0" }
|
||||||
|
wasmer-runtime = "0.17.0"
|
||||||
|
|
||||||
toml = "0.5.6"
|
toml = "0.5.6"
|
||||||
|
serde = { version = "1.0.111", features = ["derive"] }
|
||||||
|
serde_json = "1.0.53"
|
||||||
|
serde_derive = "1.0.111"
|
||||||
|
@ -1,6 +1,17 @@
|
|||||||
[ipfs_node]
|
[[core_module]]
|
||||||
[imports]
|
name = "ipfs_node.wasm"
|
||||||
|
mem_pages_count = 100
|
||||||
|
logger_enabled = true
|
||||||
|
|
||||||
|
[core_module.imports]
|
||||||
|
mysql = "/usr/bin/mysql"
|
||||||
ipfs = "/usr/bin/ipfs"
|
ipfs = "/usr/bin/ipfs"
|
||||||
|
|
||||||
[wasi]
|
[core_module.wasi]
|
||||||
preopened_dirs = ["/tmp"]
|
envs = ["asdsad=sdaasd"]
|
||||||
|
preopened_files = ["/tmp/file1"]
|
||||||
|
mapped_dirs = { tmp = "/tmp", tmp2 = "/tmp" }
|
||||||
|
|
||||||
|
[rpc_module]
|
||||||
|
mem_pages_count = 100
|
||||||
|
logger_enabled = true
|
||||||
|
175
examples/ipfs_node/src/config.rs
Normal file
175
examples/ipfs_node/src/config.rs
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* 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::errors::NodeError;
|
||||||
|
|
||||||
|
use serde_derive::Deserialize;
|
||||||
|
use toml::from_slice;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
An example of a config:
|
||||||
|
|
||||||
|
[ipfs_node]
|
||||||
|
mem_pages_count_count = 100
|
||||||
|
logger_enabled = true
|
||||||
|
|
||||||
|
[imports]
|
||||||
|
ipfs = "/usr/bin/ipfs"
|
||||||
|
mysql = "/usr/bin/mysql"
|
||||||
|
|
||||||
|
[wasi]
|
||||||
|
preopened_files = ["/tmp/file1"]
|
||||||
|
[mapped_dirs]
|
||||||
|
tmp = "/tmp"
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub(crate) struct RawCoreModulesConfig {
|
||||||
|
pub core_module: Vec<RawModuleConfig>,
|
||||||
|
pub rpc_module: Option<RawRPCModuleConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub(crate) struct RawModuleConfig {
|
||||||
|
pub name: String,
|
||||||
|
pub mem_pages_count: Option<u32>,
|
||||||
|
pub logger_enabled: Option<bool>,
|
||||||
|
pub imports: Option<toml::value::Table>,
|
||||||
|
pub wasi: Option<RawWASIConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub(crate) struct RawWASIConfig {
|
||||||
|
pub envs: Option<Vec<String>>,
|
||||||
|
pub preopened_files: Option<Vec<String>>,
|
||||||
|
pub mapped_dirs: Option<toml::value::Table>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub(crate) struct RawRPCModuleConfig {
|
||||||
|
pub mem_pages_count: Option<u32>,
|
||||||
|
pub logger_enabled: Option<bool>,
|
||||||
|
pub wasi: Option<RawWASIConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct NodeConfig {
|
||||||
|
pub modules_config: HashMap<String, ModuleConfig>,
|
||||||
|
pub rpc_module_config: Option<ModuleConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct ModuleConfig {
|
||||||
|
pub mem_pages_count: Option<u32>,
|
||||||
|
pub logger_enabled: Option<bool>,
|
||||||
|
pub imports: Option<Vec<(String, String)>>,
|
||||||
|
pub wasi: Option<WASIConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct WASIConfig {
|
||||||
|
pub envs: Option<Vec<Vec<u8>>>,
|
||||||
|
pub preopened_files: Option<Vec<String>>,
|
||||||
|
pub mapped_dirs: Option<Vec<(String, String)>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parse_config_from_file(
|
||||||
|
config_file_path: std::path::PathBuf,
|
||||||
|
) -> Result<NodeConfig, NodeError> {
|
||||||
|
let file_content = std::fs::read(config_file_path)?;
|
||||||
|
let config: RawCoreModulesConfig =
|
||||||
|
from_slice(&file_content).map_err(|err| NodeError::ConfigParseError(format!("{}", err)))?;
|
||||||
|
|
||||||
|
let modules_config = config
|
||||||
|
.core_module
|
||||||
|
.into_iter()
|
||||||
|
.map(|module| {
|
||||||
|
let imports: Option<Vec<(String, String)>> = module.imports.map(|import| {
|
||||||
|
import
|
||||||
|
.into_iter()
|
||||||
|
.map(|(import_func_name, host_cmd)| {
|
||||||
|
(import_func_name, host_cmd.try_into::<String>().unwrap())
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
});
|
||||||
|
|
||||||
|
let wasi = module.wasi.map(|wasi| {
|
||||||
|
let envs = wasi
|
||||||
|
.envs
|
||||||
|
.map(|env| env.into_iter().map(|e| e.into_bytes()).collect::<Vec<_>>());
|
||||||
|
|
||||||
|
let mapped_dirs = wasi.mapped_dirs.map(|mapped_dir| {
|
||||||
|
mapped_dir
|
||||||
|
.into_iter()
|
||||||
|
.map(|(from, to)| (from, to.try_into::<String>().unwrap()))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
});
|
||||||
|
WASIConfig {
|
||||||
|
envs,
|
||||||
|
preopened_files: wasi.preopened_files,
|
||||||
|
mapped_dirs,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
(
|
||||||
|
module.name,
|
||||||
|
ModuleConfig {
|
||||||
|
mem_pages_count: module.mem_pages_count,
|
||||||
|
logger_enabled: module.logger_enabled,
|
||||||
|
imports,
|
||||||
|
wasi,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
let rpc_module_config = config.rpc_module.map(|rpc_module| {
|
||||||
|
let wasi = rpc_module.wasi.map(|wasi| {
|
||||||
|
let envs = wasi
|
||||||
|
.envs
|
||||||
|
.map(|env| env.into_iter().map(|e| e.into_bytes()).collect::<Vec<_>>());
|
||||||
|
|
||||||
|
let mapped_dirs = wasi.mapped_dirs.map(|mapped_dir| {
|
||||||
|
mapped_dir
|
||||||
|
.into_iter()
|
||||||
|
.map(|(from, to)| (from, to.try_into::<String>().unwrap()))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
});
|
||||||
|
WASIConfig {
|
||||||
|
envs,
|
||||||
|
preopened_files: wasi.preopened_files,
|
||||||
|
mapped_dirs,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ModuleConfig {
|
||||||
|
mem_pages_count: rpc_module.mem_pages_count,
|
||||||
|
logger_enabled: rpc_module.logger_enabled,
|
||||||
|
imports: None,
|
||||||
|
wasi,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"parsed modules config:\n{:?}\nparsed rpc config:\n{:?}",
|
||||||
|
modules_config, rpc_module_config
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(NodeConfig {
|
||||||
|
modules_config,
|
||||||
|
rpc_module_config,
|
||||||
|
})
|
||||||
|
}
|
@ -16,13 +16,16 @@
|
|||||||
|
|
||||||
use fce::FCEError;
|
use fce::FCEError;
|
||||||
|
|
||||||
use std::io::{Error as IOError, IoSliceMut};
|
use std::io::Error as IOError;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum NodeError {
|
pub enum NodeError {
|
||||||
|
/// An error related to config parsing.
|
||||||
|
ConfigParseError(String),
|
||||||
|
|
||||||
/// Various errors related to file io.
|
/// Various errors related to file io.
|
||||||
IOError(IOError),
|
IOError(String),
|
||||||
|
|
||||||
/// WIT doesn't contain such type.
|
/// WIT doesn't contain such type.
|
||||||
WasmProcessError(FCEError),
|
WasmProcessError(FCEError),
|
||||||
@ -33,7 +36,8 @@ impl Error for NodeError {}
|
|||||||
impl std::fmt::Display for NodeError {
|
impl std::fmt::Display for NodeError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||||
match self {
|
match self {
|
||||||
NodeError::IOError(err) => write!(f, "{}", err),
|
NodeError::ConfigParseError(err_msg) => write!(f, "{}", err_msg),
|
||||||
|
NodeError::IOError(err_msg) => write!(f, "{}", err_msg),
|
||||||
NodeError::WasmProcessError(err) => write!(f, "{}", err),
|
NodeError::WasmProcessError(err) => write!(f, "{}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,7 +45,7 @@ impl std::fmt::Display for NodeError {
|
|||||||
|
|
||||||
impl From<IOError> for NodeError {
|
impl From<IOError> for NodeError {
|
||||||
fn from(err: IOError) -> Self {
|
fn from(err: IOError) -> Self {
|
||||||
NodeError::IOError(err)
|
NodeError::IOError(format!("{}", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
54
examples/ipfs_node/src/imports.rs
Normal file
54
examples/ipfs_node/src/imports.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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 wasmer_core::vm::Ctx;
|
||||||
|
use wasmer_core::typed_func::DynamicFunc;
|
||||||
|
|
||||||
|
pub(super) fn log_utf8_string(ctx: &mut Ctx, offset: i32, size: i32) {
|
||||||
|
use wasmer_core::memory::ptr::{Array, WasmPtr};
|
||||||
|
|
||||||
|
let wasm_ptr = WasmPtr::<u8, Array>::new(offset as _);
|
||||||
|
match wasm_ptr.get_utf8_string(ctx.memory(0), size as _) {
|
||||||
|
Some(msg) => print!("{}", msg),
|
||||||
|
None => print!("ipfs node logger: incorrect UTF8 string's been supplied to logger"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn create_host_import_func(host_cmd: String) -> DynamicFunc<'static> {
|
||||||
|
use wasmer_core::types::Value;
|
||||||
|
use wasmer_core::types::Type;
|
||||||
|
use wasmer_core::types::FuncSig;
|
||||||
|
|
||||||
|
let func = Box::new(move |ctx: &mut Ctx, inputs: &[Value]| -> Vec<Value> {
|
||||||
|
use wasmer_core::memory::ptr::{Array, WasmPtr};
|
||||||
|
|
||||||
|
// TODO: refactor this
|
||||||
|
let array_ptr = inputs[0].to_u128() as i32;
|
||||||
|
let array_size = inputs[1].to_u128() as i32;
|
||||||
|
|
||||||
|
let wasm_ptr = WasmPtr::<u8, Array>::new(array_ptr as _);
|
||||||
|
match wasm_ptr.get_utf8_string(ctx.memory(0), array_size as _) {
|
||||||
|
Some(msg) => print!("{}", msg),
|
||||||
|
None => print!("ipfs node logger: incorrect UTF8 string's been supplied to logger"),
|
||||||
|
}
|
||||||
|
vec![]
|
||||||
|
});
|
||||||
|
|
||||||
|
DynamicFunc::new(
|
||||||
|
std::sync::Arc::new(FuncSig::new(vec![Type::I32, Type::I32], vec![])),
|
||||||
|
func,
|
||||||
|
)
|
||||||
|
}
|
@ -16,60 +16,9 @@
|
|||||||
|
|
||||||
mod node;
|
mod node;
|
||||||
mod errors;
|
mod errors;
|
||||||
|
mod config;
|
||||||
|
mod imports;
|
||||||
|
|
||||||
use fce::IValue;
|
pub use node::IpfsNode;
|
||||||
use fce::FCE;
|
pub use node::NodeModule;
|
||||||
use fce::FCEError;
|
pub(crate) use imports::log_utf8_string;
|
||||||
use fce::FCEModuleConfig;
|
|
||||||
use fce::WasmProcess;
|
|
||||||
|
|
||||||
const IPFS_NODE: &str =
|
|
||||||
"/Users/mike/dev/work/fluence/wasm/fce/target/wasm32-unknown-unknown/release/ipfs_node_wit.wasm";
|
|
||||||
|
|
||||||
const IPFS_RPC: &str =
|
|
||||||
"/Users/mike/dev/work/fluence/wasm/fce/target/wasm32-unknown-unknown/release/ipfs_rpc_wit.wasm";
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let ipfs_node_bytes = std::fs::read(IPFS_NODE).unwrap();
|
|
||||||
let ipfs_rpc_bytes = std::fs::read(IPFS_RPC).unwrap();
|
|
||||||
|
|
||||||
let mut fce = FCE::new();
|
|
||||||
let config = FCEModuleConfig::default();
|
|
||||||
|
|
||||||
println!("loading ipfs node module");
|
|
||||||
fce.load_module("node", &ipfs_node_bytes, config.clone())
|
|
||||||
.expect("module successfully created");
|
|
||||||
|
|
||||||
println!("loading ipfs rpc module");
|
|
||||||
fce.load_module("rpc", &ipfs_rpc_bytes, config.clone())
|
|
||||||
.expect("module successfully created");
|
|
||||||
|
|
||||||
let result = fce
|
|
||||||
.call("node_rpc", "invoke", &[IValue::String("aaaa".to_string())])
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("execution result {:?}", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
fn logger_log_utf8_string(ctx: &mut Ctx, offset: i32, size: i32) {
|
|
||||||
use wasmer_runtime_core::memory::ptr::{Array, WasmPtr};
|
|
||||||
|
|
||||||
let wasm_ptr = WasmPtr::<u8, Array>::new(offset as _);
|
|
||||||
match wasm_ptr.get_utf8_string(ctx.memory(0), size as _) {
|
|
||||||
Some(msg) => print!("{}", msg),
|
|
||||||
None => print!("fce logger: incorrect UTF8 string's been supplied to logger"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn ipfs_call(ctx: &mut Ctx, ptr: i32, size: i32) {
|
|
||||||
use wasmer_runtime_core::memory::ptr::{Array, WasmPtr};
|
|
||||||
|
|
||||||
let wasm_ptr = WasmPtr::<u8, Array>::new(ptr as _);
|
|
||||||
match wasm_ptr.get_utf8_string(ctx.memory(0), size as _) {
|
|
||||||
Some(msg) => println!("host ipfs_call: {}", msg),
|
|
||||||
None => println!("fce logger: incorrect UTF8 string's been supplied to logger"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
45
examples/ipfs_node/src/main.rs
Normal file
45
examples/ipfs_node/src/main.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mod node;
|
||||||
|
mod errors;
|
||||||
|
mod config;
|
||||||
|
mod imports;
|
||||||
|
|
||||||
|
use node::IpfsNode;
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
const IPFS_MODULES_DIR: &str = "/Users/mike/dev/work/fluence/wasm/fce/bin/wasm_modules";
|
||||||
|
|
||||||
|
const IPFS_MODULES_CONFIG_PATH: &str =
|
||||||
|
"/Users/mike/dev/work/fluence/wasm/fce/examples/ipfs_node/Config.toml";
|
||||||
|
|
||||||
|
const IPFS_RPC: &str = "/Users/mike/dev/work/fluence/wasm/fce/bin/wasm_ipfs_rpc_wit.wasm";
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let ipfs_rpc = std::fs::read(IPFS_RPC).unwrap();
|
||||||
|
|
||||||
|
let mut ipfs_node = IpfsNode::new(
|
||||||
|
PathBuf::from(IPFS_MODULES_DIR),
|
||||||
|
PathBuf::from(IPFS_MODULES_CONFIG_PATH),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let result = ipfs_node.rpc_call(&ipfs_rpc).unwrap();
|
||||||
|
|
||||||
|
println!("execution result {:?}", result);
|
||||||
|
}
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
use super::errors::NodeError;
|
use super::errors::NodeError;
|
||||||
|
|
||||||
|
use wasmer_core::import::ImportObject;
|
||||||
|
use wasmer_runtime::{imports, func};
|
||||||
use fce::FCE;
|
use fce::FCE;
|
||||||
use fce::WasmProcess;
|
use fce::WasmProcess;
|
||||||
use fce::NodeFunction;
|
use fce::NodeFunction;
|
||||||
@ -24,55 +26,61 @@ use fce::FCEModuleConfig;
|
|||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use crate::config::ModuleConfig;
|
||||||
|
|
||||||
pub(crate) struct IpfsNode {
|
pub struct IpfsNode {
|
||||||
process: FCE,
|
process: FCE,
|
||||||
// names of core modules that is loaded to FCE
|
// names of core modules that is loaded to FCE
|
||||||
module_names: Vec<String>,
|
module_names: Vec<String>,
|
||||||
|
rpc_module_config: FCEModuleConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct NodeModule<'a> {
|
pub struct NodeModule<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub functions: Vec<NodeFunction<'a>>,
|
pub functions: Vec<NodeFunction<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IpfsNode {
|
impl IpfsNode {
|
||||||
pub fn new(core_modules_dir: PathBuf, _config_file: PathBuf) -> Result<Self, NodeError> {
|
pub fn new(core_modules_dir: PathBuf, config_file_path: PathBuf) -> Result<Self, NodeError> {
|
||||||
let mut wasm_process = FCE::new();
|
let mut wasm_process = FCE::new();
|
||||||
let mut module_names = Vec::new();
|
let mut module_names = Vec::new();
|
||||||
let core_module_config = FCEModuleConfig::default();
|
let mut core_modules_config = crate::config::parse_config_from_file(config_file_path)?;
|
||||||
|
|
||||||
for entry in fs::read_dir(core_modules_dir)? {
|
for entry in fs::read_dir(core_modules_dir)? {
|
||||||
let path = entry?.path();
|
let path = entry?.path();
|
||||||
if !path.is_dir() {
|
if path.is_dir() {
|
||||||
let module_name = path.file_name().unwrap();
|
continue;
|
||||||
let module_name = module_name.to_os_string().into_string().unwrap();
|
}
|
||||||
//.ok_or_else(|| Err(NodeError::IOError()))?;
|
|
||||||
|
let module_name = path.file_name().unwrap();
|
||||||
|
let module_name = module_name
|
||||||
|
.to_os_string()
|
||||||
|
.into_string()
|
||||||
|
.map_err(|e| NodeError::IOError(format!("failed to read from {:?} file", e)))?;
|
||||||
|
|
||||||
println!("module name is {}", module_name);
|
|
||||||
let module_bytes = fs::read(path.clone())?;
|
let module_bytes = fs::read(path.clone())?;
|
||||||
|
|
||||||
wasm_process.load_module(
|
let core_module_config =
|
||||||
module_name.clone(),
|
Self::make_wasm_config(core_modules_config.modules_config.remove(&module_name))?;
|
||||||
&module_bytes,
|
wasm_process.load_module(module_name.clone(), &module_bytes, core_module_config)?;
|
||||||
core_module_config.clone(),
|
|
||||||
)?;
|
|
||||||
module_names.push(module_name);
|
module_names.push(module_name);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
let rpc_module_config = Self::make_wasm_config(core_modules_config.rpc_module_config)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
process: wasm_process,
|
process: wasm_process,
|
||||||
module_names,
|
module_names,
|
||||||
|
rpc_module_config,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rpc_call(&mut self, wasm_rpc: &[u8]) -> Result<Vec<IValue>, NodeError> {
|
pub fn rpc_call(&mut self, wasm_rpc: &[u8]) -> Result<Vec<IValue>, NodeError> {
|
||||||
let core_module_config = FCEModuleConfig::default();
|
|
||||||
let rpc_module_name = "ipfs_rpc";
|
let rpc_module_name = "ipfs_rpc";
|
||||||
|
|
||||||
self.process
|
self.process
|
||||||
.load_module(rpc_module_name, wasm_rpc, core_module_config)?;
|
.load_module(rpc_module_name, wasm_rpc, self.rpc_module_config.clone())?;
|
||||||
let call_result = self.process.call(
|
let call_result = self.process.call(
|
||||||
rpc_module_name,
|
rpc_module_name,
|
||||||
"invoke",
|
"invoke",
|
||||||
@ -96,4 +104,63 @@ impl IpfsNode {
|
|||||||
|
|
||||||
modules
|
modules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_wasm_config(config: Option<ModuleConfig>) -> Result<FCEModuleConfig, NodeError> {
|
||||||
|
use crate::imports::create_host_import_func;
|
||||||
|
use crate::imports::log_utf8_string;
|
||||||
|
use wasmer_core::import::Namespace;
|
||||||
|
|
||||||
|
let mut wasm_module_config = FCEModuleConfig::default();
|
||||||
|
|
||||||
|
let module_config = match config {
|
||||||
|
Some(config) => config,
|
||||||
|
None => return Ok(wasm_module_config),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(mem_pages_count) = module_config.mem_pages_count {
|
||||||
|
wasm_module_config.mem_pages_count = mem_pages_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut namespace = Namespace::new();
|
||||||
|
|
||||||
|
if let Some(logger_enabled) = module_config.logger_enabled {
|
||||||
|
if logger_enabled {
|
||||||
|
namespace.insert("log_utf8_string", func!(log_utf8_string));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(imports) = module_config.imports {
|
||||||
|
for (import_name, host_cmd) in imports {
|
||||||
|
let host_import = create_host_import_func(host_cmd);
|
||||||
|
namespace.insert(import_name, host_import);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut import_object = ImportObject::new();
|
||||||
|
import_object.register("host", namespace);
|
||||||
|
|
||||||
|
if let Some(wasi) = module_config.wasi {
|
||||||
|
if let Some(envs) = wasi.envs {
|
||||||
|
wasm_module_config.wasi_envs = envs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(preopened_files) = wasi.preopened_files {
|
||||||
|
wasm_module_config.wasi_preopened_files = preopened_files
|
||||||
|
.iter()
|
||||||
|
.map(|file| PathBuf::from(file))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(mapped_dirs) = wasi.mapped_dirs {
|
||||||
|
wasm_module_config.wasi_mapped_dirs = mapped_dirs
|
||||||
|
.into_iter()
|
||||||
|
.map(|(from, to)| (from, PathBuf::from(to)))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wasm_module_config.imports = import_object;
|
||||||
|
|
||||||
|
Ok(wasm_module_config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,14 +56,11 @@ pub unsafe fn get(hash_ptr: *mut u8, hash_size: usize) {
|
|||||||
std::mem::forget(result);
|
std::mem::forget(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[link(wasm_import_module = "logger")]
|
#[link(wasm_import_module = "host")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
/// Writes a byte string of size bytes that starts from ptr to a logger.
|
/// Writes a byte string of size bytes that starts from ptr to a logger.
|
||||||
fn log_utf8_string(ptr: i32, size: i32);
|
fn log_utf8_string(ptr: i32, size: i32);
|
||||||
}
|
|
||||||
|
|
||||||
#[link(wasm_import_module = "host")]
|
|
||||||
extern "C" {
|
|
||||||
/// Put a file to ipfs, returns ipfs hash of the file.
|
/// Put a file to ipfs, returns ipfs hash of the file.
|
||||||
fn ipfs(ptr: i32, size: i32);
|
fn ipfs(ptr: i32, size: i32);
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
call-core 0 ;; call allocate
|
call-core 0 ;; call allocate
|
||||||
arg.get 0
|
arg.get 0
|
||||||
string.lower_memory
|
string.lower_memory
|
||||||
call-core 7 ;; call node.get
|
call-core 7 ;; call self.get
|
||||||
call-core 3 ;; call get_result_ptr
|
call-core 3 ;; call get_result_ptr
|
||||||
call-core 2 ;; call get_result_size
|
call-core 2 ;; call get_result_size
|
||||||
string.lift_memory
|
string.lift_memory
|
||||||
|
@ -41,13 +41,13 @@ pub unsafe fn invoke(file_content_ptr: *mut u8, file_content_size: usize) {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
#[link(wasm_import_module = "logger")]
|
#[link(wasm_import_module = "host")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
/// Writes a byte string of size bytes that starts from ptr to a logger.
|
/// Writes a byte string of size bytes that starts from ptr to a logger.
|
||||||
fn log_utf8_string(ptr: i32, size: i32);
|
fn log_utf8_string(ptr: i32, size: i32);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[link(wasm_import_module = "node")]
|
#[link(wasm_import_module = "ipfs_node.wasm")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
/// Put a file to ipfs, returns ipfs hash of the file.
|
/// Put a file to ipfs, returns ipfs hash of the file.
|
||||||
fn put(ptr: i32, size: i32);
|
fn put(ptr: i32, size: i32);
|
||||||
|
@ -33,11 +33,11 @@
|
|||||||
(@interface export "set_result_size" (func 4)) ;; 5
|
(@interface export "set_result_size" (func 4)) ;; 5
|
||||||
(@interface export "set_result_ptr" (func 4)) ;; 6
|
(@interface export "set_result_ptr" (func 4)) ;; 6
|
||||||
|
|
||||||
(@interface import "node" "get" (func (type 5)))
|
(@interface import "ipfs_node.wasm" "get" (func (type 5)))
|
||||||
(@interface import "node" "put" (func (type 5)))
|
(@interface import "ipfs_node.wasm" "put" (func (type 5)))
|
||||||
|
|
||||||
(@interface import "node" "get" (func (type 7))) ;; 7
|
(@interface import "ipfs_node.wasm" "get" (func (type 7))) ;; 7
|
||||||
(@interface import "node" "put" (func (type 8))) ;; 8
|
(@interface import "ipfs_node.wasm" "put" (func (type 8))) ;; 8
|
||||||
|
|
||||||
(@interface func (type 2)
|
(@interface func (type 2)
|
||||||
arg.get 0
|
arg.get 0
|
||||||
@ -58,7 +58,7 @@
|
|||||||
arg.get 0
|
arg.get 0
|
||||||
arg.get 1
|
arg.get 1
|
||||||
string.lift_memory
|
string.lift_memory
|
||||||
call-core 7 ;; call node.get that returns string
|
call-core 7 ;; call ipfs_node.get that returns string
|
||||||
dup
|
dup
|
||||||
string.size
|
string.size
|
||||||
call-core 0 ;; call allocate
|
call-core 0 ;; call allocate
|
||||||
|
@ -25,12 +25,8 @@ pub struct FCEModuleConfig {
|
|||||||
/// Each Wasm pages is 65536 bytes long.
|
/// Each Wasm pages is 65536 bytes long.
|
||||||
pub mem_pages_count: u32,
|
pub mem_pages_count: u32,
|
||||||
|
|
||||||
/// If true, registers the logger Wasm module with name 'logger'.
|
|
||||||
/// This functionality is just for debugging, and this module will be disabled in future.
|
|
||||||
pub logger_enabled: bool,
|
|
||||||
|
|
||||||
/// Import object that will be used in module instantiation process.
|
/// Import object that will be used in module instantiation process.
|
||||||
pub import_object: ImportObject,
|
pub imports: ImportObject,
|
||||||
|
|
||||||
/// Desired WASI version.
|
/// Desired WASI version.
|
||||||
pub wasi_version: WasiVersion,
|
pub wasi_version: WasiVersion,
|
||||||
@ -51,8 +47,7 @@ impl Default for FCEModuleConfig {
|
|||||||
Self {
|
Self {
|
||||||
// 65536*1600 ~ 100 Mb
|
// 65536*1600 ~ 100 Mb
|
||||||
mem_pages_count: 1600,
|
mem_pages_count: 1600,
|
||||||
logger_enabled: true,
|
imports: ImportObject::new(),
|
||||||
import_object: ImportObject::new(),
|
|
||||||
wasi_version: WasiVersion::Latest,
|
wasi_version: WasiVersion::Latest,
|
||||||
wasi_envs: vec![],
|
wasi_envs: vec![],
|
||||||
wasi_preopened_files: vec![],
|
wasi_preopened_files: vec![],
|
||||||
@ -70,12 +65,6 @@ impl FCEModuleConfig {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn with_logger_enable(mut self, logger_enable: bool) -> Self {
|
|
||||||
self.logger_enabled = logger_enable;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn with_wasi_version(mut self, wasi_version: WasiVersion) -> Self {
|
pub fn with_wasi_version(mut self, wasi_version: WasiVersion) -> Self {
|
||||||
self.wasi_version = wasi_version;
|
self.wasi_version = wasi_version;
|
||||||
|
@ -54,7 +54,10 @@ impl WasmProcess for FCE {
|
|||||||
Some(mut module) => unsafe {
|
Some(mut module) => unsafe {
|
||||||
Ok(Arc::get_mut_unchecked(&mut module).call(func_name, argument)?)
|
Ok(Arc::get_mut_unchecked(&mut module).call(func_name, argument)?)
|
||||||
},
|
},
|
||||||
None => Err(FCEError::NoSuchModule),
|
None => {
|
||||||
|
println!("no such module");
|
||||||
|
Err(FCEError::NoSuchModule)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +73,7 @@ impl WasmProcess for FCE {
|
|||||||
let _prepared_wasm_bytes =
|
let _prepared_wasm_bytes =
|
||||||
super::prepare::prepare_module(wasm_bytes, config.mem_pages_count)?;
|
super::prepare::prepare_module(wasm_bytes, config.mem_pages_count)?;
|
||||||
|
|
||||||
let module = FCEModule::new(&wasm_bytes, config.import_object, &self.modules)?;
|
let module = FCEModule::new(&wasm_bytes, config.imports, &self.modules)?;
|
||||||
|
|
||||||
match self.modules.entry(module_name.into()) {
|
match self.modules.entry(module_name.into()) {
|
||||||
Entry::Vacant(entry) => {
|
Entry::Vacant(entry) => {
|
||||||
|
@ -104,10 +104,16 @@ impl FCEModule {
|
|||||||
) -> Result<(&Vec<IType>, &Vec<IType>), FCEError> {
|
) -> Result<(&Vec<IType>, &Vec<IType>), FCEError> {
|
||||||
match self.exports_funcs.get(function_name) {
|
match self.exports_funcs.get(function_name) {
|
||||||
Some(func) => Ok((&func.inputs, &func.outputs)),
|
Some(func) => Ok((&func.inputs, &func.outputs)),
|
||||||
None => Err(FCEError::NoSuchFunction(format!(
|
None => {
|
||||||
|
for func in self.exports_funcs.iter() {
|
||||||
|
println!("{}", func.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(FCEError::NoSuchFunction(format!(
|
||||||
"{} has't been found during its signature looking up",
|
"{} has't been found during its signature looking up",
|
||||||
function_name
|
function_name
|
||||||
))),
|
)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,17 +132,23 @@ impl FCEModule {
|
|||||||
|
|
||||||
wit.implementations()
|
wit.implementations()
|
||||||
.filter_map(|(adapter_function_type, core_function_type)| {
|
.filter_map(|(adapter_function_type, core_function_type)| {
|
||||||
match wit.export_by_type(*core_function_type) {
|
match wit.exports_by_type(*core_function_type) {
|
||||||
Some(export_function_name) => {
|
Some(export_function_name) => {
|
||||||
Some((adapter_function_type, *export_function_name))
|
Some((adapter_function_type, export_function_name))
|
||||||
}
|
}
|
||||||
// pass functions that aren't export
|
// pass functions that aren't export
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.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)| {
|
.map(|(adapter_function_type, export_function_name)| {
|
||||||
let adapter_instructions = wit.adapter_by_type_r(*adapter_function_type)?;
|
let adapter_instructions = wit.adapter_by_type_r(adapter_function_type)?;
|
||||||
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 {
|
WITAstType::Function {
|
||||||
@ -211,15 +223,21 @@ impl FCEModule {
|
|||||||
let namespaces = wit
|
let namespaces = wit
|
||||||
.implementations()
|
.implementations()
|
||||||
.filter_map(|(adapter_function_type, core_function_type)| {
|
.filter_map(|(adapter_function_type, core_function_type)| {
|
||||||
match wit.import_by_type(*core_function_type) {
|
match wit.imports_by_type(*core_function_type) {
|
||||||
Some(import) => Some((adapter_function_type, *import)),
|
Some(import) => Some((adapter_function_type, import)),
|
||||||
// skip functions that aren't export
|
// skip functions that aren't import
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.map(|(adapter_function_type, import_function_names)| {
|
||||||
|
import_function_names
|
||||||
|
.iter()
|
||||||
|
.map(move |import_function_name| (*adapter_function_type, import_function_name))
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
.map(|(adapter_function_type, (import_namespace, import_name))| {
|
.map(|(adapter_function_type, (import_namespace, import_name))| {
|
||||||
let adapter_instructions = wit.adapter_by_type_r(*adapter_function_type)?;
|
let adapter_instructions = wit.adapter_by_type_r(adapter_function_type)?;
|
||||||
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, .. } => {
|
WITAstType::Function { inputs, .. } => {
|
||||||
@ -228,7 +246,7 @@ impl FCEModule {
|
|||||||
let wit_import = dyn_func_from_raw_import(inputs.clone(), inner_import);
|
let wit_import = dyn_func_from_raw_import(inputs.clone(), inner_import);
|
||||||
|
|
||||||
let mut namespace = Namespace::new();
|
let mut namespace = Namespace::new();
|
||||||
namespace.insert(import_name, wit_import);
|
namespace.insert(*import_name, wit_import);
|
||||||
|
|
||||||
Ok((import_namespace.to_string(), namespace))
|
Ok((import_namespace.to_string(), namespace))
|
||||||
}
|
}
|
||||||
@ -238,12 +256,23 @@ impl FCEModule {
|
|||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Result<HashMap<String, Namespace>, FCEError>>()?;
|
.collect::<Result<multimap::MultiMap<String, Namespace>, FCEError>>()?;
|
||||||
|
|
||||||
let mut import_object = ImportObject::new();
|
let mut import_object = ImportObject::new();
|
||||||
|
|
||||||
for (namespace_name, namespace) in namespaces {
|
// TODO: refactor it
|
||||||
import_object.register(namespace_name, namespace);
|
for (namespace_name, namespaces) in namespaces.iter_all() {
|
||||||
|
let mut result_namespace = Namespace::new();
|
||||||
|
for namespace in namespaces {
|
||||||
|
use wasmer_core::import::LikeNamespace;
|
||||||
|
|
||||||
|
result_namespace.insert(
|
||||||
|
namespace.get_exports()[0].0.clone(),
|
||||||
|
namespace.get_exports()[0].1.clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
import_object.register(namespace_name, result_namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(import_object)
|
Ok(import_object)
|
||||||
|
@ -91,7 +91,10 @@ impl WITInstance {
|
|||||||
WITFunction::from_import(module.clone(), import_name.to_string())?;
|
WITFunction::from_import(module.clone(), import_name.to_string())?;
|
||||||
Ok((start_index + idx as usize, func))
|
Ok((start_index + idx as usize, func))
|
||||||
}
|
}
|
||||||
None => Err(FCEError::NoSuchModule),
|
None => {
|
||||||
|
println!("no such module: {}", import_namespace);
|
||||||
|
Err(FCEError::NoSuchModule)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Result<HashMap<_, _>, _>>()
|
.collect::<Result<HashMap<_, _>, _>>()
|
||||||
|
@ -19,6 +19,7 @@ use super::FCEError;
|
|||||||
use super::IValue;
|
use super::IValue;
|
||||||
use super::IType;
|
use super::IType;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct NodeFunction<'a> {
|
pub struct NodeFunction<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub inputs: &'a Vec<IType>,
|
pub inputs: &'a Vec<IType>,
|
||||||
|
Loading…
Reference in New Issue
Block a user