mirror of
https://github.com/sagiegurari/duckscript
synced 2024-10-06 16:09:39 +00:00
commit
cd540244f7
|
@ -1,5 +1,14 @@
|
|||
## CHANGELOG
|
||||
|
||||
### v0.8.4
|
||||
|
||||
* New --collection flag to json_parse command which returns maps/arrays instead of variables #175
|
||||
* New --collection flag to json_encode command which encodes maps/arrays instead of variables #175
|
||||
|
||||
### v0.8.3
|
||||
|
||||
* Fix release with recursive flag to support set data structures as well.
|
||||
|
||||
### v0.8.2 (2021-06-04)
|
||||
|
||||
* Upgrade dependencies #179
|
||||
|
|
24
Cargo.lock
generated
24
Cargo.lock
generated
|
@ -454,9 +454,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.95"
|
||||
version = "0.2.97"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"
|
||||
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
|
@ -585,9 +585,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.7.2"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
|
||||
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
|
@ -672,9 +672,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
|
@ -779,9 +779,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.2.0"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3670b1d2fdf6084d192bc71ead7aabe6c06aa2ea3fbd9cc3ac111fa5c2b1bd84"
|
||||
checksum = "23a2ac85147a3a11d77ecf1bc7166ec0b92febfa4461c37944e180f319ece467"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
|
@ -792,9 +792,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.2.0"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3676258fd3cfe2c9a0ec99ce3038798d847ce3e4bb17746373eb9f0f1ac16339"
|
||||
checksum = "7e4effb91b4b8b6fb7732e670b6cee160278ff8e6bf485c7805d9e319d76e284"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
|
@ -825,9 +825,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.72"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
|
||||
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
76
docs/sdk.md
76
docs/sdk.md
|
@ -172,6 +172,7 @@
|
|||
* [std::time::CurrentTimeMillies (current_time)](#std__time__CurrentTimeMillies)
|
||||
* [std::var::GetAllVarNames (get_all_var_names)](#std__var__GetAllVarNames)
|
||||
* [std::var::GetByName (get_by_name)](#std__var__GetByName)
|
||||
* [std::var::IsDefined (is_defined)](#std__var__IsDefined)
|
||||
* [std::var::Set (set)](#std__var__Set)
|
||||
* [std::var::SetByName (set_by_name)](#std__var__SetByName)
|
||||
* [std::var::Unset (unset)](#std__var__Unset)
|
||||
|
@ -410,12 +411,12 @@ release [-r|--recursive] handle
|
|||
Releases an internal handle stored in the runtime memory.<br>
|
||||
Certain commands (such as **array**) will create a handle and the variable will only hold a reference to that handle.<br>
|
||||
In order to release those handles once they are no longer needed, the release command should be used.<br>
|
||||
By providing the recursive flag, it will also go over the data values (array items, map values, ...) and release each one of them as well
|
||||
if they are handles to other arrays/maps/...
|
||||
By providing the recursive flag, it will also go over the data values (array items, map values, set keys, ...) and release each one of them as well
|
||||
if they are handles to other arrays/maps/sets/...
|
||||
|
||||
#### Parameters
|
||||
|
||||
* Optional recursive flag (default false)
|
||||
* Optional recursive (-r/--recursive) flag (default false)
|
||||
* The handle name.
|
||||
|
||||
#### Return Value
|
||||
|
@ -4104,11 +4105,14 @@ string = json_encode var_name
|
|||
```
|
||||
|
||||
This function will encode all variables, starting from the root variable as a JSON string.<br>
|
||||
Since duckscript is untyped, all boolean and numeric values will be encoded as strings.
|
||||
Since duckscript is untyped, all boolean and numeric values will be encoded as strings.<br>
|
||||
If --collection is passed, the provided value is considered as string or a map/array handle which is used to fetch
|
||||
the tree data and create the json string.
|
||||
|
||||
#### Parameters
|
||||
|
||||
The root variable name
|
||||
* Option --collection flag to make the encoding use the maps/arrays and values
|
||||
* The root variable name (or a handle/value in case --collection is provided)
|
||||
|
||||
#### Return Value
|
||||
|
||||
|
@ -4117,8 +4121,13 @@ The JSON string
|
|||
#### Examples
|
||||
|
||||
```sh
|
||||
# will parse and encode to plain variables
|
||||
package = json_parse "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
|
||||
jsonstring = json_encode package
|
||||
|
||||
# will parse and encode to maps/arrays
|
||||
package = json_parse --collection "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
|
||||
jsonstring = json_encode --collection ${package}
|
||||
```
|
||||
|
||||
|
||||
|
@ -4141,17 +4150,23 @@ root.child[5]
|
|||
root.child.length
|
||||
```
|
||||
|
||||
In case the --collection flag is provided, it will instead create maps/array as needed and return the root handle (or primitive value) of
|
||||
the json data.
|
||||
Make sure to use the release with the recursive flag on the root object to release the entire memory once done.
|
||||
|
||||
#### Parameters
|
||||
|
||||
The JSON string to parse.
|
||||
* Optional --collection flag to parse and return value/map/array
|
||||
* The JSON string to parse.
|
||||
|
||||
#### Return Value
|
||||
|
||||
The root value.
|
||||
The root value/handle.
|
||||
|
||||
#### Examples
|
||||
|
||||
```sh
|
||||
# parse to simple variables
|
||||
package = json_parse "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
|
||||
|
||||
assert_eq ${package} "[OBJECT]"
|
||||
|
@ -4162,6 +4177,26 @@ assert_eq ${package.keywords.length} 2
|
|||
assert_eq ${package.keywords[0]} test1
|
||||
assert_eq ${package.keywords[1]} test2
|
||||
assert_eq ${package.directories.test} spec
|
||||
|
||||
# parse to maps/arrays
|
||||
package = json_parse --collection "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
|
||||
name = map_get ${package} name
|
||||
assert_eq ${name} "my package"
|
||||
version = map_get ${package} version
|
||||
assert_eq ${version} 1
|
||||
public = map_get ${package} public
|
||||
assert_false ${public}
|
||||
keywords_handle = map_get ${package} keywords
|
||||
length = array_length ${keywords_handle}
|
||||
assert_eq ${length} 2
|
||||
value = array_pop ${keywords_handle}
|
||||
assert_eq ${value} test2
|
||||
value = array_pop ${keywords_handle}
|
||||
assert_eq ${value} test1
|
||||
directories = map_get ${package} directories
|
||||
directory = map_get ${directories} test
|
||||
assert_eq ${directory} spec
|
||||
release --recursive ${package}
|
||||
```
|
||||
|
||||
|
||||
|
@ -6338,6 +6373,33 @@ assert_eq ${value} test
|
|||
#### Aliases:
|
||||
get_by_name
|
||||
|
||||
<a name="std__var__IsDefined"></a>
|
||||
## std::var::IsDefined
|
||||
```sh
|
||||
var = is_defined key
|
||||
```
|
||||
|
||||
Returns true if the provided variable name (not value) exists.
|
||||
|
||||
#### Parameters
|
||||
|
||||
The variable name.
|
||||
|
||||
#### Return Value
|
||||
|
||||
True if the variable is defined.
|
||||
|
||||
#### Examples
|
||||
|
||||
```sh
|
||||
key = set "hello world"
|
||||
exists = is_defined key
|
||||
```
|
||||
|
||||
|
||||
#### Aliases:
|
||||
is_defined
|
||||
|
||||
<a name="std__var__Set"></a>
|
||||
## std::var::Set
|
||||
```sh
|
||||
|
|
|
@ -3,11 +3,14 @@ string = json_encode var_name
|
|||
```
|
||||
|
||||
This function will encode all variables, starting from the root variable as a JSON string.<br>
|
||||
Since duckscript is untyped, all boolean and numeric values will be encoded as strings.
|
||||
Since duckscript is untyped, all boolean and numeric values will be encoded as strings.<br>
|
||||
If --collection is passed, the provided value is considered as string or a map/array handle which is used to fetch
|
||||
the tree data and create the json string.
|
||||
|
||||
#### Parameters
|
||||
|
||||
The root variable name
|
||||
* Option --collection flag to make the encoding use the maps/arrays and values
|
||||
* The root variable name (or a handle/value in case --collection is provided)
|
||||
|
||||
#### Return Value
|
||||
|
||||
|
@ -16,6 +19,11 @@ The JSON string
|
|||
#### Examples
|
||||
|
||||
```sh
|
||||
# will parse and encode to plain variables
|
||||
package = json_parse "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
|
||||
jsonstring = json_encode package
|
||||
|
||||
# will parse and encode to maps/arrays
|
||||
package = json_parse --collection "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
|
||||
jsonstring = json_encode --collection ${package}
|
||||
```
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use crate::sdk::std::json::OBJECT_VALUE;
|
||||
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 serde_json::map::Map;
|
||||
use serde_json::Value;
|
||||
use serde_json::{Number, Value};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -92,7 +93,10 @@ fn encode_any(name: &str, values: &HashMap<&str, &str>) -> Result<Value, String>
|
|||
}
|
||||
}
|
||||
|
||||
fn encode(name: &str, variables: &HashMap<String, String>) -> Result<String, String> {
|
||||
fn encode_from_variables(
|
||||
name: &str,
|
||||
variables: &HashMap<String, String>,
|
||||
) -> Result<String, String> {
|
||||
let mut object_variables: HashMap<&str, &str> = HashMap::new();
|
||||
|
||||
for (key, value) in variables {
|
||||
|
@ -111,6 +115,68 @@ fn encode(name: &str, variables: &HashMap<String, String>) -> Result<String, Str
|
|||
}
|
||||
}
|
||||
|
||||
fn encode_from_state_value(
|
||||
state_value: &StateValue,
|
||||
state: &HashMap<String, StateValue>,
|
||||
) -> Result<Value, String> {
|
||||
match state_value {
|
||||
StateValue::Boolean(value) => Ok(Value::Bool(*value)),
|
||||
StateValue::Number(value) => Ok(Value::Number(Number::from(*value))),
|
||||
StateValue::UnsignedNumber(value) => Ok(Value::Number(Number::from(*value))),
|
||||
StateValue::Number32Bit(value) => Ok(Value::Number(Number::from(*value))),
|
||||
StateValue::UnsignedNumber32Bit(value) => Ok(Value::Number(Number::from(*value))),
|
||||
StateValue::Number64Bit(value) => Ok(Value::Number(Number::from(*value))),
|
||||
StateValue::UnsignedNumber64Bit(value) => Ok(Value::Number(Number::from(*value))),
|
||||
StateValue::String(value) => match state.get(value) {
|
||||
Some(sub_state_value) => encode_from_state_value(sub_state_value, state),
|
||||
None => Ok(Value::String(value.to_string())),
|
||||
},
|
||||
StateValue::List(list) => {
|
||||
let mut items = vec![];
|
||||
|
||||
for item in list {
|
||||
match encode_from_state_value(item, state) {
|
||||
Ok(item_value) => {
|
||||
items.push(item_value);
|
||||
}
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
}
|
||||
|
||||
Ok(Value::Array(items))
|
||||
}
|
||||
StateValue::SubState(sub_state) => {
|
||||
let mut items = Map::new();
|
||||
|
||||
for (key, value) in sub_state {
|
||||
match encode_from_state_value(value, state) {
|
||||
Ok(item_value) => {
|
||||
items.insert(key.to_string(), item_value);
|
||||
}
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Value::Object(items))
|
||||
}
|
||||
StateValue::ByteArray(_) => Err("Unsupported value type.".to_string()),
|
||||
StateValue::Set(_) => Err("Unsupported value type.".to_string()),
|
||||
StateValue::Any(_) => Err("Unsupported value type.".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_from_state(value: &str, state: &HashMap<String, StateValue>) -> Result<String, String> {
|
||||
let json_value = match state.get(value) {
|
||||
Some(state_value) => encode_from_state_value(state_value, state),
|
||||
None => Ok(Value::String(value.to_string())),
|
||||
};
|
||||
|
||||
match json_value {
|
||||
Ok(json_value_obj) => Ok(json_value_obj.to_string()),
|
||||
Err(error) => Err(error.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct CommandImpl {
|
||||
package: String,
|
||||
|
@ -140,7 +206,7 @@ impl Command for CommandImpl {
|
|||
fn run_with_context(
|
||||
&self,
|
||||
arguments: Vec<String>,
|
||||
_state: &mut HashMap<String, StateValue>,
|
||||
state: &mut HashMap<String, StateValue>,
|
||||
variables: &mut HashMap<String, String>,
|
||||
_output_variable: Option<String>,
|
||||
_instructions: &Vec<Instruction>,
|
||||
|
@ -150,9 +216,24 @@ impl Command for CommandImpl {
|
|||
if arguments.is_empty() {
|
||||
CommandResult::Error("No JSON root variable name provided.".to_string())
|
||||
} else {
|
||||
match encode(&arguments[0], variables) {
|
||||
Ok(output) => CommandResult::Continue(Some(output)),
|
||||
Err(error) => CommandResult::Error(error),
|
||||
let (start_index, as_state) = if arguments.len() > 1 && arguments[0] == "--collection" {
|
||||
(1, true)
|
||||
} else {
|
||||
(0, false)
|
||||
};
|
||||
|
||||
if as_state {
|
||||
let state = get_handles_sub_state(state);
|
||||
|
||||
match encode_from_state(&arguments[start_index], state) {
|
||||
Ok(output) => CommandResult::Continue(Some(output)),
|
||||
Err(error) => CommandResult::Error(error),
|
||||
}
|
||||
} else {
|
||||
match encode_from_variables(&arguments[start_index], variables) {
|
||||
Ok(output) => CommandResult::Continue(Some(output)),
|
||||
Err(error) => CommandResult::Error(error),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,17 +12,23 @@ root.child[5]
|
|||
root.child.length
|
||||
```
|
||||
|
||||
In case the --collection flag is provided, it will instead create maps/array as needed and return the root handle (or primitive value) of
|
||||
the json data.
|
||||
Make sure to use the release with the recursive flag on the root object to release the entire memory once done.
|
||||
|
||||
#### Parameters
|
||||
|
||||
The JSON string to parse.
|
||||
* Optional --collection flag to parse and return value/map/array
|
||||
* The JSON string to parse.
|
||||
|
||||
#### Return Value
|
||||
|
||||
The root value.
|
||||
The root value/handle.
|
||||
|
||||
#### Examples
|
||||
|
||||
```sh
|
||||
# parse to simple variables
|
||||
package = json_parse "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
|
||||
|
||||
assert_eq ${package} "[OBJECT]"
|
||||
|
@ -33,4 +39,24 @@ assert_eq ${package.keywords.length} 2
|
|||
assert_eq ${package.keywords[0]} test1
|
||||
assert_eq ${package.keywords[1]} test2
|
||||
assert_eq ${package.directories.test} spec
|
||||
|
||||
# parse to maps/arrays
|
||||
package = json_parse --collection "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
|
||||
name = map_get ${package} name
|
||||
assert_eq ${name} "my package"
|
||||
version = map_get ${package} version
|
||||
assert_eq ${version} 1
|
||||
public = map_get ${package} public
|
||||
assert_false ${public}
|
||||
keywords_handle = map_get ${package} keywords
|
||||
length = array_length ${keywords_handle}
|
||||
assert_eq ${length} 2
|
||||
value = array_pop ${keywords_handle}
|
||||
assert_eq ${value} test2
|
||||
value = array_pop ${keywords_handle}
|
||||
assert_eq ${value} test1
|
||||
directories = map_get ${package} directories
|
||||
directory = map_get ${directories} test
|
||||
assert_eq ${directory} spec
|
||||
release --recursive ${package}
|
||||
```
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::sdk::std::json::OBJECT_VALUE;
|
||||
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;
|
||||
|
@ -46,6 +47,41 @@ fn create_variables(data: Value, name: &str, variables: &mut HashMap<String, Str
|
|||
};
|
||||
}
|
||||
|
||||
fn create_structure(data: Value, state: &mut HashMap<String, StateValue>) -> Option<String> {
|
||||
match data {
|
||||
Value::Null => None,
|
||||
Value::Bool(value) => Some(value.to_string()),
|
||||
Value::Number(value) => Some(value.to_string()),
|
||||
Value::String(value) => Some(value),
|
||||
Value::Array(list) => {
|
||||
let mut state_list = vec![];
|
||||
|
||||
for item in list {
|
||||
if let Some(value) = create_structure(item, state) {
|
||||
state_list.push(StateValue::String(value));
|
||||
}
|
||||
}
|
||||
|
||||
let key = put_handle(state, StateValue::List(state_list));
|
||||
|
||||
Some(key)
|
||||
}
|
||||
Value::Object(map) => {
|
||||
let mut state_map = HashMap::new();
|
||||
|
||||
for (key, value) in map {
|
||||
if let Some(value) = create_structure(value, state) {
|
||||
state_map.insert(key, StateValue::String(value));
|
||||
}
|
||||
}
|
||||
|
||||
let key = put_handle(state, StateValue::SubState(state_map));
|
||||
|
||||
Some(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct CommandImpl {
|
||||
package: String,
|
||||
|
@ -75,7 +111,7 @@ impl Command for CommandImpl {
|
|||
fn run_with_context(
|
||||
&self,
|
||||
arguments: Vec<String>,
|
||||
_state: &mut HashMap<String, StateValue>,
|
||||
state: &mut HashMap<String, StateValue>,
|
||||
variables: &mut HashMap<String, String>,
|
||||
output_variable: Option<String>,
|
||||
_instructions: &Vec<Instruction>,
|
||||
|
@ -85,15 +121,25 @@ impl Command for CommandImpl {
|
|||
if arguments.is_empty() {
|
||||
CommandResult::Error("No JSON string provided.".to_string())
|
||||
} else {
|
||||
match parse_json(&arguments[0]) {
|
||||
let (json_index, as_state) = if arguments.len() > 1 && arguments[0] == "--collection" {
|
||||
(1, true)
|
||||
} else {
|
||||
(0, false)
|
||||
};
|
||||
|
||||
match parse_json(&arguments[json_index]) {
|
||||
Ok(data) => {
|
||||
let output = match output_variable {
|
||||
Some(name) => {
|
||||
create_variables(data, &name, variables);
|
||||
if as_state {
|
||||
create_structure(data, state)
|
||||
} else {
|
||||
create_variables(data, &name, variables);
|
||||
|
||||
match variables.get(&name) {
|
||||
Some(value) => Some(value.to_string()),
|
||||
None => None,
|
||||
match variables.get(&name) {
|
||||
Some(value) => Some(value.to_string()),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
None => Some("true".to_string()),
|
||||
|
|
|
@ -13,7 +13,7 @@ fn run_no_args() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn run_all_types() {
|
||||
fn run_all_types_as_vars() {
|
||||
let context = test::run_script_and_validate(
|
||||
vec![create("")],
|
||||
r#"
|
||||
|
|
|
@ -5,12 +5,12 @@ release [-r|--recursive] handle
|
|||
Releases an internal handle stored in the runtime memory.<br>
|
||||
Certain commands (such as **array**) will create a handle and the variable will only hold a reference to that handle.<br>
|
||||
In order to release those handles once they are no longer needed, the release command should be used.<br>
|
||||
By providing the recursive flag, it will also go over the data values (array items, map values, ...) and release each one of them as well
|
||||
if they are handles to other arrays/maps/...
|
||||
By providing the recursive flag, it will also go over the data values (array items, map values, set keys, ...) and release each one of them as well
|
||||
if they are handles to other arrays/maps/sets/...
|
||||
|
||||
#### Parameters
|
||||
|
||||
* Optional recursive flag (default false)
|
||||
* Optional recursive (-r/--recursive) flag (default false)
|
||||
* The handle name.
|
||||
|
||||
#### Return Value
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::utils::pckg;
|
||||
use crate::utils::state::remove_handle;
|
||||
use crate::utils::state::{remove_handle, remove_handle_recursive};
|
||||
use duckscript::types::command::{Command, CommandResult, Commands};
|
||||
use duckscript::types::instruction::Instruction;
|
||||
use duckscript::types::runtime::StateValue;
|
||||
|
@ -9,41 +9,6 @@ use std::collections::HashMap;
|
|||
#[path = "./mod_test.rs"]
|
||||
mod mod_test;
|
||||
|
||||
fn remove(state: &mut HashMap<String, StateValue>, key: &str, recursive: bool) -> bool {
|
||||
match remove_handle(state, key.to_string()) {
|
||||
Some(state_value) => {
|
||||
if recursive {
|
||||
match state_value {
|
||||
StateValue::SubState(map) => {
|
||||
for (_, map_value) in map {
|
||||
match map_value {
|
||||
StateValue::String(value) => remove(state, &value, recursive),
|
||||
_ => true,
|
||||
};
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
StateValue::List(list) => {
|
||||
for value in list {
|
||||
match value {
|
||||
StateValue::String(value) => remove(state, &value, recursive),
|
||||
_ => true,
|
||||
};
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
_ => true,
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct CommandImpl {
|
||||
package: String,
|
||||
|
@ -90,7 +55,12 @@ impl Command for CommandImpl {
|
|||
(arguments[0].to_string(), false)
|
||||
};
|
||||
|
||||
let removed = remove(state, &key, recursive);
|
||||
let removed = if recursive {
|
||||
remove_handle_recursive(state, key)
|
||||
} else {
|
||||
let old_value = remove_handle(state, key);
|
||||
old_value.is_some()
|
||||
};
|
||||
|
||||
CommandResult::Continue(Some(removed.to_string()))
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr
|
|||
|
||||
commands.set(get_all_var_names::create(&package))?;
|
||||
commands.set(get_by_name::create(&package))?;
|
||||
commands.set(is_defined::create(PACKAGE))?;
|
||||
commands.set(is_defined::create(&package))?;
|
||||
commands.set(set::create(&package))?;
|
||||
commands.set(set_by_name::create(&package))?;
|
||||
commands.set(unset::create(&package)?)?;
|
||||
|
|
|
@ -68,6 +68,43 @@ pub(crate) fn remove_handle(
|
|||
handle_state.remove(&key)
|
||||
}
|
||||
|
||||
pub(crate) fn remove_handle_recursive(
|
||||
state: &mut HashMap<String, StateValue>,
|
||||
key: String,
|
||||
) -> bool {
|
||||
match remove_handle(state, key.to_string()) {
|
||||
Some(state_value) => match state_value {
|
||||
StateValue::List(list) => {
|
||||
for value in list {
|
||||
if let StateValue::String(value) = value {
|
||||
remove_handle_recursive(state, value);
|
||||
};
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
StateValue::Set(set) => {
|
||||
for value in set {
|
||||
remove_handle_recursive(state, value);
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
StateValue::SubState(map) => {
|
||||
for (_, map_value) in map {
|
||||
if let StateValue::String(value) = map_value {
|
||||
remove_handle_recursive(state, value);
|
||||
};
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
_ => true,
|
||||
},
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn return_handle(
|
||||
state: &mut HashMap<String, StateValue>,
|
||||
key: String,
|
||||
|
|
|
@ -52,7 +52,7 @@ fn test_simple_types
|
|||
assert_false ${defined}
|
||||
end
|
||||
|
||||
fn test_all_types
|
||||
fn test_all_types_as_vars
|
||||
jsonstring = set "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
|
||||
package = json_parse ${jsonstring}
|
||||
|
||||
|
@ -98,3 +98,43 @@ fn test_all_types
|
|||
assert_eq ${package2.keywords[1].directories.test} spec
|
||||
end
|
||||
|
||||
fn test_all_types_as_collections
|
||||
jsonstring = set "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
|
||||
package = json_parse --collection ${jsonstring}
|
||||
|
||||
name = map_get ${package} name
|
||||
assert_eq ${name} "my package"
|
||||
version = map_get ${package} version
|
||||
assert_eq ${version} 1
|
||||
public = map_get ${package} public
|
||||
assert_false ${public}
|
||||
keywords_handle = map_get ${package} keywords
|
||||
length = array_length ${keywords_handle}
|
||||
assert_eq ${length} 2
|
||||
value = array_get ${keywords_handle} 0
|
||||
assert_eq ${value} test1
|
||||
value = array_get ${keywords_handle} 1
|
||||
assert_eq ${value} test2
|
||||
directories = map_get ${package} directories
|
||||
directory = map_get ${directories} test
|
||||
assert_eq ${directory} spec
|
||||
|
||||
map_put ${package} name "my package 2"
|
||||
name = map_get ${package} name
|
||||
assert_eq ${name} "my package 2"
|
||||
|
||||
update_jsonstring = json_encode --collection ${package}
|
||||
|
||||
release --recursive ${package}
|
||||
|
||||
package2 = json_parse ${update_jsonstring}
|
||||
assert_eq ${package2} "[OBJECT]"
|
||||
assert_eq ${package2.name} "my package 2"
|
||||
assert_eq ${package2.version} 1
|
||||
assert_eq ${package2.publish} false
|
||||
assert_eq ${package2.keywords.length} 2
|
||||
assert_eq ${package2.keywords[0]} test1
|
||||
assert_eq ${package2.keywords[1]} test2
|
||||
assert_eq ${package2.directories.test} spec
|
||||
end
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
fn test_all_types
|
||||
fn test_all_types_as_vars
|
||||
package = json_parse "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
|
||||
|
||||
assert_eq ${package} "[OBJECT]"
|
||||
|
@ -12,3 +12,45 @@ fn test_all_types
|
|||
assert_eq ${package.directories.test} spec
|
||||
end
|
||||
|
||||
fn test_all_types_as_collections
|
||||
package = json_parse --collection "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
|
||||
|
||||
output = is_map ${package}
|
||||
assert ${output}
|
||||
|
||||
name = map_get ${package} name
|
||||
assert_eq ${name} "my package"
|
||||
|
||||
version = map_get ${package} version
|
||||
assert_eq ${version} 1
|
||||
|
||||
public = map_get ${package} public
|
||||
assert_false ${public}
|
||||
|
||||
keywords_handle = map_get ${package} keywords
|
||||
output = is_array ${keywords_handle}
|
||||
assert ${output}
|
||||
|
||||
length = array_length ${keywords_handle}
|
||||
assert_eq ${length} 2
|
||||
value = array_pop ${keywords_handle}
|
||||
assert_eq ${value} test2
|
||||
value = array_pop ${keywords_handle}
|
||||
assert_eq ${value} test1
|
||||
|
||||
directories = map_get ${package} directories
|
||||
output = is_map ${directories}
|
||||
assert ${output}
|
||||
|
||||
directory = map_get ${directories} test
|
||||
assert_eq ${directory} spec
|
||||
|
||||
release --recursive ${package}
|
||||
output = is_map ${package}
|
||||
assert_false ${output}
|
||||
output = is_array ${keywords_handle}
|
||||
assert_false ${output}
|
||||
output = is_map ${directories}
|
||||
assert_false ${output}
|
||||
end
|
||||
|
||||
|
|
|
@ -20,6 +20,10 @@ fn test_release_recursive
|
|||
sub_array_handle2 = array
|
||||
array_handle = array ${sub_array_handle2}
|
||||
|
||||
sub_set_handle = set_new
|
||||
set_handle = set_new ${sub_set_handle}
|
||||
array_push ${array_handle} ${set_handle}
|
||||
|
||||
handle = array ${array_handle} ${map_handle}
|
||||
|
||||
exists = is_array ${handle}
|
||||
|
@ -32,6 +36,10 @@ fn test_release_recursive
|
|||
assert ${exists}
|
||||
exists = is_array ${sub_array_handle2}
|
||||
assert ${exists}
|
||||
exists = is_set ${set_handle}
|
||||
assert ${exists}
|
||||
exists = is_set ${sub_set_handle}
|
||||
assert ${exists}
|
||||
|
||||
release -r ${handle}
|
||||
|
||||
|
@ -45,4 +53,8 @@ fn test_release_recursive
|
|||
assert_false ${exists}
|
||||
exists = is_array ${sub_array_handle2}
|
||||
assert_false ${exists}
|
||||
exists = is_set ${set_handle}
|
||||
assert_false ${exists}
|
||||
exists = is_set ${sub_set_handle}
|
||||
assert_false ${exists}
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue