use alloc::string::{String, ToString};
use num_bigint::BigUint;
#[cfg(not(feature = "std"))]
#[allow(unused_imports)]
use num_traits::float::FloatCore;
use num_traits::{FromPrimitive, ToPrimitive, Zero};
use crate::{ChineseCase, ChineseCountMethod, ChineseExponent, ChineseNumber, ChineseVariant};
pub(crate) fn unsigned_integer_to_chinese_low(
chinese_variant: ChineseVariant,
chinese_case: ChineseCase,
dependent: bool,
mut value: u128,
) -> String {
debug_assert!(value < 1_0000_0000_0000_0000);
let mut s = String::new();
let mut lower_d = (value % 10) as u8;
value /= 10;
if lower_d > 0 {
s.push_str(
unsafe { ChineseNumber::from_ordinal_unsafe(lower_d) }
.to_str(chinese_variant, chinese_case),
);
} else if value == 0 {
return ChineseNumber::零.to_str(chinese_variant, chinese_case).to_string();
}
let d = (value % 10) as u8;
value /= 10;
if d > 0 {
s.insert_str(0, ChineseExponent::十.to_str(chinese_variant, chinese_case));
if value > 0 || dependent || d > 1 {
s.insert_str(
0,
unsafe { ChineseNumber::from_ordinal_unsafe(d) }
.to_str(chinese_variant, chinese_case),
);
}
}
if value == 0 {
return s;
}
lower_d = d;
let mut i = ChineseExponent::百.ordinal();
loop {
let d = (value % 10) as u8;
value /= 10;
if d > 0 {
if lower_d < 1 && !s.is_empty() {
s.insert_str(0, ChineseNumber::零.to_str(chinese_variant, chinese_case));
}
s.insert_str(
0,
unsafe { ChineseExponent::from_ordinal_unsafe(i) }
.to_str(chinese_variant, chinese_case),
);
s.insert_str(
0,
unsafe { ChineseNumber::from_ordinal_unsafe(d) }
.to_str(chinese_variant, chinese_case),
);
}
if value == 0 {
break;
}
lower_d = d;
i += 1;
}
s
}
pub(crate) fn unsigned_integer_to_chinese_ten_thousand(
chinese_variant: ChineseVariant,
chinese_case: ChineseCase,
dependent: bool,
mut value: u128,
) -> String {
let mut lower_d = value % 1_0000;
value /= 1_0000;
let mut has_more = value > 0;
let mut s = if lower_d > 0 {
unsigned_integer_to_chinese_low(
chinese_variant,
chinese_case,
dependent || has_more,
lower_d,
)
} else if value == 0 {
return ChineseNumber::零.to_str(chinese_variant, chinese_case).to_string();
} else {
String::new()
};
if !has_more {
return s;
}
let mut i = ChineseExponent::萬.ordinal();
loop {
let d = value % 1_0000;
value /= 1_0000;
has_more = value > 0;
if d > 0 {
if lower_d < 1000 && !s.is_empty() {
s.insert_str(0, ChineseNumber::零.to_str(chinese_variant, chinese_case));
}
s.insert_str(
0,
unsafe { ChineseExponent::from_ordinal_unsafe(i) }
.to_str(chinese_variant, chinese_case),
);
s.insert_str(
0,
unsigned_integer_to_chinese_low(
chinese_variant,
chinese_case,
dependent || has_more,
d,
)
.as_str(),
);
}
if !has_more {
break;
}
lower_d = d;
i += 1;
}
s
}
pub(crate) fn big_unsigned_integer_to_chinese_ten_thousand(
chinese_variant: ChineseVariant,
chinese_case: ChineseCase,
dependent: bool,
mut value: BigUint,
) -> String {
debug_assert!(value < BigUint::from(10u8).pow(52));
let big_0 = BigUint::zero();
let big_1_0000 = BigUint::from(1_0000u16);
let mut lower_d = (value.clone() % &big_1_0000).to_u128().unwrap();
value /= &big_1_0000;
let mut has_more = value > big_0;
let mut s = if lower_d > 0 {
unsigned_integer_to_chinese_low(
chinese_variant,
chinese_case,
dependent || has_more,
lower_d,
)
} else if value == big_0 {
return ChineseNumber::零.to_str(chinese_variant, chinese_case).to_string();
} else {
String::new()
};
if !has_more {
return s;
}
let mut i = ChineseExponent::萬.ordinal();
loop {
let d = (value.clone() % &big_1_0000).to_u128().unwrap();
value /= &big_1_0000;
has_more = value > big_0;
if d > 0 {
if lower_d < 1000 && !s.is_empty() {
s.insert_str(0, ChineseNumber::零.to_str(chinese_variant, chinese_case));
}
s.insert_str(
0,
unsafe { ChineseExponent::from_ordinal_unsafe(i) }
.to_str(chinese_variant, chinese_case),
);
s.insert_str(
0,
unsigned_integer_to_chinese_low(
chinese_variant,
chinese_case,
dependent || has_more,
d,
)
.as_str(),
);
}
if !has_more {
break;
}
lower_d = d;
i += 1;
}
s
}
pub(crate) fn unsigned_integer_to_chinese_middle(
chinese_variant: ChineseVariant,
chinese_case: ChineseCase,
dependent: bool,
mut value: u128,
) -> String {
let mut lower_d = value % 1_0000_0000;
value /= 1_0000_0000;
let mut has_more = value > 0;
let mut s = if lower_d > 0 {
unsigned_integer_to_chinese_ten_thousand(
chinese_variant,
chinese_case,
dependent || has_more,
lower_d,
)
} else if value == 0 {
return ChineseNumber::零.to_str(chinese_variant, chinese_case).to_string();
} else {
String::new()
};
if !has_more {
return s;
}
let mut i = ChineseExponent::億.ordinal();
loop {
let d = value % 1_0000_0000;
value /= 1_0000_0000;
has_more = value > 0;
if d > 0 {
if lower_d < 1000_0000 && !s.is_empty() {
s.insert_str(0, ChineseNumber::零.to_str(chinese_variant, chinese_case));
}
s.insert_str(
0,
unsafe { ChineseExponent::from_ordinal_unsafe(i) }
.to_str(chinese_variant, chinese_case),
);
s.insert_str(
0,
unsigned_integer_to_chinese_ten_thousand(
chinese_variant,
chinese_case,
dependent || has_more,
d,
)
.as_str(),
);
}
if !has_more {
break;
}
lower_d = d;
i += 1;
}
s
}
pub(crate) fn big_unsigned_integer_to_chinese_middle(
chinese_variant: ChineseVariant,
chinese_case: ChineseCase,
dependent: bool,
mut value: BigUint,
) -> String {
debug_assert!(value < BigUint::from(10u8).pow(96));
let big_0 = BigUint::zero();
let big_1_0000_0000 = BigUint::from(1_0000_0000u32);
let mut lower_d = (value.clone() % &big_1_0000_0000).to_u128().unwrap();
value /= &big_1_0000_0000;
let mut has_more = value > big_0;
let mut s = if lower_d > 0 {
unsigned_integer_to_chinese_ten_thousand(
chinese_variant,
chinese_case,
dependent || has_more,
lower_d,
)
} else if value == big_0 {
return ChineseNumber::零.to_str(chinese_variant, chinese_case).to_string();
} else {
String::new()
};
if !has_more {
return s;
}
let mut i = ChineseExponent::億.ordinal();
loop {
let d = (value.clone() % &big_1_0000_0000).to_u128().unwrap();
value /= &big_1_0000_0000;
has_more = value > big_0;
if d > 0 {
if lower_d < 1000_0000 && !s.is_empty() {
s.insert_str(0, ChineseNumber::零.to_str(chinese_variant, chinese_case));
}
s.insert_str(
0,
unsafe { ChineseExponent::from_ordinal_unsafe(i) }
.to_str(chinese_variant, chinese_case),
);
s.insert_str(
0,
unsigned_integer_to_chinese_ten_thousand(
chinese_variant,
chinese_case,
dependent || has_more,
d,
)
.as_str(),
);
}
if !has_more {
break;
}
lower_d = d;
i += 1;
}
s
}
pub(crate) fn unsigned_integer_to_chinese_high(
chinese_variant: ChineseVariant,
chinese_case: ChineseCase,
dependent: bool,
mut value: u128,
) -> String {
let mut w = 1_0000_0000_0000_0000;
let mut lower_d = value % w;
value /= w;
let mut has_more = value > 0;
let mut s = if lower_d > 0 {
unsigned_integer_to_chinese_middle(
chinese_variant,
chinese_case,
dependent || has_more,
lower_d,
)
} else if value == 0 {
return ChineseNumber::零.to_str(chinese_variant, chinese_case).to_string();
} else {
String::new()
};
if !has_more {
return s;
}
let mut i = ChineseExponent::兆.ordinal();
let mut previous_w = w;
loop {
let d = value % w;
value /= w;
has_more = value > 0;
if d > 0 {
if lower_d < previous_w / 10 && !s.is_empty() {
s.insert_str(0, ChineseNumber::零.to_str(chinese_variant, chinese_case));
}
s.insert_str(
0,
unsafe { ChineseExponent::from_ordinal_unsafe(i) }
.to_str(chinese_variant, chinese_case),
);
s.insert_str(
0,
unsigned_integer_to_chinese_high(
chinese_variant,
chinese_case,
dependent || has_more,
d,
)
.as_str(),
);
}
if !has_more {
break;
}
lower_d = d;
i += 1;
previous_w = w;
w *= w;
}
s
}
pub(crate) fn big_unsigned_integer_to_chinese_high(
chinese_variant: ChineseVariant,
chinese_case: ChineseCase,
dependent: bool,
mut value: BigUint,
) -> String {
let big_0 = BigUint::zero();
let big_10 = BigUint::from(10u8);
let mut w = BigUint::from(1_0000_0000_0000_0000u64);
let mut lower_d = value.clone() % &w;
value /= &w;
let mut has_more = value > big_0;
let mut s = if lower_d > big_0 {
unsigned_integer_to_chinese_middle(
chinese_variant,
chinese_case,
dependent || has_more,
lower_d.to_u128().unwrap(),
)
} else if value == big_0 {
return ChineseNumber::零.to_str(chinese_variant, chinese_case).to_string();
} else {
String::new()
};
if !has_more {
return s;
}
let mut i = ChineseExponent::兆.ordinal();
let mut previous_w = w.clone();
loop {
let d = value.clone() % &w;
value /= &w;
has_more = value > big_0;
if d > big_0 {
if lower_d < previous_w / &big_10 && !s.is_empty() {
s.insert_str(0, ChineseNumber::零.to_str(chinese_variant, chinese_case));
}
s.insert_str(
0,
unsafe { ChineseExponent::from_ordinal_unsafe(i) }
.to_str(chinese_variant, chinese_case),
);
s.insert_str(
0,
big_unsigned_integer_to_chinese_high(
chinese_variant,
chinese_case,
dependent || has_more,
d.clone(),
)
.as_str(),
);
}
if !has_more {
break;
}
lower_d = d;
i += 1;
previous_w = w.clone();
w = w.clone() * w;
}
s
}
pub(crate) fn positive_float_to_chinese(
chinese_variant: ChineseVariant,
chinese_case: ChineseCase,
method: ChineseCountMethod,
value: f64,
) -> String {
let (integer, fraction) = {
let integer = BigUint::from_f64(value.trunc()).unwrap();
let fraction = ((value.fract() * 100.0).round() % 100f64) as u8;
(integer, fraction)
};
let big_0 = BigUint::zero();
let mut s = if integer > big_0 {
match method {
ChineseCountMethod::Low => unsigned_integer_to_chinese_low(
chinese_variant,
chinese_case,
false,
integer.to_u128().unwrap(),
),
ChineseCountMethod::TenThousand => big_unsigned_integer_to_chinese_ten_thousand(
chinese_variant,
chinese_case,
false,
integer.clone(),
),
ChineseCountMethod::Middle => big_unsigned_integer_to_chinese_middle(
chinese_variant,
chinese_case,
false,
integer.clone(),
),
ChineseCountMethod::High => big_unsigned_integer_to_chinese_high(
chinese_variant,
chinese_case,
false,
integer.clone(),
),
}
} else {
String::new()
};
if fraction >= 10 {
let msd = fraction / 10;
let lsd = fraction % 10;
s.push_str(
unsafe { ChineseNumber::from_ordinal_unsafe(msd) }
.to_str(chinese_variant, chinese_case),
);
s.push_str(ChineseExponent::角.to_str(chinese_variant, chinese_case));
if lsd > 0 {
s.push_str(
unsafe { ChineseNumber::from_ordinal_unsafe(lsd) }
.to_str(chinese_variant, chinese_case),
);
s.push_str(ChineseExponent::分.to_str(chinese_variant, chinese_case));
}
} else if fraction >= 1 {
s.push_str(
unsafe { ChineseNumber::from_ordinal_unsafe(fraction) }
.to_str(chinese_variant, chinese_case),
);
s.push_str(ChineseExponent::分.to_str(chinese_variant, chinese_case));
} else if integer == big_0 {
s.push_str(ChineseNumber::零.to_str(chinese_variant, chinese_case));
}
s
}