#![no_std]
extern crate alloc;
use alloc::borrow::Borrow;
use alloc::collections::BTreeMap;
use alloc::vec::Vec;
pub struct Module<K, V> {
pub data: V,
modules: BTreeMap<K, Module<K, V>>,
}
impl<K: Ord, V> From<V> for Module<K, V> {
fn from(data: V) -> Self {
Self {
data,
modules: Default::default(),
}
}
}
impl<K: Ord, V: Default> Default for Module<K, V> {
fn default() -> Self {
Module {
data: Default::default(),
modules: Default::default(),
}
}
}
impl<K: Ord, V> Module<K, V> {
pub fn get<'q, Q: 'q, I>(mut self: &Self, path: I) -> Option<&Self>
where
K: Borrow<Q>,
Q: Ord + ?Sized,
I: Iterator<Item = &'q Q>,
{
for p in path {
self = self.modules.get(p)?;
}
Some(self)
}
}
pub struct Context<K, V> {
root: Module<K, V>,
open: Vec<(K, Module<K, V>)>,
}
impl<K, V> From<Module<K, V>> for Context<K, V> {
fn from(root: Module<K, V>) -> Self {
let open = Vec::new();
Self { root, open }
}
}
impl<K: Ord, V: Default> Default for Context<K, V> {
fn default() -> Self {
Self::from(Module::default())
}
}
impl<K: Ord, V: Default> Context<K, V> {
pub fn new() -> Self {
Default::default()
}
pub fn open_or_default(&mut self, name: K) {
let module = self.remove(&name).unwrap_or_default();
self.open.push((name, module))
}
}
impl<K: Ord, V> Context<K, V> {
pub fn open_or(&mut self, name: K, module: Module<K, V>) {
let module = self.remove(&name).unwrap_or(module);
self.open.push((name, module))
}
pub fn open_or_else(&mut self, name: K, f: impl FnOnce() -> Module<K, V>) {
let module = self.remove(&name).unwrap_or_else(f);
self.open.push((name, module))
}
pub fn insert(&mut self, name: K, module: Module<K, V>) -> Option<Module<K, V>> {
self.get_mut().modules.insert(name, module)
}
pub fn remove(&mut self, name: &K) -> Option<Module<K, V>> {
self.get_mut().modules.remove(name)
}
pub fn close(&mut self) -> bool {
if let Some((name, module)) = self.open.pop() {
self.get_mut().modules.insert(name, module);
return true;
}
false
}
pub fn find<'a, 'q, Q: 'q, I>(&'a self, path: I) -> impl Iterator<Item = &'a Module<K, V>>
where
K: Borrow<Q>,
Q: Ord + ?Sized,
I: Iterator<Item = &'q Q> + Clone,
{
let patc = path.clone();
let open = self.open.iter().rev();
let init = open.filter_map(move |o| o.1.get(patc.clone()));
let mut last = Some(move || self.root.get(path));
init.chain(core::iter::from_fn(move || last.take()?()))
}
}
impl<K, V> Context<K, V> {
pub fn get(&self) -> &Module<K, V> {
match self.open.iter().last() {
None => &self.root,
Some((_name, module)) => module,
}
}
pub fn get_mut(&mut self) -> &mut Module<K, V> {
match self.open.iter_mut().last() {
None => &mut self.root,
Some((_name, module)) => module,
}
}
pub fn get_path(&self) -> impl Iterator<Item = &K> {
self.open.iter().map(|(key, _)| key)
}
}
impl<K: Ord, V> From<Context<K, V>> for Module<K, V> {
fn from(mut ctx: Context<K, V>) -> Self {
while ctx.close() {}
ctx.root
}
}