wit refactoring

This commit is contained in:
vms 2020-07-09 15:55:58 +03:00
parent d524eebc55
commit 9a02ffc54f
26 changed files with 497 additions and 483 deletions

38
Cargo.lock generated
View File

@ -376,7 +376,7 @@ dependencies = [
"parity-wasm", "parity-wasm",
"pwasm-utils", "pwasm-utils",
"serde", "serde",
"wasmer-interface-types", "wasmer-interface-types 0.17.0 (git+https://github.com/fluencelabs/interface-types)",
"wasmer-runtime", "wasmer-runtime",
"wasmer-runtime-core", "wasmer-runtime-core",
"wasmer-wasi", "wasmer-wasi",
@ -388,7 +388,7 @@ name = "fce-wit-interfaces"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"multimap", "multimap",
"wasmer-interface-types", "wasmer-interface-types 0.17.0 (git+https://github.com/fluencelabs/interface-types)",
] ]
[[package]] [[package]]
@ -423,7 +423,7 @@ dependencies = [
[[package]] [[package]]
name = "fluence-sdk-wit" name = "fluence-sdk-wit"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/fluencelabs/rust-sdk#d3f5a15730f97f642f07d64f50efab061218cc9f" source = "git+https://github.com/fluencelabs/rust-sdk#bee1983d97da6acc53fecf8b6695810410502b8d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -431,7 +431,6 @@ dependencies = [
"serde_json", "serde_json",
"syn", "syn",
"uuid", "uuid",
"wasmer-interface-types",
] ]
[[package]] [[package]]
@ -711,6 +710,12 @@ version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
[[package]]
name = "once_cell"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d"
[[package]] [[package]]
name = "page_size" name = "page_size"
version = "0.4.2" version = "0.4.2"
@ -1228,6 +1233,16 @@ dependencies = [
"wasmparser 0.51.4", "wasmparser 0.51.4",
] ]
[[package]]
name = "wasmer-interface-types"
version = "0.17.0"
source = "git+http://github.com/fluencelabs/interface-types?branch=byte_array#bb9e4dbdfc0da6e6803392664a1c34284e418a58"
dependencies = [
"nom",
"serde",
"wast",
]
[[package]] [[package]]
name = "wasmer-interface-types" name = "wasmer-interface-types"
version = "0.17.0" version = "0.17.0"
@ -1357,10 +1372,11 @@ name = "wit-generator"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fluence-sdk-wit", "fluence-sdk-wit",
"once_cell",
"serde", "serde",
"serde_json", "serde_json",
"walrus", "walrus",
"wasmer-interface-types", "wasmer-interface-types 0.17.0 (git+http://github.com/fluencelabs/interface-types?branch=byte_array)",
"wit-parser", "wit-parser",
] ]
@ -1371,16 +1387,6 @@ dependencies = [
"anyhow", "anyhow",
"fce-wit-interfaces", "fce-wit-interfaces",
"walrus", "walrus",
"wasmer-interface-types", "wasmer-interface-types 0.17.0 (git+http://github.com/fluencelabs/interface-types?branch=byte_array)",
"wasmer-runtime-core", "wasmer-runtime-core",
] ]
[[package]]
name = "wit_embedder"
version = "0.1.0"
dependencies = [
"clap",
"exitfailure",
"failure",
"wit-parser",
]

View File

@ -9,8 +9,7 @@ members = [
"examples/ipfs_node/wasm/ipfs_rpc", "examples/ipfs_node/wasm/ipfs_rpc",
"examples/simple_greeting", "examples/simple_greeting",
"fluence-faas", "fluence-faas",
"tools/fce-cli", "tools/cli",
"tools/wit_embedder",
] ]
[profile.release] [profile.release]

View File

@ -8,6 +8,7 @@ edition = "2018"
wit-parser = { path = "../wit-parser" } wit-parser = { path = "../wit-parser" }
walrus = "0.17.0" walrus = "0.17.0"
fluence-sdk-wit = { git = "https://github.com/fluencelabs/rust-sdk" } fluence-sdk-wit = { git = "https://github.com/fluencelabs/rust-sdk" }
wasmer-wit = { package = "wasmer-interface-types", git = "http://github.com/fluencelabs/interface-types", branch = "master", features = ["serde"] } once_cell = "1.4.0"
wasmer-wit = { package = "wasmer-interface-types", git = "http://github.com/fluencelabs/interface-types", branch = "byte_array", features = ["serde"] }
serde = { version = "1.0.110", features = ["derive"] } serde = { version = "1.0.110", features = ["derive"] }
serde_json = "1.0.56" serde_json = "1.0.56"

View File

@ -0,0 +1,90 @@
/*
* 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::ast::Interfaces;
use wasmer_wit::types::InterfaceType as IType;
use once_cell::sync::Lazy;
pub(crate) struct ApiExportFuncDescriptor {
pub(crate) name: &'static str,
pub(crate) id: u32,
pub(crate) input_types: Vec<IType>,
pub(crate) output_types: Vec<IType>,
}
impl ApiExportFuncDescriptor {
pub fn update_interfaces(&self, interfaces: &mut Interfaces<'_>) {
let func_type = wasmer_wit::ast::Type::Function {
inputs: self.input_types.clone(),
outputs: self.output_types.clone(),
};
interfaces.types.push(func_type);
let export = wasmer_wit::ast::Export {
name: self.name,
function_type: self.id,
};
interfaces.exports.push(export);
}
}
pub(crate) static ALLOCATE_FUNC: Lazy<ApiExportFuncDescriptor> =
Lazy::new(|| ApiExportFuncDescriptor {
name: "allocate",
id: 0,
input_types: vec![IType::I32],
output_types: vec![IType::I32],
});
pub(crate) static DEALLOCATE_FUNC: Lazy<ApiExportFuncDescriptor> =
Lazy::new(|| ApiExportFuncDescriptor {
name: "deallocate",
id: 1,
input_types: vec![IType::I32, IType::I32],
output_types: vec![],
});
pub(crate) static GET_RESULT_SIZE_FUNC: Lazy<ApiExportFuncDescriptor> =
Lazy::new(|| ApiExportFuncDescriptor {
name: "get_result_size",
id: 2,
input_types: vec![],
output_types: vec![IType::I32],
});
pub(crate) static GET_RESULT_PTR_FUNC: Lazy<ApiExportFuncDescriptor> =
Lazy::new(|| ApiExportFuncDescriptor {
name: "get_result_ptr",
id: 3,
input_types: vec![],
output_types: vec![IType::I32],
});
pub(crate) static SET_RESULT_SIZE_FUNC: Lazy<ApiExportFuncDescriptor> =
Lazy::new(|| ApiExportFuncDescriptor {
name: "set_result_size",
id: 4,
input_types: vec![IType::I32],
output_types: vec![],
});
pub(crate) static SET_RESULT_PTR_FUNC: Lazy<ApiExportFuncDescriptor> =
Lazy::new(|| ApiExportFuncDescriptor {
name: "set_result_ptr",
id: 5,
input_types: vec![IType::I32],
output_types: vec![],
});

View File

@ -1,9 +1,25 @@
mod fn_wit_generator; /*
mod foreign_mod_wit_generator; * Copyright 2020 Fluence Labs Limited
mod record_wit_generator; *
* 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 fn_instructions;
mod foreign_mod_instructions;
mod record_instructions;
mod utils; mod utils;
use super::FCEAst; use fluence_sdk_wit::FCEAst;
use wasmer_wit::types::InterfaceType as IType; use wasmer_wit::types::InterfaceType as IType;
use wasmer_wit::ast::Interfaces; use wasmer_wit::ast::Interfaces;

View File

@ -1,7 +1,24 @@
/*
* 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::WITGenerator; use super::WITGenerator;
use super::Interfaces; use super::Interfaces;
use super::utils::ptype_to_itype;
use super::FnInstructionGenerator; use super::FnInstructionGenerator;
use super::utils::ptype_to_itype;
use crate::default_export_api_config::*;
use fluence_sdk_wit::AstFunctionItem; use fluence_sdk_wit::AstFunctionItem;
use fluence_sdk_wit::ParsedType; use fluence_sdk_wit::ParsedType;
@ -75,6 +92,7 @@ impl WITGenerator for AstFunctionItem {
} }
impl FnInstructionGenerator for ParsedType { impl FnInstructionGenerator for ParsedType {
#[rustfmt::skip]
fn generate_instructions_for_input_type(&self, index: u32) -> Vec<Instruction> { fn generate_instructions_for_input_type(&self, index: u32) -> Vec<Instruction> {
match self { match self {
ParsedType::I8 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS8], ParsedType::I8 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS8],
@ -90,14 +108,14 @@ impl FnInstructionGenerator for ParsedType {
ParsedType::Utf8String => vec![ ParsedType::Utf8String => vec![
Instruction::ArgumentGet { index }, Instruction::ArgumentGet { index },
Instruction::StringSize, Instruction::StringSize,
Instruction::CallCore { function_index: 0 }, Instruction::CallCore { function_index: ALLOCATE_FUNC.id },
Instruction::ArgumentGet { index }, Instruction::ArgumentGet { index },
Instruction::StringLowerMemory, Instruction::StringLowerMemory,
], ],
ParsedType::ByteVector => vec![ ParsedType::ByteVector => vec![
Instruction::ArgumentGet { index }, Instruction::ArgumentGet { index },
Instruction::StringSize, Instruction::StringSize,
Instruction::CallCore { function_index: 0 }, Instruction::CallCore { function_index: ALLOCATE_FUNC.id },
Instruction::ArgumentGet { index }, Instruction::ArgumentGet { index },
Instruction::StringLowerMemory, Instruction::StringLowerMemory,
], ],
@ -105,6 +123,7 @@ impl FnInstructionGenerator for ParsedType {
} }
} }
#[rustfmt::skip]
fn generate_instructions_for_output_type(&self) -> Vec<Instruction> { fn generate_instructions_for_output_type(&self) -> Vec<Instruction> {
match self { match self {
ParsedType::I8 => vec![Instruction::S8FromI32], ParsedType::I8 => vec![Instruction::S8FromI32],
@ -118,20 +137,20 @@ impl FnInstructionGenerator for ParsedType {
ParsedType::F32 => vec![], ParsedType::F32 => vec![],
ParsedType::F64 => vec![], ParsedType::F64 => vec![],
ParsedType::Utf8String => vec![ ParsedType::Utf8String => vec![
Instruction::CallCore { function_index: 3 }, Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id },
Instruction::CallCore { function_index: 2 }, Instruction::CallCore { function_index: GET_RESULT_SIZE_FUNC.id },
Instruction::StringLiftMemory, Instruction::StringLiftMemory,
Instruction::CallCore { function_index: 3 }, Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id },
Instruction::CallCore { function_index: 2 }, Instruction::CallCore { function_index: GET_RESULT_SIZE_FUNC.id },
Instruction::CallCore { function_index: 1 }, Instruction::CallCore { function_index: DEALLOCATE_FUNC.id },
], ],
ParsedType::ByteVector => vec![ ParsedType::ByteVector => vec![
Instruction::CallCore { function_index: 3 }, Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id },
Instruction::CallCore { function_index: 2 }, Instruction::CallCore { function_index: GET_RESULT_SIZE_FUNC.id },
Instruction::StringLiftMemory, Instruction::ByteArrayLiftMemory,
Instruction::CallCore { function_index: 3 }, Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id },
Instruction::CallCore { function_index: 2 }, Instruction::CallCore { function_index: GET_RESULT_SIZE_FUNC.id },
Instruction::CallCore { function_index: 1 }, Instruction::CallCore { function_index: DEALLOCATE_FUNC.id },
], ],
_ => unimplemented!(), _ => unimplemented!(),
} }

View File

@ -1,7 +1,24 @@
/*
* 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::WITGenerator; use super::WITGenerator;
use super::Interfaces; use super::Interfaces;
use super::utils::ptype_to_itype; use super::utils::ptype_to_itype;
use super::ForeignModInstructionGenerator; use super::ForeignModInstructionGenerator;
use crate::default_export_api_config::*;
use fluence_sdk_wit::AstExternModItem; use fluence_sdk_wit::AstExternModItem;
use fluence_sdk_wit::AstExternFnItem; use fluence_sdk_wit::AstExternFnItem;
@ -18,7 +35,7 @@ impl WITGenerator for AstExternModItem {
fn generate_wit_for_import<'a>( fn generate_wit_for_import<'a>(
import: &'a AstExternFnItem, import: &'a AstExternFnItem,
namespace: &'a String, namespace: &'a str,
interfaces: &mut Interfaces<'a>, interfaces: &mut Interfaces<'a>,
) { ) {
use wasmer_wit::ast::Type; use wasmer_wit::ast::Type;
@ -111,6 +128,7 @@ impl ForeignModInstructionGenerator for ParsedType {
} }
} }
#[rustfmt::skip]
fn generate_instructions_for_output_type(&self) -> Vec<Instruction> { fn generate_instructions_for_output_type(&self) -> Vec<Instruction> {
match self { match self {
ParsedType::I8 => vec![Instruction::I32FromS8], ParsedType::I8 => vec![Instruction::I32FromS8],
@ -126,20 +144,20 @@ impl ForeignModInstructionGenerator for ParsedType {
ParsedType::Utf8String => vec![ ParsedType::Utf8String => vec![
Instruction::Dup, Instruction::Dup,
Instruction::StringSize, Instruction::StringSize,
Instruction::CallCore { function_index: 0 }, Instruction::CallCore { function_index: ALLOCATE_FUNC.id },
Instruction::Swap2, Instruction::Swap2,
Instruction::StringLowerMemory, Instruction::StringLowerMemory,
Instruction::CallCore { function_index: 4 }, Instruction::CallCore { function_index: SET_RESULT_SIZE_FUNC.id },
Instruction::CallCore { function_index: 5 }, Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.id },
], ],
ParsedType::ByteVector => vec![ ParsedType::ByteVector => vec![
Instruction::Dup, Instruction::Dup,
Instruction::StringSize, Instruction::ByteArraySize,
Instruction::CallCore { function_index: 0 }, Instruction::CallCore { function_index: ALLOCATE_FUNC.id },
Instruction::Swap2, Instruction::Swap2,
Instruction::StringLowerMemory, Instruction::ByteArrayLowerMemory,
Instruction::CallCore { function_index: 4 }, Instruction::CallCore { function_index: SET_RESULT_SIZE_FUNC.id },
Instruction::CallCore { function_index: 5 }, Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.id },
], ],
_ => unimplemented!(), _ => unimplemented!(),
} }

View File

@ -0,0 +1,26 @@
/*
* 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::WITGenerator;
use super::Interfaces;
use fluence_sdk_wit::AstRecordItem;
impl WITGenerator for AstRecordItem {
fn generate_wit<'a>(&'a self, _interfaces: &mut Interfaces<'a>) {
unimplemented!()
}
}

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 super::IType; use super::IType;
use fluence_sdk_wit::ParsedType; use fluence_sdk_wit::ParsedType;

View File

@ -0,0 +1,73 @@
/*
* 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::instructions_generator::WITGenerator;
use crate::default_export_api_config::*;
pub use fluence_sdk_wit::FCEAst;
use wasmer_wit::ast::Interfaces;
// TODO: add error handling
/// Parse generated by rust-sdk AST types, generate instructions and embed them to Wasm file.
pub fn embed_wit(path: std::path::PathBuf) {
let wasm_module = walrus::ModuleConfig::new()
.parse_file(path.clone())
.unwrap();
let ast_set = wasm_ast_extractor(&wasm_module);
let interfaces = generate_interfaces(&ast_set);
let mut wasm_module = wit_parser::embed_wit(wasm_module, &interfaces);
wasm_module.emit_wasm_file(path).unwrap();
}
/// Extract all custom AST types previously embedded by rust-sdk from compiled binary.
fn wasm_ast_extractor(wasm_module: &walrus::Module) -> Vec<fluence_sdk_wit::FCEAst> {
let mut extracted_ast = Vec::new();
// 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);
let decoded_json: fluence_sdk_wit::FCEAst = serde_json::from_slice(&raw_data).unwrap();
extracted_ast.push(decoded_json);
}
extracted_ast
}
fn generate_interfaces(ast_set: &[FCEAst]) -> Interfaces<'_> {
let mut interfaces = Interfaces::default();
generate_default_export_api(&mut interfaces);
for ast in ast_set {
ast.generate_wit(&mut interfaces);
}
interfaces
}
fn generate_default_export_api(interfaces: &mut Interfaces) {
ALLOCATE_FUNC.update_interfaces(interfaces);
DEALLOCATE_FUNC.update_interfaces(interfaces);
SET_RESULT_SIZE_FUNC.update_interfaces(interfaces);
SET_RESULT_PTR_FUNC.update_interfaces(interfaces);
GET_RESULT_SIZE_FUNC.update_interfaces(interfaces);
GET_RESULT_PTR_FUNC.update_interfaces(interfaces);
}

View File

@ -1,109 +1,21 @@
mod wit_generator; /*
mod wasm_ast_extractor; * 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 wit_generator::WITGenerator; mod default_export_api_config;
mod instructions_generator;
mod interface_generator;
pub use fluence_sdk_wit::FCEAst; pub use interface_generator::embed_wit;
use wasmer_wit::ast::Interfaces;
pub fn embed_wit(path: std::path::PathBuf) {
let ast_set = wasm_ast_extractor::wasm_ast_extractor(path.clone()).unwrap();
let interfaces = generate_interfaces(&ast_set);
wit_parser::embed_wit(path.clone(), path.clone(), &interfaces).unwrap();
}
fn generate_interfaces(ast_set: &[FCEAst]) -> Interfaces<'_> {
let mut interfaces = Interfaces::default();
generate_default_api(&mut interfaces);
for ast in ast_set {
ast.generate_wit(&mut interfaces);
}
interfaces
}
fn generate_default_api(interfaces: &mut Interfaces) {
use wasmer_wit::ast::Type;
use wasmer_wit::ast::Export;
use wasmer_wit::types::InterfaceType as IType;
let allocate_inputs = vec![IType::I32];
let allocate_outputs = vec![IType::I32];
let allocate_func_type = Type::Function {
inputs: allocate_inputs,
outputs: allocate_outputs,
};
let deallocate_inputs = vec![IType::I32, IType::I32];
let deallocate_outputs = vec![];
let deallocate_func_type = Type::Function {
inputs: deallocate_inputs,
outputs: deallocate_outputs,
};
let get_result_inputs = vec![];
let get_result_outputs = vec![IType::I32];
let get_result_size_func_type = Type::Function {
inputs: get_result_inputs.clone(),
outputs: get_result_outputs.clone(),
};
let get_result_ptr_func_type = Type::Function {
inputs: get_result_inputs,
outputs: get_result_outputs,
};
let set_result_inputs = vec![IType::I32];
let set_result_outputs = vec![];
let set_result_size_func_type = Type::Function {
inputs: set_result_inputs.clone(),
outputs: set_result_outputs.clone(),
};
let set_result_ptr_func_type = Type::Function {
inputs: set_result_inputs,
outputs: set_result_outputs,
};
interfaces.types.push(allocate_func_type);
interfaces.types.push(deallocate_func_type);
interfaces.types.push(get_result_size_func_type);
interfaces.types.push(get_result_ptr_func_type);
interfaces.types.push(set_result_size_func_type);
interfaces.types.push(set_result_ptr_func_type);
let allocate_export = Export {
name: "allocate",
function_type: 0,
};
interfaces.exports.push(allocate_export);
let deallocate_export = Export {
name: "deallocate",
function_type: 1,
};
interfaces.exports.push(deallocate_export);
let get_result_size_export = Export {
name: "get_result_size",
function_type: 2,
};
interfaces.exports.push(get_result_size_export);
let get_result_ptr_export = Export {
name: "get_result_ptr",
function_type: 3,
};
interfaces.exports.push(get_result_ptr_export);
let set_result_size_export = Export {
name: "set_result_size",
function_type: 4,
};
interfaces.exports.push(set_result_size_export);
let set_result_ptr_export = Export {
name: "set_result_ptr",
function_type: 5,
};
interfaces.exports.push(set_result_ptr_export);
}

View File

@ -1,28 +0,0 @@
use walrus::ModuleConfig;
#[derive(Default, Clone)]
struct WasmAst {
exports: Vec<fluence_sdk_wit::AstFunctionItem>,
imports: Vec<fluence_sdk_wit::AstExternModItem>,
records: Vec<fluence_sdk_wit::AstRecordItem>,
}
pub(crate) fn wasm_ast_extractor(
wasm_path: std::path::PathBuf,
) -> Result<Vec<fluence_sdk_wit::FCEAst>, std::io::Error> {
let module = ModuleConfig::new().parse_file(wasm_path).unwrap();
let mut decoded_ast = Vec::new();
for custom_module in 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);
let decoded_json: fluence_sdk_wit::FCEAst = serde_json::from_slice(&raw_data).unwrap();
decoded_ast.push(decoded_json);
}
Ok(decoded_ast)
}

View File

@ -1,10 +0,0 @@
use super::WITGenerator;
use super::Interfaces;
use fluence_sdk_wit::AstRecordItem;
impl WITGenerator for AstRecordItem {
fn generate_wit<'a>(&'a self, _interfaces: &mut Interfaces<'a>) {
unimplemented!()
}
}

View File

@ -11,7 +11,7 @@ path = "src/lib.rs"
[dependencies] [dependencies]
walrus = "0.17.0" walrus = "0.17.0"
wasmer-core = { package = "wasmer-runtime-core", git = "https://github.com/fluencelabs/wasmer", branch = "fluence" } wasmer-core = { package = "wasmer-runtime-core", git = "https://github.com/fluencelabs/wasmer", branch = "fluence" }
wasmer-wit = { package = "wasmer-interface-types", git = "https://github.com/fluencelabs/interface-types", branch = "master" } wasmer-wit = { package = "wasmer-interface-types", git = "https://github.com/fluencelabs/interface-types", branch = "byte_array" }
fce-wit-interfaces = { path = "../fce-wit-interfaces" } fce-wit-interfaces = { path = "../fce-wit-interfaces" }
anyhow = "1.0.31" anyhow = "1.0.31"

View File

@ -21,15 +21,27 @@ use walrus::ModuleConfig;
use std::path::PathBuf; use std::path::PathBuf;
pub fn delete_wit_section( /// Delete all custom sections with WIT from provided Wasm file.
pub fn delete_wit_section_from_file(
in_wasm_path: PathBuf, in_wasm_path: PathBuf,
out_wasm_path: PathBuf, out_wasm_path: PathBuf,
) -> Result<(), WITParserError> { ) -> Result<(), WITParserError> {
let mut module = ModuleConfig::new() let module = ModuleConfig::new()
.parse_file(&in_wasm_path) .parse_file(&in_wasm_path)
.map_err(WITParserError::CorruptedWasmFile)?; .map_err(WITParserError::CorruptedWasmFile)?;
let wit_section_ids = module let mut module = delete_wit_section(module);
module
.emit_wasm_file(&out_wasm_path)
.map_err(WITParserError::WasmEmitError)?;
Ok(())
}
/// Delete all custom sections with WIT from provided Wasm module.
pub fn delete_wit_section(mut wasm_module: walrus::Module) -> walrus::Module {
let wit_section_ids = wasm_module
.customs .customs
.iter() .iter()
.filter_map(|(id, section)| { .filter_map(|(id, section)| {
@ -42,12 +54,8 @@ pub fn delete_wit_section(
.collect::<Vec<_>>(); .collect::<Vec<_>>();
for id in wit_section_ids { for id in wit_section_ids {
module.customs.delete(id); wasm_module.customs.delete(id);
} }
module wasm_module
.emit_wasm_file(&out_wasm_path)
.map_err(WITParserError::WasmEmitError)?;
Ok(())
} }

View File

@ -26,23 +26,20 @@ use wasmer_wit::{
use std::path::PathBuf; use std::path::PathBuf;
/// Embed provided WIT to a Wasm file by path.
pub fn embed_text_wit( pub fn embed_text_wit(
in_wasm_path: PathBuf, in_wasm_path: PathBuf,
out_wasm_path: PathBuf, out_wasm_path: PathBuf,
wit: &str, wit: &str,
) -> Result<(), WITParserError> { ) -> Result<(), WITParserError> {
let mut module = ModuleConfig::new() let module = ModuleConfig::new()
.parse_file(&in_wasm_path) .parse_file(&in_wasm_path)
.map_err(WITParserError::CorruptedWasmFile)?; .map_err(WITParserError::CorruptedWasmFile)?;
let buffer = Buffer::new(wit)?; let buffer = Buffer::new(wit)?;
let ast = parse(&buffer)?; let ast = parse(&buffer)?;
let mut bytes = vec![]; let mut module = embed_wit(module, &ast);
ast.to_bytes(&mut bytes)?;
let custom = WITCustom(bytes);
module.customs.add(custom);
module module
.emit_wasm_file(&out_wasm_path) .emit_wasm_file(&out_wasm_path)
.map_err(WITParserError::WasmEmitError)?; .map_err(WITParserError::WasmEmitError)?;
@ -50,23 +47,14 @@ pub fn embed_text_wit(
Ok(()) Ok(())
} }
pub fn embed_wit( /// Embed provided WIT to a Wasm module.
in_wasm_path: PathBuf, pub fn embed_wit(mut wasm_module: walrus::Module, interfaces: &Interfaces<'_>) -> walrus::Module {
out_wasm_path: PathBuf,
interfaces: &Interfaces<'_>,
) -> Result<(), WITParserError> {
let mut module = ModuleConfig::new()
.parse_file(&in_wasm_path)
.map_err(WITParserError::CorruptedWasmFile)?;
let mut bytes = vec![]; let mut bytes = vec![];
interfaces.to_bytes(&mut bytes)?; // TODO: think about possible errors here
interfaces.to_bytes(&mut bytes).unwrap();
let custom = WITCustom(bytes); let custom = WITCustom(bytes);
module.customs.add(custom); wasm_module.customs.add(custom);
module
.emit_wasm_file(&out_wasm_path)
.map_err(WITParserError::WasmEmitError)?;
Ok(()) wasm_module
} }

View File

@ -32,8 +32,9 @@ mod extractor;
pub use errors::WITParserError; pub use errors::WITParserError;
pub use embedder::embed_text_wit;
pub use embedder::embed_wit; pub use embedder::embed_wit;
pub use embedder::embed_text_wit;
pub use deleter::delete_wit_section; pub use deleter::delete_wit_section;
pub use deleter::delete_wit_section_from_file;
pub use extractor::extract_wit; pub use extractor::extract_wit;
pub use extractor::extract_text_wit; pub use extractor::extract_text_wit;

View File

@ -41,7 +41,7 @@ where
let mut full_path = std::path::PathBuf::from(to_dir); let mut full_path = std::path::PathBuf::from(to_dir);
// TODO: optimize this // TODO: optimize this
#[warn(clippy::while_let_on_iterator)] #[allow(clippy::while_let_on_iterator)]
while let Some(component) = components.next() { while let Some(component) = components.next() {
full_path.push(component); full_path.push(component);
} }

View File

@ -5,7 +5,7 @@ authors = ["Fluence Labs"]
edition = "2018" edition = "2018"
[[bin]] [[bin]]
name = "fce_cli" name = "fce"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]

View File

@ -16,6 +16,16 @@ pub fn build<'a, 'b>() -> App<'a, 'b> {
.help("path to the wasm file")]) .help("path to the wasm file")])
} }
pub fn show_wit<'a, 'b>() -> App<'a, 'b> {
SubCommand::with_name("show")
.about("show WIT in provided Wasm file")
.args(&[Arg::with_name(IN_WASM_PATH)
.required(true)
.takes_value(true)
.short("i")
.help("path to the wasm file")])
}
pub fn validate<'a, 'b>() -> App<'a, 'b> { pub fn validate<'a, 'b>() -> App<'a, 'b> {
SubCommand::with_name("validate") SubCommand::with_name("validate")
.about("validates provided Wasm file to suite Fluence network requirements") .about("validates provided Wasm file to suite Fluence network requirements")

59
tools/cli/src/build.rs Normal file
View File

@ -0,0 +1,59 @@
/*
* 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::path::PathBuf;
use std::process::Command;
#[derive(serde::Deserialize)]
#[serde(tag = "reason", rename_all = "kebab-case")]
enum DiagnosticMessage {
BuildScriptExecuted,
BuildFinished,
CompilerArtifact { executable: String },
RunWithArgs,
}
// TODO: add error handling
pub(crate) fn build<P: Into<PathBuf>>(wasm_path: P) {
use std::io::Read;
let mut cargo = Command::new("cargo");
cargo.arg("build").arg("--target").arg("wasm32-wasi");
cargo.arg("--message-format").arg("json-render-diagnostics");
cargo.arg("--manifest-path").arg(wasm_path.into());
let mut process = cargo.stdout(std::process::Stdio::piped()).spawn().unwrap();
let mut output = String::new();
process
.stdout
.take()
.unwrap()
.read_to_string(&mut output)
.unwrap();
let _status = process.wait().unwrap();
let mut wasms = Vec::new();
for line in output.lines() {
if let Ok(DiagnosticMessage::CompilerArtifact { executable }) = serde_json::from_str(line) {
wasms.push(executable)
}
}
let wasm_path = std::path::PathBuf::from(wasms.first().unwrap());
wit_generator::embed_wit(wasm_path);
}

68
tools/cli/src/main.rs Normal file
View File

@ -0,0 +1,68 @@
/*
* 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.
*/
#![warn(rust_2018_idioms)]
#![deny(
dead_code,
nonstandard_style,
unused_imports,
unused_mut,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
mod args;
mod build;
use clap::App;
use clap::AppSettings;
pub fn main() -> Result<(), exitfailure::ExitFailure> {
let app = App::new("CLI tool for embedding WIT to provided Wasm file")
.version(args::VERSION)
.author(args::AUTHORS)
.about(args::DESCRIPTION)
.setting(AppSettings::ArgRequiredElseHelp)
.subcommand(args::build())
.subcommand(args::show_wit())
.subcommand(args::validate());
match app.get_matches().subcommand() {
("build", Some(arg)) => {
let wasm_path = arg.value_of(args::IN_WASM_PATH).unwrap();
let wasm_path = std::path::PathBuf::from(wasm_path);
crate::build::build(wasm_path);
Ok(())
}
("show", Some(arg)) => {
let wasm_path = arg.value_of(args::IN_WASM_PATH).unwrap();
let wasm_path = std::path::PathBuf::from(wasm_path);
let result = wit_parser::extract_text_wit(wasm_path)?;
println!("{}", result);
Ok(())
}
("validate", Some(arg)) => {
let _wasm_path = arg.value_of(args::IN_WASM_PATH).unwrap();
Ok(())
}
c => Err(failure::err_msg(format!("Unexpected command: {}", c.0)).into()),
}
}

View File

@ -1,98 +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.
*/
#![warn(rust_2018_idioms)]
#![deny(
// dead_code,
nonstandard_style,
unused_imports,
unused_mut,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
mod args;
use args::*;
use clap::{App, AppSettings};
use std::process::Command;
#[derive(serde::Deserialize)]
#[serde(tag = "reason", rename_all = "kebab-case")]
enum DiagnosticMessage {
BuildScriptExecuted,
BuildFinished,
CompilerArtifact { executable: String },
RunWithArgs,
}
pub fn main() -> Result<(), exitfailure::ExitFailure> {
let app = App::new("CLI tool for embedding WIT to provided Wasm file")
.version(VERSION)
.author(AUTHORS)
.about(DESCRIPTION)
.setting(AppSettings::ArgRequiredElseHelp)
.subcommand(build())
.subcommand(validate());
match app.get_matches().subcommand() {
("build", Some(arg)) => {
use std::io::Read;
let wasm_path = arg.value_of(IN_WASM_PATH).unwrap();
// wit_embedder::delete_wit_section(wasm_path.clone(), wasm_path.clone());
let mut cargo = Command::new("cargo");
cargo.arg("build").arg("--target").arg("wasm32-wasi");
cargo.arg("--message-format").arg("json-render-diagnostics");
cargo.arg("--manifest-path").arg(wasm_path);
let mut process = cargo.stdout(std::process::Stdio::piped()).spawn().unwrap();
let mut output = String::new();
process
.stdout
.take()
.unwrap()
.read_to_string(&mut output)
.unwrap();
let _status = process.wait().unwrap();
let mut wasms = Vec::new();
for line in output.lines() {
match serde_json::from_str(line) {
Ok(DiagnosticMessage::CompilerArtifact { executable }) => {
wasms.push(executable)
}
_ => {}
}
}
let wasm_path = std::path::PathBuf::from(wasms.first().unwrap());
wit_generator::embed_wit(wasm_path);
Ok(())
}
("validate", Some(arg)) => {
let _wasm_path = arg.value_of(IN_WASM_PATH).unwrap();
Ok(())
}
c => Err(failure::err_msg(format!("Unexpected command: {}", c.0)).into()),
}
}

View File

@ -1,15 +0,0 @@
[package]
name = "wit_embedder"
version = "0.1.0"
authors = ["Fluence Labs"]
edition = "2018"
[[bin]]
name = "wit_embedder"
path = "src/main.rs"
[dependencies]
wit-parser = { path = "../../crates/wit-parser" }
clap = "2.33.1"
exitfailure = "0.5.1"
failure = "0.1.5"

View File

@ -1,56 +0,0 @@
use clap::{App, Arg, SubCommand};
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const AUTHORS: &str = env!("CARGO_PKG_AUTHORS");
pub const DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION");
pub const IN_WASM_PATH: &str = "in-wasm-path";
pub const WIT_PATH: &str = "wit-path";
pub const OUT_WASM_PATH: &str = "out-wasm-path";
pub fn embed_wit<'a, 'b>() -> App<'a, 'b> {
SubCommand::with_name("embed")
.about("embed WIT to provided Wasm file")
.args(&[
Arg::with_name(IN_WASM_PATH)
.required(true)
.takes_value(true)
.short("i")
.help("path to the wasm file"),
Arg::with_name(WIT_PATH)
.required(true)
.takes_value(true)
.short("w")
.help("path to file with WIT"),
Arg::with_name(OUT_WASM_PATH)
.takes_value(true)
.short("o")
.help("path to result file with embedded WIT"),
])
}
pub fn show_wit<'a, 'b>() -> App<'a, 'b> {
SubCommand::with_name("show")
.about("show WIT in provided Wasm file")
.args(&[Arg::with_name(IN_WASM_PATH)
.required(true)
.takes_value(true)
.short("i")
.help("path to the wasm file")])
}
pub fn delete_wit<'a, 'b>() -> App<'a, 'b> {
SubCommand::with_name("delete")
.about("delete all WIT sections in provided Wasm file")
.args(&[
Arg::with_name(IN_WASM_PATH)
.required(true)
.takes_value(true)
.short("i")
.help("path to the wasm file"),
Arg::with_name(OUT_WASM_PATH)
.takes_value(true)
.short("o")
.help("path to result file with deleted WIT sections"),
])
}

View File

@ -1,89 +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.
*/
#![warn(rust_2018_idioms)]
#![deny(
dead_code,
nonstandard_style,
unused_imports,
unused_mut,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
mod args;
use args::*;
use wit_parser::embed_text_wit;
use wit_parser::extract_text_wit;
use wit_parser::delete_wit_section;
use clap::{App, AppSettings};
use std::path::PathBuf;
pub fn main() -> Result<(), exitfailure::ExitFailure> {
let app = App::new("CLI tool for embedding WIT to provided Wasm file")
.version(VERSION)
.author(AUTHORS)
.about(DESCRIPTION)
.setting(AppSettings::ArgRequiredElseHelp)
.subcommand(embed_wit())
.subcommand(show_wit())
.subcommand(delete_wit());
match app.get_matches().subcommand() {
("embed", Some(arg)) => {
let in_wasm_path = arg.value_of(IN_WASM_PATH).unwrap();
let wit_path = arg.value_of(WIT_PATH).unwrap();
let out_wasm_path = match arg.value_of(OUT_WASM_PATH) {
Some(path) => path,
None => in_wasm_path,
};
let wit = String::from_utf8(std::fs::read(wit_path)?).unwrap();
embed_text_wit(
PathBuf::from(in_wasm_path),
PathBuf::from(out_wasm_path),
&wit,
)?;
Ok(())
}
("show", Some(arg)) => {
let wasm_path = arg.value_of(IN_WASM_PATH).unwrap();
let wasm_path = PathBuf::from(wasm_path);
let result = extract_text_wit(wasm_path)?;
println!("{}", result);
Ok(())
}
("delete", Some(arg)) => {
let in_wasm_path = arg.value_of(IN_WASM_PATH).unwrap();
let out_wasm_path = match arg.value_of(OUT_WASM_PATH) {
Some(path) => path,
None => in_wasm_path,
};
delete_wit_section(PathBuf::from(in_wasm_path), PathBuf::from(out_wasm_path))?;
Ok(())
}
c => Err(failure::err_msg(format!("Unexpected command: {}", c.0)).into()),
}
}