From e7cacc74b1b26c1ab6b36b00c9acfe30c9581b40 Mon Sep 17 00:00:00 2001 From: sagie gur ari Date: Fri, 24 Jan 2020 16:20:19 +0000 Subject: [PATCH] New array_push command --- CHANGELOG.md | 1 + docs/sdk.md | 30 +++++ .../src/sdk/std/collections/array_pop/mod.rs | 37 +++++- .../sdk/std/collections/array_push/help.md | 22 ++++ .../src/sdk/std/collections/array_push/mod.rs | 120 ++++++++++++++++++ .../std/collections/array_push/mod_test.rs | 50 ++++++++ duckscript_sdk/src/sdk/std/collections/mod.rs | 4 +- test/std/collections/array_push_test.ds | 51 ++++++++ 8 files changed, 313 insertions(+), 2 deletions(-) create mode 100644 duckscript_sdk/src/sdk/std/collections/array_push/help.md create mode 100755 duckscript_sdk/src/sdk/std/collections/array_push/mod.rs create mode 100644 duckscript_sdk/src/sdk/std/collections/array_push/mod_test.rs create mode 100644 test/std/collections/array_push_test.ds diff --git a/CHANGELOG.md b/CHANGELOG.md index 727c796..4d87ae9 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### v0.1.9 +* New array_push command. * New concat command. * Improve wget input parsing diff --git a/docs/sdk.md b/docs/sdk.md index 8e1853d..c046a88 100644 --- a/docs/sdk.md +++ b/docs/sdk.md @@ -18,6 +18,7 @@ * [std::collections::ArrayIsEmpty (array_is_empty)](#std__collections__ArrayIsEmpty) * [std::collections::ArrayLength (array_length, arrlen)](#std__collections__ArrayLength) * [std::collections::ArrayPop (array_pop)](#std__collections__ArrayPop) +* [std::collections::ArrayPush (array_push)](#std__collections__ArrayPush) * [std::collections::IsArray (is_array)](#std__collections__IsArray) * [std::collections::Range (range)](#std__collections__Range) * [std::collections::ReadProperties (read_properties)](#std__collections__ReadProperties) @@ -834,6 +835,35 @@ assert_eq ${last_element} 3 #### Aliases: array_pop + +## std::collections::ArrayPush +```sh +var = array_push handle value +``` + +Pushes an additional value to an existing array. + +#### Parameters + +The array handle. + +#### Return Value + +True if a new value was pushed. + +#### Examples + +```sh +handle = array 1 2 3 +array_push ${handle} 4 +last_element = array_pop ${handle} +assert_eq ${last_element} 4 +``` + + +#### Aliases: +array_push + ## std::collections::IsArray ```sh diff --git a/duckscript_sdk/src/sdk/std/collections/array_pop/mod.rs b/duckscript_sdk/src/sdk/std/collections/array_pop/mod.rs index 1f1d6d5..71510df 100755 --- a/duckscript_sdk/src/sdk/std/collections/array_pop/mod.rs +++ b/duckscript_sdk/src/sdk/std/collections/array_pop/mod.rs @@ -93,7 +93,42 @@ impl Command for CommandImpl { None => CommandResult::Continue(None), } } - _ => CommandResult::Error("Invalid handle provided.".to_string()), + StateValue::Boolean(value) => { + state.insert(key.to_string(), StateValue::Boolean(value)); + CommandResult::Error("Invalid handle provided.".to_string()) + } + StateValue::Number(value) => { + state.insert(key.to_string(), StateValue::Number(value)); + CommandResult::Error("Invalid handle provided.".to_string()) + } + StateValue::UnsignedNumber(value) => { + state.insert(key.to_string(), StateValue::UnsignedNumber(value)); + CommandResult::Error("Invalid handle provided.".to_string()) + } + StateValue::Number32Bit(value) => { + state.insert(key.to_string(), StateValue::Number32Bit(value)); + CommandResult::Error("Invalid handle provided.".to_string()) + } + StateValue::UnsignedNumber32Bit(value) => { + state.insert(key.to_string(), StateValue::UnsignedNumber32Bit(value)); + CommandResult::Error("Invalid handle provided.".to_string()) + } + StateValue::Number64Bit(value) => { + state.insert(key.to_string(), StateValue::Number64Bit(value)); + CommandResult::Error("Invalid handle provided.".to_string()) + } + StateValue::UnsignedNumber64Bit(value) => { + state.insert(key.to_string(), StateValue::UnsignedNumber64Bit(value)); + CommandResult::Error("Invalid handle provided.".to_string()) + } + StateValue::String(value) => { + state.insert(key.to_string(), StateValue::String(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()) + } }, None => CommandResult::Error( format!("Array for handle: {} not found.", key).to_string(), diff --git a/duckscript_sdk/src/sdk/std/collections/array_push/help.md b/duckscript_sdk/src/sdk/std/collections/array_push/help.md new file mode 100644 index 0000000..eb2ac84 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/collections/array_push/help.md @@ -0,0 +1,22 @@ +```sh +var = array_push handle value +``` + +Pushes an additional value to an existing array. + +#### Parameters + +The array handle. + +#### Return Value + +True if a new value was pushed. + +#### Examples + +```sh +handle = array 1 2 3 +array_push ${handle} 4 +last_element = array_pop ${handle} +assert_eq ${last_element} 4 +``` diff --git a/duckscript_sdk/src/sdk/std/collections/array_push/mod.rs b/duckscript_sdk/src/sdk/std/collections/array_push/mod.rs new file mode 100755 index 0000000..3f183cc --- /dev/null +++ b/duckscript_sdk/src/sdk/std/collections/array_push/mod.rs @@ -0,0 +1,120 @@ +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; + +#[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, "ArrayPush") + } + + fn aliases(&self) -> Vec { + vec!["array_push".to_string()] + } + + fn help(&self) -> String { + include_str!("help.md").to_string() + } + + fn clone_and_box(&self) -> Box { + Box::new((*self).clone()) + } + + fn requires_context(&self) -> bool { + true + } + + fn run_with_context( + &self, + arguments: Vec, + state: &mut HashMap, + _variables: &mut HashMap, + _output_variable: Option, + _instructions: &Vec, + _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.remove(key) { + Some(state_value) => match state_value { + StateValue::List(mut list) => { + let mut skip = true; + for argument in &arguments { + if skip { + skip = false; + } else { + list.push(StateValue::String(argument.to_string())) + } + } + + state.insert(key.to_string(), StateValue::List(list)); + + CommandResult::Continue(Some("true".to_string())) + } + StateValue::Boolean(value) => { + state.insert(key.to_string(), StateValue::Boolean(value)); + CommandResult::Error("Invalid handle provided.".to_string()) + } + StateValue::Number(value) => { + state.insert(key.to_string(), StateValue::Number(value)); + CommandResult::Error("Invalid handle provided.".to_string()) + } + StateValue::UnsignedNumber(value) => { + state.insert(key.to_string(), StateValue::UnsignedNumber(value)); + CommandResult::Error("Invalid handle provided.".to_string()) + } + StateValue::Number32Bit(value) => { + state.insert(key.to_string(), StateValue::Number32Bit(value)); + CommandResult::Error("Invalid handle provided.".to_string()) + } + StateValue::UnsignedNumber32Bit(value) => { + state.insert(key.to_string(), StateValue::UnsignedNumber32Bit(value)); + CommandResult::Error("Invalid handle provided.".to_string()) + } + StateValue::Number64Bit(value) => { + state.insert(key.to_string(), StateValue::Number64Bit(value)); + CommandResult::Error("Invalid handle provided.".to_string()) + } + StateValue::UnsignedNumber64Bit(value) => { + state.insert(key.to_string(), StateValue::UnsignedNumber64Bit(value)); + CommandResult::Error("Invalid handle provided.".to_string()) + } + StateValue::String(value) => { + state.insert(key.to_string(), StateValue::String(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()) + } + }, + None => CommandResult::Error( + format!("Array for handle: {} not found.", key).to_string(), + ), + } + } + } +} + +pub(crate) fn create(package: &str) -> Box { + Box::new(CommandImpl { + package: package.to_string(), + }) +} diff --git a/duckscript_sdk/src/sdk/std/collections/array_push/mod_test.rs b/duckscript_sdk/src/sdk/std/collections/array_push/mod_test.rs new file mode 100644 index 0000000..511b86e --- /dev/null +++ b/duckscript_sdk/src/sdk/std/collections/array_push/mod_test.rs @@ -0,0 +1,50 @@ +use super::*; +use crate::sdk::std::collections::{array, array_pop}; +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 = array_push", "out"); +} + +#[test] +fn run_not_found() { + test::run_script_and_error(vec![create("")], "out = array_push bad_handle 1", "out"); +} + +#[test] +fn run_only_array_not_found() { + test::run_script_and_error(vec![create("")], "out = array_push bad_handle", "out"); +} + +#[test] +fn run_found_no_input() { + test::run_script_and_validate( + vec![create(""), array::create(""), array_pop::create("")], + r#" + handle = array 1 2 3 + array_push ${handle} + out = array_pop ${handle} + "#, + CommandValidation::Match("out".to_string(), "3".to_string()), + ); +} + +#[test] +fn run_found() { + test::run_script_and_validate( + vec![create(""), array::create(""), array_pop::create("")], + r#" + handle = array 1 2 3 + array_push ${handle} 4 + out = array_pop ${handle} + "#, + CommandValidation::Match("out".to_string(), "4".to_string()), + ); +} diff --git a/duckscript_sdk/src/sdk/std/collections/mod.rs b/duckscript_sdk/src/sdk/std/collections/mod.rs index 80b2e15..fb93335 100755 --- a/duckscript_sdk/src/sdk/std/collections/mod.rs +++ b/duckscript_sdk/src/sdk/std/collections/mod.rs @@ -1,7 +1,8 @@ pub(crate) mod array; mod array_is_empty; pub(crate) mod array_length; -mod array_pop; +pub(crate) mod array_pop; +mod array_push; mod is_array; mod range; mod read_properties; @@ -17,6 +18,7 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr let package = pckg::concat(parent, PACKAGE); commands.set(array::create(&package))?; + commands.set(array_push::create(&package))?; commands.set(array_is_empty::create(&package)?)?; commands.set(array_length::create(&package))?; commands.set(array_pop::create(&package))?; diff --git a/test/std/collections/array_push_test.ds b/test/std/collections/array_push_test.ds new file mode 100644 index 0000000..773f9e5 --- /dev/null +++ b/test/std/collections/array_push_test.ds @@ -0,0 +1,51 @@ + +function test_array_with_data + arr = array a + counter = range 1 4 + for index in ${counter} + array_push ${arr} ${index} + end + + last_element = array_pop ${arr} + assert_eq ${last_element} 3 + + last_element = array_pop ${arr} + assert_eq ${last_element} 2 + + last_element = array_pop ${arr} + assert_eq ${last_element} 1 + + last_element = array_pop ${arr} + assert_eq ${last_element} a + + last_element = array_pop ${arr} + defined = is_defined last_element + assert_false ${defined} + + released = release ${arr} + assert ${released} +end + +function test_array_empty + arr = array + counter = range 1 4 + for index in ${counter} + array_push ${arr} ${index} + end + + last_element = array_pop ${arr} + assert_eq ${last_element} 3 + + last_element = array_pop ${arr} + assert_eq ${last_element} 2 + + last_element = array_pop ${arr} + assert_eq ${last_element} 1 + + last_element = array_pop ${arr} + defined = is_defined last_element + assert_false ${defined} + + released = release ${arr} + assert ${released} +end