derive query parsing in the router macro
This commit is contained in:
1 parent
c8a9a7b1d5
commit
8a44fe8d03
6 files changed
+175
-17
No files matched your search
@@ -4,12 +4,62 @@ use syn::{Ident, Type};
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct QuerySegment {
|
||||
pub enum QuerySegment {
|
||||
Single(FullQuerySegment),
|
||||
Segments(Vec<QueryArgument>),
|
||||
}
|
||||
|
||||
impl QuerySegment {
|
||||
pub fn contains_ident(&self, ident: &Ident) -> bool {
|
||||
match self {
|
||||
QuerySegment::Single(segment) => segment.ident == *ident,
|
||||
QuerySegment::Segments(segments) => {
|
||||
segments.iter().any(|segment| segment.ident == *ident)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(&self) -> TokenStream2 {
|
||||
match self {
|
||||
QuerySegment::Single(segment) => segment.parse(),
|
||||
QuerySegment::Segments(segments) => {
|
||||
let mut tokens = TokenStream2::new();
|
||||
tokens.extend(quote! { let split_query: std::collections::HashMap<&str, &str> = query.split('&').filter_map(|s| s.split_once('=')).collect(); });
|
||||
for segment in segments {
|
||||
tokens.extend(segment.parse());
|
||||
}
|
||||
tokens
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self) -> TokenStream2 {
|
||||
match self {
|
||||
QuerySegment::Single(segment) => segment.write(),
|
||||
QuerySegment::Segments(segments) => {
|
||||
let mut tokens = TokenStream2::new();
|
||||
tokens.extend(quote! { write!(f, "?")?; });
|
||||
let mut segments_iter = segments.iter();
|
||||
if let Some(first_segment) = segments_iter.next() {
|
||||
tokens.extend(first_segment.write());
|
||||
}
|
||||
for segment in segments_iter {
|
||||
tokens.extend(quote! { write!(f, "&")?; });
|
||||
tokens.extend(segment.write());
|
||||
}
|
||||
tokens
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FullQuerySegment {
|
||||
pub ident: Ident,
|
||||
pub ty: Type,
|
||||
}
|
||||
|
||||
impl QuerySegment {
|
||||
impl FullQuerySegment {
|
||||
pub fn parse(&self) -> TokenStream2 {
|
||||
let ident = &self.ident;
|
||||
let ty = &self.ty;
|
||||
@@ -25,3 +75,29 @@ impl QuerySegment {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct QueryArgument {
|
||||
pub ident: Ident,
|
||||
pub ty: Type,
|
||||
}
|
||||
|
||||
impl QueryArgument {
|
||||
pub fn parse(&self) -> TokenStream2 {
|
||||
let ident = &self.ident;
|
||||
let ty = &self.ty;
|
||||
quote! {
|
||||
let #ident = match split_query.get(stringify!(#ident)) {
|
||||
Some(query_argument) => <#ty as dioxus_router::routable::FromQueryArgument>::from_query_argument(query_argument).unwrap_or_default(),
|
||||
None => <#ty as Default>::default(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self) -> TokenStream2 {
|
||||
let ident = &self.ident;
|
||||
quote! {
|
||||
write!(f, "{}={}", stringify!(#ident), #ident)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user