Add some methods for std::borrow::Cow
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
Iterator<Item=Cow<'_, ...>> to Iterator<Item=Cow<'_, OsStr>>, but I had to write the match expression every time. It was too cumbersome.
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:
- Is it possible to remove the lifetime
'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?
- Why not add From<&str> for &OsStr?
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)
}
Example
use std::borrow::Cow;
use std::ffi::OsStr;
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),
}
}
}
fn main(){
let cow = Cow::Borrow("test");
let cow : Cow<'_, OsStr> = cow.map_ref_or_owned(AsRef::as_ref, Into::into);
let cow = Cow::Borrow(std::path::Path::new("test/"));
let cow : Cow<'_, OsStr> = cow.map_ref_or_owned(AsRef::as_ref, Into::into);
}