mirror of
https://github.com/uutils/coreutils
synced 2024-11-16 09:48:03 +00:00
expr: make substr infallible
Instead of returning an Err it should return the "null string" (in our case that's the empty string) when the offset or length is invalid.
This commit is contained in:
parent
4061ada132
commit
218f523e1b
2 changed files with 41 additions and 24 deletions
|
@ -153,7 +153,7 @@ impl AstNode {
|
|||
":" | "match" => operator_match(&operand_values),
|
||||
"length" => Ok(prefix_operator_length(&operand_values)),
|
||||
"index" => Ok(prefix_operator_index(&operand_values)),
|
||||
"substr" => prefix_operator_substr(&operand_values),
|
||||
"substr" => Ok(prefix_operator_substr(&operand_values)),
|
||||
|
||||
_ => Err(format!("operation not implemented: {}", op_type)),
|
||||
},
|
||||
|
@ -522,35 +522,23 @@ fn prefix_operator_index(values: &[String]) -> String {
|
|||
"0".to_string()
|
||||
}
|
||||
|
||||
fn prefix_operator_substr(values: &[String]) -> Result<String, String> {
|
||||
fn prefix_operator_substr(values: &[String]) -> String {
|
||||
assert!(values.len() == 3);
|
||||
let subj = &values[0];
|
||||
let mut idx = match values[1].parse::<i64>() {
|
||||
Ok(i) => i,
|
||||
Err(_) => return Err("expected integer as POS arg to 'substr'".to_string()),
|
||||
let idx = match values[1]
|
||||
.parse::<usize>()
|
||||
.ok()
|
||||
.and_then(|v| v.checked_sub(1))
|
||||
{
|
||||
Some(i) => i,
|
||||
None => return String::new(),
|
||||
};
|
||||
let mut len = match values[2].parse::<i64>() {
|
||||
let len = match values[2].parse::<usize>() {
|
||||
Ok(i) => i,
|
||||
Err(_) => return Err("expected integer as LENGTH arg to 'substr'".to_string()),
|
||||
Err(_) => return String::new(),
|
||||
};
|
||||
|
||||
if idx <= 0 || len <= 0 {
|
||||
return Ok("".to_string());
|
||||
}
|
||||
|
||||
let mut out_str = String::new();
|
||||
for ch in subj.chars() {
|
||||
idx -= 1;
|
||||
if idx <= 0 {
|
||||
if len <= 0 {
|
||||
break;
|
||||
}
|
||||
len -= 1;
|
||||
|
||||
out_str.push(ch);
|
||||
}
|
||||
}
|
||||
Ok(out_str)
|
||||
subj.chars().skip(idx).take(len).collect()
|
||||
}
|
||||
|
||||
fn bool_as_int(b: bool) -> i64 {
|
||||
|
|
|
@ -54,3 +54,32 @@ fn test_and() {
|
|||
|
||||
new_ucmd!().args(&["", "&", "1"]).run().stdout_is("0\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_substr() {
|
||||
new_ucmd!()
|
||||
.args(&["substr", "abc", "1", "1"])
|
||||
.succeeds()
|
||||
.stdout_only("a\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_substr() {
|
||||
new_ucmd!()
|
||||
.args(&["substr", "abc", "0", "1"])
|
||||
.fails()
|
||||
.status_code(1)
|
||||
.stdout_only("\n");
|
||||
|
||||
new_ucmd!()
|
||||
.args(&["substr", "abc", &(std::usize::MAX.to_string() + "0"), "1"])
|
||||
.fails()
|
||||
.status_code(1)
|
||||
.stdout_only("\n");
|
||||
|
||||
new_ucmd!()
|
||||
.args(&["substr", "abc", "0", &(std::usize::MAX.to_string() + "0")])
|
||||
.fails()
|
||||
.status_code(1)
|
||||
.stdout_only("\n");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue