use core::slice::Iter;
use crate::path::{Param, Pattern};
pub struct Node {
pub pattern: Pattern,
pub route: Option<usize>,
entries: Vec<usize>,
}
pub struct RouteEntry<'a, T> {
key: usize,
store: &'a mut RouteStore<T>,
}
pub struct RouteStore<T> {
nodes: Vec<Node>,
routes: Vec<T>,
}
impl Node {
pub fn new(pattern: Pattern) -> Self {
Self {
pattern,
entries: Vec::new(),
route: None,
}
}
pub fn entries(&self) -> Iter<usize> {
self.entries.iter()
}
pub fn param(&self) -> Option<&Param> {
match &self.pattern {
Pattern::CatchAll(param) | Pattern::Dynamic(param) => Some(param),
_ => None,
}
}
}
impl Node {
fn push(&mut self, key: usize) -> usize {
self.entries.push(key);
key
}
}
impl<'a, T> RouteEntry<'a, T> {
pub fn push(&mut self, node: Node) -> usize {
let next_node_index = self.store.push(node);
self.store.get_mut(self.key).push(next_node_index);
next_node_index
}
pub fn insert_route(&mut self, route: T) -> usize {
let route_index = self.store.push_route(route);
self.store.get_mut(self.key).route = Some(route_index);
route_index
}
pub fn get_or_insert_route_with<F>(&mut self, f: F) -> usize
where
F: FnOnce() -> T,
{
let route = self.store.get(self.key).route;
route.unwrap_or_else(|| self.insert_route(f()))
}
}
impl<T> RouteStore<T> {
pub fn new() -> Self {
Self {
nodes: Vec::new(),
routes: Vec::new(),
}
}
pub fn entry(&mut self, key: usize) -> RouteEntry<T> {
RouteEntry { key, store: self }
}
pub fn push(&mut self, node: Node) -> usize {
let key = self.nodes.len();
self.nodes.push(node);
key
}
pub fn get(&self, key: usize) -> &Node {
&self.nodes[key]
}
pub fn get_mut(&mut self, key: usize) -> &mut Node {
&mut self.nodes[key]
}
pub fn route(&self, key: usize) -> Option<&T> {
self.routes.get(key)
}
pub fn route_mut(&mut self, key: usize) -> &mut T {
&mut self.routes[key]
}
}
impl<T> RouteStore<T> {
fn push_route(&mut self, route: T) -> usize {
let index = self.routes.len();
self.routes.push(route);
index
}
}