Note that this requires wrapping at the caller side, as shown in this example.
Unfortunately (if I understand right), there is no idiomatic way to do it with zero-cost at runtime.
It's possible to work with the Cow type though. Perhaps that's a feasible solution for you? (Note that this also requires wrapping the value at the caller side.)
Depending on which problem you try to solve (perhaps you could share the context), you might also get away with using Borrow<T> as a bound: it is implemented both by owned types and references and allows you to obtain a reference to T. (I know this is the opposite of what you asked for, but perhaps it helps you anyway with your problem.)
It behaves correct but I was wondering if the to_owned call (or clone call, indirectly) would be a little expensive in term of performance if I had already owned x.
Of what type(s) is x in your example? I guess it could be any type that implements Into<JsValue> plus references to those types?
The idiomatic approach seems to omit .to_owned() in the macro and add it at the caller side, where needed. I'm not sure about that though. It's noisy, but maybe the most idiomatic approach.
P.S.: If you work with arrays, it might be a bit verbose, though, and require .into_iter().map(ToOwned::to_owned).collect::<Vec<_>>() instead of just .to_owned() though:
fn main() {
let vec_with_refs = vec!["Hello", "World"];
let _: Vec<String> = vec_with_refs.into_iter().map(ToOwned::to_owned).collect();
}
Side note: While there is a method Iterator::cloned (and also copied), I don't see a method Iterator::owned (which I missed in the past as well). Maybe such a method could/should be added to std?
The normal way to solve this category of problem is to define a trait for the operation you want to end up with:
trait MyIntoJsValue {
fn into_js_value(self) -> JsValue;
}
impl<T: ToOwned> MyIntoJsValue for &T
where
T::Owned: MyIntoJsValue,
{
fn into_js_value(self) -> JsValue {
self.to_owned().into_js_value()
}
}
impl MyIntoJsValue for String {
fn into_js_value(self) -> JsValue {
JsValue::from(self)
}
}
// and so on...
This avoids needing the condition āis not a referenceā which cannot be generally expressed in current Rust, because it applies to each of the non-reference types individually. It contains no unnecessary clones. The disadvantage, of course, is that if you do have an implementation that applies to āall non-referencesā, you still have to list all the types it applies to.
In the future, this might be solvable with implementation specialization, allowing you to write two blanket implementations for MyIntoJsValue and specify that the non-reference one takes priority where they overlap (which they won't in practice). However, all solutions will probably involve traits, not a compile-time if.
I share the same thoughts. Therefore, I have been looking for a way to add this trait to all types. Thank you for letting me know that it is not possible.
I agree that such features may likely be implemented using traits in the future. I believe these kinds of traits would provide library developers with a powerful tool to create API with reduced syntactic noise. By the way, I was wondering if there are any related RFCs scheduled at the moment. Thank you for your insights.