mod adobe_arabic;
mod adobe_cns1;
mod adobe_gb1;
mod adobe_japan1;
mod adobe_korea1;
#[inline]
pub fn lookup_adobe_gb1(cid: u16) -> Option<u32> {
adobe_gb1::lookup(cid)
}
#[inline]
pub fn lookup_adobe_japan1(cid: u16) -> Option<u32> {
adobe_japan1::lookup(cid)
}
#[inline]
pub fn lookup_adobe_cns1(cid: u16) -> Option<u32> {
adobe_cns1::lookup(cid)
}
#[inline]
pub fn lookup_adobe_korea1(cid: u16) -> Option<u32> {
adobe_korea1::lookup(cid)
}
#[inline]
pub fn lookup_adobe_arabic(cid: u16) -> Option<u32> {
adobe_arabic::lookup(cid)
}
mod reverse {
use std::collections::HashMap;
use std::sync::OnceLock;
fn build_reverse_map(forward: fn(u16) -> Option<u32>) -> HashMap<u32, u16> {
let mut map = HashMap::new();
for cid in 0..=u16::MAX {
if let Some(unicode) = forward(cid) {
map.entry(unicode).or_insert(cid);
}
}
map
}
fn reverse_lookup(
cache: &OnceLock<HashMap<u32, u16>>,
forward: fn(u16) -> Option<u32>,
unicode: u32,
) -> Option<u16> {
cache.get_or_init(|| build_reverse_map(forward)).get(&unicode).copied()
}
static REV_GB1: OnceLock<HashMap<u32, u16>> = OnceLock::new();
static REV_JAPAN1: OnceLock<HashMap<u32, u16>> = OnceLock::new();
static REV_CNS1: OnceLock<HashMap<u32, u16>> = OnceLock::new();
static REV_KOREA1: OnceLock<HashMap<u32, u16>> = OnceLock::new();
pub(super) fn unicode_to_cid_gb1(unicode: u32) -> Option<u16> {
reverse_lookup(&REV_GB1, super::lookup_adobe_gb1, unicode)
}
pub(super) fn unicode_to_cid_japan1(unicode: u32) -> Option<u16> {
reverse_lookup(&REV_JAPAN1, super::lookup_adobe_japan1, unicode)
}
pub(super) fn unicode_to_cid_cns1(unicode: u32) -> Option<u16> {
reverse_lookup(&REV_CNS1, super::lookup_adobe_cns1, unicode)
}
pub(super) fn unicode_to_cid_korea1(unicode: u32) -> Option<u16> {
reverse_lookup(&REV_KOREA1, super::lookup_adobe_korea1, unicode)
}
}
#[inline]
pub fn unicode_to_cid_gb1(unicode: u32) -> Option<u16> {
reverse::unicode_to_cid_gb1(unicode)
}
#[inline]
pub fn unicode_to_cid_japan1(unicode: u32) -> Option<u16> {
reverse::unicode_to_cid_japan1(unicode)
}
#[inline]
pub fn unicode_to_cid_cns1(unicode: u32) -> Option<u16> {
reverse::unicode_to_cid_cns1(unicode)
}
#[inline]
pub fn unicode_to_cid_korea1(unicode: u32) -> Option<u16> {
reverse::unicode_to_cid_korea1(unicode)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_adobe_gb1_ascii_from_cid() {
assert_eq!(lookup_adobe_gb1(34), Some(0x41));
assert_eq!(lookup_adobe_gb1(91), Some(0x7A));
}
#[test]
fn test_adobe_japan1_ascii_from_cid() {
assert_eq!(lookup_adobe_japan1(34), Some(0x41));
assert_eq!(lookup_adobe_japan1(91), Some(0x7A));
}
#[test]
fn test_adobe_japan1_hiragana() {
assert_eq!(lookup_adobe_japan1(843), Some(0x3042));
}
#[test]
fn test_cid_tables_map_to_ideographs_not_radical_forms() {
assert_eq!(lookup_adobe_japan1(2664), Some(0x9752)); assert_eq!(lookup_adobe_japan1(2666), Some(0x6589)); }
#[test]
fn test_adobe_cns1_ascii_from_cid() {
assert_eq!(lookup_adobe_cns1(34), Some(0x41));
}
#[test]
fn test_adobe_korea1_ascii_from_cid() {
assert_eq!(lookup_adobe_korea1(34), Some(0x41));
}
#[test]
fn test_adobe_korea1_hangul() {
assert_eq!(lookup_adobe_korea1(1086), Some(0xAC00));
}
#[test]
fn test_unicode_to_cid_cns1_round_trips_ascii() {
assert_eq!(unicode_to_cid_cns1(0x54), Some(53));
assert_eq!(lookup_adobe_cns1(53), Some(0x54));
}
#[test]
fn test_unicode_to_cid_gb1_round_trips_ascii() {
assert_eq!(unicode_to_cid_gb1(0x41), Some(34));
}
#[test]
fn test_unicode_to_cid_japan1_round_trips_ascii() {
assert_eq!(unicode_to_cid_japan1(0x41), Some(34));
}
#[test]
fn test_unicode_to_cid_korea1_round_trips_ascii() {
assert_eq!(unicode_to_cid_korea1(0x41), Some(34));
}
#[test]
fn test_unicode_to_cid_returns_none_for_unmapped_codepoint() {
assert_eq!(unicode_to_cid_cns1(0xFFFE), None);
}
}