Make Router faster to clone (#1123)

* Make `Router` faster to clone

* changelog

* Update axum/src/routing/mod.rs

Co-authored-by: Jonas Platte <jplatte+git@posteo.de>

* fix

* Update axum/src/routing/mod.rs

Co-authored-by: Jonas Platte <jplatte+git@posteo.de>

Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
This commit is contained in:
David Pedersen 2022-06-27 11:00:19 +02:00 committed by GitHub
parent 523c7fed88
commit cb207472f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 8 deletions

View file

@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
# Unreleased # Unreleased
- None. - **fixed:** Make `Router` cheaper to clone ([#1123])
[#1123]: https://github.com/tokio-rs/axum/pull/1123
# 0.5.9 (20. June, 2022) # 0.5.9 (20. June, 2022)

View file

@ -64,7 +64,7 @@ impl RouteId {
/// The router type for composing handlers and services. /// The router type for composing handlers and services.
pub struct Router<B = Body> { pub struct Router<B = Body> {
routes: HashMap<RouteId, Endpoint<B>>, routes: HashMap<RouteId, Endpoint<B>>,
node: Node, node: Arc<Node>,
fallback: Fallback<B>, fallback: Fallback<B>,
nested_at_root: bool, nested_at_root: bool,
} }
@ -73,7 +73,7 @@ impl<B> Clone for Router<B> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
routes: self.routes.clone(), routes: self.routes.clone(),
node: self.node.clone(), node: Arc::clone(&self.node),
fallback: self.fallback.clone(), fallback: self.fallback.clone(),
nested_at_root: self.nested_at_root, nested_at_root: self.nested_at_root,
} }
@ -162,9 +162,12 @@ where
Err(service) => Endpoint::Route(Route::new(service)), Err(service) => Endpoint::Route(Route::new(service)),
}; };
if let Err(err) = self.node.insert(path, id) { let mut node =
Arc::try_unwrap(Arc::clone(&self.node)).unwrap_or_else(|node| (*node).clone());
if let Err(err) = node.insert(path, id) {
self.panic_on_matchit_error(err); self.panic_on_matchit_error(err);
} }
self.node = Arc::new(node);
self.routes.insert(id, service); self.routes.insert(id, service);
@ -211,12 +214,12 @@ where
panic!("Cannot nest `Router`s that has a fallback"); panic!("Cannot nest `Router`s that has a fallback");
} }
for (id, nested_path) in node.route_id_to_path { for (id, nested_path) in &node.route_id_to_path {
let route = routes.remove(&id).unwrap(); let route = routes.remove(id).unwrap();
let full_path: Cow<str> = if &*nested_path == "/" { let full_path: Cow<str> = if &**nested_path == "/" {
path.into() path.into()
} else if path == "/" { } else if path == "/" {
(&*nested_path).into() (&**nested_path).into()
} else if let Some(path) = path.strip_suffix('/') { } else if let Some(path) = path.strip_suffix('/') {
format!("{}{}", path, nested_path).into() format!("{}{}", path, nested_path).into()
} else { } else {
@ -632,6 +635,7 @@ impl<B> fmt::Debug for Endpoint<B> {
} }
#[test] #[test]
#[allow(warnings)]
fn traits() { fn traits() {
use crate::test_helpers::*; use crate::test_helpers::*;
assert_send::<Router<()>>(); assert_send::<Router<()>>();