Skip to content

Commit fa8e8ca

Browse files
committed
feat: supports removing node by path
1 parent c147468 commit fa8e8ca

File tree

2 files changed

+267
-8
lines changed

2 files changed

+267
-8
lines changed

Diff for: src/lib.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@
139139
extern crate alloc;
140140

141141
use alloc::{
142+
collections::BTreeMap,
142143
string::{String, ToString},
143144
vec::Vec,
144145
};
@@ -155,7 +156,7 @@ pub use parser::{Kind, Parser, Piece, Position};
155156
#[derive(Clone, Debug)]
156157
pub struct PathTree<T> {
157158
id: usize,
158-
routes: Vec<(T, Vec<Piece>)>,
159+
routes: BTreeMap<usize, (T, Vec<Piece>)>,
159160
pub node: Node<usize>,
160161
}
161162

@@ -171,7 +172,7 @@ impl<T> PathTree<T> {
171172
pub fn new() -> Self {
172173
Self {
173174
id: 0,
174-
routes: Vec::new(),
175+
routes: BTreeMap::new(),
175176
node: Node::new(Key::String(Vec::new()), None),
176177
}
177178
}
@@ -193,14 +194,15 @@ impl<T> PathTree<T> {
193194
};
194195

195196
if let Some(id) = node.value {
196-
self.routes[id].0 = value;
197+
let route = self.routes.get_mut(&id).expect("route should exist");
198+
route.0 = value;
197199
if overwritten {
198-
self.routes[id].1 = pieces;
200+
route.1 = pieces;
199201
}
200202
id
201203
} else {
202-
self.routes.push((value, pieces));
203204
let id = self.id;
205+
self.routes.insert(id, (value, pieces));
204206
node.value = Some(id);
205207
self.id += 1;
206208
id
@@ -212,7 +214,7 @@ impl<T> PathTree<T> {
212214
pub fn find<'a, 'b>(&'a self, path: &'b str) -> Option<(&T, Path<'a, 'b>)> {
213215
let bytes = path.as_bytes();
214216
self.node.find(bytes).and_then(|(id, ranges)| {
215-
self.get_route(*id).map(|(value, pieces)| {
217+
self.routes.get(id).map(|(value, pieces)| {
216218
(
217219
value,
218220
Path {
@@ -230,11 +232,17 @@ impl<T> PathTree<T> {
230232
})
231233
}
232234

235+
pub fn remove(&mut self, path: &str) -> Option<T> {
236+
self.node
237+
.remove(path.as_bytes())
238+
.and_then(|id| self.routes.remove(&id).map(|(value, _)| value))
239+
}
240+
233241
/// Gets the route by id.
234242
#[must_use]
235243
#[inline]
236244
pub fn get_route(&self, index: usize) -> Option<&(T, Vec<Piece>)> {
237-
self.routes.get(index)
245+
self.routes.get(&index)
238246
}
239247

240248
/// Generates URL with the params.

Diff for: src/node.rs

+252-1
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,258 @@ impl<T: fmt::Debug> Node<T> {
384384

385385
pub fn find(&self, bytes: &[u8]) -> Option<(&T, SmallVec<[Range<usize>; 8]>)> {
386386
let mut ranges = SmallVec::<[Range<usize>; 8]>::new(); // opt!
387-
return self._find(0, bytes, &mut ranges).map(|t| (t, ranges));
387+
self._find(0, bytes, &mut ranges).map(|t| (t, ranges))
388+
}
389+
390+
pub fn _remove(&mut self, mut start: usize, mut bytes: &[u8]) -> Option<T> {
391+
let mut m = bytes.len();
392+
match &self.key {
393+
Key::String(s) => {
394+
let n = s.len();
395+
let mut flag = m >= n;
396+
397+
// opt!
398+
if flag {
399+
if n == 1 {
400+
flag = s[0] == bytes[0];
401+
} else {
402+
flag = s == &bytes[..n];
403+
}
404+
}
405+
406+
// starts with prefix
407+
if flag {
408+
m -= n;
409+
start += n;
410+
bytes = &bytes[n..];
411+
412+
if m == 0 {
413+
return self.value.take();
414+
} else {
415+
// static
416+
if let Some(id) = self.nodes0.as_mut().and_then(|nodes| {
417+
nodes
418+
.binary_search_by(|node| match &node.key {
419+
Key::String(s) => {
420+
// s[0].cmp(&bytes[0])
421+
// opt!
422+
// lets `/` at end
423+
compare(s[0], bytes[0])
424+
}
425+
Key::Parameter(_) => unreachable!(),
426+
})
427+
.ok()
428+
.and_then(|i| nodes[i]._remove(start, bytes))
429+
}) {
430+
return Some(id);
431+
}
432+
}
433+
434+
// parameter
435+
if let Some(id) = self.nodes1.as_mut().and_then(|nodes| {
436+
let b = m > 0;
437+
nodes
438+
.iter_mut()
439+
.filter(|node| match node.key {
440+
Key::Parameter(pk)
441+
if pk == Kind::Normal || pk == Kind::OneOrMore =>
442+
{
443+
b
444+
}
445+
_ => true,
446+
})
447+
.find_map(|node| node._remove(start, bytes))
448+
}) {
449+
return Some(id);
450+
}
451+
} else if n == 1 && s[0] == b'/' {
452+
if let Some(id) = self.nodes1.as_mut().and_then(|nodes| {
453+
nodes
454+
.iter_mut()
455+
.filter(|node| {
456+
matches!(node.key,
457+
Key::Parameter(pk)
458+
if pk == Kind::OptionalSegment
459+
|| pk == Kind::ZeroOrMoreSegment
460+
)
461+
})
462+
.find_map(|node| node._remove(start, bytes))
463+
}) {
464+
return Some(id);
465+
}
466+
}
467+
}
468+
Key::Parameter(k) => match k {
469+
Kind::Normal | Kind::Optional | Kind::OptionalSegment => {
470+
if m == 0 {
471+
if k == &Kind::Normal {
472+
return None;
473+
}
474+
475+
// last
476+
if self.nodes0.is_none() && self.nodes1.is_none() {
477+
return self.value.take();
478+
}
479+
} else {
480+
// static
481+
if let Some(id) = self.nodes0.as_mut().and_then(|nodes| {
482+
nodes.iter_mut().find_map(|node| match &node.key {
483+
Key::String(s) => {
484+
let mut keep_running = true;
485+
if let Some(n) = bytes
486+
.iter()
487+
// as it turns out doing .copied() here is much slower than dereferencing in the closure
488+
// https://godbolt.org/z/7dnW91T1Y
489+
.take_while(|b| {
490+
if keep_running && **b == b'/' {
491+
keep_running = false;
492+
true
493+
} else {
494+
keep_running
495+
}
496+
})
497+
.enumerate()
498+
.find_map(|(n, b)| (s[0] == *b).then_some(n))
499+
{
500+
node._remove(start + n, &bytes[n..])
501+
} else {
502+
None
503+
}
504+
}
505+
Key::Parameter(_) => unreachable!(),
506+
})
507+
}) {
508+
return Some(id);
509+
}
510+
511+
// parameter => `:a:b:c`
512+
if let Some(id) = self.nodes1.as_mut().and_then(|nodes| {
513+
let b = m - 1 > 0;
514+
nodes
515+
.iter_mut()
516+
.filter(|node| match node.key {
517+
Key::Parameter(pk)
518+
if pk == Kind::Normal || pk == Kind::OneOrMore =>
519+
{
520+
b
521+
}
522+
_ => true,
523+
})
524+
.find_map(|node| node._remove(start + 1, &bytes[1..]))
525+
}) {
526+
return Some(id);
527+
}
528+
}
529+
530+
// parameter => `:a:b?:c?`
531+
if k == &Kind::Optional || k == &Kind::OptionalSegment {
532+
if let Some(id) = self.nodes1.as_mut().and_then(|nodes| {
533+
let b = m > 0;
534+
nodes
535+
.iter_mut()
536+
.filter(|node| match &node.key {
537+
Key::Parameter(pk)
538+
if pk == &Kind::Normal || pk == &Kind::OneOrMore =>
539+
{
540+
b
541+
}
542+
_ => true,
543+
})
544+
.find_map(|node| node._remove(start, bytes))
545+
}) {
546+
// param should be empty
547+
return Some(id);
548+
}
549+
}
550+
551+
if let Some(n) = bytes.iter().position(|b| *b == b'/') {
552+
bytes = &bytes[n..];
553+
} else {
554+
if self.value.is_some() {
555+
return self.value.take();
556+
}
557+
bytes = &bytes[m..];
558+
}
559+
560+
if k == &Kind::OptionalSegment {
561+
if let Some(id) = self.nodes0.as_mut().and_then(|nodes| {
562+
nodes
563+
.last_mut()
564+
.filter(|node| match &node.key {
565+
Key::String(s) => s[0] == b'/',
566+
Key::Parameter(_) => unreachable!(),
567+
})
568+
.and_then(|node| node._remove(start, bytes))
569+
}) {
570+
return Some(id);
571+
}
572+
}
573+
}
574+
Kind::OneOrMore | Kind::ZeroOrMore | Kind::ZeroOrMoreSegment => {
575+
let is_one_or_more = k == &Kind::OneOrMore;
576+
if m == 0 {
577+
if is_one_or_more {
578+
return None;
579+
}
580+
581+
if self.nodes0.is_none() && self.nodes1.is_none() {
582+
return self.value.take();
583+
}
584+
} else {
585+
if self.nodes0.is_none() && self.nodes1.is_none() {
586+
if self.value.is_some() {
587+
return self.value.take();
588+
}
589+
}
590+
591+
// static
592+
if let Some(id) = self.nodes0.as_mut().and_then(|nodes| {
593+
nodes.iter_mut().find_map(|node| {
594+
if let Key::String(s) = &node.key {
595+
let right_length = if is_one_or_more {
596+
m > s.len()
597+
} else {
598+
m >= s.len()
599+
};
600+
if right_length {
601+
return if let Some(n) = bytes
602+
.iter()
603+
.enumerate()
604+
.find_map(|(n, b)| (s[0] == *b).then_some(n))
605+
{
606+
node._remove(start + n, &bytes[n..])
607+
} else {
608+
None
609+
};
610+
}
611+
}
612+
None
613+
})
614+
}) {
615+
return Some(id);
616+
}
617+
}
618+
619+
if k == &Kind::ZeroOrMoreSegment {
620+
return self.nodes0.as_mut().and_then(|nodes| {
621+
nodes
622+
.iter_mut()
623+
.last()
624+
.filter(|node| match &node.key {
625+
Key::String(s) => s[0] == b'/',
626+
Key::Parameter(_) => unreachable!(),
627+
})
628+
.and_then(|node| node._remove(start, bytes))
629+
});
630+
}
631+
}
632+
},
633+
}
634+
None
635+
}
636+
637+
pub fn remove(&mut self, bytes: &[u8]) -> Option<T> {
638+
self._remove(0, bytes)
388639
}
389640
}
390641

0 commit comments

Comments
 (0)