Skip to content
This repository has been archived by the owner on Jun 17, 2023. It is now read-only.

Commit

Permalink
rename crate to prefix_tree_map
Browse files Browse the repository at this point in the history
  • Loading branch information
EAimTY committed Dec 5, 2021
1 parent a53a1ae commit 6fff3cd
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 34 deletions.
9 changes: 8 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
[package]
name = "trie_map"
name = "prefix_tree_map"
description = "A Rust implementation of generic prefix tree (trie) map with wildcard capture support"
categories = ["data-structures"]
keywords = ["trie", "prefix", "tree", "map", "collection"]
version = "0.1.0"
authors = ["EAimTY <ea.imty@gmail.com>"]
edition = "2021"
readme = "README.md"
license = "GPL-3.0-or-later"
repository = "https://github.com/EAimTY/prefix_tree_map"

[dependencies]
30 changes: 17 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
# trie_map
A Rust implementation of generic trie map with wildcard capture support.
# prefix_tree_map
A Rust implementation of generic prefix tree (trie) map with wildcard capture support.

[![Version](https://img.shields.io/crates/v/prefix_tree_map.svg?style=flat)](https://crates.io/crates/prefix_tree_map)
[![Documentation](https://img.shields.io/badge/docs-release-brightgreen.svg?style=flat)](https://docs.rs/prefix_tree_map)
[![License](https://img.shields.io/crates/l/prefix_tree_map.svg?style=flat)](https://github.com/EAimTY/prefix_tree_map/blob/master/LICENSE)

## Design
[Trie](https://en.wikipedia.org/wiki/Trie) is a good data structure for storing key-value pairs with wildcard support ability.

This trie map implementation supports any type of key and value, as long as key parts are implemented the `Ord` and `Clone` trait. Internally, nodes are stored in a sorted `Vec`. So technically it can achieve `O(log n)` time complexity on finding every node by using binary search on the sorted `Vec`.
This prefix tree map implementation supports any type of key and value, as long as key parts are implemented the `Ord` and `Clone` trait. Internally, nodes are stored in a sorted `Vec`. So technically it can achieve `O(log n)` time complexity on finding every node by using binary search on the sorted `Vec`.

Using as a route-table-like structure could be the best scenario for this crate.

Expand All @@ -15,26 +19,26 @@ Using as a route-table-like structure could be the best scenario for this crate.
- **Wildcard Capture Support** - Capture wildcard characters in a map while matching.
- **Generalization** - Supports any type of key and value, as long as key parts are implemented the `Ord` and `Clone` trait.
- **Capture Map Customization** - Customize the way key parts captured by wildcard stored.
- **No recursion in find operations** - Rather than store the whole context of every node searching, this trie map only store those tiny wildcard node pointers for backtracking on heap.
- **No recursion in find operations** - Rather than store the whole context of every node searching, this prefix tree map only store those tiny wildcard node pointers for backtracking on heap.

### Cons
- The map itself is immutable, because the map builder is using Binary Heap to sort the nodes when they are inserted. We can't get a item from a Binary Heap without iterating the whole Binary Heap. Once the `build()` is called, Binary Heaps are converted into sorted `Vec`s. We can't push any item to the `Vec` without a whole sort operation.
- Currently, a single wildcard cannot be matched more than one time. It means `word` can be matched by `w**d`, not `w*d`.

## Usage
```rust
use trie_map::TrieMapBuilder;
use prefix_tree_map::PrefixTreeMapBuilder;

let mut map_builder = TrieMapBuilder::new();
let mut map_builder = PrefixTreeMapBuilder::new();

// To insert an exact key path, call `insert_exact()`
map_builder.insert_exact(["path", "to", "value"], "value0");

// Insert into a existed key path could overwrite the value in it
map_builder.insert_exact(["path", "to", "value"], "value1");

// To insert an key path with wildcards, mark key parts using `trie_map::KeyPart` and call `insert()`
use trie_map::KeyPart;
// To insert an key path with wildcards, mark key parts using `prefix_tree_map::KeyPart` and call `insert()`
use prefix_tree_map::KeyPart;

map_builder.insert(
[
Expand Down Expand Up @@ -100,7 +104,7 @@ impl Map {
}
}

use trie_map::CaptureMap;
use prefix_tree_map::CaptureMap;

impl CaptureMap<&str, &str> for Map {
fn insert(&mut self, key: &str, value: &str) {
Expand All @@ -125,9 +129,9 @@ impl CaptureMap<&str, &str> for Map {
}

fn capture() {
use trie_map::{KeyPart, TrieMapBuilder};
use prefix_tree_map::{KeyPart, PrefixTreeMapBuilder};

let mut builder = TrieMapBuilder::new();
let mut builder = PrefixTreeMapBuilder::new();

builder.insert(
[
Expand Down Expand Up @@ -159,11 +163,11 @@ fn capture() {
}
```

For more infomation, check out [examples/router.rs](https://github.com/EAimTY/trie_map/blob/master/examples/router.rs)
For more infomation, check out [examples/router.rs](https://github.com/EAimTY/prefix_tree_map/blob/master/examples/router.rs)

## Examples

Check [examples](https://github.com/EAimTY/trie_map/tree/master/examples).
Check [examples](https://github.com/EAimTY/prefix_tree_map/tree/master/examples).

## License
GNU General Public License v3.0
6 changes: 3 additions & 3 deletions examples/router.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use trie_map::{CaptureMap, KeyPart, TrieMap, TrieMapBuilder};
use prefix_tree_map::{CaptureMap, KeyPart, PrefixTreeMap, PrefixTreeMapBuilder};

struct Router {
table: TrieMap<&'static str, Param, Handler>,
table: PrefixTreeMap<&'static str, Param, Handler>,
}

#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
Expand All @@ -25,7 +25,7 @@ fn product_handler(id: &str) {

impl Router {
fn new() -> Self {
let mut builder = TrieMapBuilder::new();
let mut builder = PrefixTreeMapBuilder::new();

let user_url = "/user/:user_id/home";
let product_url = "/product/:product_id/info";
Expand Down
20 changes: 10 additions & 10 deletions src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::{
key_part::KeyPart,
trie_map::{Node, TrieMap},
prefix_tree_map::{Node, PrefixTreeMap},
};
use std::collections::BinaryHeap;

/// The trie map builder.
/// The prefix tree map builder.
#[derive(Clone)]
pub struct TrieMapBuilder<E, W, V> {
pub struct PrefixTreeMapBuilder<E, W, V> {
root: NodeBuilder<E, W, V>,
}

Expand All @@ -17,12 +17,12 @@ struct NodeBuilder<E, W, V> {
children: Option<BinaryHeap<NodeBuilder<E, W, V>>>,
}

impl<E, W, V> TrieMapBuilder<E, W, V>
impl<E, W, V> PrefixTreeMapBuilder<E, W, V>
where
E: Clone + Ord,
W: Clone + Ord,
{
/// Create a new `TrieMapBuilder`.
/// Create a new `PrefixTreeMapBuilder`.
pub fn new() -> Self {
Self {
root: NodeBuilder {
Expand All @@ -33,7 +33,7 @@ where
}
}

/// Insert a new value into the trie map.
/// Insert a new value into the prefix tree map.
///
/// Key parts need to be marked by [`KeyPart`](enum.KeyPart.html).
///
Expand Down Expand Up @@ -83,9 +83,9 @@ where
self.insert(key.into_iter().map(KeyPart::Exact), value);
}

/// Build the trie map.
pub fn build(self) -> TrieMap<E, W, V> {
TrieMap {
/// Build the prefix tree map.
pub fn build(self) -> PrefixTreeMap<E, W, V> {
PrefixTreeMap {
root: Self::node_builder_to_node(self.root),
}
}
Expand All @@ -110,7 +110,7 @@ where
}
}

impl<E, W, V> Default for TrieMapBuilder<E, W, V>
impl<E, W, V> Default for PrefixTreeMapBuilder<E, W, V>
where
E: Clone + Ord,
W: Clone + Ord,
Expand Down
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
mod builder;
mod capture_map;
mod key_part;
mod trie_map;
mod prefix_tree_map;

pub use self::{
builder::TrieMapBuilder, capture_map::CaptureMap, key_part::KeyPart, trie_map::TrieMap,
builder::PrefixTreeMapBuilder, capture_map::CaptureMap, key_part::KeyPart,
prefix_tree_map::PrefixTreeMap,
};
10 changes: 5 additions & 5 deletions src/trie_map.rs → src/prefix_tree_map.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{capture_map::CaptureMap, key_part::KeyPart};
use std::fmt::Debug;

/// The trie map.
/// The prefix tree map.
#[derive(Clone)]
pub struct TrieMap<E, W, V> {
pub struct PrefixTreeMap<E, W, V> {
pub(crate) root: Node<E, W, V>,
}

Expand All @@ -14,7 +14,7 @@ pub(crate) struct Node<E, W, V> {
pub(crate) children: Option<Vec<Node<E, W, V>>>,
}

impl<E, W, V> TrieMap<E, W, V>
impl<E, W, V> PrefixTreeMap<E, W, V>
where
E: Clone + Ord,
W: Clone + Ord,
Expand Down Expand Up @@ -178,9 +178,9 @@ where
}
}

impl<E: Debug, W: Debug, V: Debug> Debug for TrieMap<E, W, V> {
impl<E: Debug, W: Debug, V: Debug> Debug for PrefixTreeMap<E, W, V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "TrieMap {{ root: {:?} }}", self.root)
write!(f, "PrefixTreeMap {{ root: {:?} }}", self.root)
}
}

Expand Down

0 comments on commit 6fff3cd

Please sign in to comment.