This commit is contained in:
Greg Johnston 2024-03-08 12:57:32 -05:00
parent 9cdd8cac15
commit db4c1cb4b3
8 changed files with 223 additions and 186 deletions

View file

@ -7,7 +7,7 @@ version.workspace = true
any_spawner = { workspace = true }
either_of = { workspace = true }
reactive_graph = { workspace = true }
tachys = { workspace = true }
tachys = { workspace = true, features = ["reactive_graph"] }
url = "2"
js-sys = { version = "0.3" }
wasm-bindgen = { version = "0.2" }

View file

@ -0,0 +1,52 @@
use crate::RouteData;
use either_of::*;
use tachys::{renderer::Renderer, view::Render};
pub trait ChooseView<R>
where
R: Renderer,
{
type Output: Render<R>;
fn choose(self, route_data: RouteData<R>) -> Self::Output;
}
impl<F, View, R> ChooseView<R> for F
where
F: Fn(RouteData<R>) -> View,
View: Render<R>,
R: Renderer,
{
type Output = View;
fn choose(self, route_data: RouteData<R>) -> Self::Output {
self(route_data)
}
}
impl<R> ChooseView<R> for ()
where
R: Renderer,
{
type Output = ();
fn choose(self, _route_data: RouteData<R>) -> Self::Output {}
}
impl<A, B, Rndr> ChooseView<Rndr> for Either<A, B>
where
A: ChooseView<Rndr>,
B: ChooseView<Rndr>,
Rndr: Renderer,
{
type Output = Either<A::Output, B::Output>;
fn choose(self, route_data: RouteData<Rndr>) -> Self::Output {
match self {
Either::Left(f) => Either::Left(f.choose(route_data)),
Either::Right(f) => Either::Right(f.choose(route_data)),
}
}
}
// TODO add other Either implementations

View file

@ -84,7 +84,6 @@ impl PossibleRouteMatch for WildcardSegment {
mod tests {
use super::PossibleRouteMatch;
use crate::{ParamSegment, StaticSegment, WildcardSegment};
use alloc::vec::Vec;
#[test]
fn single_param_match() {

View file

@ -76,7 +76,6 @@ impl PossibleRouteMatch for StaticSegment {
#[cfg(test)]
mod tests {
use super::{PossibleRouteMatch, StaticSegment};
use alloc::vec::Vec;
#[test]
fn single_static_match() {

View file

@ -1,4 +1,6 @@
mod choose_view;
mod path_segment;
pub use choose_view::*;
pub use path_segment::*;
mod horizontal;
mod nested;
@ -40,12 +42,15 @@ impl<Children, Rndr> Routes<Children, Rndr> {
}
}
impl<'a, Children, Rndr> Routes<Children, Rndr>
impl<Children, Rndr> Routes<Children, Rndr>
where
Rndr: Renderer + 'static,
Children: MatchNestedRoutes<'a, Rndr>,
Children: MatchNestedRoutes<Rndr>,
{
pub fn match_route(&'a self, path: &'a str) -> Option<Children::Match> {
pub fn match_route<'a>(
&'a self,
path: &'a str,
) -> Option<Children::Match<'a>> {
let path = match &self.base {
None => path,
Some(base) => {
@ -72,10 +77,10 @@ where
}
pub fn generate_routes(
&'a self,
&self,
) -> (
Option<&str>,
impl IntoIterator<Item = Vec<PathSegment>> + 'a,
impl IntoIterator<Item = Vec<PathSegment>> + '_,
) {
(self.base.as_deref(), self.children.generate_routes())
}
@ -98,22 +103,27 @@ where
fn to_params(&self) -> Self::Params;
fn into_child(self) -> Option<Self::Child>;
fn to_view(&self) -> impl Fn() -> View;
fn into_view_and_child(
self,
) -> (
impl ChooseView<R, Output = Self::View> + 'a,
Option<Self::Child>,
);
}
pub trait MatchNestedRoutes<'a, R>
pub trait MatchNestedRoutes<R>
where
R: Renderer,
{
type Data;
type Match: MatchInterface<'a, R>;
type Match<'a>: MatchInterface<'a, R>
where
Self: 'a;
fn match_nested(
fn match_nested<'a>(
&'a self,
path: &'a str,
) -> (Option<(RouteMatchId, Self::Match)>, &'a str);
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &str);
fn generate_routes(
&self,
@ -124,14 +134,17 @@ where
mod tests {
use super::{NestedRoute, ParamSegment, Routes};
use crate::{MatchInterface, PathSegment, StaticSegment, WildcardSegment};
use std::marker::PhantomData;
use tachys::renderer::dom::Dom;
#[test]
pub fn matches_single_root_route() {
let routes = Routes::new(NestedRoute {
let routes = Routes::<_, Dom>::new(NestedRoute {
segments: StaticSegment("/"),
children: (),
data: (),
view: || (),
view: |_| (),
rndr: PhantomData,
});
let matched = routes.match_route("/");
assert!(matched.is_some());
@ -151,10 +164,12 @@ mod tests {
segments: (StaticSegment("author"), StaticSegment("contact")),
children: (),
data: (),
view: "Contact Me",
view: |_| "Contact Me",
rndr: PhantomData,
},
data: (),
view: "Home",
view: |_| "Home",
rndr: PhantomData,
});
// route generation
@ -188,9 +203,11 @@ mod tests {
children: (),
data: (),
view: "Contact Me",
rndr: PhantomData,
},
data: (),
view: "Home",
rndr: PhantomData,
});
let matched = routes.match_route("/");
assert!(matched.is_none());
@ -207,16 +224,19 @@ mod tests {
children: (),
data: (),
view: || (),
rndr: PhantomData,
},
NestedRoute {
segments: StaticSegment("about"),
children: (),
data: (),
view: || (),
rndr: PhantomData,
},
),
data: (),
view: || (),
rndr: PhantomData,
},
NestedRoute {
segments: StaticSegment("/blog"),
@ -226,16 +246,19 @@ mod tests {
children: (),
data: (),
view: || (),
rndr: PhantomData,
},
NestedRoute {
segments: (StaticSegment("post"), ParamSegment("id")),
children: (),
data: (),
view: || (),
rndr: PhantomData,
},
),
data: (),
view: || (),
rndr: PhantomData,
},
));
@ -289,16 +312,19 @@ mod tests {
children: (),
data: (),
view: || (),
rndr: PhantomData,
},
NestedRoute {
segments: StaticSegment("about"),
children: (),
data: (),
view: || (),
rndr: PhantomData,
},
),
data: (),
view: || (),
rndr: PhantomData,
},
NestedRoute {
segments: StaticSegment("/blog"),
@ -308,12 +334,14 @@ mod tests {
children: (),
data: (),
view: || (),
rndr: PhantomData,
},
NestedRoute {
segments: StaticSegment("category"),
children: (),
data: (),
view: || (),
rndr: PhantomData,
},
NestedRoute {
segments: (
@ -323,10 +351,12 @@ mod tests {
children: (),
data: (),
view: || (),
rndr: PhantomData,
},
),
data: (),
view: || (),
rndr: PhantomData,
},
NestedRoute {
segments: (
@ -336,6 +366,7 @@ mod tests {
children: (),
data: (),
view: || (),
rndr: PhantomData,
},
),
"/portfolio",

View file

@ -2,21 +2,24 @@ use super::{
MatchInterface, MatchNestedRoutes, PartialPathMatch, PathSegment,
PossibleRouteMatch, RouteMatchId,
};
use crate::{ChooseView, RouteData};
use core::{fmt, iter};
use tachys::renderer::Renderer;
use std::marker::PhantomData;
use tachys::{renderer::Renderer, view::Render};
mod tuples;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct NestedRoute<Segments, Children, Data, View> {
pub struct NestedRoute<Segments, Children, Data, ViewFn, R> {
pub segments: Segments,
pub children: Children,
pub data: Data,
pub view: View,
pub view: ViewFn,
pub rndr: PhantomData<R>,
}
#[derive(PartialEq, Eq)]
pub struct NestedMatch<'a, ParamsIter, Child, ViewFn, View> {
pub struct NestedMatch<'a, ParamsIter, Child, ViewFn> {
id: RouteMatchId,
/// The portion of the full path matched only by this nested route.
matched: &'a str,
@ -24,12 +27,11 @@ pub struct NestedMatch<'a, ParamsIter, Child, ViewFn, View> {
params: ParamsIter,
/// The nested route.
child: Child,
view_fn: ViewFn,
view: View
view_fn: &'a ViewFn,
}
impl<'a, ParamsIter, Child, View> fmt::Debug
for NestedMatch<'a, ParamsIter, Child, View>
impl<'a, ParamsIter, Child, ViewFn> fmt::Debug
for NestedMatch<'a, ParamsIter, Child, ViewFn>
where
ParamsIter: fmt::Debug,
Child: fmt::Debug,
@ -43,16 +45,18 @@ where
}
}
impl<'a, ParamsIter, Child, ViewFn, View, Rndr> MatchInterface<'a, Rndr>
for NestedMatch<'a, ParamsIter, Child, ViewFn, View>
impl<'a, ParamsIter, Child, ViewFn, Rndr> MatchInterface<'a, Rndr>
for NestedMatch<'a, ParamsIter, Child, ViewFn>
where
Rndr: Renderer + 'static,
ParamsIter: IntoIterator<Item = (&'a str, &'a str)> + Clone,
Child: MatchInterface<'a, Rndr>,
ViewFn: Fn(RouteData<Rndr>),
ViewFn::Output: Render<Rndr>,
{
type Params = ParamsIter;
type Child = Child;
type View = View;
type View = ViewFn::Output;
fn as_id(&self) -> RouteMatchId {
self.id
@ -66,43 +70,43 @@ where
self.params.clone()
}
fn into_child(self) -> Option<Self::Child> {
Some(self.child)
}
fn to_view(&self) -> Self::ViewFn {
self.view
fn into_view_and_child(
self,
) -> (
impl ChooseView<Rndr, Output = Self::View> + 'a,
Option<Self::Child>,
) {
(self.view_fn, Some(self.child))
}
}
impl<'a, ParamsIter, Child, View> NestedMatch<'a, ParamsIter, Child, View> {
impl<'a, ParamsIter, Child, ViewFn> NestedMatch<'a, ParamsIter, Child, ViewFn> {
pub fn matched(&self) -> &'a str {
self.matched
}
}
impl<'a, Segments, Children, Data, View, Rndr> MatchNestedRoutes<'a, Rndr>
for NestedRoute<Segments, Children, Data, View>
impl<Segments, Children, Data, ViewFn, Rndr> MatchNestedRoutes<Rndr>
for NestedRoute<Segments, Children, Data, ViewFn, Rndr>
where
Rndr: Renderer + 'static,
Segments: PossibleRouteMatch,
Children: MatchNestedRoutes<'a, Rndr>,
<Segments::ParamsIter<'a> as IntoIterator>::IntoIter: Clone,
<<Children::Match as MatchInterface<'a, Rndr>>::Params as IntoIterator>::IntoIter:
Children: MatchNestedRoutes<Rndr>,
for<'a> <Segments::ParamsIter<'a> as IntoIterator>::IntoIter: Clone,
for <'a> <<Children::Match<'a> as MatchInterface<'a, Rndr>>::Params as IntoIterator>::IntoIter:
Clone,
Children: 'a,
View: 'a,
ViewFn: Fn(RouteData<Rndr>),
{
type Data = Data;
type Match = NestedMatch<'a, iter::Chain<
type Match<'a> = NestedMatch<'a, iter::Chain<
<Segments::ParamsIter<'a> as IntoIterator>::IntoIter,
<<Children::Match as MatchInterface<'a, Rndr>>::Params as IntoIterator>::IntoIter,
>, Children::Match, View>;
<<Children::Match<'a> as MatchInterface<'a, Rndr>>::Params as IntoIterator>::IntoIter,
>, Children::Match<'a>, ViewFn> where <Children as MatchNestedRoutes<Rndr>>::Match<'a>: 'a, ViewFn: 'a, Children: 'a, Segments: 'a, Data: 'a;
fn match_nested(
fn match_nested<'a>(
&'a self,
path: &'a str,
) -> (Option<(RouteMatchId, Self::Match)>, &'a str) {
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &'a str) {
self.segments
.test(path)
.and_then(
@ -125,7 +129,7 @@ where
matched,
params: params.chain(inner.to_params()),
child: inner,
view: &self.view,
view_fn: &self.view,
},
)),
remaining,

View file

@ -1,4 +1,5 @@
use super::{MatchInterface, MatchNestedRoutes, PathSegment, RouteMatchId};
use crate::ChooseView;
use core::iter;
use either_of::*;
use tachys::renderer::Renderer;
@ -23,24 +24,27 @@ where
iter::empty()
}
fn into_child(self) -> Option<Self::Child> {
None
fn into_view_and_child(
self,
) -> (
impl ChooseView<Rndr, Output = Self::View> + 'a,
Option<Self::Child>,
) {
((), None)
}
fn to_view(&self) -> Self::View {}
}
impl<'a, Rndr> MatchNestedRoutes<'a, Rndr> for ()
impl<Rndr> MatchNestedRoutes<Rndr> for ()
where
Rndr: Renderer,
{
type Data = ();
type Match = ();
type Match<'a> = ();
fn match_nested(
fn match_nested<'a>(
&self,
path: &'a str,
) -> (Option<(RouteMatchId, Self::Match)>, &'a str) {
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &'a str) {
(Some((RouteMatchId(0), ())), path)
}
@ -72,27 +76,28 @@ where
self.0.to_params()
}
fn into_child(self) -> Option<Self::Child> {
self.0.into_child()
}
fn to_view(&self) -> Self::View {
self.0.to_view()
fn into_view_and_child(
self,
) -> (
impl ChooseView<Rndr, Output = Self::View> + 'a,
Option<Self::Child>,
) {
self.0.into_view_and_child()
}
}
impl<'a, A, Rndr> MatchNestedRoutes<'a, Rndr> for (A,)
impl<A, Rndr> MatchNestedRoutes<Rndr> for (A,)
where
A: MatchNestedRoutes<'a, Rndr>,
A: MatchNestedRoutes<Rndr>,
Rndr: Renderer,
{
type Data = A::Data;
type Match = A::Match;
type Match<'a> = A::Match<'a> where A: 'a;
fn match_nested(
fn match_nested<'a>(
&'a self,
path: &'a str,
) -> (Option<(RouteMatchId, Self::Match)>, &'a str) {
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &'a str) {
self.0.match_nested(path)
}
@ -105,7 +110,7 @@ where
impl<'a, A, B, Rndr> MatchInterface<'a, Rndr> for Either<A, B>
where
Rndr: Renderer + 'a,
Rndr: Renderer,
A: MatchInterface<'a, Rndr>,
B: MatchInterface<'a, Rndr>,
{
@ -137,34 +142,38 @@ where
}
}
fn into_child(self) -> Option<Self::Child> {
Some(match self {
Either::Left(i) => Either::Left(i.into_child()?),
Either::Right(i) => Either::Right(i.into_child()?),
})
}
fn to_view(&self) -> Self::View {
fn into_view_and_child(
self,
) -> (
impl ChooseView<Rndr, Output = Self::View> + 'a,
Option<Self::Child>,
) {
match self {
Either::Left(i) => Either::Left(i.to_view()),
Either::Right(i) => Either::Right(i.to_view()),
Either::Left(i) => {
let (view, child) = i.into_view_and_child();
(Either::Left(view), child.map(Either::Left))
}
Either::Right(i) => {
let (view, child) = i.into_view_and_child();
(Either::Right(view), child.map(Either::Right))
}
}
}
}
impl<'a, A, B, Rndr> MatchNestedRoutes<'a, Rndr> for (A, B)
impl<A, B, Rndr> MatchNestedRoutes<Rndr> for (A, B)
where
A: MatchNestedRoutes<'a, Rndr>,
B: MatchNestedRoutes<'a, Rndr>,
A: MatchNestedRoutes<Rndr>,
B: MatchNestedRoutes<Rndr>,
Rndr: Renderer + 'static,
{
type Data = (A::Data, B::Data);
type Match = Either<A::Match, B::Match>;
type Match<'a> = Either<A::Match<'a>, B::Match<'a>> where A: 'a, B: 'a;
fn match_nested(
fn match_nested<'a>(
&'a self,
path: &'a str,
) -> (Option<(RouteMatchId, Self::Match)>, &'a str) {
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &'a str) {
#[allow(non_snake_case)]
let (A, B) = &self;
if let (Some((id, matched)), remaining) = A.match_nested(path) {
@ -209,7 +218,6 @@ macro_rules! tuples {
Rndr: Renderer + 'static,
$($ty: MatchInterface<'a, Rndr>),*,
$($ty::Child: 'a),*,
$($ty::View: 'a),*,
{
type Params = $either<$(
<$ty::Params as IntoIterator>::IntoIter,
@ -241,7 +249,7 @@ macro_rules! tuples {
})
}
fn to_view(&self) -> Self::View {
fn to_view(&self) -> impl ChooseView<Rndr, Output = Self::View> {
match self {
$($either::$ty(i) => $either::$ty(i.to_view()),)*
}
@ -282,7 +290,7 @@ macro_rules! tuples {
}
}
}
/*
tuples!(EitherOf3 => A = 0, B = 1, C = 2);
tuples!(EitherOf4 => A = 0, B = 1, C = 2, D = 3);
tuples!(EitherOf5 => A = 0, B = 1, C = 2, D = 3, E = 4);
@ -297,3 +305,4 @@ tuples!(EitherOf13 => A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6, H = 7, I
tuples!(EitherOf14 => A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6, H = 7, I = 8, J = 9, K = 10, L = 11, M = 12, N = 13);
tuples!(EitherOf15 => A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6, H = 7, I = 8, J = 9, K = 10, L = 11, M = 12, N = 13, O = 14);
tuples!(EitherOf16 => A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6, H = 7, I = 8, J = 9, K = 10, L = 11, M = 12, N = 13, O = 14, P = 15);
*/

View file

@ -5,7 +5,7 @@ use crate::{
MatchInterface, MatchNestedRoutes, PossibleRouteMatch, RouteMatchId,
Routes,
},
Params,
ChooseView, Params,
};
use core::marker::PhantomData;
use either_of::*;
@ -84,89 +84,28 @@ where
}
}
trait ChooseView<R>
where
R: Renderer,
{
type Output;
fn choose(self, route_data: RouteData<R>) -> Self::Output;
}
pub struct RouteData<'a, R>
pub struct RouteData<R>
where
R: Renderer,
{
pub params: ArcMemo<Params>,
pub outlet: Box<dyn FnOnce() -> AnyView<R> + 'a>,
pub outlet: Box<dyn FnOnce() -> AnyView<R>>,
}
impl<F, View, R> ChooseView<R> for F
where
F: Fn(RouteData<R>) -> View,
R: Renderer,
{
type Output = View;
fn choose(self, route_data: RouteData<R>) -> Self::Output {
self(route_data)
}
}
impl<R> ChooseView<R> for ()
where
R: Renderer,
{
type Output = ();
fn choose(self, _route_data: RouteData<R>) -> Self::Output {
()
}
}
impl<A, FnA, B, FnB, Rndr> ChooseView<Rndr> for Either<FnA, FnB>
where
FnA: Fn(RouteData<Rndr>) -> A,
FnB: Fn(RouteData<Rndr>) -> B,
Rndr: Renderer,
{
type Output = Either<A, B>;
fn choose(self, route_data: RouteData<Rndr>) -> Self::Output {
match self {
Either::Left(f) => Either::Left(f(route_data)),
Either::Right(f) => Either::Right(f(route_data)),
}
}
}
impl<Rndr, Loc, FallbackFn, Fallback, Children, View> Render<Rndr>
impl<Rndr, Loc, FallbackFn, Fallback, Children> Render<Rndr>
for Router<Rndr, Loc, Children, FallbackFn>
where
Loc: Location,
FallbackFn: Fn() -> Fallback + 'static,
Fallback: Render<Rndr>,
for<'a> Children: MatchNestedRoutes<'a, Rndr> + 'static,
for<'a> <<Children as MatchNestedRoutes<'a, Rndr>>::Match as MatchInterface<
'a,
R,
>>::View: ChooseView<Rndr, Output = View>,
for<'a> <<Children as MatchNestedRoutes<'a, Rndr>>::Match as MatchInterface<
'a,
R,
>>::Child: std::fmt::Debug,
View: Render<Rndr> + IntoAny<Rndr> + 'static,
View::State: 'static,
Children: MatchNestedRoutes<Rndr> + 'static,
/*View: Render<Rndr> + IntoAny<Rndr> + 'static,
View::State: 'static,*/
Fallback::State: 'static,
Rndr: Renderer + 'static,
{
type State = RenderEffect<
EitherState<
NestedRouteState<View::State>,
<Fallback as Render<Rndr>>::State,
Rndr,
>,
>;
type State =
RenderEffect<EitherState<(), <Fallback as Render<Rndr>>::State, Rndr>>;
type FallibleState = ();
fn build(self) -> Self::State {
@ -191,29 +130,33 @@ where
if let Some(new_match) = new_match {
match &mut prev.state {
Either::Left(prev) => {
nested_rebuild(&outer_owner, prev, new_match);
//nested_rebuild(&outer_owner, prev, new_match);
}
Either::Right(_) => {
Either::<_, Fallback>::Left(NestedRouteView::new(
/*Either::<_, Fallback>::Left(NestedRouteView::new(
&outer_owner,
new_match,
))
.rebuild(&mut prev);
.rebuild(&mut prev);*/
}
}
} else {
Either::<NestedRouteView<View, Rndr>, _>::Right((self
/*Either::<NestedRouteView<View, Rndr>, _>::Right((self
.fallback)(
))
.rebuild(&mut prev);
.rebuild(&mut prev);*/
}
prev
} else {
match new_match {
Some(matched) => Either::Left(NestedRouteView::new(
Some(matched) =>
/*Either::Left(NestedRouteView::new(
&outer_owner,
matched,
)),
))*/
{
Either::Left(())
}
_ => Either::Right((self.fallback)()),
}
.build()
@ -235,14 +178,14 @@ where
}
}
fn nested_rebuild<'a, NewMatch, R>(
/*fn nested_rebuild<NewMatch, R>(
outer_owner: &Owner,
current: &mut NestedRouteState<
<<NewMatch::View as ChooseView<R>>::Output as Render<R>>::State,
>,
new: NewMatch,
) where
NewMatch: MatchInterface<'a, R> + 'a,
NewMatch: MatchInterface<R>,
NewMatch::View: ChooseView<R>,
<NewMatch::View as ChooseView<R>>::Output: Render<R> + IntoAny<R> + 'static,
NewMatch::Child: std::fmt::Debug,
@ -270,7 +213,7 @@ fn nested_rebuild<'a, NewMatch, R>(
// update params, in case they're different
// TODO
}
}*/
pub struct NestedRouteView<View, R>
where
@ -288,11 +231,12 @@ impl<View, R> NestedRouteView<View, R>
where
R: Renderer + 'static,
{
pub fn new<'a, Matcher>(outer_owner: &Owner, route_match: Matcher) -> Self
pub fn new<Matcher>(outer_owner: &Owner, route_match: Matcher) -> Self
where
Matcher: MatchInterface<'a, R>,
Matcher::View: ChooseView<R, Output = View>,
Matcher::Child: std::fmt::Debug,
Matcher: for<'a> MatchInterface<'a, R, View = View> + 'static,
for<'a> <Matcher as MatchInterface<'a, R>>::View:
ChooseView<R, Output = View>,
for<'a> <Matcher as MatchInterface<'a, R>>::Child: std::fmt::Debug,
View: IntoAny<R> + 'static,
{
let params = ArcRwSignal::new(
@ -304,14 +248,13 @@ where
);
let matched = ArcRwSignal::new(route_match.as_matched().to_string());
let id = route_match.as_id();
let view = route_match.to_view();
let (view, child) = route_match.into_view_and_child();
let route_data = RouteData {
params: {
let params = params.clone();
ArcMemo::new(move |_| params.get())
},
outlet: Box::new({
let child = route_match.into_child();
move || {
child
.map(|child| {
@ -323,7 +266,6 @@ where
}),
outlet: Box::new(|| ().into_any())
};*/
let view = child.to_view();
format!("{child:?}")
})
.into_any()
@ -413,11 +355,11 @@ where
}
}
trait RouteView<'a, R>: MatchInterface<'a, R>
trait RouteView<R>: for<'a> MatchInterface<'a, R>
where
R: Renderer,
{
type RouteViewChild: RouteView<'a, R>;
type RouteViewChild: RouteView<R>;
type RouteView: Render<R>;
fn into_child(self) -> Option<Self::RouteViewChild>;
@ -429,14 +371,14 @@ where
Loc: Location,
FallbackFn: Fn() -> Fallback + 'static,
Fallback: RenderHtml<Rndr>,
for<'a> Children: MatchNestedRoutes<'a, Rndr> + 'static,
for<'a> <<Children as MatchNestedRoutes<'a, Rndr>>::Match as MatchInterface<
Children: MatchNestedRoutes<Rndr> + 'static,
for<'a> <<Children as MatchNestedRoutes<Rndr>>::Match<'a> as MatchInterface<
'a,
R,
Rndr,
>>::View: ChooseView<Rndr, Output = View>,
for<'a> <<Children as MatchNestedRoutes<'a, Rndr>>::Match as MatchInterface<
for<'a> <<Children as MatchNestedRoutes<Rndr>>::Match<'a> as MatchInterface<
'a,
R,
Rndr,
>>::Child: std::fmt::Debug,
View: Render<Rndr> + IntoAny<Rndr> + 'static,
View::State: 'static,
@ -465,10 +407,10 @@ where
Loc: Location,
FallbackFn: Fn() -> Fallback,
Fallback: Render<Rndr>,
for<'a> Children: MatchNestedRoutes<'a, Rndr>,
for<'a> <<Children as MatchNestedRoutes<'a, Rndr>>::Match as MatchInterface<
Children: MatchNestedRoutes<Rndr>,
for<'a> <<Children as MatchNestedRoutes<Rndr>>::Match<'a> as MatchInterface<
'a,
R,
Rndr,
>>::View: ChooseView<Rndr, Output = View>,
Rndr: Renderer,
Router<Rndr, Loc, Children, FallbackFn>: RenderHtml<Rndr>,
@ -503,6 +445,7 @@ macro_rules! tuples {
where
Rndr: Renderer,
$([<Fn $ty>]: Fn(RouteData<Rndr>) -> $ty,)*
$($ty: Render<Rndr>,)*
{
type Output = $either<$($ty,)*>;