mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 14:54:16 +00:00
work on routing utils
This commit is contained in:
parent
4d3fb37b35
commit
21e53042e8
6 changed files with 207 additions and 130 deletions
|
@ -15,9 +15,14 @@ pub use static_segment::*;
|
|||
/// as subsequent segments of the URL and tries to match them all. For a "vertical"
|
||||
/// matching that sees a tuple as alternatives to one another, see [`RouteChild`](super::RouteChild).
|
||||
pub trait PossibleRouteMatch {
|
||||
type ParamsIter<'a>: IntoIterator<Item = (&'a str, &'a str)>;
|
||||
|
||||
fn matches<'a>(&self, path: &'a str) -> Option<&'a str>;
|
||||
|
||||
fn test<'a>(&self, path: &'a str) -> Option<PartialPathMatch<'a>>;
|
||||
fn test<'a>(
|
||||
&self,
|
||||
path: &'a str,
|
||||
) -> Option<PartialPathMatch<'a, Self::ParamsIter<'a>>>;
|
||||
|
||||
fn generate_path(&self, path: &mut Vec<PathSegment>);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
use super::{PartialPathMatch, PossibleRouteMatch};
|
||||
use crate::PathSegment;
|
||||
use alloc::vec::Vec;
|
||||
use core::iter;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ParamSegment(pub &'static str);
|
||||
|
||||
impl PossibleRouteMatch for ParamSegment {
|
||||
type ParamsIter<'a> = iter::Once<(&'a str, &'a str)>;
|
||||
|
||||
fn matches<'a>(&self, path: &'a str) -> Option<&'a str> {
|
||||
let mut matched_len = 0;
|
||||
let mut test = path.chars().peekable();
|
||||
|
@ -24,7 +27,10 @@ impl PossibleRouteMatch for ParamSegment {
|
|||
Some(&path[0..matched_len])
|
||||
}
|
||||
|
||||
fn test<'a>(&self, path: &'a str) -> Option<PartialPathMatch<'a>> {
|
||||
fn test<'a>(
|
||||
&self,
|
||||
path: &'a str,
|
||||
) -> Option<PartialPathMatch<'a, Self::ParamsIter<'a>>> {
|
||||
let mut matched_len = 0;
|
||||
let mut param_offset = 0;
|
||||
let mut param_len = 0;
|
||||
|
@ -49,7 +55,7 @@ impl PossibleRouteMatch for ParamSegment {
|
|||
|
||||
let (matched, remaining) = path.split_at(matched_len);
|
||||
let param_value =
|
||||
vec![(self.0, &path[param_offset..param_len + param_offset])];
|
||||
iter::once((self.0, &path[param_offset..param_len + param_offset]));
|
||||
Some(PartialPathMatch::new(remaining, param_value, matched))
|
||||
}
|
||||
|
||||
|
@ -62,11 +68,16 @@ impl PossibleRouteMatch for ParamSegment {
|
|||
pub struct WildcardSegment(pub &'static str);
|
||||
|
||||
impl PossibleRouteMatch for WildcardSegment {
|
||||
type ParamsIter<'a> = iter::Once<(&'a str, &'a str)>;
|
||||
|
||||
fn matches<'a>(&self, path: &'a str) -> Option<&'a str> {
|
||||
Some(path)
|
||||
}
|
||||
|
||||
fn test<'a>(&self, path: &'a str) -> Option<PartialPathMatch<'a>> {
|
||||
fn test<'a>(
|
||||
&self,
|
||||
path: &'a str,
|
||||
) -> Option<PartialPathMatch<'a, Self::ParamsIter<'a>>> {
|
||||
let mut matched_len = 0;
|
||||
let mut param_offset = 0;
|
||||
let mut param_len = 0;
|
||||
|
@ -84,7 +95,7 @@ impl PossibleRouteMatch for WildcardSegment {
|
|||
|
||||
let (matched, remaining) = path.split_at(matched_len);
|
||||
let param_value =
|
||||
vec![(self.0, &path[param_offset..param_len + param_offset])];
|
||||
iter::once((self.0, &path[param_offset..param_len + param_offset]));
|
||||
Some(PartialPathMatch::new(remaining, param_value, matched))
|
||||
}
|
||||
|
||||
|
@ -106,7 +117,8 @@ mod tests {
|
|||
let matched = def.test(path).expect("couldn't match route");
|
||||
assert_eq!(matched.matched(), "/foo");
|
||||
assert_eq!(matched.remaining(), "");
|
||||
assert_eq!(matched.params()[0], ("a", "foo"));
|
||||
let params = matched.params().collect::<Vec<_>>();
|
||||
assert_eq!(params[0], ("a", "foo"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -117,7 +129,8 @@ mod tests {
|
|||
let matched = def.test(path).expect("couldn't match route");
|
||||
assert_eq!(matched.matched(), "/foo");
|
||||
assert_eq!(matched.remaining(), "/");
|
||||
assert_eq!(matched.params()[0], ("a", "foo"));
|
||||
let params = matched.params().collect::<Vec<_>>();
|
||||
assert_eq!(params[0], ("a", "foo"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -128,8 +141,9 @@ mod tests {
|
|||
let matched = def.test(path).expect("couldn't match route");
|
||||
assert_eq!(matched.matched(), "/foo/bar");
|
||||
assert_eq!(matched.remaining(), "");
|
||||
assert_eq!(matched.params()[0], ("a", "foo"));
|
||||
assert_eq!(matched.params()[1], ("b", "bar"));
|
||||
let params = matched.params().collect::<Vec<_>>();
|
||||
assert_eq!(params[0], ("a", "foo"));
|
||||
assert_eq!(params[1], ("b", "bar"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -144,6 +158,7 @@ mod tests {
|
|||
let matched = def.test(path).expect("couldn't match route");
|
||||
assert_eq!(matched.matched(), "/foo/bar/////");
|
||||
assert_eq!(matched.remaining(), "");
|
||||
assert_eq!(matched.params()[0], ("rest", "////"));
|
||||
let params = matched.params().collect::<Vec<_>>();
|
||||
assert_eq!(params[0], ("rest", "////"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
use super::{PartialPathMatch, PossibleRouteMatch};
|
||||
use crate::PathSegment;
|
||||
use alloc::vec::Vec;
|
||||
use core::iter;
|
||||
|
||||
impl PossibleRouteMatch for () {
|
||||
type ParamsIter<'a> = iter::Empty<(&'a str, &'a str)>;
|
||||
|
||||
fn matches<'a>(&self, path: &'a str) -> Option<&'a str> {
|
||||
Some(path)
|
||||
}
|
||||
|
||||
fn test<'a>(&self, path: &'a str) -> Option<PartialPathMatch<'a>> {
|
||||
Some(PartialPathMatch::new(path, [], ""))
|
||||
fn test<'a>(
|
||||
&self,
|
||||
path: &'a str,
|
||||
) -> Option<PartialPathMatch<'a, Self::ParamsIter<'a>>> {
|
||||
Some(PartialPathMatch::new(path, iter::empty(), ""))
|
||||
}
|
||||
|
||||
fn generate_path(&self, _path: &mut Vec<PathSegment>) {}
|
||||
|
@ -18,6 +24,8 @@ impl PossibleRouteMatch for () {
|
|||
pub struct StaticSegment(pub &'static str);
|
||||
|
||||
impl PossibleRouteMatch for StaticSegment {
|
||||
type ParamsIter<'a> = iter::Empty<(&'a str, &'a str)>;
|
||||
|
||||
fn matches<'a>(&self, path: &'a str) -> Option<&'a str> {
|
||||
let mut matched_len = 0;
|
||||
let mut this = self.0.chars();
|
||||
|
@ -46,12 +54,14 @@ impl PossibleRouteMatch for StaticSegment {
|
|||
}
|
||||
}
|
||||
}
|
||||
println!("matching on {self:?}, has_matched = {has_matched}");
|
||||
|
||||
has_matched.then(|| &path[matched_len..])
|
||||
}
|
||||
|
||||
fn test<'a>(&self, path: &'a str) -> Option<PartialPathMatch<'a>> {
|
||||
fn test<'a>(
|
||||
&self,
|
||||
path: &'a str,
|
||||
) -> Option<PartialPathMatch<'a, Self::ParamsIter<'a>>> {
|
||||
let mut matched_len = 0;
|
||||
let mut test = path.chars();
|
||||
let mut this = self.0.chars();
|
||||
|
@ -86,7 +96,8 @@ impl PossibleRouteMatch for StaticSegment {
|
|||
// the remaining is built from the path in, with the slice moved
|
||||
// by the length of this match
|
||||
let (matched, remaining) = path.split_at(matched_len);
|
||||
has_matched.then(|| PartialPathMatch::new(remaining, [], matched))
|
||||
has_matched
|
||||
.then(|| PartialPathMatch::new(remaining, iter::empty(), matched))
|
||||
}
|
||||
|
||||
fn generate_path(&self, path: &mut Vec<PathSegment>) {
|
||||
|
@ -105,7 +116,8 @@ mod tests {
|
|||
let matched = def.test(path).expect("couldn't match route");
|
||||
assert_eq!(matched.matched(), "/foo");
|
||||
assert_eq!(matched.remaining(), "");
|
||||
assert!(matched.params().is_empty());
|
||||
let params = matched.params().collect::<Vec<_>>();
|
||||
assert!(params.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -123,7 +135,8 @@ mod tests {
|
|||
let matched = def.test(path).expect("couldn't match route");
|
||||
assert_eq!(matched.matched(), "/foo");
|
||||
assert_eq!(matched.remaining(), "/");
|
||||
assert!(matched.params().is_empty());
|
||||
let params = matched.params().collect::<Vec<_>>();
|
||||
assert!(params.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -134,7 +147,8 @@ mod tests {
|
|||
let matched = def.test(path).expect("couldn't match route");
|
||||
assert_eq!(matched.matched(), "/foo/bar");
|
||||
assert_eq!(matched.remaining(), "");
|
||||
assert!(matched.params().is_empty());
|
||||
let params = matched.params().collect::<Vec<_>>();
|
||||
assert!(params.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -160,6 +174,7 @@ mod tests {
|
|||
let matched = def.test(path).expect("couldn't match route");
|
||||
assert_eq!(matched.matched(), "/foo/bar");
|
||||
assert_eq!(matched.remaining(), "");
|
||||
assert!(matched.params().is_empty());
|
||||
let params = matched.params().collect::<Vec<_>>();
|
||||
assert!(params.is_empty());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +1,54 @@
|
|||
use super::{PartialPathMatch, PathSegment, PossibleRouteMatch};
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use core::iter::Chain;
|
||||
|
||||
macro_rules! chain_types {
|
||||
($first:ty, $second:ty, ) => {
|
||||
Chain<
|
||||
$first,
|
||||
<<$second as PossibleRouteMatch>::ParamsIter<'a> as IntoIterator>::IntoIter
|
||||
>
|
||||
};
|
||||
($first:ty, $second:ty, $($rest:ty,)+) => {
|
||||
chain_types!(
|
||||
Chain<
|
||||
$first,
|
||||
<<$second as PossibleRouteMatch>::ParamsIter<'a> as IntoIterator>::IntoIter,
|
||||
>,
|
||||
$($rest,)+
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! tuples {
|
||||
($($ty:ident),*) => {
|
||||
impl<$($ty),*> PossibleRouteMatch for ($($ty,)*)
|
||||
($first:ident => $($ty:ident),*) => {
|
||||
impl<$first, $($ty),*> PossibleRouteMatch for ($first, $($ty,)*)
|
||||
where
|
||||
$first: PossibleRouteMatch,
|
||||
$($ty: PossibleRouteMatch),*,
|
||||
{
|
||||
type ParamsIter<'a> = chain_types!(<<$first>::ParamsIter<'a> as IntoIterator>::IntoIter, $($ty,)*);
|
||||
|
||||
fn matches<'a>(&self, path: &'a str) -> Option<&'a str>
|
||||
{
|
||||
#[allow(non_snake_case)]
|
||||
let ($($ty,)*) = &self;
|
||||
let ($first, $($ty,)*) = &self;
|
||||
let path = $first.matches(path)?;
|
||||
$(let path = $ty.matches(path)?;)*
|
||||
Some(path)
|
||||
}
|
||||
|
||||
fn test<'a>(&self, path: &'a str) -> Option<PartialPathMatch<'a>>
|
||||
{
|
||||
let mut full_params = Vec::new();
|
||||
fn test<'a>(&self, path: &'a str) -> Option<PartialPathMatch<'a, Self::ParamsIter<'a>>> {
|
||||
let mut matched_len = 0;
|
||||
#[allow(non_snake_case)]
|
||||
let ($($ty,)*) = &self;
|
||||
let ($first, $($ty,)*) = &self;
|
||||
let remaining = path;
|
||||
let PartialPathMatch {
|
||||
remaining,
|
||||
matched,
|
||||
params
|
||||
} = $first.test(remaining)?;
|
||||
matched_len += matched.len();
|
||||
let params_iter = params.into_iter();
|
||||
$(
|
||||
let PartialPathMatch {
|
||||
remaining,
|
||||
|
@ -29,18 +56,19 @@ macro_rules! tuples {
|
|||
params
|
||||
} = $ty.test(remaining)?;
|
||||
matched_len += matched.len();
|
||||
full_params.extend(params);
|
||||
let params_iter = params_iter.chain(params);
|
||||
)*
|
||||
Some(PartialPathMatch {
|
||||
remaining,
|
||||
matched: &path[0..matched_len],
|
||||
params: full_params
|
||||
params: params_iter
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_path(&self, path: &mut Vec<PathSegment>) {
|
||||
#[allow(non_snake_case)]
|
||||
let ($($ty,)*) = &self;
|
||||
let ($first, $($ty,)*) = &self;
|
||||
$first.generate_path(path);
|
||||
$(
|
||||
$ty.generate_path(path);
|
||||
)*
|
||||
|
@ -49,33 +77,33 @@ macro_rules! tuples {
|
|||
};
|
||||
}
|
||||
|
||||
tuples!(A, B);
|
||||
tuples!(A, B, C);
|
||||
tuples!(A, B, C, D);
|
||||
tuples!(A, B, C, D, E);
|
||||
tuples!(A, B, C, D, E, F);
|
||||
tuples!(A, B, C, D, E, F, G);
|
||||
tuples!(A, B, C, D, E, F, G, H);
|
||||
tuples!(A, B, C, D, E, F, G, H, I);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J, K);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J, K, L);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W);
|
||||
tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X);
|
||||
tuples!(
|
||||
tuples!(A => B);
|
||||
tuples!(A => B, C);
|
||||
tuples!(A => B, C, D);
|
||||
tuples!(A => B, C, D, E);
|
||||
tuples!(A => B, C, D, E, F);
|
||||
tuples!(A => B, C, D, E, F, G);
|
||||
tuples!(A => B, C, D, E, F, G, H);
|
||||
tuples!(A => B, C, D, E, F, G, H, I);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J, K);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J, K, L);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J, K, L, M);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J, K, L, M, N);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J, K, L, M, N, O);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W);
|
||||
tuples!(A => B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X);
|
||||
/*tuples!(
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y
|
||||
);
|
||||
tuples!(
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y,
|
||||
Z
|
||||
);
|
||||
);*/
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
mod horizontal;
|
||||
mod vertical;
|
||||
use alloc::{borrow::Cow, vec::Vec};
|
||||
use core::iter;
|
||||
pub use horizontal::*;
|
||||
use std::fmt::Debug;
|
||||
pub use vertical::*;
|
||||
|
||||
pub struct Routes<Children> {
|
||||
|
@ -29,14 +29,11 @@ impl<Children> Routes<Children> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<Children> Routes<Children>
|
||||
impl<'a, Children> Routes<Children>
|
||||
where
|
||||
Children: MatchNestedRoutes,
|
||||
Children: MatchNestedRoutes<'a>,
|
||||
{
|
||||
pub fn match_route<'a>(
|
||||
&self,
|
||||
path: &'a str,
|
||||
) -> Option<Children::Match<'a>> {
|
||||
pub fn match_route(&self, path: &'a str) -> Option<Children::Match> {
|
||||
let path = match &self.base {
|
||||
None => path,
|
||||
Some(base) if base.starts_with('/') => {
|
||||
|
@ -49,7 +46,6 @@ where
|
|||
|
||||
let (matched, remaining) = self.children.match_nested(path);
|
||||
let matched = matched?;
|
||||
println!("remaining = {remaining:?}");
|
||||
|
||||
if !remaining.is_empty() {
|
||||
None
|
||||
|
@ -59,38 +55,50 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub trait IntoParams<'a> {
|
||||
type IntoParams: IntoIterator<Item = (&'a str, &'a str)>;
|
||||
|
||||
fn to_params(&self) -> Self::IntoParams;
|
||||
}
|
||||
|
||||
pub trait MatchNestedRoutes<'a> {
|
||||
type Data;
|
||||
type ParamsIter: IntoIterator<Item = (&'a str, &'a str)> + Clone;
|
||||
type Match: IntoParams<'a>;
|
||||
|
||||
const DEPTH: usize;
|
||||
|
||||
fn matches(&self, path: &'a str) -> Option<&'a str>;
|
||||
|
||||
fn match_nested(&self, path: &'a str) -> (Option<Self::Match>, &'a str);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct NestedMatch<'a, Child> {
|
||||
pub struct NestedMatch<'a, ParamsIter, Child> {
|
||||
/// The portion of the full path matched only by this nested route.
|
||||
matched: &'a str,
|
||||
/// The map of params matched only by this nested route.
|
||||
params: Vec<(&'a str, &'a str)>,
|
||||
params: ParamsIter,
|
||||
/// The nested route.
|
||||
child: Child,
|
||||
}
|
||||
|
||||
impl<'a, Child> NestedMatch<'a, Child> {
|
||||
pub fn matched(&self) -> &'a str {
|
||||
self.matched
|
||||
}
|
||||
impl<'a, ParamsIter, Child> IntoParams<'a>
|
||||
for NestedMatch<'a, ParamsIter, Child>
|
||||
where
|
||||
ParamsIter: IntoIterator<Item = (&'a str, &'a str)> + Clone,
|
||||
{
|
||||
type IntoParams = ParamsIter;
|
||||
|
||||
pub fn matched_params(&self) -> &[(&'a str, &'a str)] {
|
||||
&self.params
|
||||
fn to_params(&self) -> Self::IntoParams {
|
||||
self.params.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MatchNestedRoutes {
|
||||
type Data;
|
||||
type Match<'a>;
|
||||
|
||||
const DEPTH: usize;
|
||||
|
||||
fn matches<'a>(&self, path: &'a str) -> Option<&'a str>;
|
||||
|
||||
fn match_nested<'a>(
|
||||
&self,
|
||||
path: &'a str,
|
||||
) -> (Option<Self::Match<'a>>, &'a str);
|
||||
impl<'a, ParamsIter, Child> NestedMatch<'a, ParamsIter, Child> {
|
||||
pub fn matched(&self) -> &'a str {
|
||||
self.matched
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
|
@ -101,37 +109,49 @@ pub struct NestedRoute<Segments, Children, Data, View> {
|
|||
pub view: View,
|
||||
}
|
||||
|
||||
impl MatchNestedRoutes for () {
|
||||
impl<'a> MatchNestedRoutes<'a> for () {
|
||||
type Data = ();
|
||||
type Match<'a> = ();
|
||||
type ParamsIter = iter::Empty<(&'a str, &'a str)>;
|
||||
type Match = ();
|
||||
|
||||
const DEPTH: usize = 0;
|
||||
|
||||
fn matches<'a>(&self, path: &'a str) -> Option<&'a str> {
|
||||
fn matches(&self, path: &'a str) -> Option<&'a str> {
|
||||
Some(path)
|
||||
}
|
||||
|
||||
fn match_nested<'a>(
|
||||
&self,
|
||||
path: &'a str,
|
||||
) -> (Option<Self::Match<'a>>, &'a str) {
|
||||
fn match_nested(&self, path: &'a str) -> (Option<Self::Match>, &'a str) {
|
||||
(Some(()), path)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Segments, Children, Data, View> MatchNestedRoutes
|
||||
impl<'a> IntoParams<'a> for () {
|
||||
type IntoParams = iter::Empty<(&'a str, &'a str)>;
|
||||
|
||||
fn to_params(&self) -> Self::IntoParams {
|
||||
iter::empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Segments, Children, Data, View> MatchNestedRoutes<'a>
|
||||
for NestedRoute<Segments, Children, Data, View>
|
||||
where
|
||||
Self: Debug,
|
||||
Segments: PossibleRouteMatch + Debug,
|
||||
Children: MatchNestedRoutes,
|
||||
Segments: PossibleRouteMatch,
|
||||
Children: MatchNestedRoutes<'a>,
|
||||
<Segments::ParamsIter<'a> as IntoIterator>::IntoIter: Clone,
|
||||
<<Children::Match as IntoParams<'a>>::IntoParams as IntoIterator>::IntoIter:
|
||||
Clone,
|
||||
{
|
||||
type Data = Data;
|
||||
type Match<'a> = NestedMatch<'a, Children::Match<'a>>;
|
||||
type ParamsIter = iter::Chain<
|
||||
<Segments::ParamsIter<'a> as IntoIterator>::IntoIter,
|
||||
<<Children::Match as IntoParams<'a>>::IntoParams as IntoIterator>::IntoIter,
|
||||
>;
|
||||
type Match = NestedMatch<'a, Self::ParamsIter, Children::Match>;
|
||||
|
||||
const DEPTH: usize = Children::DEPTH;
|
||||
|
||||
fn matches<'a>(&self, path: &'a str) -> Option<&'a str> {
|
||||
fn matches(&self, path: &'a str) -> Option<&'a str> {
|
||||
if let Some(remaining) = self.segments.matches(path) {
|
||||
self.children.matches(remaining)
|
||||
} else {
|
||||
|
@ -139,10 +159,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn match_nested<'a>(
|
||||
&self,
|
||||
path: &'a str,
|
||||
) -> (Option<Self::Match<'a>>, &'a str) {
|
||||
fn match_nested(&self, path: &'a str) -> (Option<Self::Match>, &'a str) {
|
||||
self.segments
|
||||
.test(path)
|
||||
.and_then(
|
||||
|
@ -154,11 +171,12 @@ where
|
|||
let (inner, remaining) =
|
||||
self.children.match_nested(remaining);
|
||||
let inner = inner?;
|
||||
let params = params.into_iter();
|
||||
|
||||
Some((
|
||||
Some(NestedMatch {
|
||||
matched,
|
||||
params,
|
||||
params: params.chain(inner.to_params()),
|
||||
child: inner,
|
||||
}),
|
||||
remaining,
|
||||
|
@ -166,35 +184,24 @@ where
|
|||
},
|
||||
)
|
||||
.unwrap_or((None, path))
|
||||
/*path = remaining;
|
||||
NestedMatch {
|
||||
matched_path: matched,
|
||||
params,
|
||||
};
|
||||
return self.children.match_nested_routes(path, matches);
|
||||
|
||||
// otherwise, just return the path as the remainder
|
||||
path*/
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> MatchNestedRoutes for (A,)
|
||||
impl<'a, A> MatchNestedRoutes<'a> for (A,)
|
||||
where
|
||||
A: MatchNestedRoutes,
|
||||
A: MatchNestedRoutes<'a>,
|
||||
{
|
||||
type Data = A::Data;
|
||||
type Match<'a> = A::Match<'a>;
|
||||
type ParamsIter = A::ParamsIter;
|
||||
type Match = A::Match;
|
||||
|
||||
const DEPTH: usize = A::DEPTH;
|
||||
|
||||
fn matches<'a>(&self, path: &'a str) -> Option<&'a str> {
|
||||
fn matches(&self, path: &'a str) -> Option<&'a str> {
|
||||
self.0.matches(path)
|
||||
}
|
||||
|
||||
fn match_nested<'a>(
|
||||
&self,
|
||||
path: &'a str,
|
||||
) -> (Option<Self::Match<'a>>, &'a str) {
|
||||
fn match_nested(&self, path: &'a str) -> (Option<Self::Match>, &'a str) {
|
||||
self.0.match_nested(path)
|
||||
}
|
||||
}
|
||||
|
@ -202,19 +209,21 @@ where
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{NestedRoute, Routes};
|
||||
use crate::matching::{NestedMatch, StaticSegment};
|
||||
use crate::matching::StaticSegment;
|
||||
|
||||
/* #[test]
|
||||
#[test]
|
||||
pub fn matches_single_root_route() {
|
||||
let routes = Routes::new(NestedRoute {
|
||||
segments: StaticSegment("/"),
|
||||
children: (),
|
||||
data: (),
|
||||
view: (),
|
||||
});
|
||||
let matched = routes.match_route("/");
|
||||
assert!(matched.is_some());
|
||||
let matched = routes.match_route("");
|
||||
assert!(matched.is_some())
|
||||
}*/
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn matches_nested_route() {
|
||||
|
@ -248,7 +257,7 @@ mod tests {
|
|||
view: "Home",
|
||||
});
|
||||
let matched = routes.match_route("/");
|
||||
assert_eq!(matched, None);
|
||||
assert!(matched.is_none());
|
||||
}
|
||||
|
||||
/*#[test]
|
||||
|
@ -272,21 +281,21 @@ mod tests {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PartialPathMatch<'a> {
|
||||
pub struct PartialPathMatch<'a, ParamsIter> {
|
||||
pub(crate) remaining: &'a str,
|
||||
pub(crate) params: Vec<(&'a str, &'a str)>,
|
||||
pub(crate) params: ParamsIter,
|
||||
pub(crate) matched: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> PartialPathMatch<'a> {
|
||||
impl<'a, ParamsIter> PartialPathMatch<'a, ParamsIter> {
|
||||
pub fn new(
|
||||
remaining: &'a str,
|
||||
params: impl Into<Vec<(&'a str, &'a str)>>,
|
||||
params: ParamsIter,
|
||||
matched: &'a str,
|
||||
) -> Self {
|
||||
Self {
|
||||
remaining,
|
||||
params: params.into(),
|
||||
params,
|
||||
matched,
|
||||
}
|
||||
}
|
||||
|
@ -299,8 +308,8 @@ impl<'a> PartialPathMatch<'a> {
|
|||
self.remaining
|
||||
}
|
||||
|
||||
pub fn params(&self) -> &[(&'a str, &'a str)] {
|
||||
&self.params
|
||||
pub fn params(self) -> ParamsIter {
|
||||
self.params
|
||||
}
|
||||
|
||||
pub fn matched(&self) -> &str {
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
use super::PartialPathMatch;
|
||||
|
||||
pub trait ChooseRoute {
|
||||
fn choose_route<'a>(&self, path: &'a str) -> Option<PartialPathMatch<'a>>;
|
||||
fn choose_route<'a>(
|
||||
&self,
|
||||
path: &'a str,
|
||||
) -> Option<
|
||||
PartialPathMatch<'a, impl IntoIterator<Item = (&'a str, &'a str)>>,
|
||||
>;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue