提交 0566ade0 编写于 作者: J Joshua Nelson

Use generics for interned types rather than copy-pasting impls

This makes it much simpler to add new interned types, rather than having
to add 4+ impl blocks for each type.
上级 ee8e0bc5
......@@ -4,13 +4,12 @@
use std::cmp::{Ord, Ordering, PartialOrd};
use std::collections::HashMap;
use std::convert::AsRef;
use std::ffi::OsStr;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::sync::Mutex;
// FIXME: replace with std::lazy after it gets stabilized and reaches beta
......@@ -20,15 +19,9 @@
pub struct Interned<T>(usize, PhantomData<*const T>);
impl Default for Interned<String> {
impl<T: Internable + Default> Default for Interned<T> {
fn default() -> Self {
INTERNER.intern_string(String::default())
}
}
impl Default for Interned<PathBuf> {
fn default() -> Self {
INTERNER.intern_path(PathBuf::default())
T::default().intern()
}
}
......@@ -77,87 +70,48 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
impl fmt::Debug for Interned<String> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s: &str = &*self;
f.write_fmt(format_args!("{:?}", s))
}
}
impl fmt::Debug for Interned<PathBuf> {
impl<T, U: ?Sized + fmt::Debug> fmt::Debug for Interned<T>
where
Self: Deref<Target = U>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s: &Path = &*self;
let s: &U = &*self;
f.write_fmt(format_args!("{:?}", s))
}
}
impl Hash for Interned<String> {
impl<T: Internable + Hash> Hash for Interned<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
let l = INTERNER.strs.lock().unwrap();
let l = T::intern_cache().lock().unwrap();
l.get(*self).hash(state)
}
}
impl Hash for Interned<PathBuf> {
fn hash<H: Hasher>(&self, state: &mut H) {
let l = INTERNER.paths.lock().unwrap();
l.get(*self).hash(state)
}
}
impl Deref for Interned<String> {
type Target = str;
fn deref(&self) -> &'static str {
let l = INTERNER.strs.lock().unwrap();
unsafe { mem::transmute::<&str, &'static str>(l.get(*self)) }
}
}
impl Deref for Interned<PathBuf> {
type Target = Path;
fn deref(&self) -> &'static Path {
let l = INTERNER.paths.lock().unwrap();
unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self)) }
}
}
impl AsRef<Path> for Interned<PathBuf> {
fn as_ref(&self) -> &'static Path {
let l = INTERNER.paths.lock().unwrap();
unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self)) }
}
}
impl AsRef<Path> for Interned<String> {
fn as_ref(&self) -> &'static Path {
let l = INTERNER.strs.lock().unwrap();
unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self).as_ref()) }
impl<T: Internable + Deref> Deref for Interned<T> {
type Target = T::Target;
fn deref(&self) -> &'static Self::Target {
let l = T::intern_cache().lock().unwrap();
unsafe { mem::transmute::<&Self::Target, &'static Self::Target>(l.get(*self)) }
}
}
impl AsRef<OsStr> for Interned<PathBuf> {
fn as_ref(&self) -> &'static OsStr {
let l = INTERNER.paths.lock().unwrap();
unsafe { mem::transmute::<&OsStr, &'static OsStr>(l.get(*self).as_ref()) }
impl<T: Internable + AsRef<U>, U: ?Sized> AsRef<U> for Interned<T> {
fn as_ref(&self) -> &'static U {
let l = T::intern_cache().lock().unwrap();
unsafe { mem::transmute::<&U, &'static U>(l.get(*self).as_ref()) }
}
}
impl AsRef<OsStr> for Interned<String> {
fn as_ref(&self) -> &'static OsStr {
let l = INTERNER.strs.lock().unwrap();
unsafe { mem::transmute::<&OsStr, &'static OsStr>(l.get(*self).as_ref()) }
}
}
impl PartialOrd<Interned<String>> for Interned<String> {
impl<T: Internable + PartialOrd> PartialOrd for Interned<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
let l = INTERNER.strs.lock().unwrap();
let l = T::intern_cache().lock().unwrap();
l.get(*self).partial_cmp(l.get(*other))
}
}
impl Ord for Interned<String> {
impl<T: Internable + Ord> Ord for Interned<T> {
fn cmp(&self, other: &Self) -> Ordering {
let l = INTERNER.strs.lock().unwrap();
let l = T::intern_cache().lock().unwrap();
l.get(*self).cmp(l.get(*other))
}
}
......@@ -210,6 +164,26 @@ pub struct Interner {
paths: Mutex<TyIntern<PathBuf>>,
}
trait Internable: Clone + Eq + Hash + 'static {
fn intern_cache() -> &'static Mutex<TyIntern<Self>>;
fn intern(self) -> Interned<Self> {
Self::intern_cache().lock().unwrap().intern(self)
}
}
impl Internable for String {
fn intern_cache() -> &'static Mutex<TyIntern<Self>> {
&INTERNER.strs
}
}
impl Internable for PathBuf {
fn intern_cache() -> &'static Mutex<TyIntern<Self>> {
&INTERNER.paths
}
}
impl Interner {
pub fn intern_str(&self, s: &str) -> Interned<String> {
self.strs.lock().unwrap().intern_borrow(s)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册