simplify fce_wit_interfaces

This commit is contained in:
vms 2020-06-04 19:54:23 +03:00
parent 6a7dbb47c8
commit 59f9b7555f
8 changed files with 188 additions and 64 deletions

View File

@ -0,0 +1,61 @@
/*
* 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::error::Error;
#[derive(Debug)]
pub enum FCEWITInterfacesError {
/// WIT doesn't contain such type.
NoSuchType(u32),
/// WIT doesn't contain such export.
NoSuchExport(u32),
/// WIT doesn't contain such import.
NoSuchImport(u32),
/// WIT doesn't contain such import.
NoSuchAdapter(u32),
}
impl Error for FCEWITInterfacesError {}
impl std::fmt::Display for FCEWITInterfacesError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
FCEWITInterfacesError::NoSuchType(type_id) => write!(
f,
"Loaded module doesn't contain type with idx = {}",
type_id
),
FCEWITInterfacesError::NoSuchExport(export_type_id) => write!(
f,
"Loaded module doesn't contain export with type idx = {}",
export_type_id
),
FCEWITInterfacesError::NoSuchImport(import_type_id) => write!(
f,
"Loaded module doesn't contain import with type idx = {}",
import_type_id
),
FCEWITInterfacesError::NoSuchAdapter(adapter_type_id) => write!(
f,
"Loaded module doesn't contain adapter with type idx = {}",
adapter_type_id
),
}
}
}

View File

@ -14,6 +14,8 @@
* limitations under the License.
*/
use super::errors::FCEWITInterfacesError;
use wasmer_wit::interpreter::Instruction;
use wasmer_wit::ast::*;
use multimap::MultiMap;
@ -98,12 +100,24 @@ impl<'a> FCEWITInterfaces<'a> {
}
}
pub fn types(&self) -> impl Iterator<Item = &Type> {
self.types.iter()
}
pub fn type_by_idx(&self, idx: u32) -> Option<&Type> {
self.types.get(idx as usize)
}
pub fn types(&self) -> impl Iterator<Item = &Type> {
self.types.iter()
pub fn type_by_idx_r(&self, idx: u32) -> Result<&Type, FCEWITInterfacesError> {
self.types
.get(idx as usize)
.ok_or_else(|| FCEWITInterfacesError::NoSuchType(idx))
}
pub fn imports(
&self,
) -> impl Iterator<Item = (&CoreFunctionType, &(ImportName<'a>, ImportNamespace<'a>))> {
self.imports.iter()
}
pub fn import_by_type(
@ -113,23 +127,37 @@ impl<'a> FCEWITInterfaces<'a> {
self.imports.get(&import_type)
}
pub fn imports(
pub fn import_by_type_r(
&self,
) -> impl Iterator<Item = (&CoreFunctionType, &(ImportName<'a>, ImportNamespace<'a>))> {
self.imports.iter()
import_type: CoreFunctionType,
) -> Result<&(ImportName<'a>, ImportNamespace<'a>), FCEWITInterfacesError> {
self.imports
.get(&import_type)
.ok_or_else(|| FCEWITInterfacesError::NoSuchImport(import_type))
}
pub fn adapters(&self) -> impl Iterator<Item = (&AdapterFunctionType, &Vec<Instruction>)> {
self.adapters.iter()
}
pub fn adapter_by_type(&self, adapter_type: AdapterFunctionType) -> Option<&Vec<Instruction>> {
self.adapters.get(&adapter_type)
}
pub fn adapter_by_type_r(
&self,
adapter_type: AdapterFunctionType,
) -> Result<&Vec<Instruction>, FCEWITInterfacesError> {
self.adapters
.get(&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()
}

View File

@ -0,0 +1,21 @@
/*
* 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 errors;
mod fce_wit_interfaces;
pub use fce_wit_interfaces::*;
pub use errors::*;

View File

@ -24,8 +24,8 @@
unreachable_patterns
)]
mod fce_wit_interfaces;
mod interfaces;
mod wit_parser;
pub use crate::wit_parser::*;
pub use crate::fce_wit_interfaces::*;
pub use crate::interfaces::*;

View File

@ -16,7 +16,7 @@
use super::custom::WIT_SECTION_NAME;
use super::errors::WITParserError;
use crate::fce_wit_interfaces::FCEWITInterfaces;
use crate::interfaces::FCEWITInterfaces;
use walrus::{IdsToIndices, ModuleConfig};
use wasmer_wit::ast::Interfaces;

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 errors;
mod extractor;

View File

@ -15,6 +15,8 @@
*/
use fce_wit_interfaces::WITParserError;
use fce_wit_interfaces::FCEWITInterfacesError;
use wasmer_wit::errors::InstructionError;
use wasmer_runtime::error::{
CallError, CompileError, CreationError, Error as WasmerError, ResolveError, RuntimeError,
@ -134,3 +136,15 @@ impl From<WITParserError> for FCEError {
FCEError::WITParseError(err)
}
}
impl From<FCEWITInterfacesError> for FCEError {
fn from(err: FCEWITInterfacesError) -> Self {
FCEError::IncorrectWIT(format!("{}", err))
}
}
impl From<()> for FCEError {
fn from(_err: ()) -> Self {
FCEError::IncorrectWIT(format!("failed to parse instructions for adapter type"))
}
}

View File

@ -115,33 +115,25 @@ impl FCEModule {
) -> Result<HashMap<String, WITModuleFunc>, FCEError> {
use fce_wit_interfaces::WITAstType;
wit
.implementations()
.filter_map(|(adapter_function_type, core_function_type)|
wit.implementations()
.filter_map(|(adapter_function_type, core_function_type)| {
match wit.export_by_type(*core_function_type) {
Some(export_function_name) => Some((adapter_function_type, *export_function_name)),
Some(export_function_name) => {
Some((adapter_function_type, *export_function_name))
}
// pass functions that aren't export
None => None
None => None,
}
)
})
.map(|(adapter_function_type, export_function_name)| {
let adapter_instructions = wit.adapter_by_type(*adapter_function_type)
.ok_or_else(|| FCEError::IncorrectWIT(
format!("adapter function with idx = {} hasn't been found during extracting exports by implementations", adapter_function_type)
))?;
let wit_type = wit.type_by_idx(*adapter_function_type).ok_or_else(
// TODO: change error type
|| FCEError::IncorrectWIT(format!(
"{} function id is bigger than WIT interface types count",
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)?;
match wit_type {
WITAstType::Function { inputs, outputs, .. } => {
let interpreter: WITInterpreter = adapter_instructions.try_into().map_err(|_| FCEError::IncorrectWIT(
format!("failed to parse instructions for adapter type {}", adapter_function_type)
))?;
WITAstType::Function {
inputs, outputs, ..
} => {
let interpreter: WITInterpreter = adapter_instructions.try_into()?;
Ok((
export_function_name.to_string(),
@ -149,13 +141,13 @@ impl FCEModule {
interpreter,
inputs: inputs.clone(),
outputs: outputs.clone(),
}
},
))
},
}
_ => Err(FCEError::IncorrectWIT(format!(
"type with idx = {} isn't a function type",
adapter_function_type
)))
))),
}
})
.collect::<Result<HashMap<String, WITModuleFunc>, FCEError>>()
@ -167,25 +159,29 @@ impl FCEModule {
wit_instance: Arc<MaybeUninit<WITInstance>>,
) -> Result<ImportObject, FCEError> {
use fce_wit_interfaces::WITAstType;
use super::type_converters::{itype_to_wtype, wval_to_ival};
use wasmer_core::typed_func::DynamicFunc;
use wasmer_core::types::FuncSig;
use wasmer_core::vm::Ctx;
// returns function that will be called from imports of Wasmer module
fn dyn_func_from_imports(
fn dyn_func_from_raw_import(
inputs: Vec<IType>,
func: Box<dyn Fn(&mut Ctx, &[WValue]) -> Vec<WValue> + 'static>,
) -> DynamicFunc<'static> {
use wasmer_core::types::FuncSig;
use super::type_converters::itype_to_wtype;
let signature = inputs.iter().map(itype_to_wtype).collect::<Vec<_>>();
DynamicFunc::new(Arc::new(FuncSig::new(signature, vec![])), func)
}
// creates a closure that is represent a WIT module import
fn create_raw_import(
wit_instance: Arc<MaybeUninit<WITInstance>>,
interpreter: WITInterpreter,
) -> Box<dyn for<'a, 'b> Fn(&'a mut Ctx, &'b [WValue]) -> Vec<WValue> + 'static> {
Box::new(move |_: &mut Ctx, inputs: &[WValue]| -> Vec<WValue> {
use super::type_converters::wval_to_ival;
// copy here because otherwise wit_instance will be consumed by the closure
let wit_instance_callable = wit_instance.clone();
let converted_inputs = inputs.iter().map(wval_to_ival).collect::<Vec<_>>();
@ -205,47 +201,35 @@ impl FCEModule {
let namespaces = wit
.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) {
Some(import) => Some((adapter_function_type, *import)),
// pass functions that aren't export
None => None
// skip functions that aren't export
None => None,
}
)
})
.map(|(adapter_function_type, (import_namespace, import_name))| {
let adapter_instructions = wit.adapter_by_type(*adapter_function_type)
.ok_or_else(|| FCEError::IncorrectWIT(
format!("adapter function with idx = {} hasn't been found during extracting adjusting wit imports", adapter_function_type)
))?;
let wit_type = wit.type_by_idx(*adapter_function_type).ok_or_else(
|| FCEError::IncorrectWIT(format!(
"{} function id is bigger than WIT interface types count",
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)?;
match wit_type {
WITAstType::Function { inputs, .. } => {
let interpreter: WITInterpreter = adapter_instructions.try_into().map_err(|_| FCEError::IncorrectWIT(
format!("failed to parse instructions for adapter type {}", adapter_function_type)
))?;
let interpreter: WITInterpreter = adapter_instructions.try_into()?;
let inner_import = create_raw_import(wit_instance.clone(), interpreter);
let wit_import = dyn_func_from_imports(inputs.clone(), inner_import);
let wit_import = dyn_func_from_raw_import(inputs.clone(), inner_import);
let mut namespace = Namespace::new();
namespace.insert(import_name, wit_import);
Ok((
import_namespace.to_string(),
namespace
))
},
Ok((import_namespace.to_string(), namespace))
}
_ => Err(FCEError::IncorrectWIT(format!(
"type with idx = {} isn't a function type",
adapter_function_type
)))
))),
}
}).collect::<Result<HashMap<String, Namespace>, FCEError>>()?;
})
.collect::<Result<HashMap<String, Namespace>, FCEError>>()?;
let mut import_object = ImportObject::new();