1
0

redirect.rs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. use proc_macro2::{Ident, TokenStream};
  2. use quote::{format_ident, quote};
  3. use syn::LitStr;
  4. use crate::{
  5. hash::HashFragment,
  6. nest::NestId,
  7. query::QuerySegment,
  8. segment::{create_error_type, parse_route_segments, RouteSegment},
  9. };
  10. #[derive(Debug)]
  11. pub(crate) struct Redirect {
  12. pub route: LitStr,
  13. pub nests: Vec<NestId>,
  14. pub segments: Vec<RouteSegment>,
  15. pub query: Option<QuerySegment>,
  16. pub hash: Option<HashFragment>,
  17. pub function: syn::ExprClosure,
  18. pub index: usize,
  19. }
  20. impl Redirect {
  21. pub fn error_ident(&self) -> Ident {
  22. format_ident!("Redirect{}ParseError", self.index)
  23. }
  24. pub fn error_variant(&self) -> Ident {
  25. format_ident!("Redirect{}", self.index)
  26. }
  27. pub fn error_type(&self) -> TokenStream {
  28. let error_name = self.error_ident();
  29. create_error_type(error_name, &self.segments, None)
  30. }
  31. pub fn parse_query(&self) -> TokenStream {
  32. match &self.query {
  33. Some(query) => query.parse(),
  34. None => quote! {},
  35. }
  36. }
  37. pub fn parse_hash(&self) -> TokenStream {
  38. match &self.hash {
  39. Some(hash) => hash.parse(),
  40. None => quote! {},
  41. }
  42. }
  43. pub fn parse(
  44. input: syn::parse::ParseStream,
  45. active_nests: Vec<NestId>,
  46. index: usize,
  47. ) -> syn::Result<Self> {
  48. let path = input.parse::<syn::LitStr>()?;
  49. let _ = input.parse::<syn::Token![,]>();
  50. let function = input.parse::<syn::ExprClosure>()?;
  51. let mut closure_arguments = Vec::new();
  52. for arg in function.inputs.iter() {
  53. match arg {
  54. syn::Pat::Type(pat) => match &*pat.pat {
  55. syn::Pat::Ident(ident) => {
  56. closure_arguments.push((ident.ident.clone(), (*pat.ty).clone()));
  57. }
  58. _ => {
  59. return Err(syn::Error::new_spanned(
  60. arg,
  61. "Expected closure argument to be a typed pattern",
  62. ))
  63. }
  64. },
  65. _ => {
  66. return Err(syn::Error::new_spanned(
  67. arg,
  68. "Expected closure argument to be a typed pattern",
  69. ))
  70. }
  71. }
  72. }
  73. let (segments, query, hash) = parse_route_segments(
  74. path.span(),
  75. #[allow(clippy::map_identity)]
  76. closure_arguments.iter().map(|(name, ty)| (name, ty)),
  77. &path.value(),
  78. )?;
  79. Ok(Redirect {
  80. route: path,
  81. nests: active_nests,
  82. segments,
  83. query,
  84. hash,
  85. function,
  86. index,
  87. })
  88. }
  89. }