mirror of
https://github.com/fluencelabs/marine.git
synced 2024-12-04 19:50:19 +00:00
add WIT embedder
This commit is contained in:
parent
361427f483
commit
da3b9e56ed
@ -10,11 +10,12 @@ jobs:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- fce01-{{ checksum "Cargo.toml" }}
|
||||
- fce01-{{ checksum "fce/Cargo.toml" }}
|
||||
- run: |
|
||||
rustup toolchain install stable
|
||||
rustup component add rustfmt
|
||||
rustup component add clippy
|
||||
cd fce
|
||||
cargo fmt --all -- --check --color always
|
||||
cargo build -v --all-features
|
||||
cargo test -v --all-features
|
||||
@ -23,7 +24,7 @@ jobs:
|
||||
paths:
|
||||
- ~/.cargo
|
||||
- ~/.rustup
|
||||
key: fce01-{{ checksum "Cargo.toml" }}
|
||||
key: fce01-{{ checksum "fce/Cargo.toml" }}
|
||||
|
||||
workflows:
|
||||
version: 2.1
|
||||
|
1779
Cargo.lock
generated
1779
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
50
Cargo.toml
50
Cargo.toml
@ -1,45 +1,5 @@
|
||||
[package]
|
||||
name = "FCE"
|
||||
description = "Fluence compute engine, virtual machine based on Wasmer for the Fluence network"
|
||||
version = "0.1.0"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
license = "Apache-2.0"
|
||||
keywords = ["fluence", "webassembly", "wasmer", "execution environment"]
|
||||
categories = ["webassembly"]
|
||||
maintenance = { status = "actively-developed" }
|
||||
|
||||
[lib]
|
||||
name = "fce"
|
||||
path = "src/lib.rs"
|
||||
#crate-type = ["cdylib"]
|
||||
|
||||
[[bin]]
|
||||
name = "fce_cli"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime = { git = "http://github.com/fluencelabs/wasmer", branch = "fluence" }
|
||||
wasmer-runtime-core = { git = "http://github.com/fluencelabs/wasmer", branch = "fluence" }
|
||||
wasmer-wasi = { git = "http://github.com/fluencelabs/wasmer", branch = "fluence" }
|
||||
failure = "0.1.7"
|
||||
lazy_static = "1.4.0"
|
||||
sha2 = "0.8.1"
|
||||
rustyline = "6.1.2"
|
||||
exitfailure = "0.5.1"
|
||||
boolinator = "2.4.0"
|
||||
parity-wasm = "0.41.0"
|
||||
pwasm-utils = "0.12.0"
|
||||
|
||||
[dev-dependencies]
|
||||
reqwest = "0.10.4"
|
||||
bytes = "0.5.4"
|
||||
tokio = { version = "0.2.20", features = ["blocking", "macros"] }
|
||||
|
||||
[profile.release]
|
||||
#opt-level = 3
|
||||
#debug = false
|
||||
#lto = true
|
||||
#debug-assertions = false
|
||||
#overflow-checks = false
|
||||
#panic = "abort"
|
||||
[workspace]
|
||||
members = [
|
||||
"fce",
|
||||
"wit_embedder",
|
||||
]
|
||||
|
1975
fce/Cargo.lock
generated
Normal file
1975
fce/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
45
fce/Cargo.toml
Normal file
45
fce/Cargo.toml
Normal file
@ -0,0 +1,45 @@
|
||||
[package]
|
||||
name = "FCE"
|
||||
description = "Fluence compute engine, virtual machine based on Wasmer for the Fluence network"
|
||||
version = "0.1.0"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
license = "Apache-2.0"
|
||||
keywords = ["fluence", "webassembly", "wasmer", "execution environment"]
|
||||
categories = ["webassembly"]
|
||||
maintenance = { status = "actively-developed" }
|
||||
|
||||
[lib]
|
||||
name = "fce"
|
||||
path = "src/lib.rs"
|
||||
#crate-type = ["cdylib"]
|
||||
|
||||
[[bin]]
|
||||
name = "fce_cli"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime = { git = "http://github.com/fluencelabs/wasmer", branch = "fluence" }
|
||||
wasmer-runtime-core = { git = "http://github.com/fluencelabs/wasmer", branch = "fluence" }
|
||||
wasmer-wasi = { git = "http://github.com/fluencelabs/wasmer", branch = "fluence" }
|
||||
failure = "0.1.7"
|
||||
lazy_static = "1.4.0"
|
||||
sha2 = "0.8.1"
|
||||
rustyline = "6.1.2"
|
||||
exitfailure = "0.5.1"
|
||||
boolinator = "2.4.0"
|
||||
parity-wasm = "0.41.0"
|
||||
pwasm-utils = "0.12.0"
|
||||
|
||||
[dev-dependencies]
|
||||
reqwest = "0.10.4"
|
||||
bytes = "0.5.4"
|
||||
tokio = { version = "0.2.20", features = ["blocking", "macros"] }
|
||||
|
||||
[profile.release]
|
||||
#opt-level = 3
|
||||
#debug = false
|
||||
#lto = true
|
||||
#debug-assertions = false
|
||||
#overflow-checks = false
|
||||
#panic = "abort"
|
22
wit_embedder/Cargo.toml
Normal file
22
wit_embedder/Cargo.toml
Normal file
@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "wit_embedder"
|
||||
version = "0.1.0"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
walrus = "0.17.0"
|
||||
wasmer-interface-types = { git = "https://github.com/fluencelabs/interface-types", branch = "master"}
|
||||
options = "0.5.1"
|
||||
either = "1.5.3"
|
||||
clap = "2.33.1"
|
||||
exitfailure = "0.5.1"
|
||||
failure = "0.1.5"
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
debug = false
|
||||
lto = true
|
||||
debug-assertions = false
|
||||
overflow-checks = false
|
||||
panic = "abort"
|
17
wit_embedder/src/custom.rs
Normal file
17
wit_embedder/src/custom.rs
Normal file
@ -0,0 +1,17 @@
|
||||
use std::borrow::Cow;
|
||||
use walrus::{CustomSection, IdsToIndices};
|
||||
|
||||
pub const WIT_SECTION_NAME: &str = "interface-types";
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct WITCustom(pub Vec<u8>);
|
||||
|
||||
impl CustomSection for WITCustom {
|
||||
fn name(&self) -> &str {
|
||||
WIT_SECTION_NAME
|
||||
}
|
||||
|
||||
fn data(&self, _ids_to_indices: &IdsToIndices) -> Cow<[u8]> {
|
||||
Cow::Borrowed(&self.0)
|
||||
}
|
||||
}
|
35
wit_embedder/src/embedder.rs
Normal file
35
wit_embedder/src/embedder.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use crate::custom::WITCustom;
|
||||
use std::path::PathBuf;
|
||||
use walrus::ModuleConfig;
|
||||
use wasmer_interface_types::{
|
||||
decoders::wat::{parse, Buffer},
|
||||
encoders::binary::ToBytes,
|
||||
};
|
||||
|
||||
pub struct Config {
|
||||
pub in_wasm_path: PathBuf,
|
||||
pub wit: String,
|
||||
pub out_wasm_path: PathBuf,
|
||||
}
|
||||
|
||||
pub fn embed_wit(options: &Config) -> Result<(), String> {
|
||||
let mut module = ModuleConfig::new()
|
||||
.parse_file(&options.in_wasm_path)
|
||||
.map_err(|e| format!("Failed to parse the Wasm module: {}", e))?;
|
||||
|
||||
let buffer = Buffer::new(&options.wit)
|
||||
.map_err(|e| format!("Can't parse provided Wasm module: {}", e))?;
|
||||
let ast = parse(&buffer).map_err(|e| format!("Failed to parse the WIT description: {}", e))?;
|
||||
|
||||
let mut bytes = vec![];
|
||||
ast.to_bytes(&mut bytes)
|
||||
.map_err(|_| "Failed to encode the AST into its binary representation.")?;
|
||||
|
||||
let custom = WITCustom(bytes);
|
||||
module.customs.add(custom);
|
||||
module
|
||||
.emit_wasm_file(&options.out_wasm_path)
|
||||
.map_err(|e| format!("Failed to emit Wasm file with bindings: {}", e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
35
wit_embedder/src/extracter.rs
Normal file
35
wit_embedder/src/extracter.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use std::path::PathBuf;
|
||||
use walrus::{IdsToIndices, ModuleConfig};
|
||||
|
||||
pub fn extract_wit(wasm_file: PathBuf) -> Result<String, String> {
|
||||
let module = ModuleConfig::new()
|
||||
.parse_file(wasm_file)
|
||||
.map_err(|_| "Failed to parse the Wasm module.".to_string())?;
|
||||
|
||||
let sections = module
|
||||
.customs
|
||||
.iter()
|
||||
.filter(|(_, section)| section.name() == "interface-types")
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if sections.is_empty() {
|
||||
return Err("Wasm binary doesn't contain interface types section".to_string());
|
||||
}
|
||||
if sections.len() > 1 {
|
||||
return Err("Wasm binary contains more than one interface-types section".to_string());
|
||||
}
|
||||
|
||||
let default_ids = IdsToIndices::default();
|
||||
let wit_section_bytes = sections[0].1.data(&default_ids).into_owned();
|
||||
let wit = match wasmer_interface_types::decoders::binary::parse::<()>(&wit_section_bytes) {
|
||||
Ok((remainder, wit)) if remainder.is_empty() => wit,
|
||||
Ok((remainder, _)) => {
|
||||
return Err(format!("remainder isn't empty: {:?}", remainder));
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(format!("An error occurred while parsing: {}", e));
|
||||
}
|
||||
};
|
||||
|
||||
Ok(format!("{:?}", wit))
|
||||
}
|
103
wit_embedder/src/main.rs
Normal file
103
wit_embedder/src/main.rs
Normal file
@ -0,0 +1,103 @@
|
||||
mod custom;
|
||||
mod embedder;
|
||||
mod extracter;
|
||||
|
||||
use clap::{App, AppSettings, Arg, SubCommand};
|
||||
use embedder::Config;
|
||||
use failure::err_msg;
|
||||
use std::path::PathBuf;
|
||||
|
||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
const AUTHORS: &str = env!("CARGO_PKG_AUTHORS");
|
||||
const DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION");
|
||||
|
||||
const IN_WASM_PATH: &str = "in-wasm-path";
|
||||
const WIT_PATH: &str = "wit-path";
|
||||
const OUT_WASM_PATH: &str = "out-wasm-path";
|
||||
|
||||
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"),
|
||||
])
|
||||
}
|
||||
|
||||
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 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());
|
||||
|
||||
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();
|
||||
|
||||
let options = Config {
|
||||
in_wasm_path: PathBuf::from(in_wasm_path),
|
||||
wit,
|
||||
out_wasm_path: PathBuf::from(out_wasm_path),
|
||||
};
|
||||
|
||||
match embedder::embed_wit(&options) {
|
||||
Ok(_) => {
|
||||
println!("WIT successfully embedded");
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", e);
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
("show", Some(arg)) => {
|
||||
let wasm_path = arg.value_of(IN_WASM_PATH).unwrap();
|
||||
let wasm_path = PathBuf::from(wasm_path);
|
||||
|
||||
match extracter::extract_wit(wasm_path) {
|
||||
Ok(wat) => {
|
||||
println!("extracted WIT:\n{}", wat);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", e);
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
c => Err(err_msg(format!("Unexpected command: {}", c.0)).into()),
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user