use std::convert::Into;
use std::fmt::{Display, Formatter, Debug};
use std::hash::Hash;
use std::marker::PhantomData;
use std::vec::IntoIter;
use crate::tex::catcodes::{CategoryCodeScheme, STARTING_SCHEME_U8};
use crate::utils::Ptr;
pub trait CharType:Copy+PartialEq+Eq+Hash+Display+Debug+'static+From<u8>+Default {
type Allchars<A:Default> : AllCharsTrait<Self,A>;
const MAX:Self;
fn from_u8_iter(iter:&mut IntoIter<u8>) -> Option<Self>;
fn from_str(s:&str) -> TeXStr<Self>;
fn is_eol(self) -> Option<bool>;
fn is_eol_pair(self,next:Self) -> bool;
fn par_token() -> TeXStr<Self>;
fn relax_token() -> TeXStr<Self>;
fn empty_str() -> TeXStr<Self>;
fn starting_catcode_scheme() -> CategoryCodeScheme<Self>;
fn newline() -> Self;
fn carriage_return() -> Self;
fn backslash() -> Self;
fn zeros() -> Self::Allchars<Self>;
fn ident() -> Self::Allchars<Self>;
fn rep_field<A:Clone+Default>(a:A) -> Self::Allchars<A>;
fn display_str(str:&TeXStr<Self>, f: &mut Formatter<'_>) -> std::fmt::Result {
for u in &*str.0 { write!(f,"{}",u.char_str())?; }
Ok(())
}
fn char_str(&self) -> String;
fn as_bytes(&self) -> Vec<u8>;
fn from_i64(i:i64) -> Option<Self>;
fn to_usize(self) -> usize;
}
thread_local! {
pub static PAR_U8: TeXStr<u8> = "par".into();
pub static RELAX_U8: TeXStr<u8> = "relax".into();
pub static EMPTY_U8: TeXStr<u8> = "".into();
}
impl CharType for u8 {
type Allchars<A:Default> = [A;256];
const MAX:Self=255;
fn from_u8_iter(iter: &mut IntoIter<u8>) -> Option<Self> { iter.next() }
fn newline() -> Self { b'\n' }
fn carriage_return() -> Self {b'\r'}
fn backslash() -> Self { b'\\' }
fn is_eol(self) -> Option<bool> {
match self {
b'\n' => Some(true),
b'\r' => None,
_ => Some(false)
}
}
fn from_str(s: &str) -> TeXStr<Self> {
TeXStr(Ptr::new(s.as_bytes().to_vec()))
}
fn is_eol_pair(self, next: Self) -> bool {
next == b'\n'
}
fn par_token() -> TeXStr<Self> { PAR_U8.with(|p| p.clone()) }
fn relax_token() -> TeXStr<Self> { RELAX_U8.with(|p| p.clone()) }
fn empty_str() -> TeXStr<Self> {EMPTY_U8.with(|p| p.clone()) }
fn starting_catcode_scheme() -> CategoryCodeScheme<Self> {
STARTING_SCHEME_U8.clone()
}
fn as_bytes(&self) -> Vec<u8> { vec![*self] }
fn char_str(&self) -> String {
match *self {
0 => "\\u0000".to_string(),
b'\n' => "\\n".to_string(),
b'\r' => "\\r".to_string(),
o if is_ascii(o) => (o as char).to_string(), o => format!("\\u00{:X}",o)
}
}
fn zeros() -> Self::Allchars<Self> {
[0;256]
}
fn ident() -> Self::Allchars<Self> {
let mut a = [0;256];
for i in 0..256 { a[i] = i as u8; }
a
}
fn rep_field<A: Clone+Default>(a: A) -> Self::Allchars<A> {
[ a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),
a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone(),a.clone()
]
}
fn from_i64(i: i64) -> Option<Self> {
if i == -1 {Some(255)} else if i < 0 || i > 255 { None } else { Some(i as u8) }
}
fn to_usize(self) -> usize { self as usize }
}
pub trait AllCharsTrait<C:CharType,A> {
fn get(&self, u: C) -> &A;
fn set(&mut self, u: C, v:A);
fn replace(&mut self, u: C, v:A) -> A;
}
impl<A> AllCharsTrait<u8,A> for [A;256] {
fn get(&self, u:u8) -> &A { &self[u as usize] }
fn set(&mut self, u:u8,v:A) { self[u as usize] = v }
fn replace(&mut self, u: u8, v: A) -> A {
std::mem::replace(&mut self[u as usize], v)
}
}
#[derive(Clone,PartialEq,Hash,Eq)]
pub struct TeXStr<C:CharType>(Ptr<Vec<C>>);
impl<C:CharType> TeXStr<C> {
pub fn len(&self) -> usize { self.0.len() }
pub fn as_vec(&self) -> &Vec<C> { &self.0 }
}
fn is_ascii(u:u8) -> bool { 32 <= u && u <= 126 }
impl<C:CharType> Display for TeXStr<C> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
C::display_str(self, f)
}
}
impl From<&str> for TeXStr<u8> {
fn from(s: &str) -> Self {
TeXStr(Ptr::new(s.as_bytes().to_vec()))
}
}
impl From<String> for TeXStr<u8> {
fn from(s: String) -> Self {
TeXStr(Ptr::new(s.into_bytes()))
}
}
impl<C:CharType> From<Vec<C>> for TeXStr<C> {
fn from(v: Vec<C>) -> Self {
TeXStr(Ptr::new(v))
}
}
impl CharType for char {
const MAX: Self = 255 as char;
type Allchars<A: Default> = AllUnicodeChars<A>; fn from_i64(i: i64) -> Option<Self> { if i > 0 && i < 0x110000 { Some(char::from_u32(i as u32).unwrap()) } else { None } }
fn to_usize(self) -> usize { self as usize }
fn from_str(s: &str) -> TeXStr<Self> {
TeXStr(Ptr::new(s.chars().collect()))
}
fn display_str(str: &TeXStr<Self>, f: &mut Formatter<'_>) -> std::fmt::Result {
let str : String = str.0.iter().collect();
write!(f,"{}",str)
}
fn backslash() -> Self { '\\' }
fn carriage_return() -> Self { '\r' }
fn newline() -> Self { '\n' }
fn char_str(&self) -> String { self.to_string() }
fn is_eol(self) -> Option<bool> {
match self {
'\n' => Some(true),
'\r' => None,
_ => Some(false)
}
}
fn is_eol_pair(self, next: Self) -> bool {
next == '\n' }
fn as_bytes(&self) -> Vec<u8> {
self.to_string().as_bytes().into_iter().map(|u| *u).collect()
}
fn ident() -> Self::Allchars<Self> {
todo!()
}
fn empty_str() -> TeXStr<Self> {
todo!()
}
fn par_token() -> TeXStr<Self> {
todo!()
}
fn relax_token() -> TeXStr<Self> {
todo!()
}
fn starting_catcode_scheme() -> CategoryCodeScheme<Self> {
todo!()
}
fn from_u8_iter(iter: &mut IntoIter<u8>) -> Option<Self> {
todo!()
}
fn rep_field<A: Clone + Default>(a: A) -> Self::Allchars<A> {
todo!()
}
fn zeros() -> Self::Allchars<Self> {
todo!()
}
}
pub struct AllUnicodeChars<A:Default>(PhantomData<A>);
impl<A:Default> AllCharsTrait<char,A> for AllUnicodeChars<A> {
fn get(&self, u: char) -> &A {
todo!()
}
fn set(&mut self, u: char, v: A) {
todo!()
}
fn replace(&mut self, u: char, v: A) -> A {
todo!()
}
}