mirror of
https://github.com/fluencelabs/marine.git
synced 2024-12-12 14:55:32 +00:00
Improve various stuff in REPL (#61)
This commit is contained in:
parent
65a7223803
commit
52be0dd5ed
46
Cargo.lock
generated
46
Cargo.lock
generated
@ -167,9 +167,9 @@ checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.5.0"
|
version = "3.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f07aa6688c702439a1be0307b6a94dffe1168569e45b9500c1372bc580740d59"
|
checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
@ -403,9 +403,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctor"
|
name = "ctor"
|
||||||
version = "0.1.18"
|
version = "0.1.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "10bcb9d7dcbf7002aaffbb53eac22906b64cdcc127971dcc387d8eb7c95d5560"
|
checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
@ -543,9 +543,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.26"
|
version = "0.8.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283"
|
checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
@ -1033,7 +1033,7 @@ checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi 0.10.1+wasi-snapshot-preview1",
|
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1136,9 +1136,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httparse"
|
name = "httparse"
|
||||||
version = "1.3.4"
|
version = "1.3.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
|
checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httpdate"
|
name = "httpdate"
|
||||||
@ -1171,7 +1171,7 @@ dependencies = [
|
|||||||
"httparse",
|
"httparse",
|
||||||
"httpdate",
|
"httpdate",
|
||||||
"itoa",
|
"itoa",
|
||||||
"pin-project 1.0.4",
|
"pin-project 1.0.5",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
@ -1363,9 +1363,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.83"
|
version = "0.2.85"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7eb0c4e9c72ee9d69b767adebc5f4788462a3b45624acd919475c92597bcaf4f"
|
checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "local_storage"
|
name = "local_storage"
|
||||||
@ -1754,11 +1754,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project"
|
name = "pin-project"
|
||||||
version = "1.0.4"
|
version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95b70b68509f17aa2857863b6fa00bf21fc93674c7a8893de2f469f6aa7ca2f2"
|
checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pin-project-internal 1.0.4",
|
"pin-project-internal 1.0.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1774,9 +1774,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-internal"
|
name = "pin-project-internal"
|
||||||
version = "1.0.4"
|
version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "caa25a6393f22ce819b0f50e0be89287292fda8d425be38ee0ca14c4931d9e71"
|
checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -2121,9 +2121,9 @@ checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "safe-transmute"
|
name = "safe-transmute"
|
||||||
version = "0.11.0"
|
version = "0.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50b8b2cd387f744f69469aaed197954ba4c0ecdb31e02edf99b023e0df11178a"
|
checksum = "1d95e7284b4bd97e24af76023904cd0157c9cc9da0310beb4139a1e88a748d47"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schannel"
|
name = "schannel"
|
||||||
@ -2474,9 +2474,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "0.2.24"
|
version = "0.2.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "099837d3464c16a808060bb3f02263b412f6fafcb5d01c533d309985fbeebe48"
|
checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.5.6",
|
"bytes 0.5.6",
|
||||||
"fnv",
|
"fnv",
|
||||||
@ -2776,9 +2776,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.10.1+wasi-snapshot-preview1"
|
version = "0.10.2+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "93c6c3420963c5c64bca373b25e77acb562081b9bb4dd5bb864187742186cea9"
|
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
|
@ -87,7 +87,7 @@ fn serialize_function_signature(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_record_type<'a, 'b>(
|
fn serialize_record_type(
|
||||||
id: u64,
|
id: u64,
|
||||||
record: Rc<IRecordType>,
|
record: Rc<IRecordType>,
|
||||||
record_types: &RecordTypes,
|
record_types: &RecordTypes,
|
||||||
|
@ -100,3 +100,109 @@ impl<'env_string> LoggerFilter<'env_string> {
|
|||||||
.map_or_else(|| self.default_log_level, |l| Some(*l))
|
.map_or_else(|| self.default_log_level, |l| Some(*l))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::LoggerFilter;
|
||||||
|
use log::LevelFilter;
|
||||||
|
|
||||||
|
fn test_one_level_filter(unparsed_level: &str, expected_level: LevelFilter) {
|
||||||
|
let logger_filter = LoggerFilter::from_env_string(unparsed_level);
|
||||||
|
|
||||||
|
let actual_level = logger_filter
|
||||||
|
.module_level("some_module_name")
|
||||||
|
.expect("global option should work");
|
||||||
|
assert_eq!(actual_level, expected_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn one_default_filter() {
|
||||||
|
use LevelFilter::*;
|
||||||
|
|
||||||
|
test_one_level_filter("off", Off);
|
||||||
|
test_one_level_filter("error", Error);
|
||||||
|
test_one_level_filter("warn", Warn);
|
||||||
|
test_one_level_filter("info", Info);
|
||||||
|
test_one_level_filter("debug", Debug);
|
||||||
|
test_one_level_filter("trace", Trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn module_levels() {
|
||||||
|
use LevelFilter::*;
|
||||||
|
let logger_filter = LoggerFilter::from_env_string(
|
||||||
|
"module_1=off,module_2=error,module_3=warn,module_4=info,module_5=debug,module_6=trace",
|
||||||
|
);
|
||||||
|
|
||||||
|
let actual_level = logger_filter
|
||||||
|
.module_level("module_1")
|
||||||
|
.expect("module option should work");
|
||||||
|
assert_eq!(actual_level, Off);
|
||||||
|
|
||||||
|
let actual_level = logger_filter
|
||||||
|
.module_level("module_2")
|
||||||
|
.expect("module option should work");
|
||||||
|
assert_eq!(actual_level, Error);
|
||||||
|
|
||||||
|
let actual_level = logger_filter
|
||||||
|
.module_level("module_3")
|
||||||
|
.expect("module option should work");
|
||||||
|
assert_eq!(actual_level, Warn);
|
||||||
|
|
||||||
|
let actual_level = logger_filter
|
||||||
|
.module_level("module_4")
|
||||||
|
.expect("module option should work");
|
||||||
|
assert_eq!(actual_level, Info);
|
||||||
|
|
||||||
|
let actual_level = logger_filter
|
||||||
|
.module_level("module_5")
|
||||||
|
.expect("module option should work");
|
||||||
|
assert_eq!(actual_level, Debug);
|
||||||
|
|
||||||
|
let actual_level = logger_filter
|
||||||
|
.module_level("module_6")
|
||||||
|
.expect("module option should work");
|
||||||
|
assert_eq!(actual_level, Trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mixed_default_and_module_levels() {
|
||||||
|
use LevelFilter::*;
|
||||||
|
let logger_filter = LoggerFilter::from_env_string("module_1=off,module_2=error,module_3=warn,module_4=info,module_5=debug,module_6=trace,off");
|
||||||
|
|
||||||
|
let actual_level = logger_filter
|
||||||
|
.module_level("module_1")
|
||||||
|
.expect("module option should work");
|
||||||
|
assert_eq!(actual_level, Off);
|
||||||
|
|
||||||
|
let actual_level = logger_filter
|
||||||
|
.module_level("module_2")
|
||||||
|
.expect("module option should work");
|
||||||
|
assert_eq!(actual_level, Error);
|
||||||
|
|
||||||
|
let actual_level = logger_filter
|
||||||
|
.module_level("module_3")
|
||||||
|
.expect("module option should work");
|
||||||
|
assert_eq!(actual_level, Warn);
|
||||||
|
|
||||||
|
let actual_level = logger_filter
|
||||||
|
.module_level("module_4")
|
||||||
|
.expect("module option should work");
|
||||||
|
assert_eq!(actual_level, Info);
|
||||||
|
|
||||||
|
let actual_level = logger_filter
|
||||||
|
.module_level("module_5")
|
||||||
|
.expect("module option should work");
|
||||||
|
assert_eq!(actual_level, Debug);
|
||||||
|
|
||||||
|
let actual_level = logger_filter
|
||||||
|
.module_level("module_6")
|
||||||
|
.expect("module option should work");
|
||||||
|
assert_eq!(actual_level, Trace);
|
||||||
|
|
||||||
|
let actual_level = logger_filter
|
||||||
|
.module_level("some_module_name")
|
||||||
|
.expect("global option should work");
|
||||||
|
assert_eq!(actual_level, Off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "fcli"
|
name = "fcli"
|
||||||
description = "Fluence FCE command line tool"
|
description = "Fluence FCE command line tool"
|
||||||
version = "0.1.30"
|
version = "0.1.31"
|
||||||
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"
|
||||||
|
@ -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 WIT to a provided Wasm file")
|
.about("Embed IT to a provided Wasm file")
|
||||||
.args(&[
|
.args(&[
|
||||||
Arg::with_name(IN_WASM_PATH)
|
Arg::with_name(IN_WASM_PATH)
|
||||||
.required(true)
|
.required(true)
|
||||||
@ -55,7 +55,7 @@ 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("show")
|
||||||
.about("Show WIT in provided Wasm file")
|
.about("Show IT of 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)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "frepl"
|
name = "frepl"
|
||||||
description = "Fluence FCE REPL intended for testing purposes"
|
description = "Fluence FCE REPL intended for testing purposes"
|
||||||
version = "0.1.30"
|
version = "0.1.31"
|
||||||
authors = ["Fluence Labs"]
|
authors = ["Fluence Labs"]
|
||||||
repository = "https://github.com/fluencelabs/fce/tools/repl"
|
repository = "https://github.com/fluencelabs/fce/tools/repl"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
@ -24,6 +24,6 @@ env_logger = "0.7.1"
|
|||||||
log = "0.4.11"
|
log = "0.4.11"
|
||||||
rustyline = { version = "6.1.2", features = ["with-fuzzy"] }
|
rustyline = { version = "6.1.2", features = ["with-fuzzy"] }
|
||||||
rustyline-derive = "0.3.1"
|
rustyline-derive = "0.3.1"
|
||||||
rustop = "1.1.0"
|
rustop = "1.1.1"
|
||||||
itertools = "0.9.0"
|
itertools = "0.9.0"
|
||||||
uuid = { version = "0.8.1", features = ["v4"] }
|
uuid = { version = "0.8.1", features = ["v4"] }
|
||||||
|
166
tools/repl/src/editor.rs
Normal file
166
tools/repl/src/editor.rs
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* 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 rustyline::completion::{Completer, FilenameCompleter, Pair};
|
||||||
|
use rustyline::config::OutputStreamType;
|
||||||
|
use rustyline::error::ReadlineError;
|
||||||
|
use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
|
||||||
|
use rustyline::hint::{Hinter, HistoryHinter};
|
||||||
|
use rustyline::validate::{self, MatchingBracketValidator, Validator};
|
||||||
|
use rustyline::{Cmd, CompletionType, Config, Context, EditMode, Editor, KeyPress};
|
||||||
|
use rustyline_derive::Helper;
|
||||||
|
|
||||||
|
use std::borrow::Cow::{self, Borrowed, Owned};
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
pub(super) fn init_editor() -> Editor<REPLHelper> {
|
||||||
|
let config = Config::builder()
|
||||||
|
.history_ignore_space(true)
|
||||||
|
.completion_type(CompletionType::Fuzzy)
|
||||||
|
.edit_mode(EditMode::Emacs)
|
||||||
|
.output_stream(OutputStreamType::Stdout)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let repl_hinter = REPLHinter {
|
||||||
|
commands_hints: commands_hints(),
|
||||||
|
history_hinter: HistoryHinter {},
|
||||||
|
};
|
||||||
|
let repl_helper = REPLHelper {
|
||||||
|
completer: FilenameCompleter::new(),
|
||||||
|
highlighter: MatchingBracketHighlighter::new(),
|
||||||
|
hinter: repl_hinter,
|
||||||
|
colored_prompt: "".to_owned(),
|
||||||
|
validator: MatchingBracketValidator::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut rl = Editor::with_config(config);
|
||||||
|
rl.set_helper(Some(repl_helper));
|
||||||
|
rl.bind_sequence(KeyPress::Meta('N'), Cmd::HistorySearchForward);
|
||||||
|
rl.bind_sequence(KeyPress::Meta('P'), Cmd::HistorySearchBackward);
|
||||||
|
|
||||||
|
rl
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Helper)]
|
||||||
|
pub(super) struct REPLHelper {
|
||||||
|
completer: FilenameCompleter,
|
||||||
|
highlighter: MatchingBracketHighlighter,
|
||||||
|
validator: MatchingBracketValidator,
|
||||||
|
hinter: REPLHinter,
|
||||||
|
colored_prompt: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl REPLHelper {
|
||||||
|
pub(super) fn set_prompt_color(&mut self, color: String) {
|
||||||
|
self.colored_prompt = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tries to find hint from history if its failed from supported command list.
|
||||||
|
pub(super) struct REPLHinter {
|
||||||
|
commands_hints: HashSet<String>,
|
||||||
|
history_hinter: HistoryHinter,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Completer for REPLHelper {
|
||||||
|
type Candidate = Pair;
|
||||||
|
|
||||||
|
fn complete(
|
||||||
|
&self,
|
||||||
|
line: &str,
|
||||||
|
pos: usize,
|
||||||
|
ctx: &Context<'_>,
|
||||||
|
) -> std::result::Result<(usize, Vec<Pair>), ReadlineError> {
|
||||||
|
self.completer.complete(line, pos, ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hinter for REPLHelper {
|
||||||
|
fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<String> {
|
||||||
|
if pos < line.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(hint) = self.hinter.history_hinter.hint(line, pos, ctx) {
|
||||||
|
return Some(hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.hinter
|
||||||
|
.commands_hints
|
||||||
|
.iter()
|
||||||
|
.filter_map(|hint| {
|
||||||
|
// expect hint after word complete, like redis cli, add condition:
|
||||||
|
// line.ends_with(" ")
|
||||||
|
if pos > 0 && hint.starts_with(&line[..pos]) {
|
||||||
|
Some(hint[pos..].to_owned())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Highlighter for REPLHelper {
|
||||||
|
fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> {
|
||||||
|
self.highlighter.highlight(line, pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
|
||||||
|
&'s self,
|
||||||
|
prompt: &'p str,
|
||||||
|
default: bool,
|
||||||
|
) -> Cow<'b, str> {
|
||||||
|
if default {
|
||||||
|
Borrowed(&self.colored_prompt)
|
||||||
|
} else {
|
||||||
|
Borrowed(prompt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
|
||||||
|
Owned("\x1b[1m".to_owned() + hint + "\x1b[m")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn highlight_char(&self, line: &str, pos: usize) -> bool {
|
||||||
|
self.highlighter.highlight_char(line, pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Validator for REPLHelper {
|
||||||
|
fn validate(
|
||||||
|
&self,
|
||||||
|
ctx: &mut validate::ValidationContext<'_>,
|
||||||
|
) -> rustyline::Result<validate::ValidationResult> {
|
||||||
|
self.validator.validate(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_while_typing(&self) -> bool {
|
||||||
|
self.validator.validate_while_typing()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn commands_hints() -> HashSet<String> {
|
||||||
|
let mut set = HashSet::new();
|
||||||
|
set.insert(String::from("load"));
|
||||||
|
set.insert(String::from("unload"));
|
||||||
|
set.insert(String::from("call"));
|
||||||
|
set.insert(String::from("envs"));
|
||||||
|
set.insert(String::from("fs"));
|
||||||
|
set.insert(String::from("interface"));
|
||||||
|
set.insert(String::from("help"));
|
||||||
|
set
|
||||||
|
}
|
53
tools/repl/src/logger.rs
Normal file
53
tools/repl/src/logger.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const WIT_MODULE_PATH: &str = "wasmer_interface_types_fl";
|
||||||
|
const RUST_LOG_ENV_NAME: &str = "RUST_LOG";
|
||||||
|
|
||||||
|
pub(super) fn init_logger() {
|
||||||
|
use std::io::Write;
|
||||||
|
use std::env::var;
|
||||||
|
use log::LevelFilter::Info;
|
||||||
|
use fluence_sdk_main::WASM_LOG_ENV_NAME;
|
||||||
|
|
||||||
|
match (var(RUST_LOG_ENV_NAME), var(WASM_LOG_ENV_NAME)) {
|
||||||
|
(Ok(_), _) => {}
|
||||||
|
(Err(_), Ok(wasm_log_env)) if !wasm_log_env.starts_with("off") => {
|
||||||
|
std::env::set_var(RUST_LOG_ENV_NAME, "trace")
|
||||||
|
}
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
env_logger::builder()
|
||||||
|
.format(|buf, record| {
|
||||||
|
match record.module_path() {
|
||||||
|
Some(module_path) if module_path.starts_with(WIT_MODULE_PATH) => {
|
||||||
|
writeln!(buf, "[host] {}", record.args())
|
||||||
|
}
|
||||||
|
// because of the log_utf8_string implementation, log from a wasm module always has module path
|
||||||
|
None => writeln!(buf, "[host] {}", record.args()),
|
||||||
|
Some(module_path) => writeln!(buf, "[{}] {}", module_path, record.args()),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// set a default level Info for Wasmer components
|
||||||
|
.filter(Some("cranelift_codegen"), Info)
|
||||||
|
.filter(Some("wasmer_wasi"), Info)
|
||||||
|
.filter(Some(WIT_MODULE_PATH), Info)
|
||||||
|
// the same for rustyline and fce
|
||||||
|
.filter(Some("rustyline"), Info)
|
||||||
|
.filter(Some("fce"), Info)
|
||||||
|
.init();
|
||||||
|
}
|
@ -24,29 +24,24 @@
|
|||||||
)]
|
)]
|
||||||
#![warn(rust_2018_idioms)]
|
#![warn(rust_2018_idioms)]
|
||||||
|
|
||||||
/// Command-line tool intended to test Fluence FaaS.
|
/// Command-line tool intended to test Fluence App services.
|
||||||
|
|
||||||
|
mod editor;
|
||||||
|
mod logger;
|
||||||
mod repl;
|
mod repl;
|
||||||
|
|
||||||
|
use logger::init_logger;
|
||||||
|
use editor::init_editor;
|
||||||
|
|
||||||
use repl::REPL;
|
use repl::REPL;
|
||||||
|
|
||||||
use rustyline::completion::{Completer, FilenameCompleter, Pair};
|
|
||||||
use rustyline::config::OutputStreamType;
|
|
||||||
use rustyline::error::ReadlineError;
|
use rustyline::error::ReadlineError;
|
||||||
use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
|
|
||||||
use rustyline::hint::{Hinter, HistoryHinter};
|
|
||||||
use rustyline::validate::{self, MatchingBracketValidator, Validator};
|
|
||||||
use rustyline::{Cmd, CompletionType, Config, Context, EditMode, Editor, KeyPress};
|
|
||||||
use rustyline_derive::Helper;
|
|
||||||
|
|
||||||
use std::borrow::Cow::{self, Borrowed, Owned};
|
|
||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
const HISTORY_FILE_PATH: &str = ".repl_history";
|
const HISTORY_FILE_PATH: &str = ".repl_history";
|
||||||
|
|
||||||
pub(crate) type Result<T> = std::result::Result<T, anyhow::Error>;
|
pub(crate) type ReplResult<T> = std::result::Result<T, anyhow::Error>;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> ReplResult<()> {
|
||||||
init_logger();
|
init_logger();
|
||||||
|
|
||||||
let (args, _) = rustop::opts! {
|
let (args, _) = rustop::opts! {
|
||||||
@ -56,44 +51,29 @@ fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
.parse_or_exit();
|
.parse_or_exit();
|
||||||
|
|
||||||
let config = Config::builder()
|
let mut rl = init_editor();
|
||||||
.history_ignore_space(true)
|
|
||||||
.completion_type(CompletionType::Fuzzy)
|
|
||||||
.edit_mode(EditMode::Emacs)
|
|
||||||
.output_stream(OutputStreamType::Stdout)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let repl_hinter = REPLHinter {
|
|
||||||
commands_hints: commands_hints(),
|
|
||||||
history_hinter: HistoryHinter {},
|
|
||||||
};
|
|
||||||
let repl_helper = REPLHelper {
|
|
||||||
completer: FilenameCompleter::new(),
|
|
||||||
highlighter: MatchingBracketHighlighter::new(),
|
|
||||||
hinter: repl_hinter,
|
|
||||||
colored_prompt: "".to_owned(),
|
|
||||||
validator: MatchingBracketValidator::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut rl = Editor::with_config(config);
|
|
||||||
rl.set_helper(Some(repl_helper));
|
|
||||||
rl.bind_sequence(KeyPress::Meta('N'), Cmd::HistorySearchForward);
|
|
||||||
rl.bind_sequence(KeyPress::Meta('P'), Cmd::HistorySearchBackward);
|
|
||||||
let _ = rl.load_history(HISTORY_FILE_PATH);
|
let _ = rl.load_history(HISTORY_FILE_PATH);
|
||||||
|
|
||||||
println!("Welcome to the Fluence FaaS REPL");
|
println!(
|
||||||
|
"Welcome to the FCE REPL (version {})",
|
||||||
|
env!("CARGO_PKG_VERSION")
|
||||||
|
);
|
||||||
|
|
||||||
let mut repl = REPL::new(args.config_file_path)?;
|
let mut repl = REPL::new(args.config_file_path)?;
|
||||||
|
|
||||||
let mut count = 1;
|
let mut count = 1;
|
||||||
loop {
|
loop {
|
||||||
let p = format!("\n{}> ", count);
|
let p = format!("\n{}> ", count);
|
||||||
rl.helper_mut().expect("No helper").colored_prompt = format!("\x1b[1;32m{}\x1b[0m", p);
|
rl.helper_mut()
|
||||||
|
.expect("No helper")
|
||||||
|
.set_prompt_color(format!("\x1b[1;32m{}\x1b[0m", p));
|
||||||
let readline = rl.readline(&p);
|
let readline = rl.readline(&p);
|
||||||
match readline {
|
match readline {
|
||||||
Ok(line) => {
|
Ok(line) => {
|
||||||
rl.add_history_entry(line.as_str());
|
rl.add_history_entry(line.as_str());
|
||||||
repl.execute(line.split_whitespace());
|
if !repl.execute(line.split_whitespace()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(ReadlineError::Interrupted) => {
|
Err(ReadlineError::Interrupted) => {
|
||||||
println!("CTRL-C");
|
println!("CTRL-C");
|
||||||
@ -117,146 +97,3 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_logger() {
|
|
||||||
use std::io::Write;
|
|
||||||
use std::env::var;
|
|
||||||
use log::LevelFilter::Info;
|
|
||||||
use fluence_sdk_main::WASM_LOG_ENV_NAME;
|
|
||||||
|
|
||||||
const WIT_MODULE_PATH: &str = "wasmer_interface_types_fl";
|
|
||||||
const RUST_LOG_ENV_NAME: &str = "RUST_LOG";
|
|
||||||
|
|
||||||
match (var(RUST_LOG_ENV_NAME), var(WASM_LOG_ENV_NAME)) {
|
|
||||||
(Ok(_), _) => {}
|
|
||||||
(Err(_), Ok(wasm_log_env)) if !wasm_log_env.starts_with("off") => {
|
|
||||||
std::env::set_var(RUST_LOG_ENV_NAME, "trace")
|
|
||||||
}
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
env_logger::builder()
|
|
||||||
.format(|buf, record| {
|
|
||||||
match record.module_path() {
|
|
||||||
Some(module_path) if module_path.starts_with(WIT_MODULE_PATH) => {
|
|
||||||
writeln!(buf, "[host] {}", record.args())
|
|
||||||
}
|
|
||||||
// because of the log_utf8_string implementation, log from a wasm module always has module path
|
|
||||||
None => writeln!(buf, "[host] {}", record.args()),
|
|
||||||
Some(module_path) => writeln!(buf, "[{}] {}", module_path, record.args()),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// set a default level Info for Wasmer components
|
|
||||||
.filter(Some("cranelift_codegen"), Info)
|
|
||||||
.filter(Some("wasmer_wasi"), Info)
|
|
||||||
.filter(Some(WIT_MODULE_PATH), Info)
|
|
||||||
// the same for rustyline and fce
|
|
||||||
.filter(Some("rustyline"), Info)
|
|
||||||
.filter(Some("fce"), Info)
|
|
||||||
.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Helper)]
|
|
||||||
struct REPLHelper {
|
|
||||||
completer: FilenameCompleter,
|
|
||||||
highlighter: MatchingBracketHighlighter,
|
|
||||||
validator: MatchingBracketValidator,
|
|
||||||
hinter: REPLHinter,
|
|
||||||
colored_prompt: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tries to find hint from history if its failed from supported command list.
|
|
||||||
struct REPLHinter {
|
|
||||||
commands_hints: HashSet<String>,
|
|
||||||
history_hinter: HistoryHinter,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Completer for REPLHelper {
|
|
||||||
type Candidate = Pair;
|
|
||||||
|
|
||||||
fn complete(
|
|
||||||
&self,
|
|
||||||
line: &str,
|
|
||||||
pos: usize,
|
|
||||||
ctx: &Context<'_>,
|
|
||||||
) -> std::result::Result<(usize, Vec<Pair>), ReadlineError> {
|
|
||||||
self.completer.complete(line, pos, ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hinter for REPLHelper {
|
|
||||||
fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<String> {
|
|
||||||
if pos < line.len() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(hint) = self.hinter.history_hinter.hint(line, pos, ctx) {
|
|
||||||
return Some(hint);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.hinter
|
|
||||||
.commands_hints
|
|
||||||
.iter()
|
|
||||||
.filter_map(|hint| {
|
|
||||||
// expect hint after word complete, like redis cli, add condition:
|
|
||||||
// line.ends_with(" ")
|
|
||||||
if pos > 0 && hint.starts_with(&line[..pos]) {
|
|
||||||
Some(hint[pos..].to_owned())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Highlighter for REPLHelper {
|
|
||||||
fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> {
|
|
||||||
self.highlighter.highlight(line, pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
|
|
||||||
&'s self,
|
|
||||||
prompt: &'p str,
|
|
||||||
default: bool,
|
|
||||||
) -> Cow<'b, str> {
|
|
||||||
if default {
|
|
||||||
Borrowed(&self.colored_prompt)
|
|
||||||
} else {
|
|
||||||
Borrowed(prompt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
|
|
||||||
Owned("\x1b[1m".to_owned() + hint + "\x1b[m")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn highlight_char(&self, line: &str, pos: usize) -> bool {
|
|
||||||
self.highlighter.highlight_char(line, pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Validator for REPLHelper {
|
|
||||||
fn validate(
|
|
||||||
&self,
|
|
||||||
ctx: &mut validate::ValidationContext<'_>,
|
|
||||||
) -> rustyline::Result<validate::ValidationResult> {
|
|
||||||
self.validator.validate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate_while_typing(&self) -> bool {
|
|
||||||
self.validator.validate_while_typing()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn commands_hints() -> HashSet<String> {
|
|
||||||
let mut set = HashSet::new();
|
|
||||||
set.insert(String::from("load"));
|
|
||||||
set.insert(String::from("unload"));
|
|
||||||
set.insert(String::from("call"));
|
|
||||||
set.insert(String::from("envs"));
|
|
||||||
set.insert(String::from("fs"));
|
|
||||||
set.insert(String::from("interface"));
|
|
||||||
set.insert(String::from("help"));
|
|
||||||
set
|
|
||||||
}
|
|
||||||
|
@ -14,10 +14,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::Result;
|
mod print_state;
|
||||||
|
|
||||||
|
use crate::ReplResult;
|
||||||
|
|
||||||
use fluence_app_service::AppService;
|
use fluence_app_service::AppService;
|
||||||
use fluence_app_service::TomlAppServiceConfig;
|
use fluence_app_service::TomlAppServiceConfig;
|
||||||
|
use print_state::print_envs;
|
||||||
|
use print_state::print_fs_state;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@ -30,7 +34,7 @@ macro_rules! next_argument {
|
|||||||
$arg_name
|
$arg_name
|
||||||
} else {
|
} else {
|
||||||
println!($error_msg);
|
println!($error_msg);
|
||||||
return;
|
return true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -40,12 +44,13 @@ pub(super) struct REPL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl REPL {
|
impl REPL {
|
||||||
pub fn new<S: Into<PathBuf>>(config_file_path: Option<S>) -> Result<Self> {
|
pub fn new<S: Into<PathBuf>>(config_file_path: Option<S>) -> ReplResult<Self> {
|
||||||
let app_service = Self::create_app_service(config_file_path)?;
|
let app_service = Self::create_app_service(config_file_path)?;
|
||||||
Ok(Self { app_service })
|
Ok(Self { app_service })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute<'a>(&mut self, mut args: impl Iterator<Item = &'a str>) {
|
/// Returns true, it should be the last executed command.
|
||||||
|
pub fn execute<'a>(&mut self, mut args: impl Iterator<Item = &'a str>) -> bool {
|
||||||
match args.next() {
|
match args.next() {
|
||||||
Some("new") => {
|
Some("new") => {
|
||||||
match Self::create_app_service(args.next()) {
|
match Self::create_app_service(args.next()) {
|
||||||
@ -60,7 +65,7 @@ impl REPL {
|
|||||||
let wasm_bytes = fs::read(module_path);
|
let wasm_bytes = fs::read(module_path);
|
||||||
if let Err(e) = wasm_bytes {
|
if let Err(e) = wasm_bytes {
|
||||||
println!("failed to read wasm module: {}", e);
|
println!("failed to read wasm module: {}", e);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
@ -109,7 +114,7 @@ impl REPL {
|
|||||||
Ok(module_arg) => module_arg,
|
Ok(module_arg) => module_arg,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("incorrect arguments {}", e);
|
println!("incorrect arguments {}", e);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -132,14 +137,14 @@ impl REPL {
|
|||||||
Some("envs") => {
|
Some("envs") => {
|
||||||
next_argument!(module_name, args, "Module name should be specified");
|
next_argument!(module_name, args, "Module name should be specified");
|
||||||
match self.app_service.get_wasi_state(module_name) {
|
match self.app_service.get_wasi_state(module_name) {
|
||||||
Ok(wasi_state) => Self::print_envs(wasi_state),
|
Ok(wasi_state) => print_envs(module_name, wasi_state),
|
||||||
Err(e) => println!("{}", e),
|
Err(e) => println!("{}", e),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Some("fs") => {
|
Some("fs") => {
|
||||||
next_argument!(module_name, args, "Module name should be specified");
|
next_argument!(module_name, args, "Module name should be specified");
|
||||||
match self.app_service.get_wasi_state(module_name) {
|
match self.app_service.get_wasi_state(module_name) {
|
||||||
Ok(wasi_state) => Self::print_fs_state(wasi_state),
|
Ok(wasi_state) => print_fs_state(wasi_state),
|
||||||
Err(e) => println!("{}", e),
|
Err(e) => println!("{}", e),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -147,27 +152,17 @@ impl REPL {
|
|||||||
let interface = self.app_service.get_full_interface();
|
let interface = self.app_service.get_full_interface();
|
||||||
print!("Application service interface:\n{}", interface);
|
print!("Application service interface:\n{}", interface);
|
||||||
}
|
}
|
||||||
Some("h") | Some("help") | None => {
|
Some("q") | Some("quit") => {
|
||||||
println!(
|
return false;
|
||||||
"Enter:\n\
|
|
||||||
new [config_path] - to create a new AppService (current will be removed)\n\
|
|
||||||
load <module_name> <module_path> - to load a new Wasm module into App service\n\
|
|
||||||
unload <module_name> - to unload Wasm module from AppService\n\
|
|
||||||
call <module_name> <func_name> [args] - to call function with func_name of module with module_name\n\
|
|
||||||
interface - to print public interface of current AppService\n\
|
|
||||||
envs <module_name> - to print environment variables of module with module_name\n\
|
|
||||||
fs <module_name> - to print filesystem state of module with module_name\n\
|
|
||||||
h/help - to print this message\n\
|
|
||||||
Ctrl-C - to exit"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
println!("unsupported command");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_app_service<S: Into<PathBuf>>(config_file_path: Option<S>) -> Result<AppService> {
|
_ => print_help(),
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_app_service<S: Into<PathBuf>>(config_file_path: Option<S>) -> ReplResult<AppService> {
|
||||||
let tmp_path: String = std::env::temp_dir().to_string_lossy().into();
|
let tmp_path: String = std::env::temp_dir().to_string_lossy().into();
|
||||||
let service_id = uuid::Uuid::new_v4().to_string();
|
let service_id = uuid::Uuid::new_v4().to_string();
|
||||||
|
|
||||||
@ -184,48 +179,25 @@ impl REPL {
|
|||||||
let duration = start.elapsed();
|
let duration = start.elapsed();
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"app service's created with service id = {}\nelapsed time {:?}",
|
"app service was created with service id = {}\nelapsed time {:?}",
|
||||||
service_id, duration
|
service_id, duration
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(app_service)
|
Ok(app_service)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_envs(wasi_state: &wasmer_wasi::state::WasiState) {
|
|
||||||
let envs = &wasi_state.envs;
|
|
||||||
|
|
||||||
println!("Environment variables:");
|
|
||||||
for env in envs.iter() {
|
|
||||||
match String::from_utf8(env.clone()) {
|
|
||||||
Ok(string) => println!("{}", string),
|
|
||||||
Err(_) => println!("{:?}", env),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_fs_state(wasi_state: &wasmer_wasi::state::WasiState) {
|
fn print_help() {
|
||||||
let wasi_fs = &wasi_state.fs;
|
println!(
|
||||||
|
"Commands:\n\n\
|
||||||
println!("preopened file descriptors:\n{:?}\n", wasi_fs.preopen_fds);
|
new [config_path] create a new service (current will be removed)\n\
|
||||||
|
load <module_name> <module_path> load a new Wasm module\n\
|
||||||
println!("name map:");
|
unload <module_name> unload a Wasm module\n\
|
||||||
for (name, inode) in &wasi_fs.name_map {
|
call <module_name> <func_name> [args] call function with given name from given module\n\
|
||||||
println!("{} - {:?}", name, inode);
|
interface print public interface of all loaded modules\n\
|
||||||
}
|
envs <module_name> print environment variables of a module\n\
|
||||||
|
fs <module_name> print filesystem state of a module\n\
|
||||||
println!("\nfile descriptors map:");
|
h/help print this message\n\
|
||||||
for (id, fd) in &wasi_fs.fd_map {
|
q/quit/Ctrl-C exit"
|
||||||
println!("{} - {:?}", id, fd);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
println!("\norphan file descriptors:");
|
|
||||||
for (fd, inode) in &wasi_fs.orphan_fds {
|
|
||||||
println!("{:?} - {:?}", fd, inode);
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("\ninodes:");
|
|
||||||
for (id, inode) in wasi_fs.inodes.iter().enumerate() {
|
|
||||||
println!("{}: {:?}", id, inode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
59
tools/repl/src/repl/print_state.rs
Normal file
59
tools/repl/src/repl/print_state.rs
Normal 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 wasmer_wasi::state::WasiState;
|
||||||
|
|
||||||
|
pub(super) fn print_envs(module_name: &str, wasi_state: &WasiState) {
|
||||||
|
let envs = &wasi_state.envs;
|
||||||
|
if envs.is_empty() {
|
||||||
|
println!("{} don't have environment variables", module_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Environment variables:");
|
||||||
|
for env in envs.iter() {
|
||||||
|
match String::from_utf8(env.clone()) {
|
||||||
|
Ok(string) => println!("{}", string),
|
||||||
|
Err(_) => println!("{:?}", env),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn print_fs_state(wasi_state: &WasiState) {
|
||||||
|
let wasi_fs = &wasi_state.fs;
|
||||||
|
|
||||||
|
println!("preopened file descriptors:\n{:?}\n", wasi_fs.preopen_fds);
|
||||||
|
|
||||||
|
println!("name map:");
|
||||||
|
for (name, inode) in &wasi_fs.name_map {
|
||||||
|
println!("{} - {:?}", name, inode);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("\nfile descriptors map:");
|
||||||
|
for (id, fd) in &wasi_fs.fd_map {
|
||||||
|
println!("{} - {:?}", id, fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("\norphan file descriptors:");
|
||||||
|
for (fd, inode) in &wasi_fs.orphan_fds {
|
||||||
|
println!("{:?} - {:?}", fd, inode);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("\ninodes:");
|
||||||
|
for (id, inode) in wasi_fs.inodes.iter().enumerate() {
|
||||||
|
println!("{}: {:?}", id, inode);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user