implement spread segments
This commit is contained in:
1 parent
2aadeb8046
commit
ee763d52e1
5 files changed
+238
-123
No files matched your search
@@ -93,8 +93,7 @@ impl Route {
|
||||
|
||||
pub fn routable_match(&self) -> TokenStream2 {
|
||||
let name = &self.route_name;
|
||||
let dynamic_segments: Vec<_> = self
|
||||
.dynamic_segments().collect();
|
||||
let dynamic_segments: Vec<_> = self.dynamic_segments().collect();
|
||||
let props_name = &self.props_name;
|
||||
let comp_name = &self.comp_name;
|
||||
|
||||
@@ -110,7 +109,7 @@ impl Route {
|
||||
}
|
||||
}
|
||||
|
||||
fn dynamic_segments(&self)-> impl Iterator<Item = TokenStream2> +'_{
|
||||
fn dynamic_segments(&self) -> impl Iterator<Item = TokenStream2> + '_ {
|
||||
let segments = self.route_segments.iter().filter_map(|seg| {
|
||||
seg.name().map(|name| {
|
||||
quote! {
|
||||
@@ -118,18 +117,22 @@ impl Route {
|
||||
}
|
||||
})
|
||||
});
|
||||
let query = self.query.as_ref().map(|q| {
|
||||
let name = q.name();
|
||||
quote! {
|
||||
#name
|
||||
}
|
||||
}).into_iter();
|
||||
let query = self
|
||||
.query
|
||||
.as_ref()
|
||||
.map(|q| {
|
||||
let name = q.name();
|
||||
quote! {
|
||||
#name
|
||||
}
|
||||
})
|
||||
.into_iter();
|
||||
|
||||
segments.chain(query)
|
||||
}
|
||||
|
||||
pub fn construct(&self, enum_name: Ident) -> TokenStream2 {
|
||||
let segments = self.dynamic_segments();
|
||||
let segments = self.dynamic_segments();
|
||||
let name = &self.route_name;
|
||||
|
||||
quote! {
|
||||
@@ -157,11 +160,14 @@ impl Route {
|
||||
display_match.push(quote! { Self::#error_name => write!(f, "Static segment '{}' did not match", #index)? });
|
||||
}
|
||||
RouteSegment::Dynamic(ident, ty) => {
|
||||
error_variants.push(quote! { #error_name(<#ty as std::str::FromStr>::Err) });
|
||||
let missing_error = segment.missing_error_name().unwrap();
|
||||
error_variants.push(quote! { #error_name(<#ty as dioxus_router_core::router::FromRouteSegment>::Err) });
|
||||
display_match.push(quote! { Self::#error_name(err) => write!(f, "Dynamic segment '({}:{})' did not match: {}", stringify!(#ident), stringify!(#ty), err)? });
|
||||
error_variants.push(quote! { #missing_error });
|
||||
display_match.push(quote! { Self::#missing_error => write!(f, "Dynamic segment '({}:{})' was missing", stringify!(#ident), stringify!(#ty))? });
|
||||
}
|
||||
RouteSegment::CatchAll(ident, ty) => {
|
||||
error_variants.push(quote! { #error_name(<#ty as std::str::FromStr>::Err) });
|
||||
error_variants.push(quote! { #error_name(<#ty as dioxus_router_core::router::FromRouteSegments>::Err) });
|
||||
display_match.push(quote! { Self::#error_name(err) => write!(f, "Catch-all segment '({}:{})' did not match: {}", stringify!(#ident), stringify!(#ty), err)? });
|
||||
}
|
||||
}
|
||||
@@ -195,6 +201,13 @@ impl Route {
|
||||
None => quote! {},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ends_with_catch_all(&self) -> bool {
|
||||
self.route_segments
|
||||
.last()
|
||||
.map(|seg| matches!(seg, RouteSegment::CatchAll(..)))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for Route {
|
||||
@@ -211,7 +224,7 @@ impl ToTokens for Route {
|
||||
let route = dir.join("src").join("pages").join(with_extension.clone());
|
||||
|
||||
// check if the route exists or if not use the index route
|
||||
let route = if route.exists() && without_leading_slash != "" {
|
||||
let route = if route.exists() && !without_leading_slash.is_empty() {
|
||||
with_extension.to_str().unwrap().to_string()
|
||||
} else {
|
||||
route_path.join("index.rs").to_str().unwrap().to_string()
|
||||
@@ -259,13 +272,13 @@ fn parse_route_segments(
|
||||
let spread = segment.starts_with("(...");
|
||||
|
||||
let ident = if spread {
|
||||
segment[3..segment.len() - 1].to_string()
|
||||
segment[4..segment.len() - 1].to_string()
|
||||
} else {
|
||||
segment[1..segment.len() - 1].to_string()
|
||||
};
|
||||
|
||||
let field = varient.fields.iter().find(|field| match field.ident {
|
||||
Some(ref field_ident) => field_ident.to_string() == ident,
|
||||
Some(ref field_ident) => *field_ident == ident,
|
||||
None => false,
|
||||
});
|
||||
|
||||
@@ -361,7 +374,7 @@ impl RouteSegment {
|
||||
match self {
|
||||
Self::Static(segment) => quote! { write!(f, "/{}", #segment)?; },
|
||||
Self::Dynamic(ident, _) => quote! { write!(f, "/{}", #ident)?; },
|
||||
Self::CatchAll(ident, _) => quote! { write!(f, "/{}", #ident)?; },
|
||||
Self::CatchAll(ident, _) => quote! { #ident.display_route_segements(f)?; },
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,32 +386,81 @@ impl RouteSegment {
|
||||
}
|
||||
}
|
||||
|
||||
fn missing_error_name(&self) -> Option<Ident> {
|
||||
match self {
|
||||
Self::Dynamic(ident, _) => Some(format_ident!("{}MissingError", ident)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_parse(
|
||||
&self,
|
||||
idx: usize,
|
||||
error_enum_name: &Ident,
|
||||
error_enum_varient: &Ident,
|
||||
inner_parse_enum: &Ident,
|
||||
parse_children: TokenStream2,
|
||||
) -> TokenStream2 {
|
||||
let error_name = self.error_name(idx);
|
||||
match self {
|
||||
Self::Static(segment) => {
|
||||
quote! {
|
||||
let parsed = if segment == #segment {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(#error_enum_name::#error_enum_varient(#inner_parse_enum::#error_name))
|
||||
};
|
||||
{
|
||||
let mut segments = segments.clone();
|
||||
let parsed = if let Some(#segment) = segments.next() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(#error_enum_name::#error_enum_varient(#inner_parse_enum::#error_name))
|
||||
};
|
||||
match parsed {
|
||||
Ok(_) => {
|
||||
#parse_children
|
||||
}
|
||||
Err(err) => {
|
||||
errors.push(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::Dynamic(_, ty) => {
|
||||
Self::Dynamic(name, ty) => {
|
||||
let missing_error_name = self.missing_error_name().unwrap();
|
||||
quote! {
|
||||
let parsed = <#ty as dioxus_router_core::router::FromRouteSegment>::from_route_segment(segment).map_err(|err| #error_enum_name::#error_enum_varient(#inner_parse_enum::#error_name(err)));
|
||||
{
|
||||
let mut segments = segments.clone();
|
||||
let parsed = if let Some(segment) = segments.next() {
|
||||
<#ty as dioxus_router_core::router::FromRouteSegment>::from_route_segment(segment).map_err(|err| #error_enum_name::#error_enum_varient(#inner_parse_enum::#error_name(err)))
|
||||
} else {
|
||||
Err(#error_enum_name::#error_enum_varient(#inner_parse_enum::#missing_error_name))
|
||||
};
|
||||
match parsed {
|
||||
Ok(#name) => {
|
||||
#parse_children
|
||||
}
|
||||
Err(err) => {
|
||||
errors.push(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::CatchAll(_, ty) => {
|
||||
Self::CatchAll(name, ty) => {
|
||||
quote! {
|
||||
let parsed = <#ty as dioxus_router_core::router::FromRouteSegments>::from_route_segments(segment).map_err(|err| #error_enum_name::#error_enum_varient(#inner_parse_enum::#error_name(err)));
|
||||
{
|
||||
let parsed = {
|
||||
let mut segments = segments.clone();
|
||||
let segments: Vec<_> = segments.collect();
|
||||
<#ty as dioxus_router_core::router::FromRouteSegments>::from_route_segments(&segments).map_err(|err| #error_enum_name::#error_enum_varient(#inner_parse_enum::#error_name(err)))
|
||||
};
|
||||
match parsed {
|
||||
Ok(#name) => {
|
||||
#parse_children
|
||||
}
|
||||
Err(err) => {
|
||||
errors.push(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user