Skip to content

Add std::borrow::Cow::map(self, b: B, o: O) -> Cow<'_, U> #1958

@algosul

Description

@algosul

Why not add a method std::borrow::Cow::map(self, b: B, o: O) -> Cow<'_, U>.

The cause of the problem:

  • I was writing a program to launch an external program. When adding a large number of parameters, I wanted to convert [Cow<'_, str>] to [Cow<'_, OsStr>], but I had to write the match expression every time. It was too cumbersome.
  • Using format!() returns a String, and when using a path, there is a PathBuf, but Command::args requires an IntoIterator<Item=impl AsRef<OsStr>>.

Here are some problems:

  • When shortening the lifetime of Cow, it is OK to have 'b or not. So is it possible to not have 'b?
  • For consistency, should we add the same functionality to Result?
  • Since the transformations of Cow must be performed concurrently, it is not possible to have map and map_err like Result.
  • If you want to rename it, what should it be called?
  • If two method bodies are exactly the same, should a macro be added?
    fn inner_into_os_str<'a, 'b, T: ToOwned>(source: Cow<'a, T>) -> Cow<'b, OsStr>
    where
      T::Owned: Into<OsString>,
      &'a T: Into<&'b OsStr>,
    {
      // But the trait `From<&str>` is not implemented for `&OsStr` !!!
      source.map(copy_fn!(Into::into)) // source.map(Into::<&'b OsStr>::into, Into::<OsString>::into)
    }
  • Why not add From<&str> for &OsStr?

Example

use std::borrow::Cow;

pub trait CowExt<'a, T: ?Sized + ToOwned + 'a>
{
  fn map_ref_or_owned<'b, U: ?Sized + ToOwned, B, O>(self, b: B, o: O) -> Cow<'b, U>
  where
    B: FnOnce(&'a T) -> &'b U,
    O: FnOnce(T::Owned) -> U::Owned;
  fn map_to_cow<'b, U: ?Sized + ToOwned, B, O>(self, b: B, o: O) -> Cow<'b, U>
  where
    B: FnOnce(&'a T) -> Cow<'b, U>,
    O: FnOnce(T::Owned) -> Cow<'b, U>;
}
impl<'a, T: ?Sized + ToOwned> CowExt<'a, T> for Cow<'a, T>
{
  fn map_ref_or_owned<'b, U: ?Sized + ToOwned, B, O>(self, b: B, o: O) -> Cow<'b, U>
  where
    B: FnOnce(&'a T) -> &'b U,
    O: FnOnce(T::Owned) -> U::Owned,
  {
    match self
    {
      Cow::Borrowed(borrow) => Cow::Borrowed(b(borrow)),
      Cow::Owned(owned) => Cow::Owned(o(owned)),
    }
  }

  fn map_to_cow<'b, U: ?Sized + ToOwned, B, O>(self, b: B, o: O) -> Cow<'b, U>
  where
    B: FnOnce(&'a T) -> Cow<'b, U>,
    O: FnOnce(T::Owned) -> Cow<'b, U>,
  {
    match self
    {
      Cow::Borrowed(borrow) => b(borrow),
      Cow::Owned(owned) => o(owned),
    }
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions