use crate::Env;
use crate::source::Location;
use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::HashSet;
use std::fmt::Debug;
use std::hash::Hash;
use std::hash::Hasher;
use std::rc::Rc;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Alias {
pub name: String,
pub replacement: String,
pub global: bool,
pub origin: Location,
}
#[derive(Clone, Debug, Eq)]
pub struct HashEntry(pub Rc<Alias>);
impl HashEntry {
pub fn new(name: String, replacement: String, global: bool, origin: Location) -> HashEntry {
HashEntry(Rc::new(Alias {
name,
replacement,
global,
origin,
}))
}
}
impl PartialEq for HashEntry {
fn eq(&self, other: &HashEntry) -> bool {
self.0.name == other.0.name
}
}
impl Hash for HashEntry {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.name.hash(state)
}
}
impl Borrow<str> for HashEntry {
fn borrow(&self) -> &str {
&self.0.name
}
}
pub type AliasSet = HashSet<HashEntry>;
pub trait Glossary: Debug {
#[must_use]
fn look_up(&self, name: &str) -> Option<Rc<Alias>>;
#[must_use]
fn is_empty(&self) -> bool {
false
}
}
impl<T: Glossary> Glossary for &T {
fn look_up(&self, name: &str) -> Option<Rc<Alias>> {
(**self).look_up(name)
}
fn is_empty(&self) -> bool {
(**self).is_empty()
}
}
impl<T: Glossary> Glossary for &mut T {
fn look_up(&self, name: &str) -> Option<Rc<Alias>> {
(**self).look_up(name)
}
fn is_empty(&self) -> bool {
(**self).is_empty()
}
}
impl Glossary for AliasSet {
fn look_up(&self, name: &str) -> Option<Rc<Alias>> {
self.get(name).map(|entry| entry.0.clone())
}
#[inline(always)]
fn is_empty(&self) -> bool {
self.is_empty()
}
}
#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
pub struct EmptyGlossary;
impl Glossary for EmptyGlossary {
#[inline(always)]
fn look_up(&self, _name: &str) -> Option<Rc<Alias>> {
None
}
#[inline(always)]
fn is_empty(&self) -> bool {
true
}
}
impl<T: Glossary> Glossary for RefCell<T> {
fn look_up(&self, name: &str) -> Option<Rc<Alias>> {
self.borrow().look_up(name)
}
fn is_empty(&self) -> bool {
self.borrow().is_empty()
}
}
impl<S: Debug> Glossary for Env<S> {
#[inline(always)]
fn look_up(&self, name: &str) -> Option<Rc<Alias>> {
self.aliases.look_up(name)
}
#[inline(always)]
fn is_empty(&self) -> bool {
self.aliases.is_empty()
}
}