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:
@ -15,7 +15,7 @@ pub(super) fn process_string_enum<T, E>(
|
||||
E: Display,
|
||||
{
|
||||
let span = value.span();
|
||||
if let Ok(v) = value.coerce_string() {
|
||||
if let Ok(v) = value.coerce_str() {
|
||||
match v.parse() {
|
||||
Ok(format) => {
|
||||
*config_point = format;
|
||||
|
@ -539,7 +539,7 @@ impl Value {
|
||||
process_bool_config(value, &mut errors, &mut config.filesize_metric);
|
||||
}
|
||||
"format" => {
|
||||
if let Ok(v) = value.coerce_string() {
|
||||
if let Ok(v) = value.coerce_str() {
|
||||
config.filesize_format = v.to_lowercase();
|
||||
} else {
|
||||
report_invalid_value("should be a string", span, &mut errors);
|
||||
|
@ -272,7 +272,7 @@ pub(super) fn try_parse_trim_strategy(
|
||||
}
|
||||
|
||||
fn try_parse_trim_methodology(value: &Value) -> Option<TrimStrategy> {
|
||||
if let Ok(value) = value.coerce_string() {
|
||||
if let Ok(value) = value.coerce_str() {
|
||||
match value.to_lowercase().as_str() {
|
||||
"wrapping" => {
|
||||
return Some(TrimStrategy::Wrap {
|
||||
|
@ -356,7 +356,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns this `Value` converted to a `String` or an error if it cannot be converted
|
||||
/// Returns this `Value` converted to a `str` or an error if it cannot be converted
|
||||
///
|
||||
/// Only the following `Value` cases will return an `Ok` result:
|
||||
/// - `Int`
|
||||
@ -365,9 +365,56 @@ impl Value {
|
||||
/// - `Binary` (only if valid utf-8)
|
||||
/// - `Date`
|
||||
///
|
||||
/// Prefer [`coerce_into_string`](Self::coerce_into_string)
|
||||
/// ```
|
||||
/// # use nu_protocol::Value;
|
||||
/// for val in Value::test_values() {
|
||||
/// assert_eq!(
|
||||
/// matches!(
|
||||
/// val,
|
||||
/// Value::Int { .. }
|
||||
/// | Value::Float { .. }
|
||||
/// | Value::String { .. }
|
||||
/// | Value::Binary { .. }
|
||||
/// | Value::Date { .. }
|
||||
/// ),
|
||||
/// val.coerce_str().is_ok(),
|
||||
/// );
|
||||
/// }
|
||||
/// ```
|
||||
pub fn coerce_str(&self) -> Result<Cow<str>, ShellError> {
|
||||
match self {
|
||||
Value::Int { val, .. } => Ok(Cow::Owned(val.to_string())),
|
||||
Value::Float { val, .. } => Ok(Cow::Owned(val.to_string())),
|
||||
Value::String { val, .. } => Ok(Cow::Borrowed(val)),
|
||||
Value::Binary { val, .. } => match std::str::from_utf8(val) {
|
||||
Ok(s) => Ok(Cow::Borrowed(s)),
|
||||
Err(_) => self.cant_convert_to("string"),
|
||||
},
|
||||
Value::Date { val, .. } => Ok(Cow::Owned(
|
||||
val.to_rfc3339_opts(chrono::SecondsFormat::Millis, true),
|
||||
)),
|
||||
val => val.cant_convert_to("string"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns this `Value` converted to a `String` or an error if it cannot be converted
|
||||
///
|
||||
/// # Note
|
||||
/// This function is equivalent to `value.coerce_str().map(Cow::into_owned)`
|
||||
/// which might allocate a new `String`.
|
||||
///
|
||||
/// To avoid this allocation, prefer [`coerce_str`](Self::coerce_str)
|
||||
/// if you do not need an owned `String`,
|
||||
/// or [`coerce_into_string`](Self::coerce_into_string)
|
||||
/// if you do not need to keep the original `Value` around.
|
||||
///
|
||||
/// Only the following `Value` cases will return an `Ok` result:
|
||||
/// - `Int`
|
||||
/// - `Float`
|
||||
/// - `String`
|
||||
/// - `Binary` (only if valid utf-8)
|
||||
/// - `Date`
|
||||
///
|
||||
/// ```
|
||||
/// # use nu_protocol::Value;
|
||||
/// for val in Value::test_values() {
|
||||
@ -385,17 +432,7 @@ impl Value {
|
||||
/// }
|
||||
/// ```
|
||||
pub fn coerce_string(&self) -> Result<String, ShellError> {
|
||||
match self {
|
||||
Value::Int { val, .. } => Ok(val.to_string()),
|
||||
Value::Float { val, .. } => Ok(val.to_string()),
|
||||
Value::String { val, .. } => Ok(val.clone()),
|
||||
Value::Binary { val, .. } => match std::str::from_utf8(val) {
|
||||
Ok(s) => Ok(s.to_string()),
|
||||
Err(_) => self.cant_convert_to("string"),
|
||||
},
|
||||
Value::Date { val, .. } => Ok(val.to_rfc3339_opts(chrono::SecondsFormat::Millis, true)),
|
||||
val => val.cant_convert_to("string"),
|
||||
}
|
||||
self.coerce_str().map(Cow::into_owned)
|
||||
}
|
||||
|
||||
/// Returns this `Value` converted to a `String` or an error if it cannot be converted
|
||||
@ -570,13 +607,13 @@ impl Value {
|
||||
|
||||
/// Returns this `Value` as a `u8` slice or an error if it cannot be converted
|
||||
///
|
||||
/// Prefer [`coerce_into_binary`](Self::coerce_into_binary)
|
||||
/// if you do not need to keep the original `Value` around.
|
||||
///
|
||||
/// Only the following `Value` cases will return an `Ok` result:
|
||||
/// - `Binary`
|
||||
/// - `String`
|
||||
///
|
||||
/// Prefer [`coerce_into_binary`](Self::coerce_into_binary)
|
||||
/// if you do not need to keep the original `Value` around.
|
||||
///
|
||||
/// ```
|
||||
/// # use nu_protocol::Value;
|
||||
/// for val in Value::test_values() {
|
||||
|
Reference in New Issue
Block a user