Automatically convert a RouterTarget into a Route (and back)
saschagrunert opened this issue ยท 4 comments
Hey there ๐. First of all thanks for all the efforts on 0.6.0. The new macro looks amazing!
In the old yew router implementation I had some conversion from Route to RouterTarget (and back), like here:
https://github.com/saschagrunert/yew-router/blob/5a641a0cf700c50fb63250404e3a5aa1a8b37d49/src/lib.rs#L18-L43
Do you think we can add this here as well? Because then I could change the route a bit simpler like here: https://github.com/saschagrunert/webapp.rs/pull/579/files#diff-666c67171bd81a247b854ba2bea31b18R61
I believe there exists a function to convert a type that implements Switch into a Route, but calling it in that position would be annoying.
I think that doing blanket impls of impl From<SW> for Route<T> where SW: Switch
and impl TryFrom<Route<T> for SW where SW: Switch
might be possible. The extra T
type parameter on Route may throw a wrench in things, but I'll look into it.
I'm dumb, I had a function to convert SW: Switch
to Route<T>
, and had it public, but neglected to reexport it from the lib module. I've made it permanently private and now have implemented From to convert switches back into routes.
Hey, do you think that we can also implement the conversion back from the derived target to yew_router::route::Route
? This does not seem to be supported for 0.6.1 but would be handy in this place:
This currently results in the error:
error[E0277]: the trait bound `route::RouterTarget: std::convert::From<yew_router::route::Route<()>>` is not satisfied
--> frontend/src/component/root.rs:86:67
|
86 | Message::Route(route) => self.child_component = route.into(),
| ^^^^ the trait `std::convert::From<yew_router::route::Route<()>>` is not implemented for `route::RouterTarget`
|
= note: required because of the requirements on the impl of `std::convert::Into<route::RouterTarget>` for `yew_router::route::Route<()>`
I don't think From
will ever work here, because the operation of converting from the route string to a pre-defined implementer of Switch
is fallible as the route may not match one of the provided matcher strings.
When addressing this PR, the compiler complained about implementing TryFrom<Route<_>>
for T: Switch
, although I don't recall the exact reason. I'll try to re-investigate that though.
In the meantime, calling RouterTarget::switch(route)
should give you an Option<RouterTarget>
. There are patterns for "redirecting" that I haven't adequately documented for calls to switch()
that return None
.
Edit:
I just tried:
impl <SW: Switch, T> TryFrom<Route<T>> for SW {...}
and got the following compiler error messages:
error[E0119]: conflicting implementations of trait `std::convert::TryFrom<route::Route<_>>`:
--> src/switch.rs:224:1
|
224 | impl <SW: Switch, T> TryFrom<Route<T>> for SW {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T, U> std::convert::TryFrom<U> for T
where U: std::convert::Into<T>;
error[E0210]: type parameter `SW` must be used as the type parameter for some local type (e.g., `MyStruct<SW>`)
--> src/switch.rs:224:1
|
224 | impl <SW: Switch, T> TryFrom<Route<T>> for SW {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `SW` must be used as the type parameter for some local type
|
= note: only traits defined in the current crate can be implemented for a type parameter
So this would conflict with the blanket impl, as well as some (overly strict in my opinion) coherence rules. So you are stuck with RouterTarget::switch
for Route -> RouterTarget and Route::from
for RouterTarget -> Route conversions.
It isn't inconceivable that TryFrom
could be implemented by the Switch
derive macro, but seems like non-obvious behavior, so I would rather not.