introduce fce_interfaces

This commit is contained in:
vms 2020-06-04 12:46:12 +03:00
parent 939c2e24c0
commit 8b55bf4baf
15 changed files with 544 additions and 15 deletions

18
Cargo.lock generated
View File

@ -361,6 +361,16 @@ dependencies = [
"synstructure",
]
[[package]]
name = "fce_interface"
version = "0.1.0"
dependencies = [
"anyhow",
"multimap",
"walrus",
"wasmer-interface-types",
]
[[package]]
name = "gcc"
version = "0.3.55"
@ -629,12 +639,6 @@ version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2"
[[package]]
name = "options"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cae662c78308e9d468ee0548cd8852e66a9b4a945c16ddcc6eed3dd9ef14cb0"
[[package]]
name = "page_size"
version = "0.4.2"
@ -1201,10 +1205,8 @@ name = "wit_embedder"
version = "0.1.0"
dependencies = [
"clap",
"either",
"exitfailure",
"failure",
"options",
"walrus",
"wasmer-interface-types",
]

View File

@ -1,10 +1,11 @@
[workspace]
members = [
"fce",
"tools/wit_embedder",
"crates/fce_wit_interfaces",
"examples/export_test",
"examples/ipfs_node",
"examples/ipfs_rpc",
"fce",
"tools/wit_embedder",
]
[profile.release]

View File

@ -0,0 +1,15 @@
[package]
name = "fce_interface"
version = "0.1.0"
authors = ["Fluence Labs"]
edition = "2018"
[lib]
name = "fce_interface"
src = "src/lib.rs"
[dependencies]
walrus = "0.17.0"
wasmer-wit = { package = "wasmer-interface-types", git = "https://github.com/fluencelabs/interface-types", branch = "master"}
multimap = "0.8.1"
anyhow = "1.0.31"

View File

@ -0,0 +1,156 @@
/*
* 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::types::*;
use wasmer_wit::interpreter::Instruction;
use wasmer_wit::ast::*;
use multimap::MultiMap;
use std::iter::Iterator;
use std::collections::HashMap;
pub struct FCEWITInterfaces {
/// All the types.
types: Vec<Type>,
/// All the imported functions.
imports: HashMap<CoreFunctionType, (ImportName, ImportNamespace)>,
/// All the adapters.
adapters: HashMap<AdapterFunctionType, Vec<Instruction>>,
/// All the exported functions.
exports: HashMap<CoreFunctionType, ExportName>,
/// All the implementations.
adapter_type_to_core: MultiMap<AdapterFunctionType, CoreFunctionType>,
core_type_to_adapter: MultiMap<CoreFunctionType, AdapterFunctionType>,
}
#[allow(unused)]
impl FCEWITInterfaces {
pub fn new(interfaces: Interfaces) -> Self {
let imports = interfaces
.imports
.into_iter()
.map(|import| {
(
import.function_type,
(import.namespace.to_owned(), import.name.to_owned()),
)
})
.collect::<HashMap<_, _>>();
let adapters = interfaces
.adapters
.into_iter()
.map(|adapter| (adapter.function_type, adapter.instructions))
.collect::<HashMap<_, _>>();
let exports = interfaces
.exports
.into_iter()
.map(|export| (export.function_type, export.name.to_owned()))
.collect::<HashMap<_, _>>();
let adapter_type_to_core = interfaces
.implementations
.iter()
.map(|implementation| {
(
implementation.adapter_function_type,
implementation.core_function_type,
)
})
.collect::<MultiMap<_, _>>();
let core_type_to_adapter = interfaces
.implementations
.iter()
.map(|implementation| {
(
implementation.core_function_type,
implementation.adapter_function_type,
)
})
.collect::<MultiMap<_, _>>();
Self {
types: interfaces.types,
imports,
adapters,
exports,
adapter_type_to_core,
core_type_to_adapter,
}
}
pub fn type_by_idx(&self, idx: usize) -> Option<&Type> {
self.types.get(idx)
}
pub fn types(&self) -> impl Iterator<Item = &Type> {
self.types.iter()
}
pub fn import_by_type(
&self,
import_type: CoreFunctionType,
) -> Option<&(ImportName, ImportNamespace)> {
self.imports.get(&import_type)
}
pub fn imports(
&self,
) -> impl Iterator<Item = (&CoreFunctionType, &(ImportName, ImportNamespace))> {
self.imports.iter()
}
pub fn adapter_by_type(&self, adapter_type: AdapterFunctionType) -> Option<&Vec<Instruction>> {
self.adapters.get(&adapter_type)
}
pub fn export_by_type(&self, export_type: u32) -> Option<&ExportName> {
self.exports.get(&export_type)
}
pub fn adapter_func_implementations(
&self,
) -> impl Iterator<Item = (&AdapterFunctionType, &CoreFunctionType)> {
self.adapter_type_to_core.iter()
}
pub fn core_func_implementations(
&self,
) -> impl Iterator<Item = (&CoreFunctionType, &AdapterFunctionType)> {
self.core_type_to_adapter.iter()
}
pub fn adapter_types_by_core_type(
&self,
core_function_type: CoreFunctionType,
) -> Option<&Vec<AdapterFunctionType>> {
self.adapter_type_to_core.get_vec(&core_function_type)
}
pub fn core_types_by_adapter_type(
&self,
adapter_function_type: AdapterFunctionType,
) -> Option<&Vec<CoreFunctionType>> {
self.core_type_to_adapter.get_vec(&adapter_function_type)
}
}

View File

@ -0,0 +1,28 @@
/*
* 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 fce_wit_interfaces;
mod wit_parser;
pub use fce_wit_interfaces::FCEWITInterfaces;
pub mod types {
pub type CoreFunctionType = u32;
pub type AdapterFunctionType = u32;
pub type ExportName = String;
pub type ImportName = String;
pub type ImportNamespace = String;
}

View 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 std::borrow::Cow;
use walrus::{CustomSection, IdsToIndices};
pub const WIT_SECTION_NAME: &str = "interface-types";
#[derive(Debug, Clone)]
pub(crate) struct WITCustom(pub Vec<u8>);
impl CustomSection for WITCustom {
fn name(&self) -> &str {
WIT_SECTION_NAME
}
fn data(&self, _ids_to_indices: &IdsToIndices) -> Cow<[u8]> {
Cow::Borrowed(&self.0)
}
}

View File

@ -0,0 +1,52 @@
/*
* 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::custom::WITCustom;
use super::errors::WITParserError;
use walrus::ModuleConfig;
use wasmer_wit::{
decoders::wat::{parse, Buffer},
encoders::binary::ToBytes,
};
use std::path::PathBuf;
pub struct EmbedderConfig {
pub in_wasm_path: PathBuf,
pub out_wasm_path: PathBuf,
pub wit: String,
}
pub fn embed_text_wit(options: &EmbedderConfig) -> Result<(), WITParserError> {
let mut module = ModuleConfig::new()
.parse_file(&options.in_wasm_path)
.map_err(WITParserError::CorruptedWasmFile)?;
let buffer = Buffer::new(&options.wit)?;
let ast = parse(&buffer)?;
let mut bytes = vec![];
ast.to_bytes(&mut bytes)?;
let custom = WITCustom(bytes);
module.customs.add(custom);
module
.emit_wasm_file(&options.out_wasm_path)
.map_err(WITParserError::WasmEmitError)?;
Ok(())
}

View File

@ -0,0 +1,87 @@
/*
* 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_wit::decoders::wat::Error as WATError;
use std::io::Error as StdIOError;
use std::error::Error;
#[derive(Debug)]
pub enum WITParserError {
/// WIT section is absent.
NoWITSection,
/// Multiple WIT sections.
MultipleWITSections,
/// WIT section remainder isn't empty.
WITRemainderNotEmpty,
/// An error occurred while parsing WIT section.
CorruptedWITSection,
/// An error occurred while parsing file in Wat format.
CorruptedWATFile(WATError),
/// An error occurred while parsing Wasm file
CorruptedWasmFile(anyhow::Error),
/// An error occurred while manipulating with converting ast to bytes.
AstToBytesError(StdIOError),
// Wasm emittig file error.
WasmEmitError(anyhow::Error),
}
impl Error for WITParserError {}
impl std::fmt::Display for WITParserError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
WITParserError::NoWITSection => write!(f, "Loaded module doesn't contain WIT section"),
WITParserError::MultipleWITSections => write!(
f,
"Loaded module contains multiple WIT sections that is unsupported now"
),
WITParserError::WITRemainderNotEmpty => write!(
f,
"WIT section remainder isn't empty - WIT section possibly corrupted"
),
WITParserError::CorruptedWITSection => write!(f, "WIT section is corrupted"),
WITParserError::CorruptedWATFile(err) => {
write!(f, "an error occurred while parsing wat file: {}", err)
}
WITParserError::CorruptedWasmFile(err) => {
write!(f, "Failed to parse the Wasm module: {}", err)
}
WITParserError::AstToBytesError(err) => {
write!(f, "Wasm AST converting to bytes failed with: {}", err)
}
WITParserError::WasmEmitError(err) => write!(f, "Failed to emit Wasm file: {}", err),
}
}
}
impl From<WATError> for WITParserError {
fn from(err: WATError) -> Self {
WITParserError::CorruptedWATFile(err)
}
}
impl From<StdIOError> for WITParserError {
fn from(err: StdIOError) -> Self {
WITParserError::AstToBytesError(err)
}
}

View File

@ -0,0 +1,89 @@
/*
* 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::custom::WIT_SECTION_NAME;
use super::errors::WITParserError;
use crate::fce_wit_interfaces::FCEWITInterfaces;
use walrus::{IdsToIndices, Module, ModuleConfig};
use wasmer_wit::ast::Interfaces;
use std::path::PathBuf;
pub fn extract_text_wit(wasm_file_path: PathBuf) -> Result<String, WITParserError> {
extract_wit_with_fn(
wasm_file_path,
|wit: Interfaces| -> Result<String, WITParserError> { Ok((&wit).to_string()) },
)
}
pub fn extract_fce_wit(wasm_file_path: PathBuf) -> Result<FCEWITInterfaces, WITParserError> {
extract_wit_with_fn(
wasm_file_path,
|wit: Interfaces| -> Result<FCEWITInterfaces, WITParserError> {
Ok(FCEWITInterfaces::new(wit))
},
)
}
fn extract_wit_with_fn<F, FResultType>(
wasm_file_path: PathBuf,
func: F,
) -> Result<FResultType, WITParserError>
where
F: FnOnce(Interfaces) -> Result<FResultType, WITParserError>,
{
let wit_section_bytes = extract_wit_section_bytes(wasm_file_path)?;
let raw_wit = extract_raw_interfaces(&wit_section_bytes)?;
func(raw_wit)
}
fn extract_raw_interfaces(wit_section_bytes: &[u8]) -> Result<Interfaces, WITParserError> {
let wit = match wasmer_wit::decoders::binary::parse::<()>(&wit_section_bytes) {
Ok((remainder, wit)) if remainder.is_empty() => wit,
Ok(_) => {
return Err(WITParserError::WITRemainderNotEmpty);
}
Err(_) => {
return Err(WITParserError::CorruptedWITSection);
}
};
Ok(wit)
}
fn extract_wit_section_bytes(wasm_file_path: PathBuf) -> Result<Vec<u8>, WITParserError> {
let module = ModuleConfig::new()
.parse_file(wasm_file_path)
.map_err(WITParserError::CorruptedWasmFile)?;
let sections = module
.customs
.iter()
.filter(|(_, section)| section.name() == WIT_SECTION_NAME)
.collect::<Vec<_>>();
if sections.is_empty() {
return Err(WITParserError::NoWITSection);
}
if sections.len() > 1 {
return Err(WITParserError::MultipleWITSections);
}
let default_ids = IdsToIndices::default();
Ok(sections[0].1.data(&default_ids).into_owned())
}

View File

@ -0,0 +1,6 @@
mod custom;
mod errors;
mod extracter;
mod embedder;
pub use errors::WITParserError;

View File

@ -7,8 +7,6 @@ edition = "2018"
[dependencies]
walrus = "0.17.0"
wasmer-wit = { package = "wasmer-interface-types", git = "https://github.com/fluencelabs/interface-types", branch = "master"}
options = "0.5.1"
either = "1.5.3"
clap = "2.33.1"
exitfailure = "0.5.1"
failure = "0.1.5"

View File

@ -1,8 +1,22 @@
/*
* Copyright 2020 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use std::borrow::Cow;
use walrus::{CustomSection, IdsToIndices};
pub const WIT_SECTION_NAME: &str = "interface-types";
#[derive(Debug, Clone)]
pub(crate) struct WITCustom(pub Vec<u8>);

View File

@ -1,3 +1,19 @@
/*
* 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::custom::WITCustom;
use walrus::ModuleConfig;
@ -10,8 +26,8 @@ use std::path::PathBuf;
pub struct Config {
pub in_wasm_path: PathBuf,
pub wit: String,
pub out_wasm_path: PathBuf,
pub wit: String,
}
pub fn embed_wit(options: &Config) -> Result<(), String> {

View File

@ -1,3 +1,19 @@
/*
* 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::custom::WIT_SECTION_NAME;
use walrus::{IdsToIndices, ModuleConfig};

View File

@ -1,3 +1,19 @@
/*
* 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 custom;
mod embedder;
mod extracter;