2020-07-09 15:55:58 +03:00
|
|
|
/*
|
|
|
|
* 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::default_export_api_config::*;
|
2020-07-09 20:27:50 +03:00
|
|
|
use crate::errors::WITGeneratorError;
|
|
|
|
use crate::instructions_generator::WITGenerator;
|
2020-09-16 01:14:15 +03:00
|
|
|
use crate::instructions_generator::WITResolver;
|
2020-07-09 20:27:50 +03:00
|
|
|
use crate::Result;
|
2020-07-09 15:55:58 +03:00
|
|
|
|
2021-04-26 14:02:26 +03:00
|
|
|
pub use fluence_sdk_wit::SDKAst;
|
2020-07-09 15:55:58 +03:00
|
|
|
use wasmer_wit::ast::Interfaces;
|
2020-12-29 17:51:13 +03:00
|
|
|
use wasmer_wit::IRecordType;
|
|
|
|
use wasmer_wit::IType;
|
2020-07-09 15:55:58 +03:00
|
|
|
|
|
|
|
/// Parse generated by rust-sdk AST types, generate instructions and embed them to Wasm file.
|
2020-07-09 20:27:50 +03:00
|
|
|
pub fn embed_wit(path: std::path::PathBuf) -> Result<()> {
|
2020-07-09 15:55:58 +03:00
|
|
|
let wasm_module = walrus::ModuleConfig::new()
|
|
|
|
.parse_file(path.clone())
|
2020-07-09 20:27:50 +03:00
|
|
|
.map_err(|e| WITGeneratorError::IOError(format!("{:?} can't be parsed: {:?}", path, e)))?;
|
|
|
|
|
2020-07-26 19:38:11 +03:00
|
|
|
let module_ast = wasm_ast_extractor(&wasm_module)?;
|
|
|
|
let interfaces = generate_interfaces(&module_ast)?;
|
2020-07-09 15:55:58 +03:00
|
|
|
|
2020-07-28 19:14:53 +03:00
|
|
|
let wasm_module = fce_wit_parser::delete_wit_section(wasm_module);
|
|
|
|
let mut wasm_module = fce_wit_parser::embed_wit(wasm_module, &interfaces);
|
2020-07-11 23:04:55 +03:00
|
|
|
|
2020-07-09 20:27:50 +03:00
|
|
|
wasm_module.emit_wasm_file(path).map_err(|e| {
|
2020-07-26 19:38:11 +03:00
|
|
|
WITGeneratorError::IOError(format!("resulted Wasm file can't be emitted: {:?}", e))
|
2020-07-09 20:27:50 +03:00
|
|
|
})
|
2020-07-09 15:55:58 +03:00
|
|
|
}
|
|
|
|
|
2020-07-26 19:38:11 +03:00
|
|
|
pub(crate) struct ModuleAST {
|
2021-04-26 14:02:26 +03:00
|
|
|
pub(crate) records: Vec<fluence_sdk_wit::RecordType>,
|
|
|
|
pub(crate) functions: Vec<fluence_sdk_wit::FnType>,
|
|
|
|
pub(crate) extern_mods: Vec<fluence_sdk_wit::ExternModType>,
|
2020-07-26 19:38:11 +03:00
|
|
|
}
|
|
|
|
|
2020-07-09 15:55:58 +03:00
|
|
|
/// Extract all custom AST types previously embedded by rust-sdk from compiled binary.
|
2020-07-26 19:38:11 +03:00
|
|
|
fn wasm_ast_extractor(wasm_module: &walrus::Module) -> Result<ModuleAST> {
|
|
|
|
use fluence_sdk_wit::*;
|
|
|
|
|
2021-04-26 14:02:26 +03:00
|
|
|
let mut records: Vec<RecordType> = Vec::new();
|
|
|
|
let mut functions: Vec<FnType> = Vec::new();
|
|
|
|
let mut extern_mods: Vec<ExternModType> = Vec::new();
|
2020-07-09 15:55:58 +03:00
|
|
|
|
|
|
|
// consider only sections name of that starts with GENERATED_SECTION_PREFIX
|
|
|
|
for custom_module in wasm_module.customs.iter().filter(|(_, section)| {
|
|
|
|
section
|
|
|
|
.name()
|
|
|
|
.starts_with(fluence_sdk_wit::GENERATED_SECTION_PREFIX)
|
|
|
|
}) {
|
|
|
|
let default_ids = walrus::IdsToIndices::default();
|
|
|
|
let raw_data = custom_module.1.data(&default_ids);
|
2021-04-26 14:02:26 +03:00
|
|
|
let decoded_json: SDKAst = serde_json::from_slice(&raw_data)?;
|
2020-07-26 19:38:11 +03:00
|
|
|
match decoded_json {
|
2021-04-26 14:02:26 +03:00
|
|
|
SDKAst::Record(record) => records.push(record),
|
|
|
|
SDKAst::Function(function) => functions.push(function),
|
|
|
|
SDKAst::ExternMod(extern_mod) => extern_mods.push(extern_mod),
|
2020-07-26 19:38:11 +03:00
|
|
|
}
|
2020-07-09 15:55:58 +03:00
|
|
|
}
|
|
|
|
|
2020-07-26 19:38:11 +03:00
|
|
|
Ok(ModuleAST {
|
|
|
|
records,
|
|
|
|
functions,
|
|
|
|
extern_mods,
|
|
|
|
})
|
2020-07-09 15:55:58 +03:00
|
|
|
}
|
|
|
|
|
2020-07-26 19:38:11 +03:00
|
|
|
fn generate_interfaces(module_ast: &ModuleAST) -> Result<Interfaces<'_>> {
|
2020-09-16 01:14:15 +03:00
|
|
|
let mut wit_resolver = WITResolver::default();
|
2020-07-26 19:38:11 +03:00
|
|
|
generate_default_export_api(&mut wit_resolver.interfaces);
|
2020-07-09 15:55:58 +03:00
|
|
|
|
2020-07-26 19:38:11 +03:00
|
|
|
for record in &module_ast.records {
|
|
|
|
record.generate_wit(&mut wit_resolver)?;
|
|
|
|
}
|
2020-09-16 01:14:15 +03:00
|
|
|
validate_records(&wit_resolver)?;
|
|
|
|
|
2020-07-26 19:38:11 +03:00
|
|
|
for function in &module_ast.functions {
|
|
|
|
function.generate_wit(&mut wit_resolver)?;
|
|
|
|
}
|
|
|
|
for extern_mod in &module_ast.extern_mods {
|
|
|
|
extern_mod.generate_wit(&mut wit_resolver)?;
|
2020-07-09 15:55:58 +03:00
|
|
|
}
|
|
|
|
|
2020-07-26 19:38:11 +03:00
|
|
|
Ok(wit_resolver.interfaces)
|
2020-07-09 15:55:58 +03:00
|
|
|
}
|
|
|
|
|
2020-11-05 20:58:13 +03:00
|
|
|
fn generate_default_export_api(interfaces: &mut Interfaces<'_>) {
|
2020-07-11 23:04:55 +03:00
|
|
|
// TODO: the order is matter
|
2020-07-09 15:55:58 +03:00
|
|
|
ALLOCATE_FUNC.update_interfaces(interfaces);
|
2021-04-12 00:21:47 +03:00
|
|
|
RELEASE_OBJECTS.update_interfaces(interfaces);
|
2020-07-09 15:55:58 +03:00
|
|
|
GET_RESULT_SIZE_FUNC.update_interfaces(interfaces);
|
|
|
|
GET_RESULT_PTR_FUNC.update_interfaces(interfaces);
|
2020-07-11 23:04:55 +03:00
|
|
|
SET_RESULT_SIZE_FUNC.update_interfaces(interfaces);
|
|
|
|
SET_RESULT_PTR_FUNC.update_interfaces(interfaces);
|
2020-07-09 15:55:58 +03:00
|
|
|
}
|
2020-09-16 01:14:15 +03:00
|
|
|
|
2020-11-05 20:58:13 +03:00
|
|
|
fn validate_records(wit_resolver: &WITResolver<'_>) -> Result<()> {
|
2020-09-16 01:14:15 +03:00
|
|
|
fn validate_record_type(
|
2020-12-29 17:51:13 +03:00
|
|
|
record_type: &IRecordType,
|
2020-09-16 01:14:15 +03:00
|
|
|
recursion_level: u32,
|
2020-11-05 20:58:13 +03:00
|
|
|
wit_resolver: &WITResolver<'_>,
|
2020-09-16 01:14:15 +03:00
|
|
|
) -> Result<()> {
|
2021-01-16 00:44:09 +03:00
|
|
|
if recursion_level >= crate::TYPE_RESOLVE_RECURSION_LIMIT {
|
2020-09-16 01:14:15 +03:00
|
|
|
return Err(WITGeneratorError::CorruptedRecord(String::from(
|
|
|
|
"too many inner structures level",
|
|
|
|
)));
|
|
|
|
}
|
|
|
|
|
|
|
|
for field in record_type.fields.iter() {
|
|
|
|
match &field.ty {
|
2020-12-29 17:51:13 +03:00
|
|
|
IType::Record(record_type_id) => {
|
2020-09-16 01:14:15 +03:00
|
|
|
let inner_record_type = wit_resolver.get_record_type(*record_type_id)?;
|
|
|
|
validate_record_type(&inner_record_type, recursion_level + 1, wit_resolver)?;
|
|
|
|
}
|
|
|
|
_ => continue,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
if wit_resolver.unresolved_types_count() != 0 {
|
|
|
|
return Err(WITGeneratorError::CorruptedRecord(format!(
|
|
|
|
"{} types unresolved",
|
|
|
|
wit_resolver.unresolved_types_count()
|
|
|
|
)));
|
|
|
|
}
|
|
|
|
|
|
|
|
for ty in wit_resolver.interfaces.types.iter() {
|
|
|
|
let record_type = match ty {
|
|
|
|
wasmer_wit::ast::Type::Record(ty) => ty,
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
|
|
|
|
validate_record_type(record_type, 0, wit_resolver)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|