stash
This commit is contained in:
parent
9cdd8cac15
commit
db4c1cb4b3
|
@ -7,7 +7,7 @@ version.workspace = true
|
||||||
any_spawner = { workspace = true }
|
any_spawner = { workspace = true }
|
||||||
either_of = { workspace = true }
|
either_of = { workspace = true }
|
||||||
reactive_graph = { workspace = true }
|
reactive_graph = { workspace = true }
|
||||||
tachys = { workspace = true }
|
tachys = { workspace = true, features = ["reactive_graph"] }
|
||||||
url = "2"
|
url = "2"
|
||||||
js-sys = { version = "0.3" }
|
js-sys = { version = "0.3" }
|
||||||
wasm-bindgen = { version = "0.2" }
|
wasm-bindgen = { version = "0.2" }
|
||||||
|
|
|
@ -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
|
|
@ -84,7 +84,6 @@ impl PossibleRouteMatch for WildcardSegment {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::PossibleRouteMatch;
|
use super::PossibleRouteMatch;
|
||||||
use crate::{ParamSegment, StaticSegment, WildcardSegment};
|
use crate::{ParamSegment, StaticSegment, WildcardSegment};
|
||||||
use alloc::vec::Vec;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn single_param_match() {
|
fn single_param_match() {
|
||||||
|
|
|
@ -76,7 +76,6 @@ impl PossibleRouteMatch for StaticSegment {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{PossibleRouteMatch, StaticSegment};
|
use super::{PossibleRouteMatch, StaticSegment};
|
||||||
use alloc::vec::Vec;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn single_static_match() {
|
fn single_static_match() {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
mod choose_view;
|
||||||
mod path_segment;
|
mod path_segment;
|
||||||
|
pub use choose_view::*;
|
||||||
pub use path_segment::*;
|
pub use path_segment::*;
|
||||||
mod horizontal;
|
mod horizontal;
|
||||||
mod nested;
|
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
|
where
|
||||||
Rndr: Renderer + 'static,
|
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 {
|
let path = match &self.base {
|
||||||
None => path,
|
None => path,
|
||||||
Some(base) => {
|
Some(base) => {
|
||||||
|
@ -72,10 +77,10 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_routes(
|
pub fn generate_routes(
|
||||||
&'a self,
|
&self,
|
||||||
) -> (
|
) -> (
|
||||||
Option<&str>,
|
Option<&str>,
|
||||||
impl IntoIterator<Item = Vec<PathSegment>> + 'a,
|
impl IntoIterator<Item = Vec<PathSegment>> + '_,
|
||||||
) {
|
) {
|
||||||
(self.base.as_deref(), self.children.generate_routes())
|
(self.base.as_deref(), self.children.generate_routes())
|
||||||
}
|
}
|
||||||
|
@ -98,22 +103,27 @@ where
|
||||||
|
|
||||||
fn to_params(&self) -> Self::Params;
|
fn to_params(&self) -> Self::Params;
|
||||||
|
|
||||||
fn into_child(self) -> Option<Self::Child>;
|
fn into_view_and_child(
|
||||||
|
self,
|
||||||
fn to_view(&self) -> impl Fn() -> View;
|
) -> (
|
||||||
|
impl ChooseView<R, Output = Self::View> + 'a,
|
||||||
|
Option<Self::Child>,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MatchNestedRoutes<'a, R>
|
pub trait MatchNestedRoutes<R>
|
||||||
where
|
where
|
||||||
R: Renderer,
|
R: Renderer,
|
||||||
{
|
{
|
||||||
type Data;
|
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,
|
&'a self,
|
||||||
path: &'a str,
|
path: &'a str,
|
||||||
) -> (Option<(RouteMatchId, Self::Match)>, &'a str);
|
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &str);
|
||||||
|
|
||||||
fn generate_routes(
|
fn generate_routes(
|
||||||
&self,
|
&self,
|
||||||
|
@ -124,14 +134,17 @@ where
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{NestedRoute, ParamSegment, Routes};
|
use super::{NestedRoute, ParamSegment, Routes};
|
||||||
use crate::{MatchInterface, PathSegment, StaticSegment, WildcardSegment};
|
use crate::{MatchInterface, PathSegment, StaticSegment, WildcardSegment};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use tachys::renderer::dom::Dom;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn matches_single_root_route() {
|
pub fn matches_single_root_route() {
|
||||||
let routes = Routes::new(NestedRoute {
|
let routes = Routes::<_, Dom>::new(NestedRoute {
|
||||||
segments: StaticSegment("/"),
|
segments: StaticSegment("/"),
|
||||||
children: (),
|
children: (),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: |_| (),
|
||||||
|
rndr: PhantomData,
|
||||||
});
|
});
|
||||||
let matched = routes.match_route("/");
|
let matched = routes.match_route("/");
|
||||||
assert!(matched.is_some());
|
assert!(matched.is_some());
|
||||||
|
@ -151,10 +164,12 @@ mod tests {
|
||||||
segments: (StaticSegment("author"), StaticSegment("contact")),
|
segments: (StaticSegment("author"), StaticSegment("contact")),
|
||||||
children: (),
|
children: (),
|
||||||
data: (),
|
data: (),
|
||||||
view: "Contact Me",
|
view: |_| "Contact Me",
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
data: (),
|
data: (),
|
||||||
view: "Home",
|
view: |_| "Home",
|
||||||
|
rndr: PhantomData,
|
||||||
});
|
});
|
||||||
|
|
||||||
// route generation
|
// route generation
|
||||||
|
@ -188,9 +203,11 @@ mod tests {
|
||||||
children: (),
|
children: (),
|
||||||
data: (),
|
data: (),
|
||||||
view: "Contact Me",
|
view: "Contact Me",
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
data: (),
|
data: (),
|
||||||
view: "Home",
|
view: "Home",
|
||||||
|
rndr: PhantomData,
|
||||||
});
|
});
|
||||||
let matched = routes.match_route("/");
|
let matched = routes.match_route("/");
|
||||||
assert!(matched.is_none());
|
assert!(matched.is_none());
|
||||||
|
@ -207,16 +224,19 @@ mod tests {
|
||||||
children: (),
|
children: (),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: || (),
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
NestedRoute {
|
NestedRoute {
|
||||||
segments: StaticSegment("about"),
|
segments: StaticSegment("about"),
|
||||||
children: (),
|
children: (),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: || (),
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: || (),
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
NestedRoute {
|
NestedRoute {
|
||||||
segments: StaticSegment("/blog"),
|
segments: StaticSegment("/blog"),
|
||||||
|
@ -226,16 +246,19 @@ mod tests {
|
||||||
children: (),
|
children: (),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: || (),
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
NestedRoute {
|
NestedRoute {
|
||||||
segments: (StaticSegment("post"), ParamSegment("id")),
|
segments: (StaticSegment("post"), ParamSegment("id")),
|
||||||
children: (),
|
children: (),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: || (),
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: || (),
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -289,16 +312,19 @@ mod tests {
|
||||||
children: (),
|
children: (),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: || (),
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
NestedRoute {
|
NestedRoute {
|
||||||
segments: StaticSegment("about"),
|
segments: StaticSegment("about"),
|
||||||
children: (),
|
children: (),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: || (),
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: || (),
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
NestedRoute {
|
NestedRoute {
|
||||||
segments: StaticSegment("/blog"),
|
segments: StaticSegment("/blog"),
|
||||||
|
@ -308,12 +334,14 @@ mod tests {
|
||||||
children: (),
|
children: (),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: || (),
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
NestedRoute {
|
NestedRoute {
|
||||||
segments: StaticSegment("category"),
|
segments: StaticSegment("category"),
|
||||||
children: (),
|
children: (),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: || (),
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
NestedRoute {
|
NestedRoute {
|
||||||
segments: (
|
segments: (
|
||||||
|
@ -323,10 +351,12 @@ mod tests {
|
||||||
children: (),
|
children: (),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: || (),
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: || (),
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
NestedRoute {
|
NestedRoute {
|
||||||
segments: (
|
segments: (
|
||||||
|
@ -336,6 +366,7 @@ mod tests {
|
||||||
children: (),
|
children: (),
|
||||||
data: (),
|
data: (),
|
||||||
view: || (),
|
view: || (),
|
||||||
|
rndr: PhantomData,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
"/portfolio",
|
"/portfolio",
|
||||||
|
|
|
@ -2,21 +2,24 @@ use super::{
|
||||||
MatchInterface, MatchNestedRoutes, PartialPathMatch, PathSegment,
|
MatchInterface, MatchNestedRoutes, PartialPathMatch, PathSegment,
|
||||||
PossibleRouteMatch, RouteMatchId,
|
PossibleRouteMatch, RouteMatchId,
|
||||||
};
|
};
|
||||||
|
use crate::{ChooseView, RouteData};
|
||||||
use core::{fmt, iter};
|
use core::{fmt, iter};
|
||||||
use tachys::renderer::Renderer;
|
use std::marker::PhantomData;
|
||||||
|
use tachys::{renderer::Renderer, view::Render};
|
||||||
|
|
||||||
mod tuples;
|
mod tuples;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[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 segments: Segments,
|
||||||
pub children: Children,
|
pub children: Children,
|
||||||
pub data: Data,
|
pub data: Data,
|
||||||
pub view: View,
|
pub view: ViewFn,
|
||||||
|
pub rndr: PhantomData<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
pub struct NestedMatch<'a, ParamsIter, Child, ViewFn, View> {
|
pub struct NestedMatch<'a, ParamsIter, Child, ViewFn> {
|
||||||
id: RouteMatchId,
|
id: RouteMatchId,
|
||||||
/// The portion of the full path matched only by this nested route.
|
/// The portion of the full path matched only by this nested route.
|
||||||
matched: &'a str,
|
matched: &'a str,
|
||||||
|
@ -24,12 +27,11 @@ pub struct NestedMatch<'a, ParamsIter, Child, ViewFn, View> {
|
||||||
params: ParamsIter,
|
params: ParamsIter,
|
||||||
/// The nested route.
|
/// The nested route.
|
||||||
child: Child,
|
child: Child,
|
||||||
view_fn: ViewFn,
|
view_fn: &'a ViewFn,
|
||||||
view: View
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, ParamsIter, Child, View> fmt::Debug
|
impl<'a, ParamsIter, Child, ViewFn> fmt::Debug
|
||||||
for NestedMatch<'a, ParamsIter, Child, View>
|
for NestedMatch<'a, ParamsIter, Child, ViewFn>
|
||||||
where
|
where
|
||||||
ParamsIter: fmt::Debug,
|
ParamsIter: fmt::Debug,
|
||||||
Child: fmt::Debug,
|
Child: fmt::Debug,
|
||||||
|
@ -43,16 +45,18 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, ParamsIter, Child, ViewFn, View, Rndr> MatchInterface<'a, Rndr>
|
impl<'a, ParamsIter, Child, ViewFn, Rndr> MatchInterface<'a, Rndr>
|
||||||
for NestedMatch<'a, ParamsIter, Child, ViewFn, View>
|
for NestedMatch<'a, ParamsIter, Child, ViewFn>
|
||||||
where
|
where
|
||||||
Rndr: Renderer + 'static,
|
Rndr: Renderer + 'static,
|
||||||
ParamsIter: IntoIterator<Item = (&'a str, &'a str)> + Clone,
|
ParamsIter: IntoIterator<Item = (&'a str, &'a str)> + Clone,
|
||||||
Child: MatchInterface<'a, Rndr>,
|
Child: MatchInterface<'a, Rndr>,
|
||||||
|
ViewFn: Fn(RouteData<Rndr>),
|
||||||
|
ViewFn::Output: Render<Rndr>,
|
||||||
{
|
{
|
||||||
type Params = ParamsIter;
|
type Params = ParamsIter;
|
||||||
type Child = Child;
|
type Child = Child;
|
||||||
type View = View;
|
type View = ViewFn::Output;
|
||||||
|
|
||||||
fn as_id(&self) -> RouteMatchId {
|
fn as_id(&self) -> RouteMatchId {
|
||||||
self.id
|
self.id
|
||||||
|
@ -66,43 +70,43 @@ where
|
||||||
self.params.clone()
|
self.params.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_child(self) -> Option<Self::Child> {
|
fn into_view_and_child(
|
||||||
Some(self.child)
|
self,
|
||||||
}
|
) -> (
|
||||||
|
impl ChooseView<Rndr, Output = Self::View> + 'a,
|
||||||
fn to_view(&self) -> Self::ViewFn {
|
Option<Self::Child>,
|
||||||
self.view
|
) {
|
||||||
|
(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 {
|
pub fn matched(&self) -> &'a str {
|
||||||
self.matched
|
self.matched
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Segments, Children, Data, View, Rndr> MatchNestedRoutes<'a, Rndr>
|
impl<Segments, Children, Data, ViewFn, Rndr> MatchNestedRoutes<Rndr>
|
||||||
for NestedRoute<Segments, Children, Data, View>
|
for NestedRoute<Segments, Children, Data, ViewFn, Rndr>
|
||||||
where
|
where
|
||||||
Rndr: Renderer + 'static,
|
Rndr: Renderer + 'static,
|
||||||
Segments: PossibleRouteMatch,
|
Segments: PossibleRouteMatch,
|
||||||
Children: MatchNestedRoutes<'a, Rndr>,
|
Children: MatchNestedRoutes<Rndr>,
|
||||||
<Segments::ParamsIter<'a> as IntoIterator>::IntoIter: Clone,
|
for<'a> <Segments::ParamsIter<'a> as IntoIterator>::IntoIter: Clone,
|
||||||
<<Children::Match as MatchInterface<'a, Rndr>>::Params as IntoIterator>::IntoIter:
|
for <'a> <<Children::Match<'a> as MatchInterface<'a, Rndr>>::Params as IntoIterator>::IntoIter:
|
||||||
Clone,
|
Clone,
|
||||||
Children: 'a,
|
ViewFn: Fn(RouteData<Rndr>),
|
||||||
View: 'a,
|
|
||||||
{
|
{
|
||||||
type Data = Data;
|
type Data = Data;
|
||||||
type Match = NestedMatch<'a, iter::Chain<
|
type Match<'a> = NestedMatch<'a, iter::Chain<
|
||||||
<Segments::ParamsIter<'a> as IntoIterator>::IntoIter,
|
<Segments::ParamsIter<'a> as IntoIterator>::IntoIter,
|
||||||
<<Children::Match as MatchInterface<'a, Rndr>>::Params as IntoIterator>::IntoIter,
|
<<Children::Match<'a> as MatchInterface<'a, Rndr>>::Params as IntoIterator>::IntoIter,
|
||||||
>, Children::Match, View>;
|
>, 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,
|
&'a self,
|
||||||
path: &'a str,
|
path: &'a str,
|
||||||
) -> (Option<(RouteMatchId, Self::Match)>, &'a str) {
|
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &'a str) {
|
||||||
self.segments
|
self.segments
|
||||||
.test(path)
|
.test(path)
|
||||||
.and_then(
|
.and_then(
|
||||||
|
@ -125,7 +129,7 @@ where
|
||||||
matched,
|
matched,
|
||||||
params: params.chain(inner.to_params()),
|
params: params.chain(inner.to_params()),
|
||||||
child: inner,
|
child: inner,
|
||||||
view: &self.view,
|
view_fn: &self.view,
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
remaining,
|
remaining,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use super::{MatchInterface, MatchNestedRoutes, PathSegment, RouteMatchId};
|
use super::{MatchInterface, MatchNestedRoutes, PathSegment, RouteMatchId};
|
||||||
|
use crate::ChooseView;
|
||||||
use core::iter;
|
use core::iter;
|
||||||
use either_of::*;
|
use either_of::*;
|
||||||
use tachys::renderer::Renderer;
|
use tachys::renderer::Renderer;
|
||||||
|
@ -23,24 +24,27 @@ where
|
||||||
iter::empty()
|
iter::empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_child(self) -> Option<Self::Child> {
|
fn into_view_and_child(
|
||||||
None
|
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
|
where
|
||||||
Rndr: Renderer,
|
Rndr: Renderer,
|
||||||
{
|
{
|
||||||
type Data = ();
|
type Data = ();
|
||||||
type Match = ();
|
type Match<'a> = ();
|
||||||
|
|
||||||
fn match_nested(
|
fn match_nested<'a>(
|
||||||
&self,
|
&self,
|
||||||
path: &'a str,
|
path: &'a str,
|
||||||
) -> (Option<(RouteMatchId, Self::Match)>, &'a str) {
|
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &'a str) {
|
||||||
(Some((RouteMatchId(0), ())), path)
|
(Some((RouteMatchId(0), ())), path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,27 +76,28 @@ where
|
||||||
self.0.to_params()
|
self.0.to_params()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_child(self) -> Option<Self::Child> {
|
fn into_view_and_child(
|
||||||
self.0.into_child()
|
self,
|
||||||
}
|
) -> (
|
||||||
|
impl ChooseView<Rndr, Output = Self::View> + 'a,
|
||||||
fn to_view(&self) -> Self::View {
|
Option<Self::Child>,
|
||||||
self.0.to_view()
|
) {
|
||||||
|
self.0.into_view_and_child()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, A, Rndr> MatchNestedRoutes<'a, Rndr> for (A,)
|
impl<A, Rndr> MatchNestedRoutes<Rndr> for (A,)
|
||||||
where
|
where
|
||||||
A: MatchNestedRoutes<'a, Rndr>,
|
A: MatchNestedRoutes<Rndr>,
|
||||||
Rndr: Renderer,
|
Rndr: Renderer,
|
||||||
{
|
{
|
||||||
type Data = A::Data;
|
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,
|
&'a self,
|
||||||
path: &'a str,
|
path: &'a str,
|
||||||
) -> (Option<(RouteMatchId, Self::Match)>, &'a str) {
|
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &'a str) {
|
||||||
self.0.match_nested(path)
|
self.0.match_nested(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +110,7 @@ where
|
||||||
|
|
||||||
impl<'a, A, B, Rndr> MatchInterface<'a, Rndr> for Either<A, B>
|
impl<'a, A, B, Rndr> MatchInterface<'a, Rndr> for Either<A, B>
|
||||||
where
|
where
|
||||||
Rndr: Renderer + 'a,
|
Rndr: Renderer,
|
||||||
A: MatchInterface<'a, Rndr>,
|
A: MatchInterface<'a, Rndr>,
|
||||||
B: MatchInterface<'a, Rndr>,
|
B: MatchInterface<'a, Rndr>,
|
||||||
{
|
{
|
||||||
|
@ -137,34 +142,38 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_child(self) -> Option<Self::Child> {
|
fn into_view_and_child(
|
||||||
Some(match self {
|
self,
|
||||||
Either::Left(i) => Either::Left(i.into_child()?),
|
) -> (
|
||||||
Either::Right(i) => Either::Right(i.into_child()?),
|
impl ChooseView<Rndr, Output = Self::View> + 'a,
|
||||||
})
|
Option<Self::Child>,
|
||||||
}
|
) {
|
||||||
|
|
||||||
fn to_view(&self) -> Self::View {
|
|
||||||
match self {
|
match self {
|
||||||
Either::Left(i) => Either::Left(i.to_view()),
|
Either::Left(i) => {
|
||||||
Either::Right(i) => Either::Right(i.to_view()),
|
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
|
where
|
||||||
A: MatchNestedRoutes<'a, Rndr>,
|
A: MatchNestedRoutes<Rndr>,
|
||||||
B: MatchNestedRoutes<'a, Rndr>,
|
B: MatchNestedRoutes<Rndr>,
|
||||||
Rndr: Renderer + 'static,
|
Rndr: Renderer + 'static,
|
||||||
{
|
{
|
||||||
type Data = (A::Data, B::Data);
|
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,
|
&'a self,
|
||||||
path: &'a str,
|
path: &'a str,
|
||||||
) -> (Option<(RouteMatchId, Self::Match)>, &'a str) {
|
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &'a str) {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
let (A, B) = &self;
|
let (A, B) = &self;
|
||||||
if let (Some((id, matched)), remaining) = A.match_nested(path) {
|
if let (Some((id, matched)), remaining) = A.match_nested(path) {
|
||||||
|
@ -209,7 +218,6 @@ macro_rules! tuples {
|
||||||
Rndr: Renderer + 'static,
|
Rndr: Renderer + 'static,
|
||||||
$($ty: MatchInterface<'a, Rndr>),*,
|
$($ty: MatchInterface<'a, Rndr>),*,
|
||||||
$($ty::Child: 'a),*,
|
$($ty::Child: 'a),*,
|
||||||
$($ty::View: 'a),*,
|
|
||||||
{
|
{
|
||||||
type Params = $either<$(
|
type Params = $either<$(
|
||||||
<$ty::Params as IntoIterator>::IntoIter,
|
<$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 {
|
match self {
|
||||||
$($either::$ty(i) => $either::$ty(i.to_view()),)*
|
$($either::$ty(i) => $either::$ty(i.to_view()),)*
|
||||||
}
|
}
|
||||||
|
@ -282,7 +290,7 @@ macro_rules! tuples {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
tuples!(EitherOf3 => A = 0, B = 1, C = 2);
|
tuples!(EitherOf3 => A = 0, B = 1, C = 2);
|
||||||
tuples!(EitherOf4 => A = 0, B = 1, C = 2, D = 3);
|
tuples!(EitherOf4 => A = 0, B = 1, C = 2, D = 3);
|
||||||
tuples!(EitherOf5 => A = 0, B = 1, C = 2, D = 3, E = 4);
|
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!(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!(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);
|
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);
|
||||||
|
*/
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
MatchInterface, MatchNestedRoutes, PossibleRouteMatch, RouteMatchId,
|
MatchInterface, MatchNestedRoutes, PossibleRouteMatch, RouteMatchId,
|
||||||
Routes,
|
Routes,
|
||||||
},
|
},
|
||||||
Params,
|
ChooseView, Params,
|
||||||
};
|
};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use either_of::*;
|
use either_of::*;
|
||||||
|
@ -84,89 +84,28 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ChooseView<R>
|
pub struct RouteData<R>
|
||||||
where
|
|
||||||
R: Renderer,
|
|
||||||
{
|
|
||||||
type Output;
|
|
||||||
|
|
||||||
fn choose(self, route_data: RouteData<R>) -> Self::Output;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RouteData<'a, R>
|
|
||||||
where
|
where
|
||||||
R: Renderer,
|
R: Renderer,
|
||||||
{
|
{
|
||||||
pub params: ArcMemo<Params>,
|
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
|
impl<Rndr, Loc, FallbackFn, Fallback, Children> Render<Rndr>
|
||||||
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>
|
|
||||||
for Router<Rndr, Loc, Children, FallbackFn>
|
for Router<Rndr, Loc, Children, FallbackFn>
|
||||||
where
|
where
|
||||||
Loc: Location,
|
Loc: Location,
|
||||||
FallbackFn: Fn() -> Fallback + 'static,
|
FallbackFn: Fn() -> Fallback + 'static,
|
||||||
Fallback: Render<Rndr>,
|
Fallback: Render<Rndr>,
|
||||||
for<'a> Children: MatchNestedRoutes<'a, Rndr> + 'static,
|
Children: MatchNestedRoutes<Rndr> + 'static,
|
||||||
for<'a> <<Children as MatchNestedRoutes<'a, Rndr>>::Match as MatchInterface<
|
/*View: Render<Rndr> + IntoAny<Rndr> + 'static,
|
||||||
'a,
|
View::State: 'static,*/
|
||||||
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,
|
|
||||||
Fallback::State: 'static,
|
Fallback::State: 'static,
|
||||||
Rndr: Renderer + 'static,
|
Rndr: Renderer + 'static,
|
||||||
{
|
{
|
||||||
type State = RenderEffect<
|
type State =
|
||||||
EitherState<
|
RenderEffect<EitherState<(), <Fallback as Render<Rndr>>::State, Rndr>>;
|
||||||
NestedRouteState<View::State>,
|
|
||||||
<Fallback as Render<Rndr>>::State,
|
|
||||||
Rndr,
|
|
||||||
>,
|
|
||||||
>;
|
|
||||||
type FallibleState = ();
|
type FallibleState = ();
|
||||||
|
|
||||||
fn build(self) -> Self::State {
|
fn build(self) -> Self::State {
|
||||||
|
@ -191,29 +130,33 @@ where
|
||||||
if let Some(new_match) = new_match {
|
if let Some(new_match) = new_match {
|
||||||
match &mut prev.state {
|
match &mut prev.state {
|
||||||
Either::Left(prev) => {
|
Either::Left(prev) => {
|
||||||
nested_rebuild(&outer_owner, prev, new_match);
|
//nested_rebuild(&outer_owner, prev, new_match);
|
||||||
}
|
}
|
||||||
Either::Right(_) => {
|
Either::Right(_) => {
|
||||||
Either::<_, Fallback>::Left(NestedRouteView::new(
|
/*Either::<_, Fallback>::Left(NestedRouteView::new(
|
||||||
&outer_owner,
|
&outer_owner,
|
||||||
new_match,
|
new_match,
|
||||||
))
|
))
|
||||||
.rebuild(&mut prev);
|
.rebuild(&mut prev);*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Either::<NestedRouteView<View, Rndr>, _>::Right((self
|
/*Either::<NestedRouteView<View, Rndr>, _>::Right((self
|
||||||
.fallback)(
|
.fallback)(
|
||||||
))
|
))
|
||||||
.rebuild(&mut prev);
|
.rebuild(&mut prev);*/
|
||||||
}
|
}
|
||||||
prev
|
prev
|
||||||
} else {
|
} else {
|
||||||
match new_match {
|
match new_match {
|
||||||
Some(matched) => Either::Left(NestedRouteView::new(
|
Some(matched) =>
|
||||||
|
/*Either::Left(NestedRouteView::new(
|
||||||
&outer_owner,
|
&outer_owner,
|
||||||
matched,
|
matched,
|
||||||
)),
|
))*/
|
||||||
|
{
|
||||||
|
Either::Left(())
|
||||||
|
}
|
||||||
_ => Either::Right((self.fallback)()),
|
_ => Either::Right((self.fallback)()),
|
||||||
}
|
}
|
||||||
.build()
|
.build()
|
||||||
|
@ -235,14 +178,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nested_rebuild<'a, NewMatch, R>(
|
/*fn nested_rebuild<NewMatch, R>(
|
||||||
outer_owner: &Owner,
|
outer_owner: &Owner,
|
||||||
current: &mut NestedRouteState<
|
current: &mut NestedRouteState<
|
||||||
<<NewMatch::View as ChooseView<R>>::Output as Render<R>>::State,
|
<<NewMatch::View as ChooseView<R>>::Output as Render<R>>::State,
|
||||||
>,
|
>,
|
||||||
new: NewMatch,
|
new: NewMatch,
|
||||||
) where
|
) where
|
||||||
NewMatch: MatchInterface<'a, R> + 'a,
|
NewMatch: MatchInterface<R>,
|
||||||
NewMatch::View: ChooseView<R>,
|
NewMatch::View: ChooseView<R>,
|
||||||
<NewMatch::View as ChooseView<R>>::Output: Render<R> + IntoAny<R> + 'static,
|
<NewMatch::View as ChooseView<R>>::Output: Render<R> + IntoAny<R> + 'static,
|
||||||
NewMatch::Child: std::fmt::Debug,
|
NewMatch::Child: std::fmt::Debug,
|
||||||
|
@ -270,7 +213,7 @@ fn nested_rebuild<'a, NewMatch, R>(
|
||||||
|
|
||||||
// update params, in case they're different
|
// update params, in case they're different
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}*/
|
||||||
|
|
||||||
pub struct NestedRouteView<View, R>
|
pub struct NestedRouteView<View, R>
|
||||||
where
|
where
|
||||||
|
@ -288,11 +231,12 @@ impl<View, R> NestedRouteView<View, R>
|
||||||
where
|
where
|
||||||
R: Renderer + 'static,
|
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
|
where
|
||||||
Matcher: MatchInterface<'a, R>,
|
Matcher: for<'a> MatchInterface<'a, R, View = View> + 'static,
|
||||||
Matcher::View: ChooseView<R, Output = View>,
|
for<'a> <Matcher as MatchInterface<'a, R>>::View:
|
||||||
Matcher::Child: std::fmt::Debug,
|
ChooseView<R, Output = View>,
|
||||||
|
for<'a> <Matcher as MatchInterface<'a, R>>::Child: std::fmt::Debug,
|
||||||
View: IntoAny<R> + 'static,
|
View: IntoAny<R> + 'static,
|
||||||
{
|
{
|
||||||
let params = ArcRwSignal::new(
|
let params = ArcRwSignal::new(
|
||||||
|
@ -304,14 +248,13 @@ where
|
||||||
);
|
);
|
||||||
let matched = ArcRwSignal::new(route_match.as_matched().to_string());
|
let matched = ArcRwSignal::new(route_match.as_matched().to_string());
|
||||||
let id = route_match.as_id();
|
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 {
|
let route_data = RouteData {
|
||||||
params: {
|
params: {
|
||||||
let params = params.clone();
|
let params = params.clone();
|
||||||
ArcMemo::new(move |_| params.get())
|
ArcMemo::new(move |_| params.get())
|
||||||
},
|
},
|
||||||
outlet: Box::new({
|
outlet: Box::new({
|
||||||
let child = route_match.into_child();
|
|
||||||
move || {
|
move || {
|
||||||
child
|
child
|
||||||
.map(|child| {
|
.map(|child| {
|
||||||
|
@ -323,7 +266,6 @@ where
|
||||||
}),
|
}),
|
||||||
outlet: Box::new(|| ().into_any())
|
outlet: Box::new(|| ().into_any())
|
||||||
};*/
|
};*/
|
||||||
let view = child.to_view();
|
|
||||||
format!("{child:?}")
|
format!("{child:?}")
|
||||||
})
|
})
|
||||||
.into_any()
|
.into_any()
|
||||||
|
@ -413,11 +355,11 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait RouteView<'a, R>: MatchInterface<'a, R>
|
trait RouteView<R>: for<'a> MatchInterface<'a, R>
|
||||||
where
|
where
|
||||||
R: Renderer,
|
R: Renderer,
|
||||||
{
|
{
|
||||||
type RouteViewChild: RouteView<'a, R>;
|
type RouteViewChild: RouteView<R>;
|
||||||
type RouteView: Render<R>;
|
type RouteView: Render<R>;
|
||||||
|
|
||||||
fn into_child(self) -> Option<Self::RouteViewChild>;
|
fn into_child(self) -> Option<Self::RouteViewChild>;
|
||||||
|
@ -429,14 +371,14 @@ where
|
||||||
Loc: Location,
|
Loc: Location,
|
||||||
FallbackFn: Fn() -> Fallback + 'static,
|
FallbackFn: Fn() -> Fallback + 'static,
|
||||||
Fallback: RenderHtml<Rndr>,
|
Fallback: RenderHtml<Rndr>,
|
||||||
for<'a> Children: MatchNestedRoutes<'a, Rndr> + 'static,
|
Children: MatchNestedRoutes<Rndr> + 'static,
|
||||||
for<'a> <<Children as MatchNestedRoutes<'a, Rndr>>::Match as MatchInterface<
|
for<'a> <<Children as MatchNestedRoutes<Rndr>>::Match<'a> as MatchInterface<
|
||||||
'a,
|
'a,
|
||||||
R,
|
Rndr,
|
||||||
>>::View: ChooseView<Rndr, Output = View>,
|
>>::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,
|
'a,
|
||||||
R,
|
Rndr,
|
||||||
>>::Child: std::fmt::Debug,
|
>>::Child: std::fmt::Debug,
|
||||||
View: Render<Rndr> + IntoAny<Rndr> + 'static,
|
View: Render<Rndr> + IntoAny<Rndr> + 'static,
|
||||||
View::State: 'static,
|
View::State: 'static,
|
||||||
|
@ -465,10 +407,10 @@ where
|
||||||
Loc: Location,
|
Loc: Location,
|
||||||
FallbackFn: Fn() -> Fallback,
|
FallbackFn: Fn() -> Fallback,
|
||||||
Fallback: Render<Rndr>,
|
Fallback: Render<Rndr>,
|
||||||
for<'a> Children: MatchNestedRoutes<'a, Rndr>,
|
Children: MatchNestedRoutes<Rndr>,
|
||||||
for<'a> <<Children as MatchNestedRoutes<'a, Rndr>>::Match as MatchInterface<
|
for<'a> <<Children as MatchNestedRoutes<Rndr>>::Match<'a> as MatchInterface<
|
||||||
'a,
|
'a,
|
||||||
R,
|
Rndr,
|
||||||
>>::View: ChooseView<Rndr, Output = View>,
|
>>::View: ChooseView<Rndr, Output = View>,
|
||||||
Rndr: Renderer,
|
Rndr: Renderer,
|
||||||
Router<Rndr, Loc, Children, FallbackFn>: RenderHtml<Rndr>,
|
Router<Rndr, Loc, Children, FallbackFn>: RenderHtml<Rndr>,
|
||||||
|
@ -503,6 +445,7 @@ macro_rules! tuples {
|
||||||
where
|
where
|
||||||
Rndr: Renderer,
|
Rndr: Renderer,
|
||||||
$([<Fn $ty>]: Fn(RouteData<Rndr>) -> $ty,)*
|
$([<Fn $ty>]: Fn(RouteData<Rndr>) -> $ty,)*
|
||||||
|
$($ty: Render<Rndr>,)*
|
||||||
{
|
{
|
||||||
type Output = $either<$($ty,)*>;
|
type Output = $either<$($ty,)*>;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue