From b92afb4bd89e9317429e1fef13c31c2a317bc0fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kr=C3=A1l?= <g4rrus@gmail.com> Date: Tue, 10 Oct 2017 00:18:47 +0200 Subject: [PATCH] Fix TODO in is_array function: [1 2 3][0] is now treated as a string * Fixed is_array to return false on "[1 2 3][0]" * Added derive for Copy to IsArrayHelper --- src/parser/assignments/checker.rs | 71 +++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/src/parser/assignments/checker.rs b/src/parser/assignments/checker.rs index ad919bc7..653368e1 100644 --- a/src/parser/assignments/checker.rs +++ b/src/parser/assignments/checker.rs @@ -2,12 +2,54 @@ use super::{Primitive, ReturnValue, TypeError}; use super::super::Expander; use super::super::expand_string; +use std::iter::Iterator; + +#[derive(PartialEq, Clone, Copy)] +enum IsArrayHelper { + Valid(usize), + RootBracketClosed, + Invalid, +} + /// Determines if the supplied value is either an array or a string. /// /// - `[ 1 2 3 ]` = Array /// - `[ 1 2 3 ][1]` = String /// - `string` = String -pub(crate) fn is_array(value: &str) -> bool { value.starts_with('[') && value.ends_with(']') } +pub(crate) fn is_array(value: &str) -> bool { + if value.starts_with('[') && value.ends_with(']') { + !value + .chars() + .scan(IsArrayHelper::Valid(0), |state, x| { + // If previous iteration was RootBracketClosed or Invalid then indicate invalid + if *state == IsArrayHelper::RootBracketClosed || *state == IsArrayHelper::Invalid { + *state = IsArrayHelper::Invalid; + return Some(*state); + } + + if x == '[' { + if let IsArrayHelper::Valid(open) = *state { + *state = IsArrayHelper::Valid(open + 1); + } + } else if x == ']' { + if let IsArrayHelper::Valid(open) = *state { + *state = IsArrayHelper::Valid(open - 1); + } + } + + // if true, root bracket was closed + // => any characters after this one indicate invalid array + if *state == IsArrayHelper::Valid(0) { + *state = IsArrayHelper::RootBracketClosed; + } + + Some(*state) + }) + .any(|x| x == IsArrayHelper::Invalid) + } else { + false + } +} pub(crate) fn is_boolean(value: &str) -> Result<&str, ()> { if ["true", "1", "y"].contains(&value) { @@ -34,11 +76,7 @@ fn is_integer_string(value: ReturnValue) -> Result<ReturnValue, ()> { unreachable!() }; - if is_ok { - Ok(value) - } else { - Err(()) - } + if is_ok { Ok(value) } else { Err(()) } } fn is_float_string(value: ReturnValue) -> Result<ReturnValue, ()> { @@ -48,11 +86,7 @@ fn is_float_string(value: ReturnValue) -> Result<ReturnValue, ()> { unreachable!() }; - if is_ok { - Ok(value) - } else { - Err(()) - } + if is_ok { Ok(value) } else { Err(()) } } fn is_boolean_array(values: &mut ReturnValue) -> bool { @@ -79,11 +113,7 @@ fn is_integer_array(value: ReturnValue) -> Result<ReturnValue, ()> { unreachable!() }; - if is_ok { - Ok(value) - } else { - Err(()) - } + if is_ok { Ok(value) } else { Err(()) } } fn is_float_array(value: ReturnValue) -> Result<ReturnValue, ()> { @@ -93,11 +123,7 @@ fn is_float_array(value: ReturnValue) -> Result<ReturnValue, ()> { unreachable!() }; - if is_ok { - Ok(value) - } else { - Err(()) - } + if is_ok { Ok(value) } else { Err(()) } } fn get_string<E: Expander>(shell: &E, value: &str) -> ReturnValue { @@ -159,8 +185,7 @@ mod test { #[test] fn is_array_() { assert!(is_array("[1 2 3]")); - // TODO: Fix This - // assert!(!is_array("[1 2 3][0]")); + assert!(!is_array("[1 2 3][0]")); assert!(!is_array("string")); assert!(is_array("[1 [2 3] 4 [5 6]]")) } -- GitLab