diff options
Diffstat (limited to 'vendor/unic-langid-impl/src/likelysubtags/mod.rs')
-rw-r--r-- | vendor/unic-langid-impl/src/likelysubtags/mod.rs | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/vendor/unic-langid-impl/src/likelysubtags/mod.rs b/vendor/unic-langid-impl/src/likelysubtags/mod.rs new file mode 100644 index 000000000..dad9dc9a6 --- /dev/null +++ b/vendor/unic-langid-impl/src/likelysubtags/mod.rs @@ -0,0 +1,136 @@ +mod tables; + +pub use tables::CLDR_VERSION; + +use crate::subtags; + +unsafe fn lang_from_parts( + input: (Option<u64>, Option<u32>, Option<u32>), + lang: Option<subtags::Language>, + script: Option<subtags::Script>, + region: Option<subtags::Region>, +) -> Option<( + subtags::Language, + Option<subtags::Script>, + Option<subtags::Region>, +)> { + let lang = lang + .or_else(|| input.0.map(|s| subtags::Language::from_raw_unchecked(s))) + .unwrap(); + let script = script.or_else(|| input.1.map(|s| subtags::Script::from_raw_unchecked(s))); + let region = region.or_else(|| input.2.map(|r| subtags::Region::from_raw_unchecked(r))); + Some((lang, script, region)) +} + +pub fn maximize( + lang: subtags::Language, + script: Option<subtags::Script>, + region: Option<subtags::Region>, +) -> Option<( + subtags::Language, + Option<subtags::Script>, + Option<subtags::Region>, +)> { + if !lang.is_empty() && script.is_some() && region.is_some() { + return None; + } + + if let Some(l) = Into::<Option<u64>>::into(lang) { + if let Some(r) = region { + let result = tables::LANG_REGION + .binary_search_by_key(&(&l.into(), &r.into()), |(key_l, key_r, _)| (key_l, key_r)) + .ok(); + if let Some(r) = result { + // safe because all table entries are well formed. + return unsafe { lang_from_parts(tables::LANG_REGION[r].2, None, None, None) }; + } + } + + if let Some(s) = script { + let result = tables::LANG_SCRIPT + .binary_search_by_key(&(&l.into(), &s.into()), |(key_l, key_s, _)| (key_l, key_s)) + .ok(); + if let Some(r) = result { + // safe because all table entries are well formed. + return unsafe { lang_from_parts(tables::LANG_SCRIPT[r].2, None, None, None) }; + } + } + + let result = tables::LANG_ONLY + .binary_search_by_key(&(&l.into()), |(key_l, _)| key_l) + .ok(); + if let Some(r) = result { + // safe because all table entries are well formed. + return unsafe { lang_from_parts(tables::LANG_ONLY[r].1, None, script, region) }; + } + } else if let Some(s) = script { + if let Some(r) = region { + let result = tables::SCRIPT_REGION + .binary_search_by_key(&(&s.into(), &r.into()), |(key_s, key_r, _)| (key_s, key_r)) + .ok(); + if let Some(r) = result { + // safe because all table entries are well formed. + return unsafe { lang_from_parts(tables::SCRIPT_REGION[r].2, None, None, None) }; + } + } + + let result = tables::SCRIPT_ONLY + .binary_search_by_key(&(&s.into()), |(key_s, _)| key_s) + .ok(); + if let Some(r) = result { + // safe because all table entries are well formed. + return unsafe { lang_from_parts(tables::SCRIPT_ONLY[r].1, None, None, region) }; + } + } else if let Some(r) = region { + let result = tables::REGION_ONLY + .binary_search_by_key(&(&r.into()), |(key_r, _)| key_r) + .ok(); + if let Some(r) = result { + // safe because all table entries are well formed. + return unsafe { lang_from_parts(tables::REGION_ONLY[r].1, None, None, None) }; + } + } + + None +} + +pub fn minimize( + lang: subtags::Language, + script: Option<subtags::Script>, + region: Option<subtags::Region>, +) -> Option<( + subtags::Language, + Option<subtags::Script>, + Option<subtags::Region>, +)> { + // maximize returns None when all 3 components are + // already filled so don't call it in that case. + let max_langid = if !lang.is_empty() && script.is_some() && region.is_some() { + (lang, script, region) + } else { + maximize(lang, script, region)? + }; + + if let Some(trial) = maximize(max_langid.0, None, None) { + if trial == max_langid { + return Some((max_langid.0, None, None)); + } + } + + if max_langid.2.is_some() { + if let Some(trial) = maximize(max_langid.0, None, max_langid.2) { + if trial == max_langid { + return Some((max_langid.0, None, max_langid.2)); + } + } + } + + if max_langid.1.is_some() { + if let Some(trial) = maximize(max_langid.0, max_langid.1, None) { + if trial == max_langid { + return Some((max_langid.0, max_langid.1, None)); + } + } + } + None +} |