mirror of
https://github.com/DioxusLabs/dioxus
synced 2025-02-17 06:08:26 +00:00
122 lines
4.3 KiB
Rust
122 lines
4.3 KiB
Rust
|
use quote::{format_ident, quote};
|
||
|
use syn::{Ident, Type};
|
||
|
|
||
|
use proc_macro2::TokenStream as TokenStream2;
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub enum RouteSegment {
|
||
|
Static(String),
|
||
|
Dynamic(Ident, Type),
|
||
|
CatchAll(Ident, Type),
|
||
|
}
|
||
|
|
||
|
impl RouteSegment {
|
||
|
pub fn name(&self) -> Option<Ident> {
|
||
|
match self {
|
||
|
Self::Static(_) => None,
|
||
|
Self::Dynamic(ident, _) => Some(ident.clone()),
|
||
|
Self::CatchAll(ident, _) => Some(ident.clone()),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn write_segment(&self) -> TokenStream2 {
|
||
|
match self {
|
||
|
Self::Static(segment) => quote! { write!(f, "/{}", #segment)?; },
|
||
|
Self::Dynamic(ident, _) => quote! { write!(f, "/{}", #ident)?; },
|
||
|
Self::CatchAll(ident, _) => quote! { #ident.display_route_segements(f)?; },
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn error_name(&self, idx: usize) -> Ident {
|
||
|
match self {
|
||
|
Self::Static(_) => static_segment_idx(idx),
|
||
|
Self::Dynamic(ident, _) => format_ident!("{}ParseError", ident),
|
||
|
Self::CatchAll(ident, _) => format_ident!("{}ParseError", ident),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub 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 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(name, ty) => {
|
||
|
let missing_error_name = self.missing_error_name().unwrap();
|
||
|
quote! {
|
||
|
{
|
||
|
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(name, ty) => {
|
||
|
quote! {
|
||
|
{
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn static_segment_idx(idx: usize) -> Ident {
|
||
|
format_ident!("StaticSegment{}ParseError", idx)
|
||
|
}
|