Repository: nushell/nushell
File: crates/nu-protocol/src/value/from_value.rs (Rust)

Code before:
    fn expected_type() -> Type {
        Type::String
    }
}

impl FromValue for String {
    fn from_value(v: Value) -> Result<Self, ShellError> {
        // FIXME: we may want to fail a little nicer here
        match v {
            Value::CellPath { val, .. } => Ok(val.to_string()),
            Value::String { val, .. } => Ok(val),
            v => Err(ShellError::CantConvert {
                to_type: Self::expected_type().to_string(),
                from_type: v.get_type().to_string(),
                span: v.span(),
                help: None,
            }),
        }
    }

    fn expected_type() -> Type {
        Type::String
    }
}

impl<B> FromValue for Cow<'_, B>
where
    B: ?Sized + ToOwned,
    B::Owned: FromValue,
{
    fn from_value(v: Value) -> Result<Self, ShellError> {
        <B::Owned as FromValue>::from_value(v).map(Cow::Owned)
    }

    fn expected_type() -> Type {
        <B::Owned as FromValue>::expected_type()
    }
}

// This impl is different from Vec<T> as it allows reading from Value::Binary and Value::String too.
// This also denies implementing FromValue for u8 as it would be in conflict with the Vec<T> impl.
impl FromValue for Vec<u8> {
    fn from_value(v: Value) -> Result<Self, ShellError> {
        match v {
            Value::Binary { val, .. } => Ok(val),
            Value::String { val, .. } => Ok(val.into_bytes()),
            Value::List { vals, .. } => {
                const U8MIN: i64 = u8::MIN as i64;
                const U8MAX: i64 = u8::MAX as i64;
                let mut this = Vec::with_capacity(vals.len());
                for val in vals {

Review comment (suggestion):
Minor nit this addition cuts into the logical block of owned container types `PathBuf`/`String`/`Vec<u8>` (which would be the prime candidates via `Cow<'_,Path>`/ `Cow<'_,str>`/ `Cow<'_,[u8]>`

It would make sense leaving the block intact (The general `Vec<T>` is already separated from the rest of those.)

For the less Rust literate it may be worth adding a brief comment a la
```suggestion
// This blanket impl permits the use of `Cow<'_,str/[u8]>` etc. based on the implementations for `String`/`Vec<u8>` 
impl<B> FromValue for Cow<'_, B>
```

Code after:
    fn expected_type() -> Type {
        Type::String
    }
}

impl FromValue for String {
    fn from_value(v: Value) -> Result<Self, ShellError> {
        // FIXME: we may want to fail a little nicer here
        match v {
            Value::CellPath { val, .. } => Ok(val.to_string()),
            Value::String { val, .. } => Ok(val),
            v => Err(ShellError::CantConvert {
                to_type: Self::expected_type().to_string(),
                from_type: v.get_type().to_string(),
                span: v.span(),
                help: None,
            }),
        }
    }

    fn expected_type() -> Type {
        Type::String
    }
}

// This impl is different from Vec<T> as it allows reading from Value::Binary and Value::String too.
// This also denies implementing FromValue for u8 as it would be in conflict with the Vec<T> impl.
impl FromValue for Vec<u8> {
    fn from_value(v: Value) -> Result<Self, ShellError> {
        match v {
            Value::Binary { val, .. } => Ok(val),
            Value::String { val, .. } => Ok(val.into_bytes()),
            Value::List { vals, .. } => {
                const U8MIN: i64 = u8::MIN as i64;
                const U8MAX: i64 = u8::MAX as i64;
                let mut this = Vec::with_capacity(vals.len());
                for val in vals {
                    let span = val.span();
                    let int = i64::from_value(val)?;
                    // calculating -1 on these ranges would be less readable
                    #[allow(overlapping_range_endpoints)]
                    #[allow(clippy::match_overlapping_arm)]
                    match int {
                        U8MIN..=U8MAX => this.push(int as u8),
                        i64::MIN..=U8MIN => return Err(int_too_small_error(int, U8MIN, span)),
                        U8MAX..=i64::MAX => return Err(int_too_large_error(int, U8MAX, span)),
                    };
                }
                Ok(this)
            }
            v => Err(ShellError::CantConvert {