use crate::english::encode_english;
use crate::unicode::decode_unicode;
pub const NUMERIC_INDICATOR: u8 = decode_unicode('⠼');
pub fn digit_cell(d: char) -> Option<u8> {
let letter = match d {
'1'..='9' => char::from(b'a' + (d as u8 - b'1')),
'0' => 'j',
_ => return None,
};
encode_english(letter).ok()
}
pub fn encode_number(digits: &[char]) -> Option<Vec<u8>> {
let mut out = Vec::with_capacity(digits.len() + 1);
out.push(NUMERIC_INDICATOR);
for d in digits {
out.push(digit_cell(*d)?);
}
Some(out)
}
pub fn encode_vulgar_fraction(c: char) -> Option<Vec<u8>> {
let (num, den) = crate::fraction::parse_unicode_fraction(c)?;
let mut out = Vec::with_capacity(num.len() + den.len() + 2);
out.push(NUMERIC_INDICATOR);
for d in num.chars() {
out.push(digit_cell(d)?);
}
out.push(decode_unicode('⠌'));
for d in den.chars() {
out.push(digit_cell(d)?);
}
Some(out)
}
#[cfg(test)]
mod tests {
use super::*;
#[rstest::rstest]
#[case::ninety_five("95", vec![NUMERIC_INDICATOR, decode_unicode('⠊'), decode_unicode('⠑')])]
#[case::one_zero("10", vec![NUMERIC_INDICATOR, decode_unicode('⠁'), decode_unicode('⠚')])]
#[case::all_digits("1234567890", vec![
NUMERIC_INDICATOR,
decode_unicode('⠁'), decode_unicode('⠃'), decode_unicode('⠉'), decode_unicode('⠙'),
decode_unicode('⠑'), decode_unicode('⠋'), decode_unicode('⠛'), decode_unicode('⠓'),
decode_unicode('⠊'), decode_unicode('⠚'),
])]
fn encodes_numbers(#[case] digits: &str, #[case] expected: Vec<u8>) {
let chars: Vec<char> = digits.chars().collect();
assert_eq!(encode_number(&chars), Some(expected));
}
#[rstest::rstest]
#[case::half('\u{00BD}', vec![NUMERIC_INDICATOR, decode_unicode('⠁'), decode_unicode('⠌'), decode_unicode('⠃')])]
#[case::three_eighths('\u{215C}', vec![NUMERIC_INDICATOR, decode_unicode('⠉'), decode_unicode('⠌'), decode_unicode('⠓')])]
#[case::three_quarters('\u{00BE}', vec![NUMERIC_INDICATOR, decode_unicode('⠉'), decode_unicode('⠌'), decode_unicode('⠙')])]
#[case::one_quarter('\u{00BC}', vec![NUMERIC_INDICATOR, decode_unicode('⠁'), decode_unicode('⠌'), decode_unicode('⠙')])]
fn encodes_vulgar_fractions(#[case] c: char, #[case] expected: Vec<u8>) {
assert_eq!(encode_vulgar_fraction(c), Some(expected));
}
#[test]
fn non_fraction_char_is_none() {
assert_eq!(encode_vulgar_fraction('x'), None);
}
}