mod characters;
mod longscale;
mod macros;
mod midscale;
mod myriadscale;
mod shortscale;
use characters::NumChar;
pub use longscale::LongScaleInt;
pub use midscale::MidScaleInt;
pub use myriadscale::MyriadScaleInt;
pub use shortscale::ShortScaleInt;
#[cfg(feature = "bigint")]
use num_bigint::BigUint;
#[cfg(feature = "bigint")]
pub use longscale::LongScaleBigInt;
#[cfg(feature = "bigint")]
pub use midscale::MidScaleBigInt;
#[cfg(feature = "bigint")]
pub use myriadscale::MyriadScaleBigInt;
pub(crate) mod sealed {
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
pub enum Sign {
Neg,
Nil,
Pos,
}
impl Default for Sign {
fn default() -> Self {
Self::Nil
}
}
pub trait Signed {
type Data;
fn sign(&self) -> Sign;
fn data(&self) -> &Self::Data;
}
pub trait ChineseNumeralBase: Signed {
fn to_chars(&self) -> Vec<crate::characters::NumChar>;
fn to_chars_trimmed(&self) -> Vec<crate::characters::NumChar>;
}
}
use sealed::{ChineseNumeralBase, Sign, Signed};
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Variant {
Simplified,
Traditional,
}
#[cfg(feature = "bigint")]
#[derive(Debug)]
pub enum Error {
ShortScaleOutOfRange(u128),
MyriadScaleOutOfRange(BigUint),
MidScaleOutOfRange(BigUint),
LongScaleOutOfRange(BigUint),
}
#[cfg(feature = "bigint")]
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::ShortScaleOutOfRange(value) => write!(
f,
"Absolute value {value} out of range for a short scale number"
),
Error::MyriadScaleOutOfRange(value) => write!(
f,
"Absolute value {value} out of range for a myriad scale number"
),
Error::MidScaleOutOfRange(value) => write!(
f,
"Absolute value {value} out of range for a mid-scale number"
),
Error::LongScaleOutOfRange(value) => write!(
f,
"Absolute value {value} out of range for a long scale number"
),
}
}
}
#[cfg(not(feature = "bigint"))]
#[derive(Debug)]
pub enum Error {
ShortScaleOutOfRange(u128),
}
#[cfg(not(feature = "bigint"))]
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match *self {
Error::ShortScaleOutOfRange(value) => write!(
f,
"Absolute value {value} out of range for a short scale number"
),
}
}
}
impl std::error::Error for Error {}
pub trait ChineseNumeral {
fn to_lowercase(&self, variant: Variant) -> String;
fn to_lowercase_simp(&self) -> String {
self.to_lowercase(Variant::Simplified)
}
fn to_lowercase_trad(&self) -> String {
self.to_lowercase(Variant::Traditional)
}
fn to_uppercase(&self, variant: Variant) -> String;
fn to_uppercase_simp(&self) -> String {
self.to_uppercase(Variant::Simplified)
}
fn to_uppercase_trad(&self) -> String {
self.to_uppercase(Variant::Traditional)
}
}
impl<T: ChineseNumeralBase> ChineseNumeral for T {
fn to_lowercase(&self, variant: Variant) -> String {
let method = match variant {
Variant::Simplified => NumChar::to_lowercase_simp,
Variant::Traditional => NumChar::to_lowercase_trad,
};
let mut chars = self.to_chars_trimmed();
match self.sign() {
Sign::Neg => chars.push(NumChar::Neg),
Sign::Nil => chars.push(NumChar::Zero),
_ => {}
}
chars.into_iter().rev().map(method).collect()
}
fn to_uppercase(&self, variant: Variant) -> String {
let method = match variant {
Variant::Simplified => NumChar::to_uppercase_simp,
Variant::Traditional => NumChar::to_uppercase_trad,
};
let mut chars = self.to_chars();
match self.sign() {
Sign::Neg => chars.push(NumChar::Neg),
Sign::Nil => chars.push(NumChar::Zero),
_ => {}
}
chars.into_iter().rev().map(method).collect()
}
}