Skip to content

Commit 0480642

Browse files
committed
bump: v0.7.0
1 parent dcf20be commit 0480642

File tree

6 files changed

+428
-458
lines changed

6 files changed

+428
-458
lines changed

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "path-tree"
3-
version = "0.6.0"
3+
version = "0.7.0"
44
authors = ["Fangdun Tsai <cfddream@gmail.com>"]
55
description = "path-tree is a lightweight high performance HTTP request router for Rust"
66
homepage = "https://github.com/viz-rs/path-tree"
@@ -20,7 +20,7 @@ include = [
2020
]
2121

2222
[dependencies]
23-
smallvec = "1.9.0"
23+
smallvec = "1.10.0"
2424

2525
[dev-dependencies]
2626
actix-router = "0.5"

README.md

+36-40
Original file line numberDiff line numberDiff line change
@@ -108,32 +108,30 @@ tree.insert("/:org/:repo/:page", 11);
108108
tree.insert("/:org/:repo/*", 12);
109109
tree.insert("/api/+", 13);
110110

111-
let r = tree.find("/").unwrap();
112-
assert_eq!(r.value, &0);
113-
assert_eq!(r.params(), vec![]);
111+
let (h, p) = tree.find("/").unwrap();
112+
assert_eq!(h, &0);
113+
assert_eq!(p.params(), vec![]);
114114

115-
let r = tree.find("/login").unwrap();
116-
assert_eq!(r.value, &1);
117-
assert_eq!(r.params(), vec![]);
115+
let (h, p) = tree.find("/login").unwrap();
116+
assert_eq!(h, &1);
117+
assert_eq!(p.params(), vec![]);
118118

119-
let r = tree.find("/settings/admin").unwrap();
120-
assert_eq!(r.value, &4);
121-
assert_eq!(r.params(), vec![("page", "admin")]);
119+
let (h, p) = tree.find("/settings/admin").unwrap();
120+
assert_eq!(h, &4);
121+
assert_eq!(p.params(), vec![("page", "admin")]);
122122

123-
let r = tree.find("/viz-rs").unwrap();
124-
assert_eq!(r.value, &5);
125-
assert_eq!(r.params(), vec![("user", "viz-rs")]);
123+
let (h, p) = tree.find("/viz-rs").unwrap();
124+
assert_eq!(h, &5);
125+
assert_eq!(p.params(), vec![("user", "viz-rs")]);
126126

127-
let r = tree.find("/viz-rs/path-tree").unwrap();
128-
assert_eq!(r.value, &6);
129-
assert_eq!(r.params(), vec![("user", "viz-rs"), ("repo", "path-tree")]);
127+
let (h, p) = tree.find("/viz-rs/path-tree").unwrap();
128+
assert_eq!(h, &6);
129+
assert_eq!(p.params(), vec![("user", "viz-rs"), ("repo", "path-tree")]);
130130

131-
assert_eq!(tree.url_for(*r.id, &["viz-rs", "viz"]).unwrap(), "/viz-rs/viz");
132-
133-
let r = tree.find("/rust-lang/rust-analyzer/releases/download/2022-09-12/rust-analyzer-aarch64-apple-darwin.gz").unwrap();
134-
assert_eq!(r.value, &8);
131+
let (h, p) = tree.find("/rust-lang/rust-analyzer/releases/download/2022-09-12/rust-analyzer-aarch64-apple-darwin.gz").unwrap();
132+
assert_eq!(h, &8);
135133
assert_eq!(
136-
r.params(),
134+
p.params(),
137135
vec![
138136
("org", "rust-lang"),
139137
("repo", "rust-analyzer"),
@@ -143,10 +141,10 @@ assert_eq!(
143141
]
144142
);
145143

146-
let r = tree.find("/rust-lang/rust-analyzer/tags/2022-09-12").unwrap();
147-
assert_eq!(r.value, &9);
144+
let (h, p) = tree.find("/rust-lang/rust-analyzer/tags/2022-09-12").unwrap();
145+
assert_eq!(h, &9);
148146
assert_eq!(
149-
r.params(),
147+
p.params(),
150148
vec![
151149
("org", "rust-lang"),
152150
("repo", "rust-analyzer"),
@@ -156,10 +154,10 @@ assert_eq!(
156154
]
157155
);
158156

159-
let r = tree.find("/rust-lang/rust-analyzer/actions/ci:bench").unwrap();
160-
assert_eq!(r.value, &10);
157+
let (h, p) = tree.find("/rust-lang/rust-analyzer/actions/ci:bench").unwrap();
158+
assert_eq!(h, &10);
161159
assert_eq!(
162-
r.params(),
160+
p.params(),
163161
vec![
164162
("org", "rust-lang"),
165163
("repo", "rust-analyzer"),
@@ -168,23 +166,21 @@ assert_eq!(
168166
]
169167
);
170168

171-
let r = tree.find("/rust-lang/rust-analyzer/stargazers").unwrap();
172-
assert_eq!(r.value, &11);
173-
assert_eq!(r.params(), vec![("org", "rust-lang"), ("repo", "rust-analyzer"), ("page", "stargazers")]);
174-
175-
let r = tree.find("/rust-lang/rust-analyzer/stargazers/404").unwrap();
176-
assert_eq!(r.value, &12);
177-
assert_eq!(r.params(), vec![("org", "rust-lang"), ("repo", "rust-analyzer"), ("*1", "stargazers/404")]);
169+
let (h, p) = tree.find("/rust-lang/rust-analyzer/stargazers").unwrap();
170+
assert_eq!(h, &11);
171+
assert_eq!(p.params(), vec![("org", "rust-lang"), ("repo", "rust-analyzer"), ("page", "stargazers")]);
178172

179-
let r = tree.find("/public/js/main.js").unwrap();
180-
assert_eq!(r.value, &7);
181-
assert_eq!(r.params(), vec![("any", "js/main.js")]);
173+
let (h, p) = tree.find("/rust-lang/rust-analyzer/stargazers/404").unwrap();
174+
assert_eq!(h, &12);
175+
assert_eq!(p.params(), vec![("org", "rust-lang"), ("repo", "rust-analyzer"), ("*1", "stargazers/404")]);
182176

183-
let r = tree.find("/api/v1").unwrap();
184-
assert_eq!(r.value, &13);
185-
assert_eq!(r.params(), vec![("+1", "v1")]);
177+
let (h, p) = tree.find("/public/js/main.js").unwrap();
178+
assert_eq!(h, &7);
179+
assert_eq!(p.params(), vec![("any", "js/main.js")]);
186180

187-
assert_eq!(tree.url_for(*r.id, &["repos/viz-rs"]).unwrap(), "/api/repos/viz-rs");
181+
let (h, p) = tree.find("/api/v1").unwrap();
182+
assert_eq!(h, &13);
183+
assert_eq!(p.params(), vec![("+1", "v1")]);
188184
```
189185

190186
Hyper hello example can be found [here](examples/hello.rs).

benches/bench.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ fn bench_path_find(c: &mut Criterion) {
131131
b.iter(|| {
132132
for (i, r) in ROUTES_URLS.iter().enumerate() {
133133
let n = tree.find(r).unwrap();
134-
assert_eq!(*n.value, i);
134+
assert_eq!(*n.0, i);
135135
}
136136
})
137137
})

examples/hello.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
9595

9696
async move {
9797
Ok::<_, Infallible>(match router.find(&path) {
98-
Some(route) => {
98+
Some((handler, route)) => {
9999
let p = route
100100
.params()
101101
.iter()
102102
.map(|p| (p.0.to_string(), p.1.to_string()))
103103
.collect::<Params>();
104104
req.extensions_mut().insert(p);
105-
route.value.call(req).await
105+
handler.call(req).await
106106
}
107107
None => Response::builder()
108108
.status(StatusCode::NOT_FOUND)

src/lib.rs

+60-85
Original file line numberDiff line numberDiff line change
@@ -57,30 +57,30 @@
5757
//! tree.insert("/:org/:repo/*", 12);
5858
//! tree.insert("/api/+", 13);
5959
//!
60-
//! let r = tree.find("/").unwrap();
61-
//! assert_eq!(r.value, &0);
62-
//! assert_eq!(r.params(), vec![]);
60+
//! let (h, p) = tree.find("/").unwrap();
61+
//! assert_eq!(h, &0);
62+
//! assert_eq!(p.params(), vec![]);
6363
//!
64-
//! let r = tree.find("/login").unwrap();
65-
//! assert_eq!(r.value, &1);
66-
//! assert_eq!(r.params(), vec![]);
64+
//! let (h, p) = tree.find("/login").unwrap();
65+
//! assert_eq!(h, &1);
66+
//! assert_eq!(p.params(), vec![]);
6767
//!
68-
//! let r = tree.find("/settings/admin").unwrap();
69-
//! assert_eq!(r.value, &4);
70-
//! assert_eq!(r.params(), vec![("page", "admin")]);
68+
//! let (h, p) = tree.find("/settings/admin").unwrap();
69+
//! assert_eq!(h, &4);
70+
//! assert_eq!(p.params(), vec![("page", "admin")]);
7171
//!
72-
//! let r = tree.find("/viz-rs").unwrap();
73-
//! assert_eq!(r.value, &5);
74-
//! assert_eq!(r.params(), vec![("user", "viz-rs")]);
72+
//! let (h, p) = tree.find("/viz-rs").unwrap();
73+
//! assert_eq!(h, &5);
74+
//! assert_eq!(p.params(), vec![("user", "viz-rs")]);
7575
//!
76-
//! let r = tree.find("/viz-rs/path-tree").unwrap();
77-
//! assert_eq!(r.value, &6);
78-
//! assert_eq!(r.params(), vec![("user", "viz-rs"), ("repo", "path-tree")]);
76+
//! let (h, p) = tree.find("/viz-rs/path-tree").unwrap();
77+
//! assert_eq!(h, &6);
78+
//! assert_eq!(p.params(), vec![("user", "viz-rs"), ("repo", "path-tree")]);
7979
//!
80-
//! let r = tree.find("/rust-lang/rust-analyzer/releases/download/2022-09-12/rust-analyzer-aarch64-apple-darwin.gz").unwrap();
81-
//! assert_eq!(r.value, &8);
80+
//! let (h, p) = tree.find("/rust-lang/rust-analyzer/releases/download/2022-09-12/rust-analyzer-aarch64-apple-darwin.gz").unwrap();
81+
//! assert_eq!(h, &8);
8282
//! assert_eq!(
83-
//! r.params(),
83+
//! p.params(),
8484
//! vec![
8585
//! ("org", "rust-lang"),
8686
//! ("repo", "rust-analyzer"),
@@ -90,10 +90,10 @@
9090
//! ]
9191
//! );
9292
//!
93-
//! let r = tree.find("/rust-lang/rust-analyzer/tags/2022-09-12").unwrap();
94-
//! assert_eq!(r.value, &9);
93+
//! let (h, p) = tree.find("/rust-lang/rust-analyzer/tags/2022-09-12").unwrap();
94+
//! assert_eq!(h, &9);
9595
//! assert_eq!(
96-
//! r.params(),
96+
//! p.params(),
9797
//! vec![
9898
//! ("org", "rust-lang"),
9999
//! ("repo", "rust-analyzer"),
@@ -103,10 +103,10 @@
103103
//! ]
104104
//! );
105105
//!
106-
//! let r = tree.find("/rust-lang/rust-analyzer/actions/ci:bench").unwrap();
107-
//! assert_eq!(r.value, &10);
106+
//! let (h, p) = tree.find("/rust-lang/rust-analyzer/actions/ci:bench").unwrap();
107+
//! assert_eq!(h, &10);
108108
//! assert_eq!(
109-
//! r.params(),
109+
//! p.params(),
110110
//! vec![
111111
//! ("org", "rust-lang"),
112112
//! ("repo", "rust-analyzer"),
@@ -115,21 +115,21 @@
115115
//! ]
116116
//! );
117117
//!
118-
//! let r = tree.find("/rust-lang/rust-analyzer/stargazers").unwrap();
119-
//! assert_eq!(r.value, &11);
120-
//! assert_eq!(r.params(), vec![("org", "rust-lang"), ("repo", "rust-analyzer"), ("page", "stargazers")]);
118+
//! let (h, p) = tree.find("/rust-lang/rust-analyzer/stargazers").unwrap();
119+
//! assert_eq!(h, &11);
120+
//! assert_eq!(p.params(), vec![("org", "rust-lang"), ("repo", "rust-analyzer"), ("page", "stargazers")]);
121121
//!
122-
//! let r = tree.find("/rust-lang/rust-analyzer/stargazers/404").unwrap();
123-
//! assert_eq!(r.value, &12);
124-
//! assert_eq!(r.params(), vec![("org", "rust-lang"), ("repo", "rust-analyzer"), ("*1", "stargazers/404")]);
122+
//! let (h, p) = tree.find("/rust-lang/rust-analyzer/stargazers/404").unwrap();
123+
//! assert_eq!(h, &12);
124+
//! assert_eq!(p.params(), vec![("org", "rust-lang"), ("repo", "rust-analyzer"), ("*1", "stargazers/404")]);
125125
//!
126-
//! let r = tree.find("/public/js/main.js").unwrap();
127-
//! assert_eq!(r.value, &7);
128-
//! assert_eq!(r.params(), vec![("any", "js/main.js")]);
126+
//! let (h, p) = tree.find("/public/js/main.js").unwrap();
127+
//! assert_eq!(h, &7);
128+
//! assert_eq!(p.params(), vec![("any", "js/main.js")]);
129129
//!
130-
//! let r = tree.find("/api/v1").unwrap();
131-
//! assert_eq!(r.value, &13);
132-
//! assert_eq!(r.params(), vec![("+1", "v1")]);
130+
//! let (h, p) = tree.find("/api/v1").unwrap();
131+
//! assert_eq!(h, &13);
132+
//! assert_eq!(p.params(), vec![("+1", "v1")]);
133133
//! ```
134134
135135
#![no_std]
@@ -142,12 +142,7 @@ use alloc::{
142142
string::{String, ToString},
143143
vec::Vec,
144144
};
145-
use core::{
146-
iter::{Copied, FilterMap, Zip},
147-
marker::PhantomData,
148-
slice::Iter,
149-
str::from_utf8,
150-
};
145+
use core::str::from_utf8;
151146

152147
use smallvec::SmallVec;
153148

@@ -212,21 +207,23 @@ impl<T> PathTree<T> {
212207
}
213208

214209
/// Returns the [Path] by the given path.
215-
pub fn find<'b>(&self, path: &'b str) -> Option<Path<'_, 'b, T>> {
210+
pub fn find<'a, 'b>(&'a self, path: &'b str) -> Option<(&T, Path<'a, 'b>)> {
216211
let bytes = path.as_bytes();
217212
self.node.find(bytes).and_then(|(id, ranges)| {
218213
self.get_route(*id).map(|(value, pieces)| {
219-
Path {
220-
id,
214+
(
221215
value,
222-
pieces,
223-
// opt!
224-
raws: ranges
225-
.into_iter()
226-
.filter_map(|r| from_utf8(&bytes[r]).ok())
227-
.rev()
228-
.collect(),
229-
}
216+
Path {
217+
id,
218+
pieces,
219+
// opt!
220+
raws: ranges
221+
.into_iter()
222+
.filter_map(|r| from_utf8(&bytes[r]).ok())
223+
.rev()
224+
.collect(),
225+
},
226+
)
230227
})
231228
})
232229
}
@@ -260,15 +257,14 @@ impl<T> PathTree<T> {
260257
}
261258

262259
/// Matched route path infomation.
263-
#[derive(Debug, PartialEq, Eq)]
264-
pub struct Path<'a, 'b, T> {
260+
#[derive(Clone, Debug, PartialEq, Eq)]
261+
pub struct Path<'a, 'b> {
265262
pub id: &'a usize,
266-
pub value: &'a T,
267263
pub pieces: &'a [Piece],
268264
pub raws: SmallVec<[&'b str; 4]>,
269265
}
270266

271-
impl<'a, 'b, T> Path<'a, 'b, T> {
267+
impl<'a, 'b> Path<'a, 'b> {
272268
/// Gets current path pattern.
273269
pub fn pattern(&self) -> String {
274270
let mut bytes = Vec::new();
@@ -312,14 +308,14 @@ impl<'a, 'b, T> Path<'a, 'b, T> {
312308
}
313309

314310
/// Returns the parameters of the current path.
315-
pub fn params(&self) -> Vec<(&'a str, &'b str)> {
311+
pub fn params(&self) -> Vec<(&str, &str)> {
316312
self.params_iter().collect()
317313
}
318314

319315
/// Returns the parameters iterator of the current path.
320-
pub fn params_iter<'p>(&'p self) -> ParamsIter<'p, 'a, 'b, T> {
316+
pub fn params_iter(&self) -> impl Iterator<Item = (&str, &str)> {
321317
#[inline]
322-
fn piece_filter(piece: &Piece) -> Option<&'_ str> {
318+
fn piece_filter(piece: &Piece) -> Option<&str> {
323319
match piece {
324320
Piece::String(_) => None,
325321
Piece::Parameter(p, _) => from_utf8(match p {
@@ -329,30 +325,9 @@ impl<'a, 'b, T> Path<'a, 'b, T> {
329325
}
330326
}
331327

332-
ParamsIter {
333-
iter: self
334-
.pieces
335-
.iter()
336-
.filter_map(piece_filter as fn(piece: &'a Piece) -> Option<&'a str>)
337-
.zip(self.raws.iter().copied()),
338-
_t: PhantomData,
339-
}
340-
}
341-
}
342-
343-
type FilterIter<'a> = FilterMap<Iter<'a, Piece>, fn(piece: &'a Piece) -> Option<&'a str>>;
344-
345-
/// A Parameters Iterator.
346-
pub struct ParamsIter<'p, 'a, 'b, T> {
347-
iter: Zip<FilterIter<'a>, Copied<Iter<'p, &'b str>>>,
348-
_t: PhantomData<T>,
349-
}
350-
351-
impl<'p, 'a, 'b, T> Iterator for ParamsIter<'p, 'a, 'b, T> {
352-
type Item = (&'a str, &'b str);
353-
354-
#[inline]
355-
fn next(&mut self) -> Option<Self::Item> {
356-
self.iter.next()
328+
self.pieces
329+
.iter()
330+
.filter_map(piece_filter)
331+
.zip(self.raws.iter().copied())
357332
}
358333
}

0 commit comments

Comments
 (0)