use std::borrow::Borrow;
use std::cmp::PartialEq;
use std::fmt::{Debug, Display};
use std::hash::Hash;
use std::num::NonZeroUsize;
use std::ops::Deref;
use std::sync::{Arc, Weak};
#[allow(unused)] use super::interner::Interner;
use super::typed_interner::TypedInterner;
use crate::global::{self, ev};
#[derive(Clone)]
pub struct Tok<T: Eq + Hash + Clone + Send + Sync + 'static> {
data: Arc<T>,
interner: Arc<TypedInterner<T>>,
}
impl<T: Eq + Hash + Clone + Send + Sync + 'static> Tok<T> {
#[must_use]
pub(crate) fn new(data: Arc<T>, interner: Arc<TypedInterner<T>>) -> Self {
Self { data, interner }
}
#[must_use]
pub fn id(&self) -> NonZeroUsize {
((self.data.as_ref() as *const T as usize).try_into())
.expect("Pointer can always be cast to nonzero")
}
pub fn interner_id(&self) -> NonZeroUsize {
((self.interner.as_ref() as *const _ as usize).try_into())
.expect("Pointer can always be cast to nonzero")
}
#[must_use]
pub fn usize(&self) -> usize { self.id().into() }
pub fn assert_comparable(&self, other: &Self) {
assert_eq!(
self.interner_id(),
other.interner_id(),
"Tokens must come from the same interner"
);
}
pub fn interner(&self) -> Arc<TypedInterner<T>> { self.interner.clone() }
pub fn i<Q>(q: &Q) -> Self
where
Q: ?Sized + Eq + Hash + ToOwned<Owned = T>,
T: Borrow<Q>,
{
global::i(q)
}
}
impl<T: Eq + Hash + Clone + Send + Sync + 'static> Tok<Vec<Tok<T>>> {
pub fn ev(&self) -> Vec<T> { ev(&self[..]) }
}
impl<T: Eq + Hash + Clone + Send + Sync + 'static> Tok<Vec<Tok<T>>> {
pub fn append(&self, suffix: impl IntoIterator<Item = Tok<T>>) -> Self {
let i = self.interner();
i.i(&self.iter().cloned().chain(suffix).collect::<Vec<_>>())
}
pub fn prepend(&self, prefix: impl IntoIterator<Item = Tok<T>>) -> Self {
let i = self.interner();
i.i(&prefix.into_iter().chain(self.iter().cloned()).collect::<Vec<_>>())
}
}
impl<T: Eq + Hash + Clone + Send + Sync + 'static> Deref for Tok<T> {
type Target = T;
fn deref(&self) -> &Self::Target { self.data.as_ref() }
}
impl<T: Eq + Hash + Clone + Send + Sync + Debug + 'static> Debug for Tok<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Token({} -> {:?})", self.id(), self.data.as_ref())
}
}
impl<T: Eq + Hash + Clone + Send + Sync + Display + 'static> Display
for Tok<T>
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", **self)
}
}
impl<T: Eq + Hash + Clone + Send + Sync + 'static> Eq for Tok<T> {}
impl<T: Eq + Hash + Clone + Send + Sync + 'static> PartialEq for Tok<T> {
fn eq(&self, other: &Self) -> bool {
self.assert_comparable(other);
self.id() == other.id()
}
}
impl<T: Eq + Hash + Clone + Send + Sync + 'static> Ord for Tok<T> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.assert_comparable(other);
self.id().cmp(&other.id())
}
}
impl<T: Eq + Hash + Clone + Send + Sync + 'static> PartialOrd for Tok<T> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<T: Eq + Hash + Clone + Send + Sync + 'static> Hash for Tok<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
state.write_usize(self.usize())
}
}
pub struct WeakTok<T: Eq + Hash + Clone + Send + Sync + 'static> {
data: Weak<T>,
interner: Weak<TypedInterner<T>>,
}
impl<T: Eq + Hash + Clone + Send + Sync + 'static> WeakTok<T> {
pub fn new(tok: &Tok<T>) -> Self {
Self {
data: Arc::downgrade(&tok.data),
interner: Arc::downgrade(&tok.interner),
}
}
pub fn upgrade(&self) -> Option<Tok<T>> {
Some(Tok { data: self.data.upgrade()?, interner: self.interner.upgrade()? })
}
}