matchit/tree.rs
1use crate::escape::{UnescapedRef, UnescapedRoute};
2use crate::{InsertError, MatchError, Params};
3
4use std::cell::UnsafeCell;
5use std::cmp::min;
6use std::ops::Range;
7use std::{fmt, mem};
8
9/// A radix tree used for URL path matching.
10///
11/// See [the crate documentation](crate) for details.
12pub struct Node<T> {
13 // This node's prefix.
14 pub(crate) prefix: UnescapedRoute,
15 // The priority of this node.
16 //
17 // Nodes with more children are higher priority and searched first.
18 pub(crate) priority: u32,
19 // Whether this node contains a wildcard child.
20 pub(crate) wild_child: bool,
21 // The first character of any static children, for fast linear search.
22 pub(crate) indices: Vec<u8>,
23 // The type of this node.
24 pub(crate) node_type: NodeType,
25 pub(crate) children: Vec<Self>,
26 // The value stored at this node.
27 //
28 // See `Node::at` for why an `UnsafeCell` is necessary.
29 value: Option<UnsafeCell<T>>,
30 // Parameter name remapping, stored at nodes that hold values.
31 pub(crate) remapping: ParamRemapping,
32}
33
34/// The types of nodes a tree can hold.
35#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
36pub(crate) enum NodeType {
37 /// The root path.
38 Root,
39 /// A route parameter, e.g. `/{id}`.
40 Param,
41 /// A catch-all parameter, e.g. `/*file`.
42 CatchAll,
43 /// A static prefix, e.g. `/foo`.
44 Static,
45}
46
47/// Safety: We expose `value` per Rust's usual borrowing rules, so we can just
48/// delegate these traits.
49unsafe impl<T: Send> Send for Node<T> {}
50unsafe impl<T: Sync> Sync for Node<T> {}
51
52impl<T> Node<T> {
53 // Insert a route into the tree.
54 pub fn insert(&mut self, route: String, val: T) -> Result<(), InsertError> {
55 let route = UnescapedRoute::new(route.into_bytes());
56 let (route, remapping) = normalize_params(route)?;
57 let mut remaining = route.as_ref();
58
59 self.priority += 1;
60
61 // If the tree is empty, insert the root node.
62 if self.prefix.is_empty() && self.children.is_empty() {
63 let last = self.insert_route(remaining, val)?;
64 last.remapping = remapping;
65 self.node_type = NodeType::Root;
66 return Ok(());
67 }
68
69 let mut current = self;
70 'walk: loop {
71 // Find the common prefix between the route and the current node.
72 let len = min(remaining.len(), current.prefix.len());
73 let common_prefix = (0..len)
74 .find(|&i| {
75 remaining[i] != current.prefix[i]
76 // Make sure not confuse the start of a wildcard with an escaped `{`.
77 || remaining.is_escaped(i) != current.prefix.is_escaped(i)
78 })
79 .unwrap_or(len);
80
81 // If this node has a longer prefix than we need, we have to fork and extract the
82 // common prefix into a shared parent.
83 if current.prefix.len() > common_prefix {
84 // Move the non-matching suffix into a child node.
85 let suffix = current.prefix.as_ref().slice_off(common_prefix).to_owned();
86 let child = Node {
87 prefix: suffix,
88 value: current.value.take(),
89 indices: current.indices.clone(),
90 wild_child: current.wild_child,
91 children: mem::take(&mut current.children),
92 remapping: mem::take(&mut current.remapping),
93 priority: current.priority - 1,
94 node_type: NodeType::Static,
95 };
96
97 // The current node now only holds the common prefix.
98 current.children = vec![child];
99 current.indices = vec![current.prefix[common_prefix]];
100 current.prefix = current
101 .prefix
102 .as_ref()
103 .slice_until(common_prefix)
104 .to_owned();
105 current.wild_child = false;
106 continue;
107 }
108
109 if remaining.len() == common_prefix {
110 // This node must not already contain a value.
111 if current.value.is_some() {
112 return Err(InsertError::conflict(&route, remaining, current));
113 }
114
115 // Insert the value.
116 current.value = Some(UnsafeCell::new(val));
117 current.remapping = remapping;
118 return Ok(());
119 }
120
121 // Otherwise, the route has a remaining non-matching suffix.
122 //
123 // We have to search deeper.
124 remaining = remaining.slice_off(common_prefix);
125 let next = remaining[0];
126
127 // After matching against a wildcard the next character is always `/`.
128 //
129 // Continue searching in the child node if it already exists.
130 if current.node_type == NodeType::Param && current.children.len() == 1 {
131 debug_assert_eq!(next, b'/');
132 current = &mut current.children[0];
133 current.priority += 1;
134 continue 'walk;
135 }
136
137 // Find a child node that matches the next character in the route.
138 for mut i in 0..current.indices.len() {
139 if next == current.indices[i] {
140 // Make sure not confuse the start of a wildcard with an escaped `{` or `}`.
141 if matches!(next, b'{' | b'}') && !remaining.is_escaped(0) {
142 continue;
143 }
144
145 // Continue searching in the child.
146 i = current.update_child_priority(i);
147 current = &mut current.children[i];
148 continue 'walk;
149 }
150 }
151
152 // We couldn't find a matching child.
153 //
154 // If we're not inserting a wildcard we have to create a child.
155 if (!matches!(next, b'{') || remaining.is_escaped(0))
156 && current.node_type != NodeType::CatchAll
157 {
158 current.indices.push(next);
159 let mut child = current.add_child(Node::default());
160 child = current.update_child_priority(child);
161
162 // Insert into the newly created node.
163 let last = current.children[child].insert_route(remaining, val)?;
164 last.remapping = remapping;
165 return Ok(());
166 }
167
168 // We're trying to insert a wildcard.
169 //
170 // If this node already has a wildcard child, we have to make sure it matches.
171 if current.wild_child {
172 // Wildcards are always the last child.
173 current = current.children.last_mut().unwrap();
174 current.priority += 1;
175
176 // Make sure the route parameter matches.
177 if let Some(wildcard) = remaining.get(..current.prefix.len()) {
178 if *wildcard != *current.prefix {
179 return Err(InsertError::conflict(&route, remaining, current));
180 }
181 }
182
183 // Catch-all routes cannot have children.
184 if current.node_type == NodeType::CatchAll {
185 return Err(InsertError::conflict(&route, remaining, current));
186 }
187
188 // Continue with the wildcard node.
189 continue 'walk;
190 }
191
192 // Otherwise, create a new node for the wildcard and insert the route.
193 let last = current.insert_route(remaining, val)?;
194 last.remapping = remapping;
195 return Ok(());
196 }
197 }
198
199 /// Removes a route from the tree, returning the value if the route already existed.
200 ///
201 /// The provided path should be the same as the one used to insert the route, including
202 /// wildcards.
203 pub fn remove(&mut self, route: String) -> Option<T> {
204 let route = UnescapedRoute::new(route.into_bytes());
205 let (route, remapping) = normalize_params(route).ok()?;
206 let mut remaining = route.unescaped();
207
208 // Check if we are removing the root node.
209 if remaining == self.prefix.unescaped() {
210 let value = self.value.take().map(UnsafeCell::into_inner);
211
212 // If the root node has no children, we can reset it.
213 if self.children.is_empty() {
214 *self = Node::default();
215 }
216
217 return value;
218 }
219
220 let mut current = self;
221 'walk: loop {
222 // The path is longer than this node's prefix, search deeper.
223 if remaining.len() > current.prefix.len() {
224 let (prefix, rest) = remaining.split_at(current.prefix.len());
225
226 // The prefix matches.
227 if prefix == current.prefix.unescaped() {
228 let first = rest[0];
229 remaining = rest;
230
231 // If there is a single child node, we can continue searching in the child.
232 if current.children.len() == 1 {
233 // The route matches, remove the node.
234 if current.children[0].prefix.unescaped() == remaining {
235 return current.remove_child(0, &remapping);
236 }
237
238 // Otherwise, continue searching.
239 current = &mut current.children[0];
240 continue 'walk;
241 }
242
243 // Find a child node that matches the next character in the route.
244 if let Some(i) = current.indices.iter().position(|&c| c == first) {
245 // The route matches, remove the node.
246 if current.children[i].prefix.unescaped() == remaining {
247 return current.remove_child(i, &remapping);
248 }
249
250 // Otherwise, continue searching.
251 current = &mut current.children[i];
252 continue 'walk;
253 }
254
255 // If the node has a matching wildcard child, continue searching in the child.
256 if current.wild_child
257 && remaining.first().zip(remaining.get(2)) == Some((&b'{', &b'}'))
258 {
259 // The route matches, remove the node.
260 if current.children.last_mut().unwrap().prefix.unescaped() == remaining {
261 return current.remove_child(current.children.len() - 1, &remapping);
262 }
263
264 current = current.children.last_mut().unwrap();
265 continue 'walk;
266 }
267 }
268 }
269
270 // Could not find a match.
271 return None;
272 }
273 }
274
275 /// Remove the child node at the given index, if the route parameters match.
276 fn remove_child(&mut self, i: usize, remapping: &ParamRemapping) -> Option<T> {
277 // Require an exact match to remove a route.
278 //
279 // For example, `/{a}` cannot be used to remove `/{b}`.
280 if self.children[i].remapping != *remapping {
281 return None;
282 }
283
284 // If the node does not have any children, we can remove it completely.
285 let value = if self.children[i].children.is_empty() {
286 // Removing a single child with no indices.
287 if self.children.len() == 1 && self.indices.is_empty() {
288 self.wild_child = false;
289 self.children.remove(0).value.take()
290 } else {
291 // Remove the child node.
292 let child = self.children.remove(i);
293
294 match child.node_type {
295 // Remove the index if we removed a static prefix.
296 NodeType::Static => {
297 self.indices.remove(i);
298 }
299 // Otherwise, we removed a wildcard.
300 _ => self.wild_child = false,
301 }
302
303 child.value
304 }
305 }
306 // Otherwise, remove the value but preserve the node.
307 else {
308 self.children[i].value.take()
309 };
310
311 value.map(UnsafeCell::into_inner)
312 }
313
314 // Adds a child to this node, keeping wildcards at the end.
315 fn add_child(&mut self, child: Node<T>) -> usize {
316 let len = self.children.len();
317
318 if self.wild_child && len > 0 {
319 self.children.insert(len - 1, child);
320 len - 1
321 } else {
322 self.children.push(child);
323 len
324 }
325 }
326
327 // Increments priority of the given child node, reordering the children if necessary.
328 //
329 // Returns the new index of the node.
330 fn update_child_priority(&mut self, i: usize) -> usize {
331 self.children[i].priority += 1;
332 let priority = self.children[i].priority;
333
334 // Move the node to the front as necessary.
335 let mut updated = i;
336 while updated > 0 && self.children[updated - 1].priority < priority {
337 self.children.swap(updated - 1, updated);
338 updated -= 1;
339 }
340
341 // Update the position of the indices to match.
342 if updated != i {
343 self.indices[updated..=i].rotate_right(1);
344 }
345
346 updated
347 }
348
349 // Insert a route at this node.
350 fn insert_route(
351 &mut self,
352 mut prefix: UnescapedRef<'_>,
353 val: T,
354 ) -> Result<&mut Node<T>, InsertError> {
355 let mut current = self;
356
357 loop {
358 // Search for a wildcard segment.
359 let wildcard = match find_wildcard(prefix)? {
360 Some(wildcard) => wildcard,
361 // There is no wildcard, simply insert into the current node.
362 None => {
363 current.value = Some(UnsafeCell::new(val));
364 current.prefix = prefix.to_owned();
365 return Ok(current);
366 }
367 };
368
369 // Insering a catch-all route.
370 if prefix[wildcard.clone()][1] == b'*' {
371 // Ensure there is no suffix after the parameter, e.g. `/foo/{*x}/bar`.
372 if wildcard.end != prefix.len() {
373 return Err(InsertError::InvalidCatchAll);
374 }
375
376 // Add the prefix before the wildcard into the current node.
377 if wildcard.start > 0 {
378 current.prefix = prefix.slice_until(wildcard.start).to_owned();
379 prefix = prefix.slice_off(wildcard.start);
380 }
381
382 // Add the catch-all as a child node.
383 let child = Self {
384 prefix: prefix.to_owned(),
385 node_type: NodeType::CatchAll,
386 value: Some(UnsafeCell::new(val)),
387 priority: 1,
388 ..Self::default()
389 };
390
391 let i = current.add_child(child);
392 current.wild_child = true;
393 return Ok(&mut current.children[i]);
394 }
395
396 // Otherwise, we're inserting a regular route parameter.
397 assert_eq!(prefix[wildcard.clone()][0], b'{');
398
399 // Add the prefix before the wildcard into the current node.
400 if wildcard.start > 0 {
401 current.prefix = prefix.slice_until(wildcard.start).to_owned();
402 prefix = prefix.slice_off(wildcard.start);
403 }
404
405 // Add the parameter as a child node.
406 let child = Self {
407 node_type: NodeType::Param,
408 prefix: prefix.slice_until(wildcard.len()).to_owned(),
409 ..Self::default()
410 };
411
412 let child = current.add_child(child);
413 current.wild_child = true;
414 current = &mut current.children[child];
415 current.priority += 1;
416
417 // If the route doesn't end in the wildcard, we have to insert the suffix as a child.
418 if wildcard.len() < prefix.len() {
419 prefix = prefix.slice_off(wildcard.len());
420 let child = Self {
421 priority: 1,
422 ..Self::default()
423 };
424
425 let child = current.add_child(child);
426 current = &mut current.children[child];
427 continue;
428 }
429
430 // Finally, insert the value.
431 current.value = Some(UnsafeCell::new(val));
432 return Ok(current);
433 }
434 }
435}
436
437/// A wildcard node that was skipped during a tree search.
438///
439/// Contains the state necessary to backtrack to the given node.
440struct Skipped<'n, 'p, T> {
441 // The node that was skipped.
442 node: &'n Node<T>,
443 /// The path at the time we skipped this node.
444 path: &'p [u8],
445 // The number of parameters that were present.
446 params: usize,
447}
448
449#[rustfmt::skip]
450macro_rules! backtracker {
451 ($skipped_nodes:ident, $path:ident, $current:ident, $params:ident, $backtracking:ident, $walk:lifetime) => {
452 macro_rules! try_backtrack {
453 () => {
454 // Try backtracking to any matching wildcard nodes that we skipped while
455 // traversing the tree.
456 while let Some(skipped) = $skipped_nodes.pop() {
457 if skipped.path.ends_with($path) {
458 // Restore the search state.
459 $path = skipped.path;
460 $current = &skipped.node;
461 $params.truncate(skipped.params);
462 $backtracking = true;
463 continue $walk;
464 }
465 }
466 };
467 }
468 };
469}
470
471impl<T> Node<T> {
472 // Returns the node matching the given path.
473 //
474 // Returning an `UnsafeCell` allows us to avoid duplicating the logic between `Node::at` and
475 // `Node::at_mut`, as Rust doesn't have a great way of abstracting over mutability.
476 pub fn at<'node, 'path>(
477 &'node self,
478 full_path: &'path [u8],
479 ) -> Result<(&'node UnsafeCell<T>, Params<'node, 'path>), MatchError> {
480 let mut current = self;
481 let mut path = full_path;
482 let mut backtracking = false;
483 let mut params = Params::new();
484 let mut skipped_nodes: Vec<Skipped<'_, '_, T>> = Vec::new();
485
486 'walk: loop {
487 // Initialize the backtracker.
488 backtracker!(skipped_nodes, path, current, params, backtracking, 'walk);
489
490 // Reached the end of the search.
491 if path.len() <= current.prefix.len() {
492 // Check for an exact match.
493 if *path == *current.prefix {
494 // Found the matching value.
495 if let Some(ref value) = current.value {
496 // Remap the keys of any route parameters we accumulated during the search.
497 params.for_each_key_mut(|(i, key)| *key = ¤t.remapping[i]);
498 return Ok((value, params));
499 }
500 }
501
502 // Try backtracking in case we skipped a wildcard that may match.
503 try_backtrack!();
504
505 // Otherwise, there are no matching routes in the tree.
506 return Err(MatchError::NotFound);
507 }
508
509 // Otherwise, the path is longer than this node's prefix, search deeper.
510 let (prefix, rest) = path.split_at(current.prefix.len());
511
512 // The prefix does not match.
513 if *prefix != *current.prefix {
514 // Try backtracking in case we skipped a wildcard that may match.
515 try_backtrack!();
516
517 // Otherwise, there are no matching routes in the tree.
518 return Err(MatchError::NotFound);
519 }
520
521 let previous = path;
522 path = rest;
523
524 // If we are currently backtracking, avoid searching static children
525 // that we already searched.
526 if !backtracking {
527 let next = path[0];
528
529 // Find a child node that matches the next character in the path.
530 if let Some(i) = current.indices.iter().position(|&c| c == next) {
531 // Keep track of wildcard routes that we skip.
532 //
533 // We may end up needing to backtrack later in case we do not find a
534 // match.
535 if current.wild_child {
536 skipped_nodes.push(Skipped {
537 path: previous,
538 node: current,
539 params: params.len(),
540 });
541 }
542
543 // Continue searching.
544 current = ¤t.children[i];
545 continue 'walk;
546 }
547 }
548
549 // We didn't find a matching static child.
550 //
551 // If there are no wildcards, then there are no matching routes in the tree.
552 if !current.wild_child {
553 // Try backtracking in case we skipped a wildcard that may match.
554 try_backtrack!();
555 return Err(MatchError::NotFound);
556 }
557
558 // Continue searching in the wildcard child, which is kept at the end of the list.
559 current = current.children.last().unwrap();
560 match current.node_type {
561 // Match against a route parameter.
562 NodeType::Param => {
563 // Check for more path segments.
564 let i = match path.iter().position(|&c| c == b'/') {
565 // Found another segment.
566 Some(i) => i,
567 // This is the last path segment.
568 None => {
569 let value = match current.value {
570 // Found the matching value.
571 Some(ref value) => value,
572 None => {
573 // Try backtracking in case we skipped a wildcard that may match.
574 try_backtrack!();
575
576 // Otherwise, there are no matching routes in the tree.
577 return Err(MatchError::NotFound);
578 }
579 };
580
581 // Store the parameter value.
582 // Parameters are normalized so the key is irrelevant for now.
583 params.push(b"", path);
584
585 // Remap the keys of any route parameters we accumulated during the search.
586 params.for_each_key_mut(|(i, key)| *key = ¤t.remapping[i]);
587
588 return Ok((value, params));
589 }
590 };
591
592 // Found another path segment.
593 let (param, rest) = path.split_at(i);
594
595 // If there is a static child, continue the search.
596 if let [child] = current.children.as_slice() {
597 // Store the parameter value.
598 // Parameters are normalized so the key is irrelevant for now.
599 params.push(b"", param);
600
601 // Continue searching.
602 path = rest;
603 current = child;
604 backtracking = false;
605 continue 'walk;
606 }
607
608 // Try backtracking in case we skipped a wildcard that may match.
609 try_backtrack!();
610
611 // Otherwise, there are no matching routes in the tree.
612 return Err(MatchError::NotFound);
613 }
614 NodeType::CatchAll => {
615 // Catch-all segments are only allowed at the end of the route, meaning
616 // this node must contain the value.
617 let value = match current.value {
618 // Found the matching value.
619 Some(ref value) => value,
620 // Otherwise, there are no matching routes in the tree.
621 None => return Err(MatchError::NotFound),
622 };
623
624 // Remap the keys of any route parameters we accumulated during the search.
625 params.for_each_key_mut(|(i, key)| *key = ¤t.remapping[i]);
626
627 // Store the final catch-all parameter (`{*...}`).
628 let key = ¤t.prefix[2..current.prefix.len() - 1];
629 params.push(key, path);
630
631 return Ok((value, params));
632 }
633 _ => unreachable!(),
634 }
635 }
636 }
637
638 /// Test helper that ensures route priorities are consistent.
639 #[cfg(feature = "__test_helpers")]
640 pub fn check_priorities(&self) -> Result<u32, (u32, u32)> {
641 let mut priority: u32 = 0;
642 for child in &self.children {
643 priority += child.check_priorities()?;
644 }
645
646 if self.value.is_some() {
647 priority += 1;
648 }
649
650 if self.priority != priority {
651 return Err((self.priority, priority));
652 }
653
654 Ok(priority)
655 }
656}
657
658/// An ordered list of route parameters keys for a specific route.
659///
660/// To support conflicting routes like `/{a}/foo` and `/{b}/bar`, route parameters
661/// are normalized before being inserted into the tree. Parameter remapping are
662/// stored at nodes containing values, containing the "true" names of all route parameters
663/// for the given route.
664type ParamRemapping = Vec<Vec<u8>>;
665
666/// Returns `path` with normalized route parameters, and a parameter remapping
667/// to store at the node for this route.
668///
669/// Note that the parameter remapping may contain unescaped characters.
670fn normalize_params(
671 mut path: UnescapedRoute,
672) -> Result<(UnescapedRoute, ParamRemapping), InsertError> {
673 let mut start = 0;
674 let mut original = ParamRemapping::new();
675
676 // Parameter names are normalized alphabetically.
677 let mut next = b'a';
678
679 loop {
680 // Find a wildcard to normalize.
681 let mut wildcard = match find_wildcard(path.as_ref().slice_off(start))? {
682 Some(wildcard) => wildcard,
683 // No wildcard, we are done.
684 None => return Ok((path, original)),
685 };
686
687 wildcard.start += start;
688 wildcard.end += start;
689
690 // Ensure the parameter has a valid name.
691 if wildcard.len() < 2 {
692 return Err(InsertError::InvalidParam);
693 }
694
695 // We don't need to normalize catch-all parameters, as they are always
696 // at the end of a route.
697 if path[wildcard.clone()][1] == b'*' {
698 start = wildcard.end;
699 continue;
700 }
701
702 // Normalize the parameter.
703 let removed = path.splice(wildcard.clone(), vec![b'{', next, b'}']);
704
705 // Preserve the original name for remapping.
706 let mut removed = removed.skip(1).collect::<Vec<_>>();
707 removed.pop();
708 original.push(removed);
709
710 next += 1;
711 if next > b'z' {
712 panic!("Too many route parameters.");
713 }
714
715 // Continue the search after the parameter we just normalized.
716 start = wildcard.start + 3;
717 }
718}
719
720/// Restores `route` to it's original, denormalized form.
721pub(crate) fn denormalize_params(route: &mut UnescapedRoute, params: &ParamRemapping) {
722 let mut start = 0;
723 let mut i = 0;
724
725 loop {
726 // Find a wildcard to denormalize.
727 let mut wildcard = match find_wildcard(route.as_ref().slice_off(start)).unwrap() {
728 Some(w) => w,
729 None => return,
730 };
731
732 wildcard.start += start;
733 wildcard.end += start;
734
735 // Get the corresponding parameter remapping.
736 let mut next = match params.get(i) {
737 Some(param) => param.clone(),
738 None => return,
739 };
740
741 // Denormalize this parameter.
742 next.insert(0, b'{');
743 next.push(b'}');
744 let _ = route.splice(wildcard.clone(), next.clone());
745
746 i += 1;
747 start = wildcard.start + next.len();
748 }
749}
750
751// Searches for a wildcard segment and checks the path for invalid characters.
752fn find_wildcard(path: UnescapedRef<'_>) -> Result<Option<Range<usize>>, InsertError> {
753 for (start, &c) in path.iter().enumerate() {
754 // Found an unescaped closing brace without a corresponding opening brace.
755 if c == b'}' && !path.is_escaped(start) {
756 return Err(InsertError::InvalidParam);
757 }
758
759 // Keep going until we find an unescaped opening brace.
760 if c != b'{' || path.is_escaped(start) {
761 continue;
762 }
763
764 // Ensure there is a non-empty parameter name.
765 if path.get(start + 1) == Some(&b'}') {
766 return Err(InsertError::InvalidParam);
767 }
768
769 // Find the corresponding closing brace.
770 for (i, &c) in path.iter().enumerate().skip(start + 2) {
771 match c {
772 b'}' => {
773 // This closing brace was escaped, keep searching.
774 if path.is_escaped(i) {
775 continue;
776 }
777
778 // Ensure catch-all parameters have a non-empty name.
779 if path.get(i - 1) == Some(&b'*') {
780 return Err(InsertError::InvalidParam);
781 }
782
783 if let Some(&c) = path.get(i + 1) {
784 // Prefixes after route parameters are not supported.
785 if c != b'/' {
786 return Err(InsertError::InvalidParamSegment);
787 }
788 }
789
790 return Ok(Some(start..i + 1));
791 }
792 // `*` and `/` are invalid in parameter names.
793 b'*' | b'/' => return Err(InsertError::InvalidParam),
794 _ => {}
795 }
796 }
797
798 // Missing closing brace.
799 return Err(InsertError::InvalidParam);
800 }
801
802 Ok(None)
803}
804
805impl<T> Clone for Node<T>
806where
807 T: Clone,
808{
809 fn clone(&self) -> Self {
810 let value = self.value.as_ref().map(|value| {
811 // Safety: We only expose `&mut T` through `&mut self`.
812 let value = unsafe { &*value.get() };
813 UnsafeCell::new(value.clone())
814 });
815
816 Self {
817 value,
818 prefix: self.prefix.clone(),
819 wild_child: self.wild_child,
820 node_type: self.node_type.clone(),
821 indices: self.indices.clone(),
822 children: self.children.clone(),
823 remapping: self.remapping.clone(),
824 priority: self.priority,
825 }
826 }
827}
828
829impl<T> Default for Node<T> {
830 fn default() -> Self {
831 Self {
832 remapping: ParamRemapping::new(),
833 prefix: UnescapedRoute::default(),
834 wild_child: false,
835 node_type: NodeType::Static,
836 indices: Vec::new(),
837 children: Vec::new(),
838 value: None,
839 priority: 0,
840 }
841 }
842}
843
844impl<T> fmt::Debug for Node<T>
845where
846 T: fmt::Debug,
847{
848 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
849 // Safety: We only expose `&mut T` through `&mut self`.
850 let value = unsafe { self.value.as_ref().map(|x| &*x.get()) };
851
852 let mut f = f.debug_struct("Node");
853 f.field("value", &value)
854 .field("prefix", &self.prefix)
855 .field("node_type", &self.node_type)
856 .field("children", &self.children);
857
858 // Extra information for debugging purposes.
859 #[cfg(test)]
860 {
861 let indices = self
862 .indices
863 .iter()
864 .map(|&x| char::from_u32(x as _))
865 .collect::<Vec<_>>();
866
867 let params = self
868 .remapping
869 .iter()
870 .map(|x| std::str::from_utf8(x).unwrap())
871 .collect::<Vec<_>>();
872
873 f.field("indices", &indices).field("params", ¶ms);
874 }
875
876 f.finish()
877 }
878}