use crate::prelude::{CategoryCode, CategoryCodeScheme};
use crate::tex::characters::Character;
use crate::tex::characters::CharacterMap;
use crate::utils::{HMap, Ptr};
use std::fmt::{Debug, Display, Write};
use std::hash::Hash;
use std::marker::PhantomData;
use std::num::NonZeroU32;
pub trait CSName<C: Character>: Clone + Eq + 'static + std::hash::Hash + Debug {
type Handler: CSHandler<C, Self>;
type Map<A>: CSNameMap<C, Self, A>
where
A: Clone;
fn display_fmt<W: Write>(
&self,
int: &Self::Handler,
cc: &CategoryCodeScheme<C>,
escapechar: Option<C>,
f: &mut W,
) -> std::fmt::Result {
let res = int.resolve(self);
write!(f, "{}{}", C::display_opt(escapechar), res)?;
if res.len() == 1 {
let c = res.iter().next().unwrap();
match cc.get(c) {
CategoryCode::Letter => write!(f, " "),
_ => Ok(()),
}
} else {
write!(f, " ")
}
}
fn id(&self) -> usize;
}
pub trait CSNameMap<C: Character, CS: CSName<C>, A: Clone>: Clone + Default {
fn get(&self, cs: &CS) -> Option<&A>;
fn insert(&mut self, cs: CS, a: A) -> Option<A>;
fn remove(&mut self, cs: &CS) -> Option<A>;
fn into_iter(self) -> impl Iterator<Item = (CS, A)>;
}
impl<C: Character, CS: CSName<C>, A: Clone> CSNameMap<C, CS, A> for HMap<CS, A> {
fn get(&self, cs: &CS) -> Option<&A> {
self.get(cs)
}
fn insert(&mut self, cs: CS, a: A) -> Option<A> {
self.insert(cs, a)
}
fn remove(&mut self, cs: &CS) -> Option<A> {
self.remove(cs)
}
fn into_iter(self) -> impl Iterator<Item = (CS, A)> {
<HMap<CS, A> as IntoIterator>::into_iter(self)
}
}
impl<C: Character> CSName<C> for Ptr<str> {
type Handler = ();
type Map<A>
= HMap<Self, A>
where
A: Clone;
fn id(&self) -> usize {
use std::hash::Hasher;
let mut hash = std::hash::DefaultHasher::new();
self.hash(&mut hash);
hash.finish() as usize
}
}
pub type InternedCSName<C> = (NonZeroU32, PhantomData<C>);
impl<C: Character> CSName<C> for InternedCSName<C> {
type Handler = CSInterner<C>;
type Map<A>
= CSNameVec<C, A>
where
A: Clone;
fn id(&self) -> usize {
self.0.get() as usize - 1
}
}
#[derive(Clone)]
pub struct CSNameVec<C: Character, A: Clone>(Vec<Option<A>>, PhantomData<C>);
impl<C: Character, A: Clone> Default for CSNameVec<C, A> {
fn default() -> Self {
Self(Vec::new(), PhantomData)
}
}
impl<C: Character, A: Clone> CSNameMap<C, InternedCSName<C>, A> for CSNameVec<C, A> {
fn get(&self, cs: &InternedCSName<C>) -> Option<&A> {
self.0.get(cs.0.get() as usize - 1).and_then(|x| x.as_ref())
}
fn insert(&mut self, cs: InternedCSName<C>, a: A) -> Option<A> {
let idx = cs.0.get() as usize - 1;
if self.0.len() <= idx {
self.0.resize(idx + 1, None);
}
std::mem::replace(&mut self.0[idx], Some(a))
}
fn remove(&mut self, cs: &InternedCSName<C>) -> Option<A> {
let idx = cs.0.get() as usize - 1;
if self.0.len() <= idx {
return None;
}
self.0[idx].take()
}
fn into_iter(self) -> impl Iterator<Item = (InternedCSName<C>, A)> {
self.0.into_iter().enumerate().filter_map(|(i, x)| {
x.map(|x| ((NonZeroU32::new((i + 1) as u32).unwrap(), PhantomData), x))
})
}
}
pub trait ResolvedCSName<'a, C: Character>: Display {
type Iter: Iterator<Item = C>;
fn iter(&self) -> Self::Iter;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
}
pub trait CSHandler<C: Character, CS: CSName<C>>: Default + Clone {
type Resolved<'a>: ResolvedCSName<'a, C>
where
Self: 'a;
fn cs_from_str(&mut self, s: &str) -> CS;
fn cs_from_chars(&mut self, v: &[C]) -> CS;
fn resolve<'a>(&'a self, cs: &'a CS) -> Self::Resolved<'a>;
fn par(&self) -> CS;
fn empty_str(&self) -> CS;
fn get(&self, s: &str) -> Option<CS>;
}
impl<'a, C: Character> ResolvedCSName<'a, C> for &'a str {
type Iter = C::Iter<'a>;
fn iter(&self) -> Self::Iter {
C::string_to_iter(self)
}
fn len(&self) -> usize {
C::string_to_iter(self).len()
}
}
impl<C: Character> CSHandler<C, Ptr<str>> for () {
type Resolved<'a> = &'a str;
fn cs_from_str(&mut self, s: &str) -> Ptr<str> {
s.into()
}
fn get(&self, s: &str) -> Option<Ptr<str>> {
Some(s.into())
}
fn resolve<'a>(&'a self, cs: &'a Ptr<str>) -> Self::Resolved<'a> {
cs
}
fn par(&self) -> Ptr<str> {
"par".to_string().into()
}
fn empty_str(&self) -> Ptr<str> {
"".to_string().into()
}
fn cs_from_chars(&mut self, v: &[C]) -> Ptr<str> {
let mut s = String::new();
for c in v {
c.display_fmt(&mut s);
}
s.into()
}
}
#[derive(Clone)]
pub struct CSInterner<C: Character> {
map: HMap<Box<[C]>, NonZeroU32>,
ls: Vec<C>,
idx: Vec<usize>,
}
impl<C: Character> CSInterner<C> {
#[allow(dead_code)]
fn cap(&self) -> usize {
self.idx.len()
}
fn new() -> Self {
let mut map: HMap<Box<[C]>, NonZeroU32> = HMap::default();
map.insert(Box::new([]), NonZeroU32::new(1).unwrap());
let mut r = CSInterner {
map,
ls: Vec::new(),
idx: vec![0],
};
r.from_static("par");
r
}
pub fn from_static(&mut self, s: &'static str) -> InternedCSName<C> {
C::slice_from_str(s, |s| self.intern(s))
}
pub fn from_string<S: AsRef<str>>(&mut self, s: S) -> InternedCSName<C> {
C::slice_from_str(s.as_ref(), |s| self.intern(s))
}
pub fn resolve(&self, i: InternedCSName<C>) -> &[C] {
self.get(i.0)
}
pub fn intern(&mut self, v: &[C]) -> InternedCSName<C> {
if let Some(x) = self.map.get(v) {
return (*x, PhantomData);
}
self.ls.extend(v);
let len = self.ls.len();
self.idx.push(len);
let len = self.idx.len() - 1;
let r = unsafe { NonZeroU32::new_unchecked(len as u32 + 1) };
self.map.insert(v.into(), r);
(r, PhantomData)
}
fn get(&self, i: NonZeroU32) -> &[C] {
let i = i.get() as usize - 1;
if i == 0 {
return &[];
}
let s = self.idx[i - 1];
let e = self.idx[i];
&self.ls[s..e]
}
}
impl<C: Character> CSHandler<C, InternedCSName<C>> for CSInterner<C> {
type Resolved<'a> = DisplayCSName<'a, C>;
fn cs_from_str(&mut self, s: &str) -> InternedCSName<C> {
C::slice_from_str(s, |s| self.intern(s))
}
fn get(&self, s: &str) -> Option<InternedCSName<C>> {
C::slice_from_str(s, |s| self.map.get(s).map(|i| (*i, PhantomData)))
}
fn cs_from_chars(&mut self, v: &[C]) -> InternedCSName<C> {
self.intern(v)
}
fn par(&self) -> InternedCSName<C> {
const { (NonZeroU32::new(2).unwrap(), PhantomData) }
}
fn empty_str(&self) -> InternedCSName<C> {
const { (NonZeroU32::new(1).unwrap(), PhantomData) }
}
fn resolve<'a>(&'a self, cs: &InternedCSName<C>) -> DisplayCSName<'a, C> {
DisplayCSName(self.get(cs.0))
}
}
pub struct DisplayCSName<'a, C: Character>(&'a [C]);
impl<C: Character> Display for DisplayCSName<'_, C> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for c in self.0 {
c.display_fmt(f);
}
Ok(())
}
}
impl<'a, C: Character> ResolvedCSName<'a, C> for DisplayCSName<'a, C> {
type Iter = std::iter::Copied<std::slice::Iter<'a, C>>;
fn iter(&self) -> Self::Iter {
self.0.iter().copied()
}
fn len(&self) -> usize {
self.0.len()
}
}
impl<C: Character> Default for CSInterner<C> {
fn default() -> Self {
Self::new()
}
}