forked from extern/nushell
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:
@ -262,7 +262,7 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||
// Let's try dtparse first
|
||||
if matches!(input, Value::String { .. }) && dateformat.is_none() {
|
||||
let span = input.span();
|
||||
if let Ok(input_val) = input.coerce_string() {
|
||||
if let Ok(input_val) = input.coerce_str() {
|
||||
match parse_date_from_string(&input_val, span) {
|
||||
Ok(date) => return Value::date(date, span),
|
||||
Err(_) => {
|
||||
|
@ -142,7 +142,7 @@ impl Iterator for UpdateCellIterator {
|
||||
// for a particular datatype. If it does, it will convert the cell to that datatype.
|
||||
fn process_cell(val: Value, display_as_filesizes: bool, span: Span) -> Result<Value, ShellError> {
|
||||
// step 1: convert value to string
|
||||
let val_str = val.coerce_string().unwrap_or_default();
|
||||
let val_str = val.coerce_str().unwrap_or_default();
|
||||
|
||||
// step 2: bounce string up against regexes
|
||||
if BOOLEAN_RE.is_match(&val_str) {
|
||||
@ -189,7 +189,7 @@ fn process_cell(val: Value, display_as_filesizes: bool, span: Span) -> Result<Va
|
||||
Ok(Value::int(ival, span))
|
||||
}
|
||||
} else if INTEGER_WITH_DELIMS_RE.is_match(&val_str) {
|
||||
let mut val_str = val_str;
|
||||
let mut val_str = val_str.into_owned();
|
||||
val_str.retain(|x| !['_', ','].contains(&x));
|
||||
|
||||
let ival = val_str
|
||||
|
@ -222,9 +222,7 @@ fn move_record_columns(
|
||||
|
||||
// Find indices of columns to be moved
|
||||
for column in columns.iter() {
|
||||
let column_str = column.coerce_string()?;
|
||||
|
||||
if let Some(idx) = record.index_of(&column_str) {
|
||||
if let Some(idx) = record.index_of(&column.coerce_str()?) {
|
||||
column_idx.push(idx);
|
||||
} else {
|
||||
return Err(ShellError::GenericError {
|
||||
|
@ -288,7 +288,7 @@ pub fn sort(
|
||||
.unwrap_or(Ordering::Equal)
|
||||
}
|
||||
} else if natural {
|
||||
match (a.coerce_string(), b.coerce_string()) {
|
||||
match (a.coerce_str(), b.coerce_str()) {
|
||||
(Ok(left), Ok(right)) => compare_str(left, right),
|
||||
_ => Ordering::Equal,
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ pub fn transpose(
|
||||
match &i.get_data_by_key(desc) {
|
||||
Some(x) => {
|
||||
if let Ok(s) = x.coerce_string() {
|
||||
headers.push(s.to_string());
|
||||
headers.push(s);
|
||||
} else {
|
||||
return Err(ShellError::GenericError {
|
||||
error: "Header row needs string headers".into(),
|
||||
|
@ -72,7 +72,7 @@ fn to_url(input: PipelineData, head: Span) -> Result<PipelineData, ShellError> {
|
||||
for (k, v) in val {
|
||||
match v.coerce_string() {
|
||||
Ok(s) => {
|
||||
row_vec.push((k.clone(), s.to_string()));
|
||||
row_vec.push((k.clone(), s));
|
||||
}
|
||||
_ => {
|
||||
return Err(ShellError::UnsupportedInput {
|
||||
|
@ -262,29 +262,29 @@ fn merge_record(record: &Record, head: Span, span: Span) -> Result<PathBuf, Shel
|
||||
|
||||
#[cfg(windows)]
|
||||
if let Some(val) = record.get("prefix") {
|
||||
let p = val.coerce_string()?;
|
||||
let p = val.coerce_str()?;
|
||||
if !p.is_empty() {
|
||||
result.push(p);
|
||||
result.push(p.as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(val) = record.get("parent") {
|
||||
let p = val.coerce_string()?;
|
||||
let p = val.coerce_str()?;
|
||||
if !p.is_empty() {
|
||||
result.push(p);
|
||||
result.push(p.as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
let mut basename = String::new();
|
||||
if let Some(val) = record.get("stem") {
|
||||
let p = val.coerce_string()?;
|
||||
let p = val.coerce_str()?;
|
||||
if !p.is_empty() {
|
||||
basename.push_str(&p);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(val) = record.get("extension") {
|
||||
let p = val.coerce_string()?;
|
||||
let p = val.coerce_str()?;
|
||||
if !p.is_empty() {
|
||||
basename.push('.');
|
||||
basename.push_str(&p);
|
||||
|
@ -738,9 +738,9 @@ fn heavy_lifting(code: Value, escape: bool, osc: bool, call: &Call) -> Result<St
|
||||
});
|
||||
}
|
||||
let code_string = if param_is_string {
|
||||
code.coerce_string().expect("error getting code as string")
|
||||
code.coerce_str().expect("error getting code as string")
|
||||
} else {
|
||||
"".to_string()
|
||||
"".into()
|
||||
};
|
||||
let param_is_valid_string = param_is_string && !code_string.is_empty();
|
||||
if (escape || osc) && (param_is_valid_string) {
|
||||
|
@ -150,7 +150,7 @@ pub fn sort(
|
||||
.unwrap_or(Ordering::Equal)
|
||||
}
|
||||
} else if natural {
|
||||
match (a.coerce_string(), b.coerce_string()) {
|
||||
match (a.coerce_str(), b.coerce_str()) {
|
||||
(Ok(left), Ok(right)) => compare_str(left, right),
|
||||
_ => Ordering::Equal,
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ fn process(
|
||||
new_table_name
|
||||
);
|
||||
for (column_name, column_datatype) in record {
|
||||
match column_datatype.coerce_string()?.as_str() {
|
||||
match column_datatype.coerce_str()?.as_ref() {
|
||||
"int" => {
|
||||
create_stmt.push_str(&format!("{} INTEGER, ", column_name));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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()))
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
Reference in New Issue
Block a user