nest.rs 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. use proc_macro2::TokenStream;
  2. use quote::{format_ident, quote};
  3. use syn::{Ident, LitStr};
  4. use crate::segment::{create_error_type, parse_route_segments, RouteSegment};
  5. #[derive(Debug, Clone, Copy)]
  6. pub struct NestId(pub usize);
  7. #[derive(Debug, Clone)]
  8. pub struct Nest {
  9. pub route: String,
  10. pub segments: Vec<RouteSegment>,
  11. index: usize,
  12. }
  13. impl Nest {
  14. pub fn parse(
  15. input: syn::parse::ParseStream,
  16. children_routes: Vec<syn::FieldsNamed>,
  17. index: usize,
  18. ) -> syn::Result<Self> {
  19. // Parse the route
  20. let route: LitStr = input.parse()?;
  21. let route_segments = parse_route_segments(
  22. route.span(),
  23. children_routes
  24. .iter()
  25. .flat_map(|f| f.named.iter())
  26. .map(|f| (f.ident.as_ref().unwrap(), &f.ty)),
  27. &route.value(),
  28. )?
  29. .0;
  30. for seg in &route_segments {
  31. if let RouteSegment::CatchAll(name, _) = seg {
  32. return Err(syn::Error::new_spanned(
  33. name,
  34. format!(
  35. "Catch-all segments are not allowed in nested routes: {}",
  36. route.value()
  37. ),
  38. ));
  39. }
  40. }
  41. Ok(Self {
  42. route: route.value(),
  43. segments: route_segments,
  44. index,
  45. })
  46. }
  47. }
  48. impl Nest {
  49. pub fn dynamic_segments(&self) -> impl Iterator<Item = TokenStream> + '_ {
  50. self.dynamic_segments_names().map(|i| quote! {#i})
  51. }
  52. pub fn dynamic_segments_names(&self) -> impl Iterator<Item = Ident> + '_ {
  53. self.segments.iter().filter_map(|seg| seg.name())
  54. }
  55. pub fn write(&self) -> TokenStream {
  56. let write_segments = self.segments.iter().map(|s| s.write_segment());
  57. quote! {
  58. {
  59. #(#write_segments)*
  60. }
  61. }
  62. }
  63. pub fn error_ident(&self) -> Ident {
  64. format_ident!("Nest{}ParseError", self.index)
  65. }
  66. pub fn error_variant(&self) -> Ident {
  67. format_ident!("Nest{}", self.index)
  68. }
  69. pub fn error_type(&self) -> TokenStream {
  70. let error_name = self.error_ident();
  71. create_error_type(&self.route, error_name, &self.segments, None)
  72. }
  73. }