use crate::{Translit, UnicodeScalar, is, whilst};
impl Translit {
#[must_use]
pub const fn ascii(char: char) -> &'static str {
Self::ascii_scalar(char as u32)
}
#[doc = crate::_doc_vendor!("transliteration")]
#[must_use]
pub const fn ascii_scalar(scalar: u32) -> &'static str {
let block = (scalar >> 8) as usize;
let offset = (scalar & 0xFF) as usize;
if block < Translit::ASCII_BLOCKS.len() {
let block_data = Translit::ASCII_BLOCKS[block];
if offset < block_data.len() {
return block_data[offset];
}
}
""
}
#[must_use]
pub fn ascii_of<S: UnicodeScalar>(scalar: S) -> &'static str {
Self::ascii_scalar(scalar.to_scalar())
}
#[must_use]
pub const fn has_ascii(c: char) -> bool {
!Self::ascii(c).is_empty()
}
#[must_use]
pub const fn has_ascii_scalar(scalar: u32) -> bool {
!Self::ascii_scalar(scalar).is_empty()
}
#[must_use]
pub const fn ascii_or(c: char, fallback: &'static str) -> &'static str {
let out = Self::ascii(c);
if out.is_empty() { fallback } else { out }
}
#[must_use]
pub const fn ascii_scalar_or(scalar: u32, fallback: &'static str) -> &'static str {
let out = Self::ascii_scalar(scalar);
if out.is_empty() { fallback } else { out }
}
#[must_use]
pub const fn ascii_byte(c: char) -> Option<u8> {
Self::ascii_scalar_byte(c as u32)
}
#[must_use]
pub const fn ascii_scalar_byte(scalar: u32) -> Option<u8> {
let out = Self::ascii_scalar(scalar);
let bytes = out.as_bytes();
if bytes.len() == 1 { Some(bytes[0]) } else { None }
}
#[must_use]
pub const fn ascii_len(c: char) -> usize {
Self::ascii(c).len()
}
#[must_use]
pub const fn ascii_scalar_len(scalar: u32) -> usize {
Self::ascii_scalar(scalar).len()
}
}
impl Translit {
pub fn write_ascii(src: &str, dst: &mut [u8]) -> Option<usize> {
let mut written = 0;
for c in src.chars() {
let out = Self::ascii(c).as_bytes();
is! { written + out.len() > dst.len(), return None }
whilst! { i in 0..out.len(); { dst[written + i] = out[i]; }}
written += out.len();
}
Some(written)
}
pub fn write_ascii_or(src: &str, dst: &mut [u8], fallback: &str) -> Option<usize> {
let mut written = 0;
for c in src.chars() {
let out = Self::ascii(c);
let out = if out.is_empty() { fallback } else { out };
let bytes = out.as_bytes();
is! { written + bytes.len() > dst.len(), return None }
whilst! { i in 0..bytes.len(); { dst[written + i] = bytes[i]; }}
written += bytes.len();
}
Some(written)
}
}
#[cfg(test)]
mod tests {
use super::Translit;
#[test]
fn ascii() {
assert_eq![Translit::ascii_scalar('°' as u32), "deg"];
assert_eq![Translit::ascii_scalar('α' as u32), "a"];
assert_eq![Translit::ascii_scalar('©' as u32), "(c)"];
assert_eq![Translit::ascii_scalar('㍱' as u32), "HPA"];
assert_eq![Translit::ascii_scalar('㎮' as u32), "rad/s"];
assert_eq![Translit::ascii_scalar('中' as u32), "Zhong "];
assert_eq![Translit::ascii_scalar('ff' as u32), "ff"];
assert_eq![Translit::ascii_scalar('ﬤ' as u32), "k"];
assert_eq![Translit::ascii_scalar('�' as u32), ""];
assert_eq![Translit::ascii_scalar('🚀' as u32), ""];
}
}