fix errors for nested routes

This commit is contained in:
Evan Almloff 2023-06-28 11:27:11 -07:00
parent 7b1f0c9412
commit a7f7aad947
7 changed files with 64 additions and 22 deletions

View file

@ -61,11 +61,11 @@ web-sys = { version = "0.3.61", features = ["Window", "Document", "Element", "Ht
[features]
default = ["hot-reload", "default-tls"]
router = ["dioxus-router"]
hot-reload = ["serde_json", "tokio-stream", "futures-util"]
hot-reload = ["serde_json", "futures-util"]
warp = ["dep:warp", "http-body", "ssr"]
axum = ["dep:axum", "tower-http", "ssr"]
salvo = ["dep:salvo", "ssr"]
ssr = ["server_fn/ssr", "tokio", "dioxus-ssr", "hyper", "http", "dioxus-router/ssr"]
ssr = ["server_fn/ssr", "tokio", "dioxus-ssr", "hyper", "http", "dioxus-router/ssr", "tokio-stream"]
default-tls = ["server_fn/default-tls"]
rustls = ["server_fn/rustls"]

View file

@ -7,7 +7,7 @@ publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dioxus-web = { workspace = true, features=["hydrate"], optional = true }
dioxus-web = { workspace = true, features = ["hydrate"], optional = true }
dioxus = { workspace = true }
dioxus-fullstack = { workspace = true }
axum = { version = "0.6.12", optional = true }

View file

@ -82,6 +82,6 @@ impl Nest {
pub fn error_type(&self) -> TokenStream {
let error_name = self.error_ident();
create_error_type(error_name, &self.segments)
create_error_type(error_name, &self.segments, None)
}
}

View file

@ -30,7 +30,7 @@ impl Redirect {
pub fn error_type(&self) -> TokenStream {
let error_name = self.error_ident();
create_error_type(error_name, &self.segments)
create_error_type(error_name, &self.segments, None)
}
pub fn parse_query(&self) -> TokenStream {

View file

@ -308,20 +308,11 @@ impl Route {
RouteType::Child(field) => {
let name = &self.route_name;
let child_name = field.ident.as_ref().unwrap();
let ty = &field.ty;
quote! {
{
let mut trailing = String::new();
for seg in segments {
trailing += seg;
trailing += "/";
}
trailing.pop();
#enum_name::#name {
#child_name: #ty::from_str(&trailing).unwrap(),
#(#segments,)*
}
#enum_name::#name {
#child_name,
#(#segments,)*
}
}
}
@ -343,8 +334,12 @@ impl Route {
pub fn error_type(&self) -> TokenStream2 {
let error_name = self.error_ident();
let child_type = match &self.ty {
RouteType::Child(field) => Some(&field.ty),
RouteType::Leaf { .. } => None,
};
create_error_type(error_name, &self.segments)
create_error_type(error_name, &self.segments, child_type)
}
pub fn parse_query(&self) -> TokenStream2 {

View file

@ -343,7 +343,7 @@ impl<'a> RouteTreeSegmentData<'a> {
RouteType::Child(_) => false,
};
print_route_segment(
let print_route_segment = print_route_segment(
route_segments.peekable(),
return_constructed(
insure_not_trailing,
@ -356,7 +356,32 @@ impl<'a> RouteTreeSegmentData<'a> {
&error_enum_name,
enum_varient,
&varient_parse_error,
)
);
match &route.ty {
RouteType::Child(child) => {
let ty = &child.ty;
let child_name = &child.ident;
quote! {
let mut trailing = String::new();
for seg in segments.clone() {
trailing += seg;
trailing += "/";
}
trailing.pop();
match #ty::from_str(&trailing).map_err(|err| #error_enum_name::#enum_varient(#varient_parse_error::ChildRoute(err))) {
Ok(#child_name) => {
#print_route_segment
}
Err(err) => {
errors.push(err);
}
}
}
}
RouteType::Leaf { .. } => print_route_segment,
}
}
Self::Nest { nest, children } => {
// At this point, we have matched all static segments, so we can just check if the remaining segments match the route

View file

@ -222,7 +222,11 @@ pub fn parse_route_segments<'a>(
Ok((route_segments, parsed_query))
}
pub(crate) fn create_error_type(error_name: Ident, segments: &[RouteSegment]) -> TokenStream2 {
pub(crate) fn create_error_type(
error_name: Ident,
segments: &[RouteSegment],
child_type: Option<&Type>,
) -> TokenStream2 {
let mut error_variants = Vec::new();
let mut display_match = Vec::new();
@ -249,11 +253,28 @@ pub(crate) fn create_error_type(error_name: Ident, segments: &[RouteSegment]) ->
}
}
let child_type_variant = child_type
.map(|child_type| {
quote! { ChildRoute(<#child_type as std::str::FromStr>::Err) }
})
.into_iter();
let child_type_error = child_type
.map(|_| {
quote! {
Self::ChildRoute(error) => {
write!(f, "{}", error)?
}
}
})
.into_iter();
quote! {
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq)]
pub enum #error_name {
ExtraSegments(String),
#(#child_type_variant,)*
#(#error_variants,)*
}
@ -262,7 +283,8 @@ pub(crate) fn create_error_type(error_name: Ident, segments: &[RouteSegment]) ->
match self {
Self::ExtraSegments(segments) => {
write!(f, "Found additional trailing segments: {}", segments)?
}
},
#(#child_type_error,)*
#(#display_match,)*
}
Ok(())