New bytes_to_string and string_to_bytes commands.

This commit is contained in:
sagie gur ari 2020-01-30 22:26:46 +00:00
parent 699acb12ea
commit b49bf51af6
16 changed files with 357 additions and 4 deletions

View file

@ -2,6 +2,8 @@
### v0.1.9
* New bytes_to_string command.
* New string_to_bytes command.
* Add prefix flag to write_properties command #77
* New split command #76
* New appendfile command.
@ -19,6 +21,7 @@
* Improve wget input parsing.
* Modify full named commands.
* Prevent panic for wget and http_client on invalid non http URL input.
* Runtime - Supports byte array state storage
### v0.1.8 (2020-01-24)

View file

@ -66,6 +66,7 @@
* [std::process::ProcessID (pid, process_id)](#std__process__ProcessID)
* [std::process::Watchdog (watchdog)](#std__process__Watchdog)
* [std::scope::Clear (clear_scope)](#std__scope__Clear)
* [std::string::BytesToString (bytes_to_string)](#std__string__BytesToString)
* [std::string::Concat (concat)](#std__string__Concat)
* [std::string::Contains (contains)](#std__string__Contains)
* [std::string::EndsWith (ends_with)](#std__string__EndsWith)
@ -77,6 +78,7 @@
* [std::string::Replace (replace)](#std__string__Replace)
* [std::string::Split (split)](#std__string__Split)
* [std::string::StartsWith (starts_with)](#std__string__StartsWith)
* [std::string::StringToBytes (string_to_bytes)](#std__string__StringToBytes)
* [std::string::SubString (substring)](#std__string__SubString)
* [std::string::Trim (trim)](#std__string__Trim)
* [std::string::TrimEnd (trim_end)](#std__string__TrimEnd)
@ -2502,6 +2504,37 @@ assert_false ${defined}
#### Aliases:
clear_scope
<a name="std__string__BytesToString"></a>
## std::string::BytesToString
```sh
text = bytes_to_string handle
```
Converts the provided UTF-8 binary array to string and returns it.
#### Parameters
A handle to a binary array holding UTF-8 text.
#### Return Value
The textual data.
#### Examples
```sh
handle = string_to_bytes "hello world"
text = bytes_to_string ${handle}
release ${handle}
assert_eq ${text} "hello world"
```
#### Aliases:
bytes_to_string
<a name="std__string__Concat"></a>
## std::string::Concat
@ -2867,6 +2900,37 @@ result = starts_with abcd bcd
#### Aliases:
starts_with
<a name="std__string__StringToBytes"></a>
## std::string::StringToBytes
```sh
handle = string_to_bytes text
```
Converts the provided string into binary format and returns a handle to the binary data.
#### Parameters
The text to convert.
#### Return Value
A handle to the binary data.
#### Examples
```sh
handle = string_to_bytes "hello world"
text = bytes_to_string ${handle}
release ${handle}
assert_eq ${text} "hello world"
```
#### Aliases:
string_to_bytes
<a name="std__string__SubString"></a>
## std::string::SubString
```sh

View file

@ -30,6 +30,8 @@ pub enum StateValue {
UnsignedNumber64Bit(u64),
/// textual value
String(String),
/// byte (u8) array
ByteArray(Vec<u8>),
/// list
List(Vec<StateValue>),
/// sub state value

View file

@ -24,6 +24,7 @@ include = [
[dependencies]
attohttpc = "^0.10"
base64 = "^0.11"
duckscript = { version = "^0.1.7", path = "../duckscript" }
fs_extra = "^1"
home = "^0.5"

View file

@ -1,5 +1,6 @@
use super::*;
use duckscript::types::command::Commands;
use duckscript::runner;
use duckscript::types::runtime::Context;
#[test]
fn version_test() {
@ -10,13 +11,17 @@ fn version_test() {
#[test]
fn load_valid() {
let mut commands = Commands::new();
let result = load(&mut commands);
let mut context = Context::new();
let result = load(&mut context.commands);
match result {
Ok(_) => (),
Err(e) => panic!("{:#?}", e),
};
// assert!(result.is_ok());
assert!(!commands.get_all_command_names().is_empty());
assert!(!context.commands.get_all_command_names().is_empty());
let result = runner::run_script("test_directory ../test", context);
assert!(result.is_ok());
}

View file

@ -83,6 +83,9 @@ impl Command for CommandImpl {
CommandResult::Continue(Some(value.to_string()))
}
StateValue::String(value) => CommandResult::Continue(Some(value)),
StateValue::ByteArray(_) => {
CommandResult::Error("Unsupported array element.".to_string())
}
StateValue::List(_) => {
CommandResult::Error("Unsupported array element.".to_string())
}
@ -125,6 +128,10 @@ impl Command for CommandImpl {
state.insert(key.to_string(), StateValue::String(value));
CommandResult::Error("Invalid handle provided.".to_string())
}
StateValue::ByteArray(value) => {
state.insert(key.to_string(), StateValue::ByteArray(value));
CommandResult::Error("Invalid handle provided.".to_string())
}
StateValue::SubState(value) => {
state.insert(key.to_string(), StateValue::SubState(value));
CommandResult::Error("Invalid handle provided.".to_string())

View file

@ -95,6 +95,10 @@ impl Command for CommandImpl {
state.insert(key.to_string(), StateValue::String(value));
CommandResult::Error("Invalid handle provided.".to_string())
}
StateValue::ByteArray(value) => {
state.insert(key.to_string(), StateValue::ByteArray(value));
CommandResult::Error("Invalid handle provided.".to_string())
}
StateValue::SubState(value) => {
state.insert(key.to_string(), StateValue::SubState(value));
CommandResult::Error("Invalid handle provided.".to_string())

View file

@ -248,6 +248,7 @@ fn get_next_iteration(
StateValue::Number64Bit(ref value) => Some(value.to_string()),
StateValue::UnsignedNumber64Bit(ref value) => Some(value.to_string()),
StateValue::String(ref value) => Some(value.to_string()),
StateValue::ByteArray(_) => None,
StateValue::List(_) => None,
StateValue::SubState(_) => None,
}

View file

@ -0,0 +1,24 @@
```sh
text = bytes_to_string handle
```
Converts the provided UTF-8 binary array to string and returns it.
#### Parameters
A handle to a binary array holding UTF-8 text.
#### Return Value
The textual data.
#### Examples
```sh
handle = string_to_bytes "hello world"
text = bytes_to_string ${handle}
release ${handle}
assert_eq ${text} "hello world"
```

View file

@ -0,0 +1,76 @@
use crate::utils::pckg;
use crate::utils::state::get_handles_sub_state;
use duckscript::types::command::{Command, CommandResult, Commands};
use duckscript::types::instruction::Instruction;
use duckscript::types::runtime::StateValue;
use std::collections::HashMap;
use std::str;
#[cfg(test)]
#[path = "./mod_test.rs"]
mod mod_test;
#[derive(Clone)]
pub(crate) struct CommandImpl {
package: String,
}
impl Command for CommandImpl {
fn name(&self) -> String {
pckg::concat(&self.package, "BytesToString")
}
fn aliases(&self) -> Vec<String> {
vec!["bytes_to_string".to_string()]
}
fn help(&self) -> String {
include_str!("help.md").to_string()
}
fn clone_and_box(&self) -> Box<dyn Command> {
Box::new((*self).clone())
}
fn requires_context(&self) -> bool {
true
}
fn run_with_context(
&self,
arguments: Vec<String>,
state: &mut HashMap<String, StateValue>,
_variables: &mut HashMap<String, String>,
_output_variable: Option<String>,
_instructions: &Vec<Instruction>,
_commands: &mut Commands,
_line: usize,
) -> CommandResult {
if arguments.is_empty() {
CommandResult::Error("Array handle not provided.".to_string())
} else {
let state = get_handles_sub_state(state);
let key = &arguments[0];
match state.get(key) {
Some(state_value) => match state_value {
StateValue::ByteArray(binary) => match str::from_utf8(&binary) {
Ok(text) => CommandResult::Continue(Some(text.to_string())),
Err(error) => CommandResult::Error(error.to_string()),
},
_ => CommandResult::Error("Invalid handle provided.".to_string()),
},
None => CommandResult::Error(
format!("Array for handle: {} not found.", key).to_string(),
),
}
}
}
}
pub(crate) fn create(package: &str) -> Box<dyn Command> {
Box::new(CommandImpl {
package: package.to_string(),
})
}

View file

@ -0,0 +1,31 @@
use super::*;
use crate::sdk::std::string::string_to_bytes;
use crate::test;
use crate::test::CommandValidation;
#[test]
fn common_functions() {
test::test_common_command_functions(create(""));
}
#[test]
fn run_no_args() {
test::run_script_and_error(vec![create("")], "out = bytes_to_string", "out");
}
#[test]
fn run_handle_not_found() {
test::run_script_and_error(vec![create("")], "out = bytes_to_string badhandle", "out");
}
#[test]
fn run_valid() {
test::run_script_and_validate(
vec![create(""), string_to_bytes::create("")],
r#"
handle = string_to_bytes "hello world"
out = bytes_to_string ${handle}
"#,
CommandValidation::Match("out".to_string(), "hello world".to_string()),
);
}

View file

@ -1,3 +1,4 @@
mod bytes_to_string;
mod concat;
mod contains;
mod ends_with;
@ -9,6 +10,7 @@ mod length;
mod replace;
mod split;
mod starts_with;
pub(crate) mod string_to_bytes;
mod substring;
mod trim;
mod trim_end;
@ -23,6 +25,7 @@ static PACKAGE: &str = "string";
pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptError> {
let package = pckg::concat(parent, PACKAGE);
commands.set(bytes_to_string::create(&package))?;
commands.set(concat::create(&package)?)?;
commands.set(contains::create(&package))?;
commands.set(ends_with::create(&package))?;
@ -34,6 +37,7 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr
commands.set(replace::create(&package))?;
commands.set(split::create(&package))?;
commands.set(starts_with::create(&package))?;
commands.set(string_to_bytes::create(&package))?;
commands.set(substring::create(&package))?;
commands.set(trim::create(&package))?;
commands.set(trim_start::create(&package))?;

View file

@ -0,0 +1,24 @@
```sh
handle = string_to_bytes text
```
Converts the provided string into binary format and returns a handle to the binary data.
#### Parameters
The text to convert.
#### Return Value
A handle to the binary data.
#### Examples
```sh
handle = string_to_bytes "hello world"
text = bytes_to_string ${handle}
release ${handle}
assert_eq ${text} "hello world"
```

View file

@ -0,0 +1,64 @@
use crate::utils::pckg;
use crate::utils::state::put_handle;
use duckscript::types::command::{Command, CommandResult, Commands};
use duckscript::types::instruction::Instruction;
use duckscript::types::runtime::StateValue;
use std::collections::HashMap;
#[cfg(test)]
#[path = "./mod_test.rs"]
mod mod_test;
#[derive(Clone)]
pub(crate) struct CommandImpl {
package: String,
}
impl Command for CommandImpl {
fn name(&self) -> String {
pckg::concat(&self.package, "StringToBytes")
}
fn aliases(&self) -> Vec<String> {
vec!["string_to_bytes".to_string()]
}
fn help(&self) -> String {
include_str!("help.md").to_string()
}
fn clone_and_box(&self) -> Box<dyn Command> {
Box::new((*self).clone())
}
fn requires_context(&self) -> bool {
true
}
fn run_with_context(
&self,
arguments: Vec<String>,
state: &mut HashMap<String, StateValue>,
_variables: &mut HashMap<String, String>,
_output_variable: Option<String>,
_instructions: &Vec<Instruction>,
_commands: &mut Commands,
_line: usize,
) -> CommandResult {
if arguments.is_empty() {
CommandResult::Error("Missing input.".to_string())
} else {
let array = arguments[0].clone().into_bytes();
let key = put_handle(state, StateValue::ByteArray(array));
CommandResult::Continue(Some(key))
}
}
}
pub(crate) fn create(package: &str) -> Box<dyn Command> {
Box::new(CommandImpl {
package: package.to_string(),
})
}

View file

@ -0,0 +1,34 @@
use super::*;
use crate::test;
use crate::test::CommandValidation;
use crate::utils::state::get_handles_sub_state;
use std::str;
#[test]
fn common_functions() {
test::test_common_command_functions(create(""));
}
#[test]
fn run_no_args() {
test::run_script_and_error(vec![create("")], "out = string_to_bytes", "out");
}
#[test]
fn run_valid() {
let mut context = test::run_script_and_validate(
vec![create("")],
r#"out = string_to_bytes "hello world""#,
CommandValidation::Ignore,
);
let state = get_handles_sub_state(&mut context.state);
let list_value = state.remove(context.variables.get("out").unwrap()).unwrap();
match list_value {
StateValue::ByteArray(binary) => {
let text = str::from_utf8(&binary).unwrap();
assert_eq!(text, "hello world");
}
_ => panic!("Invalid type."),
}
}

View file

@ -0,0 +1,9 @@
function test_binary_string
handle = string_to_bytes "hello world"
text = bytes_to_string ${handle}
release ${handle}
assert_eq ${text} "hello world"
end