From abcacf85dca16b2bf1355d45c195f0bc48149fce Mon Sep 17 00:00:00 2001 From: sagie gur ari Date: Tue, 14 Apr 2020 11:07:04 +0000 Subject: [PATCH] New map_keys command --- CHANGELOG.md | 1 + .../src/sdk/std/collections/map_keys/help.md | 33 ++++++++ .../src/sdk/std/collections/map_keys/mod.rs | 81 +++++++++++++++++++ .../sdk/std/collections/map_keys/mod_test.rs | 38 +++++++++ duckscript_sdk/src/sdk/std/collections/mod.rs | 2 + test/std/collections/map_keys_test.ds | 16 ++++ test/std/flowcontrol/for_in_test.ds | 21 +++++ 7 files changed, 192 insertions(+) create mode 100644 duckscript_sdk/src/sdk/std/collections/map_keys/help.md create mode 100755 duckscript_sdk/src/sdk/std/collections/map_keys/mod.rs create mode 100644 duckscript_sdk/src/sdk/std/collections/map_keys/mod_test.rs create mode 100644 test/std/collections/map_keys_test.ds diff --git a/CHANGELOG.md b/CHANGELOG.md index b6fd926..f6450b0 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### v0.3.3 +* New map_keys command. * New temp_dir command. * Runtime - Use default trait. diff --git a/duckscript_sdk/src/sdk/std/collections/map_keys/help.md b/duckscript_sdk/src/sdk/std/collections/map_keys/help.md new file mode 100644 index 0000000..70f6630 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/collections/map_keys/help.md @@ -0,0 +1,33 @@ +```sh +keys = map_keys handle +``` + +Returns a handle to an array holding all keys in the provided map handle. + +#### Parameters + +* The map handle. + +#### Return Value + +A handle to an array holding all map keys. + +#### Examples + +```sh +handle = map + +result = map_put ${handle} key1 value1 +assert_eq ${result} true +result = map_put ${handle} key2 value2 +assert_eq ${result} true + +keys = map_keys ${handle} +for key in ${keys} + value = map_get ${handle} ${key} + echo Key: ${key} Value: ${value} +end + +release ${handle} +release ${keys} +``` diff --git a/duckscript_sdk/src/sdk/std/collections/map_keys/mod.rs b/duckscript_sdk/src/sdk/std/collections/map_keys/mod.rs new file mode 100755 index 0000000..3894e3a --- /dev/null +++ b/duckscript_sdk/src/sdk/std/collections/map_keys/mod.rs @@ -0,0 +1,81 @@ +use crate::utils::pckg; +use crate::utils::state::{get_handles_sub_state, put_handle}; +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, "MapKeys") + } + + fn aliases(&self) -> Vec { + vec!["map_keys".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("Map handle not provided.".to_string()) + } else { + let handles_state = get_handles_sub_state(state); + + match handles_state.get(&arguments[0]) { + Some(state_value) => match state_value { + StateValue::SubState(ref map) => { + let mut array = vec![]; + + for map_key in map.keys() { + array.push(StateValue::String(map_key.to_string())); + } + + let key = put_handle(state, StateValue::List(array)); + + CommandResult::Continue(Some(key)) + } + _ => CommandResult::Error("Invalid handle provided.".to_string()), + }, + None => CommandResult::Error( + format!("Map for handle: {} not found.", &arguments[0]).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/map_keys/mod_test.rs b/duckscript_sdk/src/sdk/std/collections/map_keys/mod_test.rs new file mode 100644 index 0000000..5d91aaf --- /dev/null +++ b/duckscript_sdk/src/sdk/std/collections/map_keys/mod_test.rs @@ -0,0 +1,38 @@ +use super::*; +use crate::sdk::std::collections::{array_pop, map, map_put}; +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 = map_keys", "out"); +} + +#[test] +fn run_not_found() { + test::run_script_and_error(vec![create("")], "out = map_keys bad_handle", "out"); +} + +#[test] +fn run_valid() { + test::run_script_and_validate( + vec![ + create(""), + map::create(""), + map_put::create(""), + array_pop::create(""), + ], + r#" + handle = map + map_put ${handle} a 1 + keys = map_keys ${handle} + out = array_pop ${keys} + "#, + CommandValidation::Match("out".to_string(), "a".to_string()), + ); +} diff --git a/duckscript_sdk/src/sdk/std/collections/mod.rs b/duckscript_sdk/src/sdk/std/collections/mod.rs index b707d7e..35f19e5 100755 --- a/duckscript_sdk/src/sdk/std/collections/mod.rs +++ b/duckscript_sdk/src/sdk/std/collections/mod.rs @@ -13,6 +13,7 @@ mod map; mod map_clear; mod map_get; mod map_is_empty; +mod map_keys; mod map_load_properties; mod map_put; mod map_remove; @@ -46,6 +47,7 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr commands.set(map_clear::create(&package))?; commands.set(map_get::create(&package))?; commands.set(map_is_empty::create(&package)?)?; + commands.set(map_keys::create(&package))?; commands.set(map_load_properties::create(&package))?; commands.set(map_put::create(&package))?; commands.set(map_remove::create(&package))?; diff --git a/test/std/collections/map_keys_test.ds b/test/std/collections/map_keys_test.ds new file mode 100644 index 0000000..ca61ede --- /dev/null +++ b/test/std/collections/map_keys_test.ds @@ -0,0 +1,16 @@ + +fn test_map_keys + handle = map + + result = map_put ${handle} key value + assert_eq ${result} true + + keys = map_keys ${handle} + size = array_length ${keys} + assert_eq ${size} 1 + value = array_pop ${keys} + assert_eq ${value} key + + release ${handle} + release ${keys} +end diff --git a/test/std/flowcontrol/for_in_test.ds b/test/std/flowcontrol/for_in_test.ds index 4e048ee..ada82dd 100644 --- a/test/std/flowcontrol/for_in_test.ds +++ b/test/std/flowcontrol/for_in_test.ds @@ -38,3 +38,24 @@ fn test_range assert_eq ${counter} 100 released = release ${args} end + +fn test_map_keys + handle = map + + result = map_put ${handle} key1 value1 + assert_eq ${result} true + result = map_put ${handle} key2 value2 + assert_eq ${result} true + + keys = map_keys ${handle} + for key in ${keys} + valid = starts_with ${key} key + assert ${valid} + value = map_get ${handle} ${key} + valid = starts_with ${value} value + assert ${valid} + end + + release ${handle} + release ${keys} +end