1
0

route_tree.rs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. use proc_macro2::TokenStream;
  2. use quote::quote;
  3. use slab::Slab;
  4. use syn::Ident;
  5. use crate::{
  6. nest::{Nest, NestId},
  7. redirect::Redirect,
  8. route::{Route, RouteType},
  9. segment::{static_segment_idx, RouteSegment},
  10. };
  11. #[derive(Debug, Clone, Default)]
  12. pub(crate) struct RouteTree<'a> {
  13. pub roots: Vec<usize>,
  14. entries: Slab<RouteTreeSegmentData<'a>>,
  15. }
  16. impl<'a> RouteTree<'a> {
  17. pub fn get(&self, index: usize) -> Option<&RouteTreeSegmentData<'a>> {
  18. self.entries.get(index)
  19. }
  20. pub fn get_mut(&mut self, element: usize) -> Option<&mut RouteTreeSegmentData<'a>> {
  21. self.entries.get_mut(element)
  22. }
  23. fn sort_children(&mut self) {
  24. let mut old_roots = self.roots.clone();
  25. self.sort_ids(&mut old_roots);
  26. self.roots = old_roots;
  27. for id in self.roots.clone() {
  28. self.sort_children_of_id(id);
  29. }
  30. }
  31. fn sort_ids(&self, ids: &mut [usize]) {
  32. ids.sort_by_key(|&seg| {
  33. let seg = self.get(seg).unwrap();
  34. match seg {
  35. RouteTreeSegmentData::Static { .. } => 0,
  36. RouteTreeSegmentData::Nest { .. } => 1,
  37. RouteTreeSegmentData::Route(route) => {
  38. // Routes that end in a catch all segment should be checked last
  39. match route.segments.last() {
  40. Some(RouteSegment::CatchAll(..)) => 2,
  41. _ => 1,
  42. }
  43. }
  44. RouteTreeSegmentData::Redirect(redirect) => {
  45. // Routes that end in a catch all segment should be checked last
  46. match redirect.segments.last() {
  47. Some(RouteSegment::CatchAll(..)) => 2,
  48. _ => 1,
  49. }
  50. }
  51. }
  52. });
  53. }
  54. fn sort_children_of_id(&mut self, id: usize) {
  55. // Sort segments so that all static routes are checked before dynamic routes
  56. let mut children = self.children(id);
  57. self.sort_ids(&mut children);
  58. if let Some(old) = self.try_children_mut(id) {
  59. old.clone_from(&children)
  60. }
  61. for id in children {
  62. self.sort_children_of_id(id);
  63. }
  64. }
  65. fn children(&self, element: usize) -> Vec<usize> {
  66. let element = self.entries.get(element).unwrap();
  67. match element {
  68. RouteTreeSegmentData::Static { children, .. } => children.clone(),
  69. RouteTreeSegmentData::Nest { children, .. } => children.clone(),
  70. _ => Vec::new(),
  71. }
  72. }
  73. fn try_children_mut(&mut self, element: usize) -> Option<&mut Vec<usize>> {
  74. let element = self.entries.get_mut(element).unwrap();
  75. match element {
  76. RouteTreeSegmentData::Static { children, .. } => Some(children),
  77. RouteTreeSegmentData::Nest { children, .. } => Some(children),
  78. _ => None,
  79. }
  80. }
  81. fn children_mut(&mut self, element: usize) -> &mut Vec<usize> {
  82. self.try_children_mut(element)
  83. .expect("Cannot get children of non static or nest segment")
  84. }
  85. pub(crate) fn new(routes: &'a [Route], nests: &'a [Nest], redirects: &'a [Redirect]) -> Self {
  86. let routes = routes
  87. .iter()
  88. .map(|route| PathIter::new_route(route, nests))
  89. .chain(
  90. redirects
  91. .iter()
  92. .map(|redirect| PathIter::new_redirect(redirect, nests)),
  93. )
  94. .collect::<Vec<_>>();
  95. let mut myself = Self::default();
  96. myself.roots = myself.construct(routes);
  97. myself.sort_children();
  98. myself
  99. }
  100. pub fn construct(&mut self, routes: Vec<PathIter<'a>>) -> Vec<usize> {
  101. let mut segments = Vec::new();
  102. // Add all routes to the tree
  103. for mut route in routes {
  104. let mut current_route: Option<usize> = None;
  105. // First add all nests
  106. while let Some(nest) = route.next_nest() {
  107. let segments_iter = nest.segments.iter();
  108. // Add all static segments of the nest
  109. 'o: for (index, segment) in segments_iter.enumerate() {
  110. match segment {
  111. RouteSegment::Static(segment) => {
  112. // Check if the segment already exists
  113. {
  114. // Either look for the segment in the current route or in the static segments
  115. let segments = current_route
  116. .map(|id| self.children(id))
  117. .unwrap_or_else(|| segments.clone());
  118. for &seg_id in segments.iter() {
  119. let seg = self.get(seg_id).unwrap();
  120. if let RouteTreeSegmentData::Static { segment: s, .. } = seg {
  121. if *s == segment {
  122. // If it does, just update the current route
  123. current_route = Some(seg_id);
  124. continue 'o;
  125. }
  126. }
  127. }
  128. }
  129. let static_segment = RouteTreeSegmentData::Static {
  130. segment,
  131. children: Vec::new(),
  132. error_variant: StaticErrorVariant {
  133. variant_parse_error: nest.error_ident(),
  134. enum_variant: nest.error_variant(),
  135. },
  136. index,
  137. };
  138. // If it doesn't, add the segment to the current route
  139. let static_segment = self.entries.insert(static_segment);
  140. let current_children = current_route
  141. .map(|id| self.children_mut(id))
  142. .unwrap_or_else(|| &mut segments);
  143. current_children.push(static_segment);
  144. // Update the current route
  145. current_route = Some(static_segment);
  146. }
  147. // If there is a dynamic segment, stop adding static segments
  148. RouteSegment::Dynamic(..) => break,
  149. RouteSegment::CatchAll(..) => {
  150. todo!("Catch all segments are not allowed in nests")
  151. }
  152. }
  153. }
  154. // Add the nest to the current route
  155. let nest = RouteTreeSegmentData::Nest {
  156. nest,
  157. children: Vec::new(),
  158. };
  159. let nest = self.entries.insert(nest);
  160. let segments = match current_route.and_then(|id| self.get_mut(id)) {
  161. Some(RouteTreeSegmentData::Static { children, .. }) => children,
  162. Some(RouteTreeSegmentData::Nest { children, .. }) => children,
  163. Some(r) => {
  164. unreachable!("{current_route:?}\n{r:?} is not a static or nest segment",)
  165. }
  166. None => &mut segments,
  167. };
  168. segments.push(nest);
  169. // Update the current route
  170. current_route = Some(nest);
  171. }
  172. match route.next_static_segment() {
  173. // If there is a static segment, check if it already exists in the tree
  174. Some((i, segment)) => {
  175. let current_children = current_route
  176. .map(|id| self.children(id))
  177. .unwrap_or_else(|| segments.clone());
  178. let found = current_children.iter().find_map(|&id| {
  179. let seg = self.get(id).unwrap();
  180. match seg {
  181. RouteTreeSegmentData::Static { segment: s, .. } => {
  182. (s == &segment).then_some(id)
  183. }
  184. _ => None,
  185. }
  186. });
  187. match found {
  188. Some(id) => {
  189. // If it exists, add the route to the children of the segment
  190. let new_children = self.construct(vec![route]);
  191. self.children_mut(id).extend(new_children);
  192. }
  193. None => {
  194. // If it doesn't exist, add the route as a new segment
  195. let data = RouteTreeSegmentData::Static {
  196. segment,
  197. error_variant: route.error_variant(),
  198. children: self.construct(vec![route]),
  199. index: i,
  200. };
  201. let id = self.entries.insert(data);
  202. let current_children_mut = current_route
  203. .map(|id| self.children_mut(id))
  204. .unwrap_or_else(|| &mut segments);
  205. current_children_mut.push(id);
  206. }
  207. }
  208. }
  209. // If there is no static segment, add the route to the current_route
  210. None => {
  211. let id = self.entries.insert(route.final_segment);
  212. let current_children_mut = current_route
  213. .map(|id| self.children_mut(id))
  214. .unwrap_or_else(|| &mut segments);
  215. current_children_mut.push(id);
  216. }
  217. }
  218. }
  219. segments
  220. }
  221. }
  222. #[derive(Debug, Clone)]
  223. pub struct StaticErrorVariant {
  224. variant_parse_error: Ident,
  225. enum_variant: Ident,
  226. }
  227. // First deduplicate the routes by the static part of the route
  228. #[derive(Debug, Clone)]
  229. pub(crate) enum RouteTreeSegmentData<'a> {
  230. Static {
  231. segment: &'a str,
  232. error_variant: StaticErrorVariant,
  233. index: usize,
  234. children: Vec<usize>,
  235. },
  236. Nest {
  237. nest: &'a Nest,
  238. children: Vec<usize>,
  239. },
  240. Route(&'a Route),
  241. Redirect(&'a Redirect),
  242. }
  243. impl<'a> RouteTreeSegmentData<'a> {
  244. pub fn to_tokens(
  245. &self,
  246. nests: &[Nest],
  247. tree: &RouteTree,
  248. enum_name: syn::Ident,
  249. error_enum_name: syn::Ident,
  250. ) -> TokenStream {
  251. match self {
  252. RouteTreeSegmentData::Static {
  253. segment,
  254. children,
  255. index,
  256. error_variant:
  257. StaticErrorVariant {
  258. variant_parse_error,
  259. enum_variant,
  260. },
  261. } => {
  262. let children = children.iter().map(|child| {
  263. let child = tree.get(*child).unwrap();
  264. child.to_tokens(nests, tree, enum_name.clone(), error_enum_name.clone())
  265. });
  266. if segment.is_empty() {
  267. return quote! {
  268. {
  269. #(#children)*
  270. }
  271. };
  272. }
  273. let error_ident = static_segment_idx(*index);
  274. quote! {
  275. {
  276. let mut segments = segments.clone();
  277. let segment = segments.next();
  278. if let Some(segment) = segment.as_deref() {
  279. if #segment == segment {
  280. #(#children)*
  281. }
  282. else {
  283. errors.push(#error_enum_name::#enum_variant(#variant_parse_error::#error_ident(segment.to_string())))
  284. }
  285. }
  286. }
  287. }
  288. }
  289. RouteTreeSegmentData::Route(route) => {
  290. // At this point, we have matched all static segments, so we can just check if the remaining segments match the route
  291. let variant_parse_error = route.error_ident();
  292. let enum_variant = &route.route_name;
  293. let route_segments = route
  294. .segments
  295. .iter()
  296. .enumerate()
  297. .skip_while(|(_, seg)| matches!(seg, RouteSegment::Static(_)));
  298. let construct_variant = route.construct(nests, enum_name);
  299. let parse_query = route.parse_query();
  300. let parse_hash = route.parse_hash();
  301. let insure_not_trailing = match route.ty {
  302. RouteType::Leaf { .. } => route
  303. .segments
  304. .last()
  305. .map(|seg| !matches!(seg, RouteSegment::CatchAll(_, _)))
  306. .unwrap_or(true),
  307. RouteType::Child(_) => false,
  308. };
  309. let print_route_segment = print_route_segment(
  310. route_segments.peekable(),
  311. return_constructed(
  312. insure_not_trailing,
  313. construct_variant,
  314. &error_enum_name,
  315. enum_variant,
  316. &variant_parse_error,
  317. parse_query,
  318. parse_hash,
  319. ),
  320. &error_enum_name,
  321. enum_variant,
  322. &variant_parse_error,
  323. );
  324. match &route.ty {
  325. RouteType::Child(child) => {
  326. let ty = &child.ty;
  327. let child_name = &child.ident;
  328. quote! {
  329. let mut trailing = String::from("/");
  330. for seg in segments.clone() {
  331. trailing += &*seg;
  332. trailing += "/";
  333. }
  334. trailing.pop();
  335. match #ty::from_str(&trailing).map_err(|err| #error_enum_name::#enum_variant(#variant_parse_error::ChildRoute(err))) {
  336. Ok(#child_name) => {
  337. #print_route_segment
  338. }
  339. Err(err) => {
  340. errors.push(err);
  341. }
  342. }
  343. }
  344. }
  345. RouteType::Leaf { .. } => print_route_segment,
  346. }
  347. }
  348. Self::Nest { nest, children } => {
  349. // At this point, we have matched all static segments, so we can just check if the remaining segments match the route
  350. let variant_parse_error: Ident = nest.error_ident();
  351. let enum_variant = nest.error_variant();
  352. let route_segments = nest
  353. .segments
  354. .iter()
  355. .enumerate()
  356. .skip_while(|(_, seg)| matches!(seg, RouteSegment::Static(_)));
  357. let parse_children = children
  358. .iter()
  359. .map(|child| {
  360. let child = tree.get(*child).unwrap();
  361. child.to_tokens(nests, tree, enum_name.clone(), error_enum_name.clone())
  362. })
  363. .collect();
  364. print_route_segment(
  365. route_segments.peekable(),
  366. parse_children,
  367. &error_enum_name,
  368. &enum_variant,
  369. &variant_parse_error,
  370. )
  371. }
  372. Self::Redirect(redirect) => {
  373. // At this point, we have matched all static segments, so we can just check if the remaining segments match the route
  374. let variant_parse_error = redirect.error_ident();
  375. let enum_variant = &redirect.error_variant();
  376. let route_segments = redirect
  377. .segments
  378. .iter()
  379. .enumerate()
  380. .skip_while(|(_, seg)| matches!(seg, RouteSegment::Static(_)));
  381. let parse_query = redirect.parse_query();
  382. let parse_hash = redirect.parse_hash();
  383. let insure_not_trailing = redirect
  384. .segments
  385. .last()
  386. .map(|seg| !matches!(seg, RouteSegment::CatchAll(_, _)))
  387. .unwrap_or(true);
  388. let redirect_function = &redirect.function;
  389. let args = redirect_function.inputs.iter().map(|pat| match pat {
  390. syn::Pat::Type(ident) => {
  391. let name = &ident.pat;
  392. quote! {#name}
  393. }
  394. _ => panic!("Expected closure argument to be a typed pattern"),
  395. });
  396. let return_redirect = quote! {
  397. (#redirect_function)(#(#args,)*)
  398. };
  399. print_route_segment(
  400. route_segments.peekable(),
  401. return_constructed(
  402. insure_not_trailing,
  403. return_redirect,
  404. &error_enum_name,
  405. enum_variant,
  406. &variant_parse_error,
  407. parse_query,
  408. parse_hash,
  409. ),
  410. &error_enum_name,
  411. enum_variant,
  412. &variant_parse_error,
  413. )
  414. }
  415. }
  416. }
  417. }
  418. fn print_route_segment<'a, I: Iterator<Item = (usize, &'a RouteSegment)>>(
  419. mut s: std::iter::Peekable<I>,
  420. success_tokens: TokenStream,
  421. error_enum_name: &Ident,
  422. enum_variant: &Ident,
  423. variant_parse_error: &Ident,
  424. ) -> TokenStream {
  425. if let Some((i, route)) = s.next() {
  426. let children = print_route_segment(
  427. s,
  428. success_tokens,
  429. error_enum_name,
  430. enum_variant,
  431. variant_parse_error,
  432. );
  433. route.try_parse(
  434. i,
  435. error_enum_name,
  436. enum_variant,
  437. variant_parse_error,
  438. children,
  439. )
  440. } else {
  441. quote! {
  442. #success_tokens
  443. }
  444. }
  445. }
  446. fn return_constructed(
  447. insure_not_trailing: bool,
  448. construct_variant: TokenStream,
  449. error_enum_name: &Ident,
  450. enum_variant: &Ident,
  451. variant_parse_error: &Ident,
  452. parse_query: TokenStream,
  453. parse_hash: TokenStream,
  454. ) -> TokenStream {
  455. if insure_not_trailing {
  456. quote! {
  457. let remaining_segments = segments.clone();
  458. let mut segments_clone = segments.clone();
  459. let next_segment = segments_clone.next();
  460. let next_segment = next_segment.as_deref();
  461. let segment_after_next = segments_clone.next();
  462. let segment_after_next = segment_after_next.as_deref();
  463. match (next_segment, segment_after_next) {
  464. // This is the last segment, return the parsed route
  465. (None, _) | (Some(""), None) => {
  466. #parse_query
  467. #parse_hash
  468. return Ok(#construct_variant);
  469. }
  470. _ => {
  471. let mut trailing = String::new();
  472. for seg in remaining_segments {
  473. trailing += &*seg;
  474. trailing += "/";
  475. }
  476. trailing.pop();
  477. errors.push(#error_enum_name::#enum_variant(#variant_parse_error::ExtraSegments(trailing)))
  478. }
  479. }
  480. }
  481. } else {
  482. quote! {
  483. #parse_query
  484. #parse_hash
  485. return Ok(#construct_variant);
  486. }
  487. }
  488. }
  489. pub struct PathIter<'a> {
  490. final_segment: RouteTreeSegmentData<'a>,
  491. active_nests: &'a [NestId],
  492. all_nests: &'a [Nest],
  493. segments: &'a [RouteSegment],
  494. error_ident: Ident,
  495. error_variant: Ident,
  496. nest_index: usize,
  497. static_segment_index: usize,
  498. }
  499. impl<'a> PathIter<'a> {
  500. fn new_route(route: &'a Route, nests: &'a [Nest]) -> Self {
  501. Self {
  502. final_segment: RouteTreeSegmentData::Route(route),
  503. active_nests: &*route.nests,
  504. segments: &*route.segments,
  505. error_ident: route.error_ident(),
  506. error_variant: route.route_name.clone(),
  507. all_nests: nests,
  508. nest_index: 0,
  509. static_segment_index: 0,
  510. }
  511. }
  512. fn new_redirect(redirect: &'a Redirect, nests: &'a [Nest]) -> Self {
  513. Self {
  514. final_segment: RouteTreeSegmentData::Redirect(redirect),
  515. active_nests: &*redirect.nests,
  516. segments: &*redirect.segments,
  517. error_ident: redirect.error_ident(),
  518. error_variant: redirect.error_variant(),
  519. all_nests: nests,
  520. nest_index: 0,
  521. static_segment_index: 0,
  522. }
  523. }
  524. fn next_nest(&mut self) -> Option<&'a Nest> {
  525. let idx = self.nest_index;
  526. let nest_index = self.active_nests.get(idx)?;
  527. let nest = &self.all_nests[nest_index.0];
  528. self.nest_index += 1;
  529. Some(nest)
  530. }
  531. fn next_static_segment(&mut self) -> Option<(usize, &'a str)> {
  532. let idx = self.static_segment_index;
  533. let segment = self.segments.get(idx)?;
  534. match segment {
  535. RouteSegment::Static(segment) => {
  536. self.static_segment_index += 1;
  537. Some((idx, segment))
  538. }
  539. _ => None,
  540. }
  541. }
  542. fn error_variant(&self) -> StaticErrorVariant {
  543. StaticErrorVariant {
  544. variant_parse_error: self.error_ident.clone(),
  545. enum_variant: self.error_variant.clone(),
  546. }
  547. }
  548. }