pub mod consts;
pub mod glyph;
pub mod numeral;
pub mod tehta;
pub mod tema;
pub use consts::*;
pub use glyph::Glyph;
pub use numeral::Numeral;
pub use tehta::Tehta;
pub use tema::{Tema, TengwaRegular, Tyelle};
#[derive(Clone, Copy, Debug)]
pub enum Rince {
Basic,
Final,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub enum VowelStyle {
#[value(alias = "s", alias = "0")]
Separate = 0,
#[value(alias = "d", alias = "2")]
Doubled = 2,
#[value(alias = "u", alias = "1")]
Unique = 1,
}
impl VowelStyle {
pub const DEFAULT: Self = Self::Doubled;
}
impl Default for VowelStyle {
fn default() -> Self { Self::DEFAULT }
}
pub const fn punctuation(chr: char) -> Option<char> {
Some(match chr {
'\'' | '.' | ',' | '·' => PUNCT_DOT_1,
':' | ';' => PUNCT_DOT_2,
'⁝' | '︙' => PUNCT_DOT_3,
'⁘' | '⁛' | '…' => PUNCT_DOT_4,
'⸭' => PUNCT_DOT_5,
'-' => PUNCT_LINE_1,
'=' => PUNCT_LINE_2,
'?' => PUNCT_INTERR,
'!' => PUNCT_EXCLAM,
'|' | '‖' => PUNCT_PAREN,
'(' | '[' | '“' => PUNCT_PAREN_L,
')' | ']' | '”' | '„' => PUNCT_PAREN_R,
_ => { return None; }
})
}
#[derive(Clone, Copy, Debug)]
pub enum Tengwa<'t> {
Irregular(char),
Regular(TengwaRegular<'t>),
}
impl<'t> Tengwa<'t> {
pub const fn either_from(char: char) -> Self {
match TengwaRegular::find(char) {
Some(tengwa) => Self::Regular(tengwa),
None => Self::Irregular(char),
}
}
pub const fn irregular_from(char: char) -> Self {
Self::Irregular(char)
}
pub const fn try_regular_from(char: char) -> Option<Self> {
match TengwaRegular::find(char) {
Some(tengwa) => Some(Self::Regular(tengwa)),
None => None,
}
}
pub const fn as_char(&self) -> &char {
match self {
Self::Irregular(char) => char,
Self::Regular(tengwa) => tengwa.as_char(),
}
}
pub const fn as_irregular(&self) -> Option<&char> {
match self {
Self::Irregular(char) => Some(char),
Self::Regular(_) => None,
}
}
pub const fn as_regular(&self) -> Option<&TengwaRegular<'t>> {
match self {
Self::Irregular(_) => None,
Self::Regular(tengwa) => Some(tengwa),
}
}
pub const fn is_irregular(&self) -> bool {
match self {
Self::Irregular(_) => true,
Self::Regular(_) => false,
}
}
pub const fn is_regular(&self) -> bool {
match self {
Self::Irregular(_) => false,
Self::Regular(_) => true,
}
}
}
impl<'t> std::ops::Deref for Tengwa<'t> {
type Target = char;
fn deref(&self) -> &Self::Target { self.as_char() }
}
impl<'t> From<TengwaRegular<'t>> for Tengwa<'t> {
fn from(tengwa: TengwaRegular<'t>) -> Self { Self::Regular(tengwa) }
}
impl<'t> From<char> for Tengwa<'t> {
fn from(char: char) -> Self {
Self::either_from(char)
}
}
#[derive(Clone, Copy, Debug)]
pub enum BaseChar<'t> {
Carrier(bool),
Tengwa(Tengwa<'t>),
}
impl<'t> BaseChar<'t> {
pub const fn to_char(&self) -> char {
match self {
Self::Carrier(long) => carrier(*long),
Self::Tengwa(tengwa) => *tengwa.as_char(),
}
}
pub const fn tengwa(&self) -> Option<&Tengwa<'t>> {
match self {
Self::Carrier(_) => None,
Self::Tengwa(tengwa) => Some(tengwa),
}
}
}
impl<'t> From<char> for BaseChar<'t> {
fn from(char: char) -> Self {
match char {
CARRIER_LONG => Self::Carrier(true),
CARRIER_SHORT => Self::Carrier(false),
CARRIER_SHORT_LIG => Self::Carrier(false),
c => Self::Tengwa(c.into()),
}
}
}
impl<'t> From<Tengwa<'t>> for BaseChar<'t> {
fn from(tengwa: Tengwa<'t>) -> Self { Self::Tengwa(tengwa) }
}
impl<'t> From<TengwaRegular<'t>> for BaseChar<'t> {
fn from(tengwa: TengwaRegular<'t>) -> Self { Self::Tengwa(tengwa.into()) }
}
#[test]
#[cfg(test)]
fn report_sizes() {
use std::mem::size_of;
eprintln!("Glyph helpers:");
dbg!(
size_of::<glyph::Parts>(),
size_of::<glyph::TehtaChar>(),
size_of::<glyph::TengwaTehta>(),
);
eprintln!("Tengwa helpers:");
dbg!(
size_of::<Tema>(),
size_of::<&Tema>(),
size_of::<Tyelle>(),
size_of::<TengwaRegular>(),
size_of::<Tengwa>(),
size_of::<BaseChar>(),
);
eprintln!("Main:");
dbg!(
size_of::<VowelStyle>(),
size_of::<Glyph>(),
size_of::<Numeral>(),
size_of::<crate::Token>(),
);
eprintln!();
}