use error::MinusOneResult;
use ps::Powershell::{Array, Raw};
use ps::Value::Str;
use ps::{Powershell, Value};
use rule::RuleMut;
use tree::{ControlFlow, NodeMut};
fn get_at_index(s: &str, index: i64) -> Option<String> {
let mut uz_index = index as usize;
if index < 0 {
uz_index = (s.len() as i64 + index) as usize;
}
s.chars().nth(uz_index).map(|c| c.to_string())
}
fn get_array_at_index(s: &Vec<Value>, index: i64) -> Option<&Value> {
let mut uz_index = index as usize;
if index < 0 {
uz_index = (s.len() as i64 + index) as usize;
}
s.get(uz_index)
}
#[derive(Default)]
pub struct AccessString;
impl<'a> RuleMut<'a> for AccessString {
type Language = Powershell;
fn enter(
&mut self,
_node: &mut NodeMut<'a, Self::Language>,
_flow: ControlFlow,
) -> MinusOneResult<()> {
Ok(())
}
fn leave(
&mut self,
node: &mut NodeMut<'a, Self::Language>,
_flow: ControlFlow,
) -> MinusOneResult<()> {
let view = node.view();
if view.kind() == "element_access" {
if let (Some(element), Some(expression)) = (view.child(0), view.child(2)) {
match (element.data(), expression.data()) {
(Some(Raw(Str(string_element))), Some(Array(index))) => {
let mut result = vec![];
for index_value in index {
if let Some(parsed_index_value) = index_value.clone().to_i64() {
if let Some(string_result) =
get_at_index(string_element, parsed_index_value)
{
result.push(Str(string_result));
}
}
}
node.set(Array(result));
}
(Some(Raw(Str(string_element))), Some(Raw(index_value))) => {
if let Some(parsed_index_value) = index_value.clone().to_i64() {
if let Some(string_result) =
get_at_index(string_element, parsed_index_value)
{
node.set(Raw(Str(string_result)));
}
}
}
_ => {}
}
}
}
Ok(())
}
}
#[derive(Default)]
pub struct AccessArray;
impl<'a> RuleMut<'a> for AccessArray {
type Language = Powershell;
fn enter(
&mut self,
_node: &mut NodeMut<'a, Self::Language>,
_flow: ControlFlow,
) -> MinusOneResult<()> {
Ok(())
}
fn leave(
&mut self,
node: &mut NodeMut<'a, Self::Language>,
_flow: ControlFlow,
) -> MinusOneResult<()> {
let view = node.view();
if view.kind() == "element_access" {
if let (Some(element), Some(expression)) = (view.child(0), view.child(2)) {
match (element.data(), expression.data()) {
(Some(Array(array_element)), Some(Array(index))) => {
let mut result = vec![];
for index_value in index {
if let Some(parsed_index_value) = index_value.clone().to_i64() {
if let Some(value) =
get_array_at_index(array_element, parsed_index_value)
{
result.push(value.clone());
}
}
}
node.set(Array(result));
}
(Some(Array(array_element)), Some(Raw(index_value))) => {
if let Some(parsed_index_value) = index_value.clone().to_i64() {
if let Some(value) =
get_array_at_index(array_element, parsed_index_value)
{
node.set(Raw(value.clone()));
}
}
}
_ => {}
}
}
}
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
use ps::array::ParseArrayLiteral;
use ps::build_powershell_tree;
use ps::forward::Forward;
use ps::integer::ParseInt;
use ps::string::ParseString;
#[test]
fn test_access_string_element_from_int() {
let mut tree = build_powershell_tree("'abc'[0, 1]").unwrap();
tree.apply_mut(&mut (
ParseInt::default(),
Forward::default(),
ParseString::default(),
AccessString::default(),
ParseArrayLiteral::default(),
))
.unwrap();
assert_eq!(
*tree
.root()
.unwrap()
.child(0)
.unwrap()
.child(0)
.unwrap()
.data()
.expect("Inferred type"),
Array(vec![Str("a".to_string()), Str("b".to_string())])
);
}
#[test]
fn test_access_string_element_from_negative_int() {
let mut tree = build_powershell_tree("'abc'[-2, -1]").unwrap();
tree.apply_mut(&mut (
ParseInt::default(),
Forward::default(),
ParseString::default(),
AccessString::default(),
ParseArrayLiteral::default(),
))
.unwrap();
assert_eq!(
*tree
.root()
.unwrap()
.child(0)
.unwrap()
.child(0)
.unwrap()
.data()
.expect("Inferred type"),
Array(vec![Str("b".to_string()), Str("c".to_string())])
);
}
#[test]
fn test_access_string_element_from_negative_string() {
let mut tree = build_powershell_tree("'abc'['-2']").unwrap();
tree.apply_mut(&mut (
ParseInt::default(),
Forward::default(),
ParseString::default(),
AccessString::default(),
))
.unwrap();
assert_eq!(
*tree
.root()
.unwrap()
.child(0)
.unwrap()
.child(0)
.unwrap()
.data()
.expect("Inferred type"),
Raw(Str("b".to_string()))
);
}
#[test]
fn test_access_string_element_from_string() {
let mut tree = build_powershell_tree("'abc'['0']").unwrap();
tree.apply_mut(&mut (
ParseInt::default(),
Forward::default(),
ParseString::default(),
AccessString::default(),
))
.unwrap();
assert_eq!(
*tree
.root()
.unwrap()
.child(0)
.unwrap()
.child(0)
.unwrap()
.data()
.expect("Inferred type"),
Raw(Str("a".to_string()))
);
}
#[test]
fn test_access_string_multi_element_from_int() {
let mut tree = build_powershell_tree("'abc'[1, 2]").unwrap();
tree.apply_mut(&mut (
ParseInt::default(),
Forward::default(),
ParseString::default(),
AccessString::default(),
ParseArrayLiteral::default(),
))
.unwrap();
assert_eq!(
*tree
.root()
.unwrap()
.child(0)
.unwrap()
.child(0)
.unwrap()
.data()
.expect("Inferred type"),
Array(vec![Str("b".to_string()), Str("c".to_string())])
);
}
}