|
@@ -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)?;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|