diff --git a/Cargo.lock b/Cargo.lock index 61ff1bff..09e97016 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -376,7 +376,7 @@ dependencies = [ "parity-wasm", "pwasm-utils", "serde", - "wasmer-interface-types", + "wasmer-interface-types 0.17.0 (git+https://github.com/fluencelabs/interface-types)", "wasmer-runtime", "wasmer-runtime-core", "wasmer-wasi", @@ -388,7 +388,7 @@ name = "fce-wit-interfaces" version = "0.1.0" dependencies = [ "multimap", - "wasmer-interface-types", + "wasmer-interface-types 0.17.0 (git+https://github.com/fluencelabs/interface-types)", ] [[package]] @@ -423,7 +423,7 @@ dependencies = [ [[package]] name = "fluence-sdk-wit" version = "0.2.0" -source = "git+https://github.com/fluencelabs/rust-sdk#d3f5a15730f97f642f07d64f50efab061218cc9f" +source = "git+https://github.com/fluencelabs/rust-sdk#bee1983d97da6acc53fecf8b6695810410502b8d" dependencies = [ "proc-macro2", "quote", @@ -431,7 +431,6 @@ dependencies = [ "serde_json", "syn", "uuid", - "wasmer-interface-types", ] [[package]] @@ -711,6 +710,12 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" +[[package]] +name = "once_cell" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d" + [[package]] name = "page_size" version = "0.4.2" @@ -1228,6 +1233,16 @@ dependencies = [ "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]] name = "wasmer-interface-types" version = "0.17.0" @@ -1357,10 +1372,11 @@ name = "wit-generator" version = "0.1.0" dependencies = [ "fluence-sdk-wit", + "once_cell", "serde", "serde_json", "walrus", - "wasmer-interface-types", + "wasmer-interface-types 0.17.0 (git+http://github.com/fluencelabs/interface-types?branch=byte_array)", "wit-parser", ] @@ -1371,16 +1387,6 @@ dependencies = [ "anyhow", "fce-wit-interfaces", "walrus", - "wasmer-interface-types", + "wasmer-interface-types 0.17.0 (git+http://github.com/fluencelabs/interface-types?branch=byte_array)", "wasmer-runtime-core", ] - -[[package]] -name = "wit_embedder" -version = "0.1.0" -dependencies = [ - "clap", - "exitfailure", - "failure", - "wit-parser", -] diff --git a/Cargo.toml b/Cargo.toml index efccd46f..0ec97c1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,8 +9,7 @@ members = [ "examples/ipfs_node/wasm/ipfs_rpc", "examples/simple_greeting", "fluence-faas", - "tools/fce-cli", - "tools/wit_embedder", + "tools/cli", ] [profile.release] diff --git a/crates/wit-generator/Cargo.toml b/crates/wit-generator/Cargo.toml index 5557edaa..5a9c3d0f 100644 --- a/crates/wit-generator/Cargo.toml +++ b/crates/wit-generator/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" wit-parser = { path = "../wit-parser" } walrus = "0.17.0" 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_json = "1.0.56" diff --git a/crates/wit-generator/src/default_export_api_config.rs b/crates/wit-generator/src/default_export_api_config.rs new file mode 100644 index 00000000..1658a457 --- /dev/null +++ b/crates/wit-generator/src/default_export_api_config.rs @@ -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, + pub(crate) output_types: Vec, +} + +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 = + Lazy::new(|| ApiExportFuncDescriptor { + name: "allocate", + id: 0, + input_types: vec![IType::I32], + output_types: vec![IType::I32], + }); + +pub(crate) static DEALLOCATE_FUNC: Lazy = + 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 = + 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 = + 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 = + 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 = + Lazy::new(|| ApiExportFuncDescriptor { + name: "set_result_ptr", + id: 5, + input_types: vec![IType::I32], + output_types: vec![], + }); diff --git a/crates/wit-generator/src/wit_generator.rs b/crates/wit-generator/src/instructions_generator.rs similarity index 58% rename from crates/wit-generator/src/wit_generator.rs rename to crates/wit-generator/src/instructions_generator.rs index c2a559cb..75b5519a 100644 --- a/crates/wit-generator/src/wit_generator.rs +++ b/crates/wit-generator/src/instructions_generator.rs @@ -1,9 +1,25 @@ -mod fn_wit_generator; -mod foreign_mod_wit_generator; -mod record_wit_generator; +/* + * 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 fn_instructions; +mod foreign_mod_instructions; +mod record_instructions; mod utils; -use super::FCEAst; +use fluence_sdk_wit::FCEAst; use wasmer_wit::types::InterfaceType as IType; use wasmer_wit::ast::Interfaces; diff --git a/crates/wit-generator/src/wit_generator/fn_wit_generator.rs b/crates/wit-generator/src/instructions_generator/fn_instructions.rs similarity index 73% rename from crates/wit-generator/src/wit_generator/fn_wit_generator.rs rename to crates/wit-generator/src/instructions_generator/fn_instructions.rs index d6ba9ae9..219bb877 100644 --- a/crates/wit-generator/src/wit_generator/fn_wit_generator.rs +++ b/crates/wit-generator/src/instructions_generator/fn_instructions.rs @@ -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::Interfaces; -use super::utils::ptype_to_itype; use super::FnInstructionGenerator; +use super::utils::ptype_to_itype; +use crate::default_export_api_config::*; use fluence_sdk_wit::AstFunctionItem; use fluence_sdk_wit::ParsedType; @@ -75,6 +92,7 @@ impl WITGenerator for AstFunctionItem { } impl FnInstructionGenerator for ParsedType { + #[rustfmt::skip] fn generate_instructions_for_input_type(&self, index: u32) -> Vec { match self { ParsedType::I8 => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS8], @@ -90,14 +108,14 @@ impl FnInstructionGenerator for ParsedType { ParsedType::Utf8String => vec![ Instruction::ArgumentGet { index }, Instruction::StringSize, - Instruction::CallCore { function_index: 0 }, + Instruction::CallCore { function_index: ALLOCATE_FUNC.id }, Instruction::ArgumentGet { index }, Instruction::StringLowerMemory, ], ParsedType::ByteVector => vec![ Instruction::ArgumentGet { index }, Instruction::StringSize, - Instruction::CallCore { function_index: 0 }, + Instruction::CallCore { function_index: ALLOCATE_FUNC.id }, Instruction::ArgumentGet { index }, Instruction::StringLowerMemory, ], @@ -105,6 +123,7 @@ impl FnInstructionGenerator for ParsedType { } } + #[rustfmt::skip] fn generate_instructions_for_output_type(&self) -> Vec { match self { ParsedType::I8 => vec![Instruction::S8FromI32], @@ -118,20 +137,20 @@ impl FnInstructionGenerator for ParsedType { ParsedType::F32 => vec![], ParsedType::F64 => vec![], ParsedType::Utf8String => vec![ - Instruction::CallCore { function_index: 3 }, - Instruction::CallCore { function_index: 2 }, + Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id }, + Instruction::CallCore { function_index: GET_RESULT_SIZE_FUNC.id }, Instruction::StringLiftMemory, - Instruction::CallCore { function_index: 3 }, - Instruction::CallCore { function_index: 2 }, - Instruction::CallCore { function_index: 1 }, + Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id }, + Instruction::CallCore { function_index: GET_RESULT_SIZE_FUNC.id }, + Instruction::CallCore { function_index: DEALLOCATE_FUNC.id }, ], ParsedType::ByteVector => vec![ - Instruction::CallCore { function_index: 3 }, - Instruction::CallCore { function_index: 2 }, - Instruction::StringLiftMemory, - Instruction::CallCore { function_index: 3 }, - Instruction::CallCore { function_index: 2 }, - Instruction::CallCore { function_index: 1 }, + Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id }, + Instruction::CallCore { function_index: GET_RESULT_SIZE_FUNC.id }, + Instruction::ByteArrayLiftMemory, + Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id }, + Instruction::CallCore { function_index: GET_RESULT_SIZE_FUNC.id }, + Instruction::CallCore { function_index: DEALLOCATE_FUNC.id }, ], _ => unimplemented!(), } diff --git a/crates/wit-generator/src/wit_generator/foreign_mod_wit_generator.rs b/crates/wit-generator/src/instructions_generator/foreign_mod_instructions.rs similarity index 79% rename from crates/wit-generator/src/wit_generator/foreign_mod_wit_generator.rs rename to crates/wit-generator/src/instructions_generator/foreign_mod_instructions.rs index e90bafcb..5999b077 100644 --- a/crates/wit-generator/src/wit_generator/foreign_mod_wit_generator.rs +++ b/crates/wit-generator/src/instructions_generator/foreign_mod_instructions.rs @@ -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::Interfaces; use super::utils::ptype_to_itype; use super::ForeignModInstructionGenerator; +use crate::default_export_api_config::*; use fluence_sdk_wit::AstExternModItem; use fluence_sdk_wit::AstExternFnItem; @@ -18,7 +35,7 @@ impl WITGenerator for AstExternModItem { fn generate_wit_for_import<'a>( import: &'a AstExternFnItem, - namespace: &'a String, + namespace: &'a str, interfaces: &mut Interfaces<'a>, ) { use wasmer_wit::ast::Type; @@ -111,6 +128,7 @@ impl ForeignModInstructionGenerator for ParsedType { } } + #[rustfmt::skip] fn generate_instructions_for_output_type(&self) -> Vec { match self { ParsedType::I8 => vec![Instruction::I32FromS8], @@ -126,20 +144,20 @@ impl ForeignModInstructionGenerator for ParsedType { ParsedType::Utf8String => vec![ Instruction::Dup, Instruction::StringSize, - Instruction::CallCore { function_index: 0 }, + Instruction::CallCore { function_index: ALLOCATE_FUNC.id }, Instruction::Swap2, Instruction::StringLowerMemory, - Instruction::CallCore { function_index: 4 }, - Instruction::CallCore { function_index: 5 }, + Instruction::CallCore { function_index: SET_RESULT_SIZE_FUNC.id }, + Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.id }, ], ParsedType::ByteVector => vec![ Instruction::Dup, - Instruction::StringSize, - Instruction::CallCore { function_index: 0 }, + Instruction::ByteArraySize, + Instruction::CallCore { function_index: ALLOCATE_FUNC.id }, Instruction::Swap2, - Instruction::StringLowerMemory, - Instruction::CallCore { function_index: 4 }, - Instruction::CallCore { function_index: 5 }, + Instruction::ByteArrayLowerMemory, + Instruction::CallCore { function_index: SET_RESULT_SIZE_FUNC.id }, + Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.id }, ], _ => unimplemented!(), } diff --git a/crates/wit-generator/src/instructions_generator/record_instructions.rs b/crates/wit-generator/src/instructions_generator/record_instructions.rs new file mode 100644 index 00000000..13d13f06 --- /dev/null +++ b/crates/wit-generator/src/instructions_generator/record_instructions.rs @@ -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!() + } +} diff --git a/crates/wit-generator/src/wit_generator/utils.rs b/crates/wit-generator/src/instructions_generator/utils.rs similarity index 54% rename from crates/wit-generator/src/wit_generator/utils.rs rename to crates/wit-generator/src/instructions_generator/utils.rs index 1bd466df..1f0545cd 100644 --- a/crates/wit-generator/src/wit_generator/utils.rs +++ b/crates/wit-generator/src/instructions_generator/utils.rs @@ -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 fluence_sdk_wit::ParsedType; diff --git a/crates/wit-generator/src/interface_generator.rs b/crates/wit-generator/src/interface_generator.rs new file mode 100644 index 00000000..1d4587c5 --- /dev/null +++ b/crates/wit-generator/src/interface_generator.rs @@ -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 { + 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); +} diff --git a/crates/wit-generator/src/lib.rs b/crates/wit-generator/src/lib.rs index 4d650a3e..2cfae658 100644 --- a/crates/wit-generator/src/lib.rs +++ b/crates/wit-generator/src/lib.rs @@ -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; -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); -} +pub use interface_generator::embed_wit; diff --git a/crates/wit-generator/src/wasm_ast_extractor.rs b/crates/wit-generator/src/wasm_ast_extractor.rs deleted file mode 100644 index 86c10665..00000000 --- a/crates/wit-generator/src/wasm_ast_extractor.rs +++ /dev/null @@ -1,28 +0,0 @@ -use walrus::ModuleConfig; - -#[derive(Default, Clone)] -struct WasmAst { - exports: Vec, - imports: Vec, - records: Vec, -} - -pub(crate) fn wasm_ast_extractor( - wasm_path: std::path::PathBuf, -) -> Result, 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) -} diff --git a/crates/wit-generator/src/wit_generator/record_wit_generator.rs b/crates/wit-generator/src/wit_generator/record_wit_generator.rs deleted file mode 100644 index f5d081d7..00000000 --- a/crates/wit-generator/src/wit_generator/record_wit_generator.rs +++ /dev/null @@ -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!() - } -} diff --git a/crates/wit-parser/Cargo.toml b/crates/wit-parser/Cargo.toml index 0a03f889..325d8552 100644 --- a/crates/wit-parser/Cargo.toml +++ b/crates/wit-parser/Cargo.toml @@ -11,7 +11,7 @@ path = "src/lib.rs" [dependencies] walrus = "0.17.0" 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" } anyhow = "1.0.31" diff --git a/crates/wit-parser/src/deleter.rs b/crates/wit-parser/src/deleter.rs index 7b928581..b252db4f 100644 --- a/crates/wit-parser/src/deleter.rs +++ b/crates/wit-parser/src/deleter.rs @@ -21,15 +21,27 @@ use walrus::ModuleConfig; 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, out_wasm_path: PathBuf, ) -> Result<(), WITParserError> { - let mut module = ModuleConfig::new() + let module = ModuleConfig::new() .parse_file(&in_wasm_path) .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 .iter() .filter_map(|(id, section)| { @@ -42,12 +54,8 @@ pub fn delete_wit_section( .collect::>(); for id in wit_section_ids { - module.customs.delete(id); + wasm_module.customs.delete(id); } - module - .emit_wasm_file(&out_wasm_path) - .map_err(WITParserError::WasmEmitError)?; - - Ok(()) + wasm_module } diff --git a/crates/wit-parser/src/embedder.rs b/crates/wit-parser/src/embedder.rs index 744738bd..b9276fd8 100644 --- a/crates/wit-parser/src/embedder.rs +++ b/crates/wit-parser/src/embedder.rs @@ -26,23 +26,20 @@ use wasmer_wit::{ use std::path::PathBuf; +/// Embed provided WIT to a Wasm file by path. pub fn embed_text_wit( in_wasm_path: PathBuf, out_wasm_path: PathBuf, wit: &str, ) -> Result<(), WITParserError> { - let mut module = ModuleConfig::new() + let module = ModuleConfig::new() .parse_file(&in_wasm_path) .map_err(WITParserError::CorruptedWasmFile)?; let buffer = Buffer::new(wit)?; let ast = parse(&buffer)?; - let mut bytes = vec![]; - ast.to_bytes(&mut bytes)?; - - let custom = WITCustom(bytes); - module.customs.add(custom); + let mut module = embed_wit(module, &ast); module .emit_wasm_file(&out_wasm_path) .map_err(WITParserError::WasmEmitError)?; @@ -50,23 +47,14 @@ pub fn embed_text_wit( Ok(()) } -pub fn embed_wit( - in_wasm_path: PathBuf, - out_wasm_path: PathBuf, - interfaces: &Interfaces<'_>, -) -> Result<(), WITParserError> { - let mut module = ModuleConfig::new() - .parse_file(&in_wasm_path) - .map_err(WITParserError::CorruptedWasmFile)?; - +/// Embed provided WIT to a Wasm module. +pub fn embed_wit(mut wasm_module: walrus::Module, interfaces: &Interfaces<'_>) -> walrus::Module { 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); - module.customs.add(custom); - module - .emit_wasm_file(&out_wasm_path) - .map_err(WITParserError::WasmEmitError)?; + wasm_module.customs.add(custom); - Ok(()) + wasm_module } diff --git a/crates/wit-parser/src/lib.rs b/crates/wit-parser/src/lib.rs index ea51295b..20479298 100644 --- a/crates/wit-parser/src/lib.rs +++ b/crates/wit-parser/src/lib.rs @@ -32,8 +32,9 @@ mod extractor; pub use errors::WITParserError; -pub use embedder::embed_text_wit; pub use embedder::embed_wit; +pub use embedder::embed_text_wit; pub use deleter::delete_wit_section; +pub use deleter::delete_wit_section_from_file; pub use extractor::extract_wit; pub use extractor::extract_text_wit; diff --git a/examples/ipfs_node/wasm/ipfs_node/src/path.rs b/examples/ipfs_node/wasm/ipfs_node/src/path.rs index 60453c25..4f7d0d5e 100644 --- a/examples/ipfs_node/wasm/ipfs_node/src/path.rs +++ b/examples/ipfs_node/wasm/ipfs_node/src/path.rs @@ -41,7 +41,7 @@ where let mut full_path = std::path::PathBuf::from(to_dir); // TODO: optimize this - #[warn(clippy::while_let_on_iterator)] + #[allow(clippy::while_let_on_iterator)] while let Some(component) = components.next() { full_path.push(component); } diff --git a/tools/fce-cli/Cargo.toml b/tools/cli/Cargo.toml similarity index 95% rename from tools/fce-cli/Cargo.toml rename to tools/cli/Cargo.toml index 5d054e47..a9c750f9 100644 --- a/tools/fce-cli/Cargo.toml +++ b/tools/cli/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Fluence Labs"] edition = "2018" [[bin]] -name = "fce_cli" +name = "fce" path = "src/main.rs" [dependencies] diff --git a/tools/fce-cli/src/args.rs b/tools/cli/src/args.rs similarity index 74% rename from tools/fce-cli/src/args.rs rename to tools/cli/src/args.rs index c68f941b..3dbb9b23 100644 --- a/tools/fce-cli/src/args.rs +++ b/tools/cli/src/args.rs @@ -16,6 +16,16 @@ pub fn build<'a, 'b>() -> App<'a, 'b> { .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> { SubCommand::with_name("validate") .about("validates provided Wasm file to suite Fluence network requirements") diff --git a/tools/cli/src/build.rs b/tools/cli/src/build.rs new file mode 100644 index 00000000..f4ffb0d5 --- /dev/null +++ b/tools/cli/src/build.rs @@ -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>(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); +} diff --git a/tools/cli/src/main.rs b/tools/cli/src/main.rs new file mode 100644 index 00000000..1c5b7477 --- /dev/null +++ b/tools/cli/src/main.rs @@ -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()), + } +} diff --git a/tools/fce-cli/src/main.rs b/tools/fce-cli/src/main.rs deleted file mode 100644 index 98be7d54..00000000 --- a/tools/fce-cli/src/main.rs +++ /dev/null @@ -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()), - } -} diff --git a/tools/wit_embedder/Cargo.toml b/tools/wit_embedder/Cargo.toml deleted file mode 100644 index 72e8fbe9..00000000 --- a/tools/wit_embedder/Cargo.toml +++ /dev/null @@ -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" diff --git a/tools/wit_embedder/src/args.rs b/tools/wit_embedder/src/args.rs deleted file mode 100644 index 7f557b21..00000000 --- a/tools/wit_embedder/src/args.rs +++ /dev/null @@ -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"), - ]) -} diff --git a/tools/wit_embedder/src/main.rs b/tools/wit_embedder/src/main.rs deleted file mode 100644 index e90e9b9b..00000000 --- a/tools/wit_embedder/src/main.rs +++ /dev/null @@ -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()), - } -}