use std::cmp::Ordering;
use std::collections::BTreeSet;
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
use std::mem::{forget, transmute};
use std::ops::Deref;
use gc::Trace;
use spin::Mutex;
lazy_static! {
static ref SYMBOL_HEAP: Mutex<BTreeSet<&'static str>> = Mutex::new(BTreeSet::new());
}
#[derive(Clone, Copy, Eq, Finalize, Hash, PartialOrd)]
pub struct Symbol {
s: &'static str,
}
impl Symbol {
pub fn addr(self) -> usize {
self.s.as_ptr() as usize
}
pub fn as_str(self) -> &'static str {
self.s
}
}
impl Debug for Symbol {
fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
fmt.debug_tuple("Symbol").field(&self.s).finish()
}
}
impl Deref for Symbol {
type Target = str;
fn deref(&self) -> &str {
self.s
}
}
impl Display for Symbol {
fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
fmt.write_str(self.s)
}
}
impl<S: AsRef<str>> From<S> for Symbol {
fn from(s: S) -> Symbol {
let s = s.as_ref();
{
let mut heap = SYMBOL_HEAP.lock();
if heap.get(s).is_none() {
let string = s.to_owned();
let s = unsafe { transmute(&string as &str) };
forget(string);
heap.insert(s);
}
}
let s = {
let heap = SYMBOL_HEAP.lock();
heap.get(s).unwrap().clone()
};
Symbol { s }
}
}
impl Ord for Symbol {
fn cmp(&self, other: &Self) -> Ordering {
let l = self.addr();
let r = other.addr();
l.cmp(&r)
}
}
impl PartialEq for Symbol {
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == Ordering::Equal
}
}
unsafe impl Trace for Symbol {
unsafe_empty_trace!();
}