Add Value::coerce_str (#11885)

# Description
Following #11851, this PR adds one final conversion function for
`Value`. `Value::coerce_str` takes a `&Value` and converts it to a
`Cow<str>`, creating an owned `String` for types that needed converting.
Otherwise, it returns a borrowed `str` for `String` and `Binary`
`Value`s which avoids a clone/allocation. Where possible, `coerce_str`
and `coerce_into_string` should be used instead of `coerce_string`,
since `coerce_string` always allocates a new `String`.
This commit is contained in:
Ian Manske
2024-02-18 16:47:10 +00:00
committed by GitHub
parent fb4251aba7
commit 68fcd71898
34 changed files with 115 additions and 83 deletions

View File

@ -226,7 +226,7 @@ fn detect_columns(
.iter()
.take(end_index)
.skip(start_index)
.map(|v| v.coerce_string().unwrap_or_default())
.map(|v| v.coerce_str().unwrap_or_default())
.join(" ");
let binding = Value::string(combined, Span::unknown());
let last_seg = vals.split_off(end_index);

View File

@ -124,7 +124,7 @@ fn split_chars_helper(v: &Value, name: Span, graphemes: bool) -> Value {
Value::Error { error, .. } => Value::error(*error.clone(), span),
v => {
let v_span = v.span();
if let Ok(s) = v.coerce_string() {
if let Ok(s) = v.coerce_str() {
Value::list(
if graphemes {
s.graphemes(true)

View File

@ -148,7 +148,7 @@ fn split_column_helper(
collapse_empty: bool,
head: Span,
) -> Vec<Value> {
if let Ok(s) = v.coerce_string() {
if let Ok(s) = v.coerce_str() {
let split_result: Vec<_> = separator
.split(&s)
.filter(|x| !(collapse_empty && x.is_empty()))

View File

@ -160,7 +160,7 @@ enum Matcher {
impl Matcher {
pub fn new(regex: bool, lhs: Value) -> Result<Self, ShellError> {
if regex {
Ok(Matcher::Regex(Regex::new(&lhs.coerce_string()?).map_err(
Ok(Matcher::Regex(Regex::new(&lhs.coerce_str()?).map_err(
|e| ShellError::GenericError {
error: "Error with regular expression".into(),
msg: e.to_string(),
@ -180,7 +180,7 @@ impl Matcher {
pub fn compare(&self, rhs: &Value) -> Result<bool, ShellError> {
Ok(match self {
Matcher::Regex(regex) => {
if let Ok(rhs_str) = rhs.coerce_string() {
if let Ok(rhs_str) = rhs.coerce_str() {
regex.is_match(&rhs_str)
} else {
false

View File

@ -152,7 +152,7 @@ fn split_row_helper(v: &Value, regex: &Regex, max_split: Option<usize>, name: Sp
v => {
let v_span = v.span();
if let Ok(s) = v.coerce_string() {
if let Ok(s) = v.coerce_str() {
match max_split {
Some(max_split) => regex
.splitn(&s, max_split)

View File

@ -158,7 +158,7 @@ fn split_words_helper(v: &Value, word_length: Option<usize>, span: Span, graphem
Value::Error { error, .. } => Value::error(*error.clone(), v_span),
v => {
let v_span = v.span();
if let Ok(s) = v.coerce_string() {
if let Ok(s) = v.coerce_str() {
// let splits = s.unicode_words();
// let words = trim_to_words(s);
// let words: Vec<&str> = s.split_whitespace().collect();