use super::{MethodError, MethodResult, PsString, Val};
impl PsString {
fn args_for_remove_and_substring(
&self,
args: Vec<Val>,
fn_name: &str,
) -> MethodResult<(usize, usize)> {
let PsString(input) = self;
if args.len() != 2 && args.len() != 1 {
return Err(MethodError::new_incorrect_args(fn_name, args));
}
if !matches!(args[0], Val::Int(_)) {
return Err(MethodError::new_incorrect_args(fn_name, args));
}
let start_index = args[0].cast_to_int()? as usize;
let length = if args.len() == 2 {
if !matches!(args[1], Val::Int(_)) {
return Err(MethodError::new_incorrect_args(fn_name, args));
}
let length = args[1].cast_to_int()? as usize;
if start_index + length > input.len() {
return Err(MethodError::Exception(format!(
"Exception calling \"{}\" with \"2\" argument(s): \"Index and length must \
refer to a location within the string. Parameter name: length\"",
fn_name
)));
}
length
} else {
input.len()
};
if start_index > input.len() {
return Err(MethodError::Exception(format!(
"Exception calling \"{}\" with \"1\" argument(s): \"startIndex cannot be larger \
than length of string. Parameter name: startIndex\"",
fn_name
)));
}
let end_index = std::cmp::min(start_index + length, input.len());
Ok((start_index, end_index))
}
pub(super) fn substring(&self, args: Vec<Val>) -> MethodResult<Val> {
let PsString(input) = self;
let (start_index, end_index) = self.args_for_remove_and_substring(args, "Substring")?;
let res = input[start_index..end_index].to_string();
Ok(Val::String(PsString(res)))
}
pub(super) fn remove(&self, args: Vec<Val>) -> MethodResult<Val> {
let PsString(input) = self;
let (start_index, end_index) = self.args_for_remove_and_substring(args, "Remove")?;
let res = input[..start_index].to_string() + &input[end_index..];
Ok(Val::String(PsString(res)))
}
}
#[cfg(test)]
mod tests {
use crate::{PowerShellSession, PsValue};
#[test]
fn substring() {
let mut p = PowerShellSession::new();
let input = r#"
$string = 'hello, world'
$string = $string.substring(1, 4);$string"#;
let script_res = p.parse_script(input).unwrap();
assert_eq!(script_res.result(), PsValue::String("ello".to_string()));
let input = r#"
$string = 'hello, world'
$string = $string.substring(7);$string"#;
let script_res = p.parse_script(input).unwrap();
assert_eq!(script_res.result(), PsValue::String("world".to_string()));
let input = r#"
$string = 'hello, world'
$string = $string.substring(7,5);$string"#;
let script_res = p.parse_script(input).unwrap();
assert_eq!(script_res.result(), PsValue::String("world".to_string()));
let input = r#"
$string = 'hello, world'
$string = $string.substring(7,6);$string"#;
let script_res = p.parse_script(input).unwrap();
assert_eq!(
script_res.errors()[0].to_string(),
"MethodError: Exception calling \"Substring\" with \"2\" argument(s): \"Index and \
length must refer to a location within the string. Parameter name: length\""
.to_string()
);
assert_eq!(
script_res.result(),
PsValue::String(r#""hello, world".substring(7, 6)"#.to_string())
);
let input = r#"
$string = 'hello, world'
$string = $string.substring(12);$string"#;
let script_res = p.parse_script(input).unwrap();
assert_eq!(script_res.result(), PsValue::String("".to_string()));
let input = r#"
$string = 'hello, world'
$string = $string.substring(13);$string"#;
let script_res = p.parse_script(input).unwrap();
assert_eq!(
script_res.errors()[0].to_string(),
"MethodError: Exception calling \"Substring\" with \"1\" argument(s): \"startIndex \
cannot be larger than length of string. Parameter name: startIndex\""
.to_string()
);
let input = r#"
$string = 'hello, world'
$string = $string.substring(5,0);$string"#;
let script_res = p.parse_script(input).unwrap();
assert_eq!(script_res.result(), PsValue::String("".to_string()));
}
#[test]
fn remove() {
let mut p = PowerShellSession::new();
let input = r#"
$string = 'hello, world'
$string = $string.remove(1, 4);$string"#;
let script_res = p.parse_script(input).unwrap();
assert_eq!(script_res.result(), PsValue::String("h, world".to_string()));
let input = r#"
$string = 'hello, world'
$string = $string.remove(7);$string"#;
let script_res = p.parse_script(input).unwrap();
assert_eq!(script_res.result(), PsValue::String("hello, ".to_string()));
let input = r#"
$string = 'hello, world'
$string = $string.remove(7,15);$string"#;
let script_res = p.parse_script(input).unwrap();
assert_eq!(
script_res.result(),
PsValue::String("\"hello, world\".remove(7, 15)".to_string())
);
assert_eq!(
script_res.errors()[0].to_string(),
"MethodError: Exception calling \"Remove\" with \"2\" argument(s): \"Index and length \
must refer to a location within the string. Parameter name: length\""
.to_string()
);
}
}