Support versioning in CLI (#67)

This commit is contained in:
vms 2021-03-12 20:04:47 +03:00 committed by GitHub
parent b0f2738c94
commit 5effdcba72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 993 additions and 217 deletions

View File

@ -13,12 +13,12 @@ jobs:
keys: keys:
- fce04-{{ checksum "Cargo.lock" }} - fce04-{{ checksum "Cargo.lock" }}
- run: | - run: |
rustup toolchain install nightly-2020-12-15 rustup toolchain install nightly-2021-02-27
rustup default nightly-2020-12-15 rustup default nightly-2021-02-27
rustup override set nightly-2020-12-15 rustup override set nightly-2021-02-27
rustup component add rustfmt --toolchain nightly-2020-12-15 rustup component add rustfmt --toolchain nightly-2021-02-27
rustup component add clippy --toolchain nightly-2020-12-15 rustup component add clippy --toolchain nightly-2021-02-27
rustup target add wasm32-wasi rustup target add wasm32-wasi
cargo install fcli cargo install fcli

184
Cargo.lock generated
View File

@ -69,7 +69,7 @@ dependencies = [
name = "arguments-passing-test" name = "arguments-passing-test"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fluence 0.4.2", "fluence 0.5.0",
"safe-transmute", "safe-transmute",
] ]
@ -83,7 +83,7 @@ checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
name = "arrays-passing-test" name = "arrays-passing-test"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fluence 0.4.2", "fluence 0.5.0",
"safe-transmute", "safe-transmute",
] ]
@ -186,9 +186,9 @@ checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.4.2" version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]] [[package]]
name = "bytes" name = "bytes"
@ -206,7 +206,7 @@ checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
name = "call_parameters" name = "call_parameters"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fluence 0.4.2", "fluence 0.5.0",
] ]
[[package]] [[package]]
@ -421,7 +421,7 @@ dependencies = [
name = "curl_adapter" name = "curl_adapter"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fluence 0.4.2", "fluence 0.5.0",
"log", "log",
] ]
@ -626,7 +626,7 @@ name = "facade"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"fluence 0.4.2", "fluence 0.5.0",
"log", "log",
] ]
@ -680,6 +680,18 @@ dependencies = [
"wasmer-wasi-fl", "wasmer-wasi-fl",
] ]
[[package]]
name = "fce-module-manifest-parser"
version = "0.1.0"
dependencies = [
"anyhow",
"fluence-sdk-main 0.5.0",
"semver 0.11.0",
"serde",
"thiserror",
"walrus",
]
[[package]] [[package]]
name = "fce-sqlite-connector" name = "fce-sqlite-connector"
version = "0.2.0" version = "0.2.0"
@ -698,7 +710,7 @@ name = "fce-wit-generator"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"fce-wit-parser", "fce-wit-parser",
"fluence-sdk-wit 0.4.2", "fluence-sdk-wit 0.5.0",
"once_cell", "once_cell",
"serde", "serde",
"serde_json", "serde_json",
@ -721,6 +733,7 @@ dependencies = [
"anyhow", "anyhow",
"fce-wit-interfaces", "fce-wit-interfaces",
"serde", "serde",
"thiserror",
"walrus", "walrus",
"wasmer-interface-types-fl", "wasmer-interface-types-fl",
"wasmer-runtime-core-fl", "wasmer-runtime-core-fl",
@ -728,11 +741,12 @@ dependencies = [
[[package]] [[package]]
name = "fcli" name = "fcli"
version = "0.2.0" version = "0.3.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
"exitfailure", "exitfailure",
"fce-module-manifest-parser",
"fce-wit-generator", "fce-wit-generator",
"fce-wit-parser", "fce-wit-parser",
"serde", "serde",
@ -759,6 +773,16 @@ dependencies = [
"fluence-sdk-main 0.4.2", "fluence-sdk-main 0.4.2",
] ]
[[package]]
name = "fluence"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "342831732a977f13220ecd6f25c7e6b6127af8d3794d42e3c880b05e457a0484"
dependencies = [
"fluence-sdk-macro 0.5.0",
"fluence-sdk-main 0.5.0",
]
[[package]] [[package]]
name = "fluence-app-service" name = "fluence-app-service"
version = "0.5.2" version = "0.5.2"
@ -781,7 +805,7 @@ dependencies = [
"env_logger 0.7.1", "env_logger 0.7.1",
"fce", "fce",
"fce-utils", "fce-utils",
"fluence-sdk-main 0.4.2", "fluence-sdk-main 0.5.0",
"itertools", "itertools",
"log", "log",
"once_cell", "once_cell",
@ -828,6 +852,15 @@ dependencies = [
"fluence-sdk-wit 0.4.2", "fluence-sdk-wit 0.4.2",
] ]
[[package]]
name = "fluence-sdk-macro"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00c840552e5e58b62d4a272e3e4aabd548e1a4519df629a51d42157c7ecbe653"
dependencies = [
"fluence-sdk-wit 0.5.0",
]
[[package]] [[package]]
name = "fluence-sdk-main" name = "fluence-sdk-main"
version = "0.2.18" version = "0.2.18"
@ -850,6 +883,17 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "fluence-sdk-main"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f1d126f05a798c8f812fbe47a42145478ce8029e00411b04d1c5194ab368313"
dependencies = [
"fluence-sdk-macro 0.5.0",
"log",
"serde",
]
[[package]] [[package]]
name = "fluence-sdk-wit" name = "fluence-sdk-wit"
version = "0.2.18" version = "0.2.18"
@ -878,6 +922,20 @@ dependencies = [
"uuid", "uuid",
] ]
[[package]]
name = "fluence-sdk-wit"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ac71e8d48a8e2bdaccf59572dc7a8e8a1ad0de512fc452107756e37ac0bf752"
dependencies = [
"proc-macro2",
"quote",
"serde",
"serde_json",
"syn",
"uuid",
]
[[package]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
@ -917,7 +975,7 @@ dependencies = [
"clap", "clap",
"env_logger 0.7.1", "env_logger 0.7.1",
"fluence-app-service", "fluence-app-service",
"fluence-sdk-main 0.4.2", "fluence-sdk-main 0.5.0",
"itertools", "itertools",
"log", "log",
"rustop", "rustop",
@ -979,7 +1037,7 @@ checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-task", "futures-task",
"pin-project-lite 0.2.5", "pin-project-lite 0.2.6",
"pin-utils", "pin-utils",
] ]
@ -1230,9 +1288,9 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.6.1" version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"hashbrown", "hashbrown",
@ -1243,7 +1301,7 @@ dependencies = [
name = "inner-records-test" name = "inner-records-test"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fluence 0.4.2", "fluence 0.5.0",
"safe-transmute", "safe-transmute",
] ]
@ -1291,7 +1349,7 @@ dependencies = [
name = "ipfs-effector" name = "ipfs-effector"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fluence 0.4.2", "fluence 0.5.0",
"log", "log",
] ]
@ -1299,7 +1357,7 @@ dependencies = [
name = "ipfs-pure" name = "ipfs-pure"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fluence 0.4.2", "fluence 0.5.0",
"log", "log",
] ]
@ -1376,15 +1434,15 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.87" version = "0.2.88"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213" checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a"
[[package]] [[package]]
name = "local_storage" name = "local_storage"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fluence 0.4.2", "fluence 0.5.0",
"log", "log",
] ]
@ -1756,6 +1814,15 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pest"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
dependencies = [
"ucd-trie",
]
[[package]] [[package]]
name = "pin-project" name = "pin-project"
version = "1.0.5" version = "1.0.5"
@ -1784,9 +1851,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777"
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.5" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cf491442e4b033ed1c722cb9f0df5fcfcf4de682466c46469c36bc47dc5548a" checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905"
[[package]] [[package]]
name = "pin-utils" name = "pin-utils"
@ -1933,7 +2000,7 @@ dependencies = [
name = "record-effector" name = "record-effector"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fluence 0.4.2", "fluence 0.5.0",
"test-record", "test-record",
] ]
@ -1941,7 +2008,7 @@ dependencies = [
name = "record-pure" name = "record-pure"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fluence 0.4.2", "fluence 0.5.0",
"test-record", "test-record",
] ]
@ -1983,21 +2050,20 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.4.3" version = "1.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" checksum = "54fd1046a3107eb58f42de31d656fee6853e5d276c455fd943742dce89fc3dd3"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
"regex-syntax", "regex-syntax",
"thread_local",
] ]
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.22" version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
[[package]] [[package]]
name = "remove_dir_all" name = "remove_dir_all"
@ -2031,7 +2097,7 @@ dependencies = [
"mime_guess", "mime_guess",
"native-tls", "native-tls",
"percent-encoding", "percent-encoding",
"pin-project-lite 0.2.5", "pin-project-lite 0.2.6",
"serde", "serde",
"serde_urlencoded", "serde_urlencoded",
"tokio", "tokio",
@ -2067,7 +2133,7 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [ dependencies = [
"semver", "semver 0.9.0",
] ]
[[package]] [[package]]
@ -2136,9 +2202,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "security-framework" name = "security-framework"
version = "2.1.1" version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfd318104249865096c8da1dfabf09ddbb6d0330ea176812a62ec75e40c4166" checksum = "d493c5f39e02dfb062cd8f33301f90f9b13b650e8c1b1d0fd75c19dd64bff69d"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"core-foundation", "core-foundation",
@ -2163,7 +2229,16 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [ dependencies = [
"semver-parser", "semver-parser 0.7.0",
]
[[package]]
name = "semver"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
dependencies = [
"semver-parser 0.10.2",
] ]
[[package]] [[package]]
@ -2172,6 +2247,15 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "semver-parser"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
dependencies = [
"pest",
]
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.118" version = "1.0.118"
@ -2314,9 +2398,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.60" version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" checksum = "8fd9bc7ccc2688b3344c2f48b9b546648b25ce0b20fc717ee7fa7981a8ca9717"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2379,7 +2463,7 @@ dependencies = [
name = "test-record" name = "test-record"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fluence 0.4.2", "fluence 0.5.0",
] ]
[[package]] [[package]]
@ -2530,7 +2614,7 @@ checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"log", "log",
"pin-project-lite 0.2.5", "pin-project-lite 0.2.6",
"tracing-core", "tracing-core",
] ]
@ -2603,6 +2687,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "ucd-trie"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]] [[package]]
name = "unicase" name = "unicase"
version = "2.6.0" version = "2.6.0"
@ -2716,23 +2806,23 @@ dependencies = [
[[package]] [[package]]
name = "walrus" name = "walrus"
version = "0.17.0" version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f970863270179a4e0ca2bfb470931f883f7535ae8b9dac4271761fa1b77e253d" checksum = "4d470d0583e65f4cab21a1ff3c1ba3dd23ae49e68f516f0afceaeb001b32af39"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"id-arena", "id-arena",
"leb128", "leb128",
"log", "log",
"walrus-macro", "walrus-macro",
"wasmparser 0.55.0", "wasmparser 0.59.0",
] ]
[[package]] [[package]]
name = "walrus-macro" name = "walrus-macro"
version = "0.17.0" version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80927fca8665132b48c7714bcec983d6e761c60b3a9877c6cd7df86417b13573" checksum = "d7c2bb690b44cb1b0fdcc54d4998d21f8bdaf706b93775425e440b174f39ad16"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@ -2834,7 +2924,7 @@ checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1"
name = "wasm-greeting" name = "wasm-greeting"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fluence 0.4.2", "fluence 0.5.0",
] ]
[[package]] [[package]]
@ -2842,7 +2932,7 @@ name = "wasm-sqlite-test"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fce-sqlite-connector", "fce-sqlite-connector",
"fluence 0.4.2", "fluence 0.5.0",
] ]
[[package]] [[package]]
@ -3025,9 +3115,9 @@ checksum = "aeb1956b19469d1c5e63e459d29e7b5aa0f558d9f16fcef09736f8a265e6c10a"
[[package]] [[package]]
name = "wasmparser" name = "wasmparser"
version = "0.55.0" version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af931e2e1960c53f4a28b063fec4cacd036f35acbec8ff3a4739125b17382a87" checksum = "a950e6a618f62147fd514ff445b2a0b53120d382751960797f85f058c7eda9b9"
[[package]] [[package]]
name = "wast" name = "wast"

View File

@ -1,6 +1,7 @@
[workspace] [workspace]
members = [ members = [
"aquamarine-vm", "aquamarine-vm",
"crates/module-info-parser",
"crates/utils", "crates/utils",
"crates/wit-generator", "crates/wit-generator",
"crates/wit-interfaces", "crates/wit-interfaces",

View File

@ -0,0 +1,21 @@
[package]
name = "fce-module-manifest-parser"
description = "Fluence FCE Wasm module manifest parser"
version = "0.1.0"
authors = ["Fluence Labs"]
license = "Apache-2.0"
edition = "2018"
[lib]
name = "fce_module_manifest_parser"
path = "src/lib.rs"
[dependencies]
fluence-sdk-main = "0.5.0"
anyhow = "1.0.31"
walrus = "0.18.0"
semver = "0.11.0"
serde = "=1.0.118"
thiserror = "1.0.24"

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 crate::ModuleInfoResult;
use crate::ModuleInfoError;
use walrus::IdsToIndices;
use walrus::Module;
use std::borrow::Cow;
pub(super) fn extract_custom_sections_by_name<'w>(
wasm_module: &'w Module,
section_name: &str,
) -> ModuleInfoResult<Vec<Cow<'w, [u8]>>> {
let default_ids = IdsToIndices::default();
let sections = wasm_module
.customs
.iter()
.filter(|(_, section)| section.name() == section_name)
.map(|s| s.1.data(&default_ids))
.collect::<Vec<_>>();
Ok(sections)
}
pub(super) fn try_as_one_section<'s>(
mut sections: Vec<Cow<'s, [u8]>>,
section_name: &'static str,
) -> ModuleInfoResult<Cow<'s, [u8]>> {
let sections_count = sections.len();
if sections_count > 1 {
return Err(ModuleInfoError::MultipleCustomSections(
section_name,
sections_count,
));
}
if sections_count == 0 {
return Err(ModuleInfoError::NoCustomSection(section_name));
}
Ok(sections.remove(0))
}

View File

@ -0,0 +1,84 @@
/*
* 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 semver::SemVerError;
use thiserror::Error as ThisError;
use std::str::Utf8Error;
#[derive(Debug, ThisError)]
pub enum ModuleInfoError {
/// Version section is absent.
#[error("the module doesn't contain section with '{0}', probably it's compiled with an old sdk version")]
NoCustomSection(&'static str),
/// Multiple sections with the same name.
#[error("the module contains {1} sections with name '{0}' - it's corrupted")]
MultipleCustomSections(&'static str, usize),
/// Errors related to corrupted version.
#[error("{0}")]
VersionError(#[from] SDKVersionError),
/// Errors related to corrupted manifest.
#[error("{0}")]
ManifestError(#[from] ManifestError),
/// An error occurred while parsing Wasm file.
#[error("provided Wasm file is corrupted: {0}")]
CorruptedWasmFile(anyhow::Error),
}
#[derive(Debug, ThisError)]
pub enum SDKVersionError {
/// Version can't be parsed to Utf8 string.
#[error("embedded to the Wasm file version isn't valid UTF8 string: '{0}'")]
VersionNotValidUtf8(Utf8Error),
/// Version can't be parsed with semver.
#[error("embedded to the Wasm file version is corrupted: '{0}'")]
VersionCorrupted(#[from] SemVerError),
}
#[derive(Debug, ThisError, PartialEq)]
pub enum ManifestError {
/// Manifest of a Wasm file doesn't have enough bytes to read size of a field from its prefix.
#[error(
"{0} can't be read: embedded manifest doesn't contain enough bytes to read field size from prefix"
)]
NotEnoughBytesForPrefix(&'static str),
/// Manifest of a Wasm file doesn't have enough bytes to read a field.
#[error(
"{0} can't be read: embedded manifest doesn't contain enough bytes to read field of size {1}"
)]
NotEnoughBytesForField(&'static str, usize),
/// Manifest of a Wasm file doesn't have enough bytes to read field.
#[error("{0} is an invalid Utf8 string: {1}")]
FieldNotValidUtf8(&'static str, Utf8Error),
/// Size inside prefix of a field is too big (it exceeds usize or overflows with prefix size).
#[error("{0} has too big size: {1}")]
TooBigFieldSize(&'static str, u64),
/// Version can't be parsed with semver.
#[error("embedded to the Wasm file version is corrupted: '{0}'")]
ModuleVersionCorrupted(#[from] SemVerError),
/// Manifest contains some trailing characters.
#[error("embedded manifest is corrupted: there are some trailing characters")]
ManifestRemainderNotEmpty,
}

View File

@ -0,0 +1,49 @@
/*
* 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 custom_section_extractor;
mod errors;
mod manifest;
mod manifest_extractor;
mod version_extractor;
#[cfg(test)]
mod tests;
pub use errors::ModuleInfoError;
pub use errors::ManifestError;
pub use errors::SDKVersionError;
pub use version_extractor::extract_sdk_version_by_path;
pub use version_extractor::extract_sdk_version_by_module;
pub use manifest::ModuleManifest;
pub use manifest_extractor::extract_manifest_by_path;
pub use manifest_extractor::extract_version_by_module;
pub(crate) use custom_section_extractor::extract_custom_sections_by_name;
pub(crate) use custom_section_extractor::try_as_one_section;
pub(crate) type ModuleInfoResult<T> = std::result::Result<T, ModuleInfoError>;

View File

@ -0,0 +1,145 @@
/*
* 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.
*/
/// Describes manifest of a Wasm module in the Fluence network.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ModuleManifest {
pub authors: String,
pub version: semver::Version,
pub description: String,
pub repository: String,
}
use crate::ManifestError;
use std::convert::TryFrom;
use std::str::FromStr;
type Result<T> = std::result::Result<T, ManifestError>;
impl TryFrom<&[u8]> for ModuleManifest {
type Error = ManifestError;
#[rustfmt::skip]
fn try_from(value: &[u8]) -> Result<Self> {
let (authors, next_offset) = try_extract_field_as_string(value, 0, "authors")?;
let (version, next_offset) = try_extract_field_as_version(value, next_offset, "version")?;
let (description, next_offset) = try_extract_field_as_string(value, next_offset, "description")?;
let (repository, next_offset) = try_extract_field_as_string(value, next_offset, "repository")?;
if next_offset != value.len() {
return Err(ManifestError::ManifestRemainderNotEmpty)
}
let manifest = ModuleManifest {
authors,
version,
description,
repository,
};
Ok(manifest)
}
}
fn try_extract_field_as_string(
raw_manifest: &[u8],
offset: usize,
field_name: &'static str,
) -> Result<(String, usize)> {
let raw_manifest = &raw_manifest[offset..];
let (field_as_bytes, read_len) = try_extract_prefixed_field(raw_manifest, field_name)?;
let field_as_string = try_to_str(field_as_bytes, field_name)?.to_string();
Ok((field_as_string, offset + read_len))
}
fn try_extract_field_as_version(
raw_manifest: &[u8],
offset: usize,
field_name: &'static str,
) -> Result<(semver::Version, usize)> {
let raw_manifest = &raw_manifest[offset..];
let (field_as_bytes, read_len) = try_extract_prefixed_field(raw_manifest, field_name)?;
let field_as_str = try_to_str(field_as_bytes, field_name)?;
let version = semver::Version::from_str(field_as_str)?;
Ok((version, offset + read_len))
}
const PREFIX_SIZE: usize = std::mem::size_of::<u64>();
fn try_extract_prefixed_field<'a>(
array: &'a [u8],
field_name: &'static str,
) -> Result<(&'a [u8], usize)> {
let field_len = try_extract_field_len(array, field_name)?;
let field = try_extract_field(array, field_len, field_name)?;
let read_size = PREFIX_SIZE + field.len();
Ok((field, read_size))
}
fn try_extract_field_len(array: &[u8], field_name: &'static str) -> Result<usize> {
if array.len() < PREFIX_SIZE {
return Err(ManifestError::NotEnoughBytesForPrefix(field_name));
}
let mut field_len = [0u8; PREFIX_SIZE];
field_len.copy_from_slice(&array[0..PREFIX_SIZE]);
let field_len = u64::from_le_bytes(field_len);
// TODO: Until we use Wasm32 and compiles our node to x86_64, converting to usize is sound
if field_len.checked_add(PREFIX_SIZE as u64).is_none()
|| usize::try_from(field_len + PREFIX_SIZE as u64).is_err()
{
return Err(ManifestError::TooBigFieldSize(field_name, field_len));
}
// it's safe to convert it to usize because it's been checked
Ok(field_len as usize)
}
fn try_extract_field<'a>(
array: &'a [u8],
field_len: usize,
field_name: &'static str,
) -> Result<&'a [u8]> {
if array.len() < PREFIX_SIZE + field_len {
return Err(ManifestError::NotEnoughBytesForField(field_name, field_len));
}
let field = &array[PREFIX_SIZE..PREFIX_SIZE + field_len];
Ok(field)
}
fn try_to_str<'v>(value: &'v [u8], field_name: &'static str) -> Result<&'v str> {
match std::str::from_utf8(value) {
Ok(s) => Ok(s),
Err(e) => Err(ManifestError::FieldNotValidUtf8(field_name, e)),
}
}
use std::fmt;
impl fmt::Display for ModuleManifest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "authors: {}", self.authors)?;
writeln!(f, "version: {}", self.version)?;
writeln!(f, "description: {}", self.description)?;
write!(f, "repository: {}", self.repository)
}
}

View File

@ -0,0 +1,55 @@
/*
* 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::ModuleInfoResult;
use crate::ModuleInfoError;
use crate::extract_custom_sections_by_name;
use crate::try_as_one_section;
use crate::ModuleManifest;
use fluence_sdk_main::MANIFEST_SECTION_NAME;
use walrus::ModuleConfig;
use walrus::Module;
use std::borrow::Cow;
use std::path::Path;
use std::convert::TryInto;
pub fn extract_manifest_by_path(
wasm_module_path: &Path,
) -> ModuleInfoResult<Option<ModuleManifest>> {
let module = ModuleConfig::new()
.parse_file(wasm_module_path)
.map_err(ModuleInfoError::CorruptedWasmFile)?;
extract_version_by_module(&module)
}
pub fn extract_version_by_module(wasm_module: &Module) -> ModuleInfoResult<Option<ModuleManifest>> {
let sections = extract_custom_sections_by_name(&wasm_module, MANIFEST_SECTION_NAME)?;
if sections.is_empty() {
return Ok(None);
}
let section = try_as_one_section(sections, MANIFEST_SECTION_NAME)?;
let manifest = match section {
Cow::Borrowed(bytes) => bytes.try_into(),
Cow::Owned(vec) => vec.as_slice().try_into(),
}?;
Ok(Some(manifest))
}

View File

@ -0,0 +1,154 @@
/*
* 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::ManifestError;
use crate::ModuleManifest;
use std::convert::TryInto;
use std::str::FromStr;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
struct ByteEncoder {
buffer: Vec<u8>,
}
impl ByteEncoder {
pub fn new() -> Self {
<_>::default()
}
pub fn add_u64(&mut self, number: u64) {
use std::io::Write;
let number_le_bytes = number.to_le_bytes();
self.buffer
.write(&number_le_bytes)
.expect("writing to buffer should be successful");
}
pub fn add_utf8_string(&mut self, str: &str) {
use std::io::Write;
let str_as_bytes = str.as_bytes();
self.buffer
.write(&str_as_bytes)
.expect("writing to buffer should be successful");
}
pub fn add_utf8_field(&mut self, field: &str) {
let field_len = field.as_bytes().len();
self.add_u64(field_len as u64);
self.add_utf8_string(field);
}
pub fn as_bytes(&self) -> &[u8] {
&self.buffer
}
#[allow(dead_code)]
pub fn into_vec(self) -> Vec<u8> {
self.buffer
}
}
#[test]
fn test_reading_simple_config() {
let authors = "authors".to_string();
let version = semver::Version::from_str("0.1.0").unwrap();
let description = "description".to_string();
let repository = "repository".to_string();
let mut array = ByteEncoder::new();
array.add_utf8_field(&authors);
array.add_utf8_field(&version.to_string());
array.add_utf8_field(&description);
array.add_utf8_field(&repository);
let actual: ModuleManifest = array
.as_bytes()
.try_into()
.expect("module manifest should be deserialized correctly");
let expected = ModuleManifest {
authors,
version,
description,
repository,
};
assert_eq!(actual, expected);
}
#[test]
fn test_too_big_field_len() {
let mut array = ByteEncoder::new();
array.add_utf8_field("authors");
let incorrect_size = u64::MAX;
array.add_u64(incorrect_size);
array.add_utf8_string("version");
array.add_utf8_field("description");
array.add_utf8_field("repository");
let actual: Result<ModuleManifest, _> = array.as_bytes().try_into();
let expected = Err(ManifestError::TooBigFieldSize("version", incorrect_size));
assert_eq!(actual, expected);
}
#[test]
fn test_without_one_field() {
let mut array = ByteEncoder::new();
array.add_utf8_field("authors");
array.add_utf8_field("0.1.0");
array.add_utf8_field("description");
let actual: Result<ModuleManifest, _> = array.as_bytes().try_into();
let expected = Err(ManifestError::NotEnoughBytesForPrefix("repository"));
assert_eq!(actual, expected);
}
#[test]
fn test_with_empty_slice() {
let actual: Result<ModuleManifest, _> = vec![].as_slice().try_into();
let expected = Err(ManifestError::NotEnoughBytesForPrefix("authors"));
assert_eq!(actual, expected);
}
#[test]
fn test_not_enough_data_for_field() {
let mut array = ByteEncoder::new();
array.add_utf8_field("authors");
array.add_utf8_field("0.1.0");
array.add_utf8_field("description");
let too_big_size = 0xFF;
array.add_u64(too_big_size);
array.add_utf8_string("repository");
let actual: Result<ModuleManifest, _> = array.as_bytes().try_into();
let expected = Err(ManifestError::NotEnoughBytesForField(
"repository",
too_big_size as usize,
));
assert_eq!(actual, expected);
}

View File

@ -0,0 +1,64 @@
/*
* 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::ModuleInfoResult;
use crate::ModuleInfoError;
use crate::SDKVersionError;
use crate::extract_custom_sections_by_name;
use crate::try_as_one_section;
use fluence_sdk_main::VERSION_SECTION_NAME;
use walrus::ModuleConfig;
use walrus::Module;
use std::borrow::Cow;
use std::str::FromStr;
use std::path::Path;
pub fn extract_sdk_version_by_path(
wasm_module_path: &Path,
) -> ModuleInfoResult<Option<semver::Version>> {
let module = ModuleConfig::new()
.parse_file(wasm_module_path)
.map_err(ModuleInfoError::CorruptedWasmFile)?;
extract_sdk_version_by_module(&module)
}
pub fn extract_sdk_version_by_module(
wasm_module: &Module,
) -> ModuleInfoResult<Option<semver::Version>> {
let sections = extract_custom_sections_by_name(&wasm_module, VERSION_SECTION_NAME)?;
if sections.is_empty() {
return Ok(None);
}
let section = try_as_one_section(sections, VERSION_SECTION_NAME)?;
let version = match section {
Cow::Borrowed(bytes) => as_semver(bytes),
Cow::Owned(vec) => as_semver(&vec),
}?;
Ok(Some(version))
}
fn as_semver(version_as_bytes: &[u8]) -> Result<semver::Version, crate::SDKVersionError> {
match std::str::from_utf8(version_as_bytes) {
Ok(str) => Ok(semver::Version::from_str(str)?),
Err(e) => Err(SDKVersionError::VersionNotValidUtf8(e)),
}
}

View File

@ -12,9 +12,9 @@ path = "src/lib.rs"
[dependencies] [dependencies]
fce-wit-parser = { path = "../wit-parser", version = "0.2.0"} fce-wit-parser = { path = "../wit-parser", version = "0.2.0"}
fluence-sdk-wit = "=0.4.2" fluence-sdk-wit = "=0.5.0"
walrus = "0.17.0" walrus = "0.18.0"
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.24" } wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.24" }
once_cell = "1.4.0" once_cell = "1.4.0"
serde = { version = "=1.0.118", features = ["derive"] } serde = { version = "=1.0.118", features = ["derive"] }

View File

@ -14,8 +14,9 @@ path = "src/lib.rs"
fce-wit-interfaces = { path = "../wit-interfaces", version = "0.1.29" } fce-wit-interfaces = { path = "../wit-interfaces", version = "0.1.29" }
anyhow = "1.0.31" anyhow = "1.0.31"
walrus = "0.17.0" walrus = "0.18.0"
wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0"} wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0"}
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.24" } wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.24" }
serde = "=1.0.118" serde = "=1.0.118"
thiserror = "1.0.24"

View File

@ -14,17 +14,19 @@
* limitations under the License. * limitations under the License.
*/ */
use std::borrow::Cow; use walrus::CustomSection;
use walrus::{CustomSection, IdsToIndices}; use walrus::IdsToIndices;
pub const WIT_SECTION_NAME: &str = "interface-types"; use std::borrow::Cow;
pub const IT_SECTION_NAME: &str = "interface-types";
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(super) struct WITCustom(pub Vec<u8>); pub(super) struct ITCustomSection(pub Vec<u8>);
impl CustomSection for WITCustom { impl CustomSection for ITCustomSection {
fn name(&self) -> &str { fn name(&self) -> &str {
WIT_SECTION_NAME IT_SECTION_NAME
} }
fn data(&self, _ids_to_indices: &IdsToIndices) -> Cow<'_, [u8]> { fn data(&self, _ids_to_indices: &IdsToIndices) -> Cow<'_, [u8]> {

View File

@ -15,7 +15,7 @@
*/ */
use super::errors::WITParserError; use super::errors::WITParserError;
use super::custom::WIT_SECTION_NAME; use super::custom::IT_SECTION_NAME;
use walrus::ModuleConfig; use walrus::ModuleConfig;
@ -45,7 +45,7 @@ pub fn delete_wit_section(mut wasm_module: walrus::Module) -> walrus::Module {
.customs .customs
.iter() .iter()
.filter_map(|(id, section)| { .filter_map(|(id, section)| {
if section.name() == WIT_SECTION_NAME { if section.name() == IT_SECTION_NAME {
Some(id) Some(id)
} else { } else {
None None

View File

@ -14,8 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
use super::custom::WITCustom; use super::custom::ITCustomSection;
use super::errors::WITParserError; use super::errors::WITParserError;
use crate::Result;
use walrus::ModuleConfig; use walrus::ModuleConfig;
use wasmer_wit::{ use wasmer_wit::{
@ -27,11 +28,7 @@ use wasmer_wit::ToBytes;
use std::path::PathBuf; use std::path::PathBuf;
/// Embed provided WIT to a Wasm file by path. /// Embed provided WIT to a Wasm file by path.
pub fn embed_text_wit( pub fn embed_text_wit(in_wasm_path: PathBuf, out_wasm_path: PathBuf, wit: &str) -> Result<()> {
in_wasm_path: PathBuf,
out_wasm_path: PathBuf,
wit: &str,
) -> Result<(), WITParserError> {
let 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)?;
@ -53,7 +50,7 @@ pub fn embed_wit(mut wasm_module: walrus::Module, interfaces: &Interfaces<'_>) -
// TODO: think about possible errors here // TODO: think about possible errors here
interfaces.to_bytes(&mut bytes).unwrap(); interfaces.to_bytes(&mut bytes).unwrap();
let custom = WITCustom(bytes); let custom = ITCustomSection(bytes);
wasm_module.customs.add(custom); wasm_module.customs.add(custom);
wasm_module wasm_module

View File

@ -15,77 +15,57 @@
*/ */
use wasmer_wit::decoders::wat::Error as WATError; use wasmer_wit::decoders::wat::Error as WATError;
use std::io::Error as StdIOError; use thiserror::Error as ThisError;
use std::error::Error;
#[derive(Debug)] use std::io::Error as IOError;
#[derive(Debug, ThisError)]
pub enum WITParserError { pub enum WITParserError {
/// WIT section is absent. /// WIT section is absent.
NoWITSection, #[error("the module doesn't contain IT section")]
NoITSection,
/// Multiple WIT sections. /// Multiple WIT sections.
MultipleWITSections, #[error("the module contains multiple IT sections that is unsupported")]
MultipleITSections,
/// WIT section remainder isn't empty. /// WIT section remainder isn't empty.
WITRemainderNotEmpty, #[error("IT section is corrupted: IT section remainder isn't empty")]
ITRemainderNotEmpty,
/// An error occurred while parsing WIT section. /// An error occurred while parsing WIT section.
CorruptedWITSection, #[error("IT section is corrupted")]
CorruptedITSection,
// An error related to incorrect wit section. /// An error related to incorrect data of wit section.
IncorrectWIT(String), #[error("{0}")]
IncorrectITFormat(String),
/// An error occurred while parsing file in Wat format. /// An error occurred while parsing file in Wat format.
CorruptedWATFile(WATError), #[error("provided file with IT definitions is corrupted: {0}")]
CorruptedITFile(WATError),
/// An error occurred while parsing Wasm file /// An error occurred while parsing Wasm file.
#[error("provided Wasm file is corrupted: {0}")]
CorruptedWasmFile(anyhow::Error), CorruptedWasmFile(anyhow::Error),
/// An error occurred while manipulating with converting ast to bytes. /// An error occurred while manipulating with converting ast to bytes.
AstToBytesError(StdIOError), #[error("Convertation Wast to AST failed with: {0}")]
AstToBytesError(IOError),
// Wasm emittig file error. /// Wasm emitting file error.
#[error("Emitting resulted Wasm file failed with: {0}")]
WasmEmitError(anyhow::Error), WasmEmitError(anyhow::Error),
} }
impl Error for WITParserError {}
impl std::fmt::Display for WITParserError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
WITParserError::NoWITSection => write!(f, "Loaded module doesn't contain WIT section"),
WITParserError::MultipleWITSections => write!(
f,
"Loaded module contains multiple WIT sections that is unsupported now"
),
WITParserError::WITRemainderNotEmpty => write!(
f,
"WIT section remainder isn't empty - WIT section possibly corrupted"
),
WITParserError::IncorrectWIT(err_msg) => write!(f, "{}", err_msg),
WITParserError::CorruptedWITSection => write!(f, "WIT section is corrupted"),
WITParserError::CorruptedWATFile(err) => {
write!(f, "an error occurred while parsing wat file: {}", err)
}
WITParserError::CorruptedWasmFile(err) => {
write!(f, "Failed to parse the Wasm module: {}", err)
}
WITParserError::AstToBytesError(err) => {
write!(f, "Wasm AST converting to bytes failed with: {}", err)
}
WITParserError::WasmEmitError(err) => write!(f, "Failed to emit Wasm file: {}", err),
}
}
}
impl From<WATError> for WITParserError { impl From<WATError> for WITParserError {
fn from(err: WATError) -> Self { fn from(err: WATError) -> Self {
WITParserError::CorruptedWATFile(err) WITParserError::CorruptedITFile(err)
} }
} }
impl From<StdIOError> for WITParserError { impl From<IOError> for WITParserError {
fn from(err: StdIOError) -> Self { fn from(err: IOError) -> Self {
WITParserError::AstToBytesError(err) WITParserError::AstToBytesError(err)
} }
} }

View File

@ -26,8 +26,8 @@ use std::path::Path;
pub fn module_interface(module_path: &Path) -> Result<ServiceInterface> { pub fn module_interface(module_path: &Path) -> Result<ServiceInterface> {
use fce_wit_interfaces::FCEWITInterfaces; use fce_wit_interfaces::FCEWITInterfaces;
let wit_section_bytes = extract_wit_section_bytes(module_path)?; let wit_section_bytes = extract_custom_section(module_path)?;
let wit = extract_wit_with_fn(&wit_section_bytes)?; let wit = extract_wit_from_bytes(&wit_section_bytes)?;
let fce_interface = FCEWITInterfaces::new(wit); let fce_interface = FCEWITInterfaces::new(wit);
get_interface(&fce_interface) get_interface(&fce_interface)

View File

@ -88,7 +88,7 @@ fn get_exports(wit: &FCEWITInterfaces<'_>) -> Result<Vec<FCEFunctionSignature>>
}; };
Ok(signature) Ok(signature)
} }
_ => Err(WITParserError::IncorrectWIT(format!( _ => Err(WITParserError::IncorrectITFormat(format!(
"type with idx = {} isn't a function type", "type with idx = {} isn't a function type",
adapter_function_type adapter_function_type
))), ))),

View File

@ -14,8 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
use crate::custom::WIT_SECTION_NAME; use crate::custom::IT_SECTION_NAME;
use crate::errors::WITParserError; use crate::errors::WITParserError;
use crate::Result;
use walrus::{IdsToIndices, ModuleConfig}; use walrus::{IdsToIndices, ModuleConfig};
use wasmer_wit::ast::Interfaces; use wasmer_wit::ast::Interfaces;
@ -24,36 +25,34 @@ use wasmer_core::Module as WasmerModule;
use std::path::Path; use std::path::Path;
/// Extracts WIT section of provided Wasm binary and converts it to a string. /// Extracts WIT section of provided Wasm binary and converts it to a string.
pub fn extract_text_wit(wasm_file_path: &Path) -> Result<String, WITParserError> { pub fn extract_text_wit(wasm_file_path: &Path) -> Result<String> {
let wit_section_bytes = extract_wit_section_bytes(&wasm_file_path)?; let wit_section_bytes = extract_custom_section(&wasm_file_path)?;
let wit = extract_wit_with_fn(&wit_section_bytes)?; let wit = extract_wit_from_bytes(&wit_section_bytes)?;
Ok((&wit).to_string()) Ok((&wit).to_string())
} }
/// Extracts WIT section of provided Wasm binary and converts it to a FCEWITInterfaces. /// Extracts WIT section of provided Wasm binary and converts it to a FCEWITInterfaces.
pub fn extract_wit(wasmer_module: &WasmerModule) -> Result<Interfaces<'_>, WITParserError> { pub fn extract_wit(wasmer_module: &WasmerModule) -> Result<Interfaces<'_>> {
let wit_sections = wasmer_module let wit_sections = wasmer_module
.custom_sections(WIT_SECTION_NAME) .custom_sections(IT_SECTION_NAME)
.ok_or(WITParserError::NoWITSection)?; .ok_or(WITParserError::NoITSection)?;
if wit_sections.len() > 1 { if wit_sections.len() > 1 {
return Err(WITParserError::MultipleWITSections); return Err(WITParserError::MultipleITSections);
} }
extract_wit_with_fn(&wit_sections[0]) extract_wit_from_bytes(&wit_sections[0])
} }
pub(crate) fn extract_wit_with_fn( pub(crate) fn extract_wit_from_bytes(wit_section_bytes: &[u8]) -> Result<Interfaces<'_>> {
wit_section_bytes: &[u8], match wasmer_wit::decoders::binary::parse::<()>(wit_section_bytes) {
) -> Result<Interfaces<'_>, WITParserError> {
match wasmer_wit::decoders::binary::parse::<()>(&wit_section_bytes) {
Ok((remainder, wit)) if remainder.is_empty() => Ok(wit), Ok((remainder, wit)) if remainder.is_empty() => Ok(wit),
Ok(_) => Err(WITParserError::WITRemainderNotEmpty), Ok(_) => Err(WITParserError::ITRemainderNotEmpty),
Err(_) => Err(WITParserError::CorruptedWITSection), Err(_) => Err(WITParserError::CorruptedITSection),
} }
} }
pub(crate) fn extract_wit_section_bytes(wasm_file_path: &Path) -> Result<Vec<u8>, WITParserError> { pub(crate) fn extract_custom_section(wasm_file_path: &Path) -> Result<Vec<u8>> {
let module = ModuleConfig::new() let module = ModuleConfig::new()
.parse_file(wasm_file_path) .parse_file(wasm_file_path)
.map_err(WITParserError::CorruptedWasmFile)?; .map_err(WITParserError::CorruptedWasmFile)?;
@ -61,14 +60,14 @@ pub(crate) fn extract_wit_section_bytes(wasm_file_path: &Path) -> Result<Vec<u8>
let sections = module let sections = module
.customs .customs
.iter() .iter()
.filter(|(_, section)| section.name() == WIT_SECTION_NAME) .filter(|(_, section)| section.name() == IT_SECTION_NAME)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if sections.is_empty() { if sections.is_empty() {
return Err(WITParserError::NoWITSection); return Err(WITParserError::NoITSection);
} }
if sections.len() > 1 { if sections.len() > 1 {
return Err(WITParserError::MultipleWITSections); return Err(WITParserError::MultipleITSections);
} }
let default_ids = IdsToIndices::default(); let default_ids = IdsToIndices::default();

View File

@ -10,4 +10,4 @@ name = "call_parameters"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
fluence = "=0.4.2" fluence = "=0.5.0"

View File

@ -2,6 +2,8 @@
name = "wasm-greeting" name = "wasm-greeting"
version = "0.1.0" version = "0.1.0"
authors = ["Fluence Labs"] authors = ["Fluence Labs"]
description = "The greeting module for the Fluence network"
repository = "https://github.com/fluencelabs/fce/tree/master/examples/greeting"
edition = "2018" edition = "2018"
publish = false publish = false
@ -10,4 +12,4 @@ name = "greeting"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
fluence = "=0.4.2" fluence = "0.5.0"

View File

@ -15,6 +15,9 @@
*/ */
use fluence::fce; use fluence::fce;
use fluence::module_manifest;
module_manifest!();
pub fn main() {} pub fn main() {}

View File

@ -10,5 +10,5 @@ name = "ipfs_effector"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
fluence = { version = "=0.4.2", features = ["logger"] } fluence = { version = "=0.5.0", features = ["logger"] }
log = "0.4.14" log = "0.4.14"

View File

@ -21,6 +21,7 @@ mod path;
use crate::path::to_full_path; use crate::path::to_full_path;
use fluence::fce; use fluence::fce;
use fluence::module_manifest;
use fluence::WasmLoggerBuilder; use fluence::WasmLoggerBuilder;
use fluence::MountedBinaryResult; use fluence::MountedBinaryResult;
@ -28,6 +29,8 @@ const RESULT_FILE_PATH: &str = "/tmp/ipfs_rpc_file";
const IPFS_ADDR_ENV_NAME: &str = "IPFS_ADDR"; const IPFS_ADDR_ENV_NAME: &str = "IPFS_ADDR";
const TIMEOUT_ENV_NAME: &str = "timeout"; const TIMEOUT_ENV_NAME: &str = "timeout";
module_manifest!();
pub fn main() { pub fn main() {
WasmLoggerBuilder::new() WasmLoggerBuilder::new()
.with_log_level(log::LevelFilter::Info) .with_log_level(log::LevelFilter::Info)

View File

@ -10,5 +10,5 @@ name = "ipfs_pure"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
fluence = { version = "=0.4.2", features = ["logger"] } fluence = { version = "=0.5.0", features = ["logger"] }
log = "0.4.14" log = "0.4.14"

View File

@ -17,6 +17,7 @@
#![allow(improper_ctypes)] #![allow(improper_ctypes)]
use fluence::fce; use fluence::fce;
use fluence::module_manifest;
use fluence::WasmLoggerBuilder; use fluence::WasmLoggerBuilder;
use std::fs; use std::fs;
@ -24,6 +25,8 @@ use std::path::PathBuf;
const RPC_TMP_FILEPATH: &str = "/tmp/ipfs_rpc_file"; const RPC_TMP_FILEPATH: &str = "/tmp/ipfs_rpc_file";
module_manifest!();
pub fn main() { pub fn main() {
WasmLoggerBuilder::new() WasmLoggerBuilder::new()
.with_log_level(log::LevelFilter::Info) .with_log_level(log::LevelFilter::Info)

View File

@ -10,5 +10,5 @@ name = "records_effector"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
fluence = { version = "=0.4.2", features = ["logger"]} fluence = { version = "=0.5.0", features = ["logger"]}
test-record = { path = "../test-record" } test-record = { path = "../test-record" }

View File

@ -15,8 +15,12 @@
*/ */
use fluence::fce; use fluence::fce;
use fluence::module_manifest;
use test_record::TestRecord; use test_record::TestRecord;
module_manifest!();
pub fn main() {} pub fn main() {}
#[fce] #[fce]

View File

@ -10,5 +10,5 @@ name = "records_pure"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
fluence = { version = "=0.4.2", features = ["logger"]} fluence = { version = "=0.5.0", features = ["logger"]}
test-record = { path = "../test-record" } test-record = { path = "../test-record" }

View File

@ -17,8 +17,12 @@
#![allow(improper_ctypes)] #![allow(improper_ctypes)]
use fluence::fce; use fluence::fce;
use fluence::module_manifest;
use test_record::TestRecord; use test_record::TestRecord;
module_manifest!();
pub fn main() {} pub fn main() {}
#[fce] #[fce]

View File

@ -10,4 +10,4 @@ name = "test_record"
path = "src/test_record.rs" path = "src/test_record.rs"
[dependencies] [dependencies]
fluence = "=0.4.2" fluence = "=0.5.0"

View File

@ -10,5 +10,5 @@ name = "sqlite_test"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
fluence = "0.4.2" fluence = "0.5.0"
fce-sqlite-connector = "0.2.0" fce-sqlite-connector = "0.2.0"

View File

@ -15,9 +15,13 @@
*/ */
use fluence::fce; use fluence::fce;
use fluence::module_manifest;
use fce_sqlite_connector; use fce_sqlite_connector;
use fce_sqlite_connector::State; use fce_sqlite_connector::State;
module_manifest!();
pub fn main() {} pub fn main() {}
#[fce] #[fce]

View File

@ -10,5 +10,5 @@ path = "src/main.rs"
name = "curl_adapter" name = "curl_adapter"
[dependencies] [dependencies]
fluence = { version = "=0.4.2", features = ["logger"] } fluence = { version = "=0.5.0", features = ["logger"] }
log = "0.4.8" log = "0.4.8"

View File

@ -17,10 +17,13 @@
#![allow(improper_ctypes)] #![allow(improper_ctypes)]
use fluence::fce; use fluence::fce;
use fluence::module_manifest;
use fluence::WasmLoggerBuilder; use fluence::WasmLoggerBuilder;
use fluence::MountedBinaryResult; use fluence::MountedBinaryResult;
module_manifest!();
/// Log level can be changed by `RUST_LOG` env as well. /// Log level can be changed by `RUST_LOG` env as well.
pub fn main() { pub fn main() {
WasmLoggerBuilder::new().build().unwrap(); WasmLoggerBuilder::new().build().unwrap();

View File

@ -10,6 +10,6 @@ name = "facade"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
fluence = { version = "=0.4.2", features = ["logger"]} fluence = { version = "=0.5.0", features = ["logger"]}
anyhow = "1.0.31" anyhow = "1.0.31"
log = "0.4.8" log = "0.4.8"

View File

@ -16,8 +16,11 @@
#![allow(improper_ctypes)] #![allow(improper_ctypes)]
use fluence::fce; use fluence::fce;
use fluence::module_manifest;
use fluence::WasmLoggerBuilder; use fluence::WasmLoggerBuilder;
module_manifest!();
pub fn main() { pub fn main() {
WasmLoggerBuilder::new().build().unwrap(); WasmLoggerBuilder::new().build().unwrap();
} }

View File

@ -10,5 +10,5 @@ name = "local_storage"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
fluence = { version = "=0.4.2", features = ["logger"]} fluence = { version = "=0.5.0", features = ["logger"]}
log = "0.4.8" log = "0.4.8"

View File

@ -14,11 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
use std::fs;
use fluence::fce; use fluence::fce;
use fluence::module_manifest;
use fluence::WasmLoggerBuilder; use fluence::WasmLoggerBuilder;
use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
module_manifest!();
const SITES_DIR: &str = "/sites/"; const SITES_DIR: &str = "/sites/";
/// Log level can be changed by `RUST_LOG` env as well. /// Log level can be changed by `RUST_LOG` env as well.

View File

@ -9,7 +9,7 @@ edition = "2018"
[dependencies] [dependencies]
fce = { path = "../engine", version = "0.3.0" } fce = { path = "../engine", version = "0.3.0" }
fce-utils = { path = "../crates/utils", version = "0.1.29" } fce-utils = { path = "../crates/utils", version = "0.1.29" }
fluence-sdk-main = { version = "0.4.2", features = ["logger"] } fluence-sdk-main = { version = "0.5.0", features = ["logger"] }
wasmer-runtime = { package = "wasmer-runtime-fl", version = "0.17.0" } wasmer-runtime = { package = "wasmer-runtime-fl", version = "0.17.0" }
# dynamicfunc-fat-closures allows using state inside DynamicFunc # dynamicfunc-fat-closures allows using state inside DynamicFunc

View File

@ -14,5 +14,5 @@ name = "arguments_passing_effector"
path = "src/effector.rs" path = "src/effector.rs"
[dependencies] [dependencies]
fluence = "=0.4.2" fluence = "=0.5.0"
safe-transmute = "0.11.0" safe-transmute = "0.11.0"

View File

@ -14,5 +14,5 @@ name = "arrays_passing_effector"
path = "src/effector.rs" path = "src/effector.rs"
[dependencies] [dependencies]
fluence = "=0.4.2" fluence = "=0.5.0"
safe-transmute = "0.11.0" safe-transmute = "0.11.0"

View File

@ -10,5 +10,5 @@ name = "inner_records_pure"
path = "src/pure.rs" path = "src/pure.rs"
[dependencies] [dependencies]
fluence = "=0.4.2" fluence = "=0.5.0"
safe-transmute = "0.11.0" safe-transmute = "0.11.0"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "fcli" name = "fcli"
description = "Fluence FCE command line tool" description = "Fluence FCE command line tool"
version = "0.2.0" version = "0.3.0"
authors = ["Fluence Labs"] authors = ["Fluence Labs"]
repository = "https://github.com/fluencelabs/fce/tools/cli" repository = "https://github.com/fluencelabs/fce/tools/cli"
license = "Apache-2.0" license = "Apache-2.0"
@ -14,6 +14,7 @@ path = "src/main.rs"
[dependencies] [dependencies]
fce-wit-generator = { path = "../../crates/wit-generator", version = "0.2.0" } fce-wit-generator = { path = "../../crates/wit-generator", version = "0.2.0" }
fce-wit-parser = { path = "../../crates/wit-parser", version = "0.2.0" } fce-wit-parser = { path = "../../crates/wit-parser", version = "0.2.0" }
fce-module-manifest-parser = { path = "../../crates/module-info-parser", version = "0.1.0" }
anyhow = "1.0.31" anyhow = "1.0.31"
clap = "2.33.1" clap = "2.33.1"

View File

@ -34,7 +34,7 @@ pub fn build<'a, 'b>() -> App<'a, 'b> {
pub fn embed_wit<'a, 'b>() -> App<'a, 'b> { pub fn embed_wit<'a, 'b>() -> App<'a, 'b> {
SubCommand::with_name("embed") SubCommand::with_name("embed")
.about("Embed IT to a provided Wasm file") .about("Embed IT to the provided Wasm file")
.args(&[ .args(&[
Arg::with_name(IN_WASM_PATH) Arg::with_name(IN_WASM_PATH)
.required(true) .required(true)
@ -54,8 +54,19 @@ pub fn embed_wit<'a, 'b>() -> App<'a, 'b> {
} }
pub fn show_wit<'a, 'b>() -> App<'a, 'b> { pub fn show_wit<'a, 'b>() -> App<'a, 'b> {
SubCommand::with_name("show") SubCommand::with_name("it")
.about("Show IT of provided Wasm file") .about("Show IT of the provided Wasm file")
.setting(clap::AppSettings::ArgRequiredElseHelp)
.args(&[Arg::with_name(IN_WASM_PATH)
.required(true)
.takes_value(true)
.short("i")
.help("path to the Wasm file")])
}
pub fn show_manifest<'a, 'b>() -> App<'a, 'b> {
SubCommand::with_name("info")
.about("Show manifest and sdk version of the provided Wasm file")
.setting(clap::AppSettings::ArgRequiredElseHelp) .setting(clap::AppSettings::ArgRequiredElseHelp)
.args(&[Arg::with_name(IN_WASM_PATH) .args(&[Arg::with_name(IN_WASM_PATH)
.required(true) .required(true)

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
use crate::Result; use crate::CLIResult;
use crate::errors::CLIError; use crate::errors::CLIError;
use std::process::Command; use std::process::Command;
@ -28,7 +28,7 @@ enum DiagnosticMessage {
RunWithArgs, RunWithArgs,
} }
pub(crate) fn build(trailing_args: Vec<&str>) -> Result<()> { pub(crate) fn build(trailing_args: Vec<&str>) -> CLIResult<()> {
use std::io::Read; use std::io::Read;
let mut cargo = Command::new("cargo"); let mut cargo = Command::new("cargo");

View File

@ -29,73 +29,103 @@ mod args;
mod build; mod build;
mod errors; mod errors;
pub(crate) type Result<T> = std::result::Result<T, crate::errors::CLIError>; pub(crate) type CLIResult<T> = std::result::Result<T, crate::errors::CLIError>;
pub fn main() -> std::result::Result<(), anyhow::Error> { pub fn main() -> Result<(), anyhow::Error> {
let app = clap::App::new(args::DESCRIPTION) let app = clap::App::new(args::DESCRIPTION)
.version(args::VERSION) .version(args::VERSION)
.author(args::AUTHORS) .author(args::AUTHORS)
.setting(clap::AppSettings::ArgRequiredElseHelp) .setting(clap::AppSettings::ArgRequiredElseHelp)
.subcommand(args::build()) .subcommand(args::build())
.subcommand(args::embed_wit()) .subcommand(args::embed_wit())
.subcommand(args::show_manifest())
.subcommand(args::show_wit()) .subcommand(args::show_wit())
.subcommand(args::repl()); .subcommand(args::repl());
let arg_matches = app.get_matches(); let arg_matches = app.get_matches();
match arg_matches.subcommand() { match arg_matches.subcommand() {
("build", Some(args)) => { ("build", Some(args)) => build(args),
let trailing_args: Vec<&str> = args.values_of("optional").unwrap_or_default().collect(); ("embed", Some(args)) => embed(args),
("it", Some(args)) => it(args),
crate::build::build(trailing_args)?; ("info", Some(args)) => info(args),
("repl", Some(args)) => repl(args),
Ok(()) (c, _) => Err(crate::errors::CLIError::NoSuchCommand(c.to_string()).into()),
}
("embed", Some(arg)) => {
let in_wasm_path = arg.value_of(args::IN_WASM_PATH).unwrap();
let wit_path = arg.value_of(args::WIT_PATH).unwrap();
let out_wasm_path = match arg.value_of(args::OUT_WASM_PATH) {
Some(path) => path,
None => in_wasm_path,
};
let wit = String::from_utf8(std::fs::read(wit_path)?).unwrap();
fce_wit_parser::embed_text_wit(
std::path::PathBuf::from(in_wasm_path),
std::path::PathBuf::from(out_wasm_path),
&wit,
)?;
Ok(())
}
("show", Some(arg)) => {
let wasm_path = arg.value_of(args::IN_WASM_PATH).unwrap();
let wasm_path = std::path::Path::new(wasm_path);
let result = fce_wit_parser::extract_text_wit(&wasm_path)?;
println!("{}", result);
Ok(())
}
("repl", Some(args)) => {
use std::process::Command;
// use UNIX-specific API for replacing process image
use std::os::unix::process::CommandExt;
let trailing_args: Vec<&str> = args.values_of("optional").unwrap_or_default().collect();
let mut repl = Command::new("fce-repl");
repl.args(trailing_args);
let error = repl.exec();
if error.kind() == std::io::ErrorKind::NotFound {
println!("fce-repl not found, run `cargo +nightly install frepl` to install it");
} else {
// this branch should be executed if exec was successful, so just else if fine here
println!("error occurred: {:?}", error);
}
Ok(())
}
c => Err(crate::errors::CLIError::NoSuchCommand(c.0.to_string()).into()),
} }
} }
fn build(args: &clap::ArgMatches<'_>) -> Result<(), anyhow::Error> {
let trailing_args: Vec<&str> = args.values_of("optional").unwrap_or_default().collect();
crate::build::build(trailing_args)?;
Ok(())
}
fn embed(args: &clap::ArgMatches<'_>) -> Result<(), anyhow::Error> {
let in_wasm_path = args.value_of(args::IN_WASM_PATH).unwrap();
let wit_path = args.value_of(args::WIT_PATH).unwrap();
let out_wasm_path = match args.value_of(args::OUT_WASM_PATH) {
Some(path) => path,
None => in_wasm_path,
};
let wit = String::from_utf8(std::fs::read(wit_path)?).unwrap();
fce_wit_parser::embed_text_wit(
std::path::PathBuf::from(in_wasm_path),
std::path::PathBuf::from(out_wasm_path),
&wit,
)?;
Ok(())
}
fn it(args: &clap::ArgMatches<'_>) -> Result<(), anyhow::Error> {
let wasm_path = args.value_of(args::IN_WASM_PATH).unwrap();
let wasm_path = std::path::Path::new(wasm_path);
let it = fce_wit_parser::extract_text_wit(&wasm_path)?;
println!("{}", it);
Ok(())
}
fn info(args: &clap::ArgMatches<'_>) -> Result<(), anyhow::Error> {
let wasm_path = args.value_of(args::IN_WASM_PATH).unwrap();
let wasm_path = std::path::Path::new(wasm_path);
let sdk_version = fce_module_manifest_parser::extract_sdk_version_by_path(&wasm_path)?;
let module_manifest = fce_module_manifest_parser::extract_manifest_by_path(&wasm_path)?;
match sdk_version {
Some(sdk_version) => println!("sdk version: {}", sdk_version),
None => println!("module doesn't contain sdk version"),
}
match module_manifest {
Some(manifest) => println!("{}", manifest),
None => println!("module doesn't contain module manifest"),
}
Ok(())
}
fn repl(args: &clap::ArgMatches<'_>) -> Result<(), anyhow::Error> {
use std::process::Command;
// use UNIX-specific API for replacing process image
use std::os::unix::process::CommandExt;
let trailing_args: Vec<&str> = args.values_of("optional").unwrap_or_default().collect();
let mut repl = Command::new("fce-repl");
repl.args(trailing_args);
let error = repl.exec();
if error.kind() == std::io::ErrorKind::NotFound {
println!("fce-repl not found, run `cargo +nightly install frepl` to install it");
} else {
// this branch should be executed if exec was successful, so just else if fine here
println!("error occurred: {:?}", error);
}
Ok(())
}

View File

@ -13,7 +13,7 @@ path = "src/main.rs"
[dependencies] [dependencies]
fluence-app-service = { path = "../../fluence-app-service", version = "0.5.2", features = ["raw-module-api"] } fluence-app-service = { path = "../../fluence-app-service", version = "0.5.2", features = ["raw-module-api"] }
fluence-sdk-main = { version = "0.4.2", features = ["logger"] } fluence-sdk-main = { version = "0.5.0", features = ["logger"] }
anyhow = "1.0.31" anyhow = "1.0.31"
clap = "2.33.1" clap = "2.33.1"