macro_loop 0.4.3

A macro for writing repetitive Rust code using loops, conditionals, and bindings
Documentation
use std::collections::HashMap;

use syn::Error;

use super::*;

pub struct Namespace<'p, 'v> {
    parent: Option<&'p Namespace<'p, 'v>>,
    names: HashMap<NameId, ValueRef<'v>>,
    new_names: HashMap<NameId, ValueRef<'v>>,
}

impl<'p, 'v> Namespace<'p, 'v> {
    pub fn new() -> Self {
        Self {
            parent: None,
            names: HashMap::new(),
            new_names: HashMap::new(),
        }
    }

    pub fn fork(&self) -> Namespace {
        Namespace {
            parent: Some(self),
            names: HashMap::new(),
            new_names: HashMap::new(),
        }
    }

    pub fn insert(&mut self, name: &Name, value: ValueRef<'v>) -> syn::Result<()> {
        match self.new_names.insert(name.id().clone(), value) {
            None => Ok(()),
            Some(_) => Err(Error::new(name.span(), format!("duplicate name `{name}`"))),
        }
    }

    pub fn flush(&mut self) {
        for (k, v) in self.new_names.drain() {
            self.names.insert(k, v);
        }
    }

    pub fn get(&self, name: &Name) -> syn::Result<&Value> {
        if let Some(value) = self.new_names.get(name) {
            Ok(value)
        } else if let Some(value) = self.names.get(name) {
            Ok(value)
        } else if let Some(parent) = self.parent {
            parent.get(name)
        } else {
            Err(Error::new(name.span(), format!("cannot find {name}")))
        }
    }
}