chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

View File

@@ -0,0 +1,68 @@
[
{
"input": "Pl",
"output": "pl"
},
{
"input": "eN-uS",
"output": "en-US"
},
{
"input": "ZH-hans-hK",
"output": "zh-Hans-HK"
},
{
"input": "en-scouse-fonipa",
"output": "en-fonipa-scouse"
},
{
"input": {
"type": "Locale",
"identifier": "en-US-t-es-AR-x-foo"
},
"output": {
"type": "Locale",
"identifier": "en-US-t-es-ar-x-foo"
}
},
{
"input": {
"type": "Locale",
"identifier": "en-t-en-Latn-CA-emodeng"
},
"output": {
"type": "Locale",
"identifier": "en-t-en-latn-ca-emodeng"
}
},
{
"input": {
"type": "Locale",
"identifier": "EN-US-T-ES-AR-X-FOO"
},
"output": {
"type": "Locale",
"identifier": "en-US-t-es-ar-x-foo"
}
},
{
"input": {
"type": "Locale",
"identifier": "EN-T-EN-LATN-CA-EMODENG"
},
"output": {
"type": "Locale",
"identifier": "en-t-en-latn-ca-emodeng"
}
},
{
"input": {
"type": "Locale",
"identifier": "UND-CYRL-T-ES-LATN-M0-UNGEGN"
},
"output": {
"type": "Locale",
"identifier": "und-Cyrl-t-es-latn-m0-ungegn"
}
}
]

View File

@@ -0,0 +1,162 @@
[
{
"input": {
"type": "Locale",
"identifier": "cmn-hans-cn-t-ca-u-ca-x_t-u"
},
"output": {
"error": "InvalidExtension",
"text": "unused"
}
},
{
"input": {
"type": "Locale",
"identifier": "pl-US-x-waytoolongkey"
},
"output": {
"error": "InvalidExtension",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "pl-US-x-@A-3"
},
"output": {
"error": "InvalidExtension",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "pl-US-t-h0"
},
"output": {
"error": "InvalidExtension",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "pl-US-t-h0-x-foo"
},
"output": {
"error": "InvalidExtension",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "pl-US-t-h0"
},
"output": {
"error": "InvalidExtension",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "und-t-m0"
},
"output": {
"error": "InvalidExtension",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "und-t-m0-n0-mixed"
},
"output": {
"error": "InvalidExtension",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "da-u"
},
"output": {
"error": "InvalidExtension",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "da-u--"
},
"output": {
"error": "InvalidExtension",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "da-u-t-latn"
},
"output": {
"error": "InvalidExtension",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "cmn-hans-cn-u-u"
},
"output": {
"error": "InvalidExtension",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "de-u-ca-"
},
"output": {
"error": "InvalidExtension",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "de-u-ca-gregory-"
},
"output": {
"error": "InvalidExtension",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "de-u-ca-gregory-u-hc-hc24"
},
"output": {
"error": "DuplicatedExtension",
"text": "Duplicated extension"
}
},
{
"input": {
"type": "Locale",
"identifier": "de-l-foo-l-bar"
},
"output": {
"error": "DuplicatedExtension",
"text": "Duplicated extension"
}
}
]

View File

@@ -0,0 +1,142 @@
[
{
"input": "-",
"output": {
"error": "InvalidLanguage",
"text": "The given language subtag is invalid"
}
},
{
"input": "--",
"output": {
"error": "InvalidLanguage",
"text": "The given subtag is invalid"
}
},
{
"input": "en-",
"output": {
"error": "InvalidSubtag",
"text": "The given subtag is invalid"
}
},
{
"input": "-en",
"output": {
"error": "InvalidLanguage",
"text": "The given subtag is invalid"
}
},
{
"input": "en-us-",
"output": {
"error": "InvalidSubtag",
"text": "The given subtag is invalid"
}
},
{
"input": "en_us",
"output": {
"error": "InvalidLanguage",
"text": "The given language subtag is invalid"
}
},
{
"input": "en--US",
"output": {
"error": "InvalidSubtag",
"text": "The given subtag is invalid"
}
},
{
"input": "-e-",
"output": {
"error": "InvalidLanguage",
"text": "The given subtag is invalid"
}
},
{
"input": "a1a",
"output": {
"error": "InvalidLanguage",
"text": "The given language subtag is invalid"
}
},
{
"input": "Arab-US",
"output": {
"error": "InvalidLanguage",
"text": "The given language subtag is invalid"
}
},
{
"input": "",
"output": {
"error": "InvalidLanguage",
"text": "The given language subtag is invalid"
}
},
{
"input": "pl-DSDAFAFDF",
"output": {
"error": "InvalidSubtag",
"text": "Invalid subtag"
}
},
{
"input": "pl-Latn-$1231",
"output": {
"error": "InvalidSubtag",
"text": "Invalid subtag"
}
},
{
"input": "pl-Latn-US-$1231",
"output": {
"error": "InvalidSubtag",
"text": "Invalid subtag"
}
},
{
"input": "pl-Latn-12",
"output": {
"error": "InvalidSubtag",
"text": "Invalid subtag"
}
},
{
"input": "pl-Latn-a12",
"output": {
"error": "InvalidSubtag",
"text": "Invalid subtag"
}
},
{
"input": "pl-Latn-US-3-dd",
"output": {
"error": "InvalidSubtag",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "pl-Latn-US-variant-h0-hybrid"
},
"output": {
"error": "InvalidSubtag",
"text": "Invalid subtag"
}
},
{
"input": {
"type": "Locale",
"identifier": "en-variant-emodeng-emodeng"
},
"output": {
"error": "InvalidSubtag",
"text": "Invalid subtag"
}
}
]

View File

@@ -0,0 +1,167 @@
[
{
"input": "en",
"output": {
"type": "LanguageIdentifier",
"language": "en"
}
},
{
"input": "lij",
"output": {
"type": "LanguageIdentifier",
"language": "lij"
}
},
{
"input": "en-Latn",
"output": {
"type": "LanguageIdentifier",
"language": "en",
"script": "Latn"
}
},
{
"input": "lij-Arab",
"output": {
"type": "LanguageIdentifier",
"language": "lij",
"script": "Arab"
}
},
{
"input": "en-Latn-US",
"output": {
"type": "LanguageIdentifier",
"language": "en",
"script": "Latn",
"region": "US"
}
},
{
"input": "lij-Arab-FA",
"output": {
"type": "LanguageIdentifier",
"language": "lij",
"script": "Arab",
"region": "FA"
}
},
{
"input": "en-Latn-US-windows",
"output": {
"type": "LanguageIdentifier",
"language": "en",
"script": "Latn",
"region": "US",
"variants": ["windows"]
}
},
{
"input": "lij-Arab-FA-linux",
"output": {
"type": "LanguageIdentifier",
"language": "lij",
"script": "Arab",
"region": "FA",
"variants": ["linux"]
}
},
{
"input": "lij-Arab-FA-linux-nedis",
"output": {
"type": "LanguageIdentifier",
"language": "lij",
"script": "Arab",
"region": "FA",
"variants": ["linux", "nedis"]
}
},
{
"input": "EN-latn-us",
"output": {
"type": "LanguageIdentifier",
"language": "en",
"script": "Latn",
"region": "US"
}
},
{
"input": "sl-nedis",
"output": {
"type": "LanguageIdentifier",
"language": "sl",
"variants": ["nedis"]
}
},
{
"input": "de-CH-1996",
"output": {
"type": "LanguageIdentifier",
"language": "de",
"region": "CH",
"variants": ["1996"]
}
},
{
"input": "sr-Latn",
"output": {
"type": "LanguageIdentifier",
"language": "sr",
"script": "Latn"
}
},
{
"input": "es-419",
"output": {
"type": "LanguageIdentifier",
"language": "es",
"region": "419"
}
},
{
"input": "und-Latn-US",
"output": {
"type": "LanguageIdentifier",
"script": "Latn",
"region": "US"
}
},
{
"input": "und",
"output": {
"type": "LanguageIdentifier"
}
},
{
"input": "und-Latn",
"output": {
"type": "LanguageIdentifier",
"script": "Latn"
}
},
{
"input": "pl-macos-Windows-nedis-aRabic",
"output": {
"type": "LanguageIdentifier",
"language": "pl",
"variants": ["arabic", "macos", "nedis", "windows"]
}
},
{
"input": "und-Latn-macos",
"output": {
"type": "LanguageIdentifier",
"script": "Latn",
"variants": ["macos"]
}
},
{
"input": "und-Latn-312",
"output": {
"type": "LanguageIdentifier",
"script": "Latn",
"region": "312"
}
}
]

View File

@@ -0,0 +1,298 @@
[
{
"input": {
"type": "Locale",
"identifier": "en-u-hc-h12"
},
"output": {
"type": "Locale",
"language": "en",
"extensions": {
"unicode": {
"keywords": {
"hc": "h12"
}
}
}
}
},
{
"input": {
"type": "Locale",
"identifier": "en-US-u-hc-h23"
},
"output": {
"type": "Locale",
"language": "en",
"region": "US",
"extensions": {
"unicode": {
"keywords": {
"hc": "h23"
}
}
}
}
},
{
"input": {
"type": "Locale",
"identifier": "en-US-u-foo"
},
"output": {
"type": "Locale",
"language": "en",
"region": "US",
"extensions": {
"unicode": {
"attributes": [
"foo"
]
}
}
}
},
{
"input": {
"type": "Locale",
"identifier": "en-US-u-hc-h23-ca-islamic-civil-ss-true"
},
"output": {
"type": "Locale",
"language": "en",
"region": "US",
"extensions": {
"unicode": {
"keywords": {
"hc": "h23",
"ca": "islamic-civil",
"ss": "true"
}
}
}
}
},
{
"input": {
"type": "Locale",
"identifier": "en-US-t-pl-latn-de"
},
"output": {
"type": "Locale",
"language": "en",
"region": "US",
"extensions": {
"transform": {
"tlang": "pl-Latn-DE"
}
}
}
},
{
"input": {
"type": "Locale",
"identifier": "en-US-x-private-foobar"
},
"output": {
"type": "Locale",
"language": "en",
"region": "US",
"extensions": {
"private": ["private", "foobar"]
}
}
},
{
"input": {
"type": "Locale",
"identifier": "en-US-t-h0-hybrid-k0-platform-s0-true"
},
"output": {
"type": "Locale",
"language": "en",
"region": "US",
"extensions": {
"transform": {
"tfields": {
"h0": "hybrid",
"k0": "platform",
"s0": "true"
}
}
}
}
},
{
"input": {
"type": "Locale",
"identifier": "en-US-t-es-ar-x-foo"
},
"output": {
"type": "Locale",
"language": "en",
"region": "US",
"extensions": {
"transform": {
"tlang": "es-AR"
},
"private": ["foo"]
}
}
},
{
"input": {
"type": "Locale",
"identifier": "en-US-u-ca-buddhist-hc-h12-t-es-ar-h0-hybrid-x-private-foobar"
},
"output": {
"type": "Locale",
"language": "en",
"region": "US",
"extensions": {
"unicode": {
"keywords": {
"ca": "buddhist",
"hc": "h12"
}
},
"transform": {
"tlang": "es-AR",
"tfields": {
"h0": "hybrid"
}
},
"private": ["private", "foobar"]
}
}
},
{
"input": {
"type": "Locale",
"language": "es",
"region": "MX",
"extensions": {
"unicode": {
"keywords": {
"ca": "islamic",
"co": "search",
"nu": "roman"
}
}
}
},
"output": {
"type": "Locale",
"identifier": "es-MX-u-ca-islamic-co-search-nu-roman"
}
},
{
"input": {
"type": "Locale",
"identifier": "und-u-kn"
},
"output": {
"type": "Locale",
"identifier": "und-u-kn"
}
},
{
"input": {
"type": "Locale",
"identifier": "und-u-kn-ca-calendar"
},
"output": {
"type": "Locale",
"identifier": "und-u-ca-calendar-kn"
}
},
{
"input": {
"type": "Locale",
"identifier": "und-u-kn-nu-arab"
},
"output": {
"type": "Locale",
"identifier": "und-u-kn-nu-arab"
}
},
{
"input": {
"type": "Locale",
"identifier": "und-t-m0-true"
},
"output": {
"type": "Locale",
"identifier": "und-t-m0-true"
}
},
{
"input": {
"type": "Locale",
"identifier": "und-t-m0-true-n0-mixed"
},
"output": {
"type": "Locale",
"identifier": "und-t-m0-true-n0-mixed"
}
},
{
"input": {
"type": "Locale",
"identifier": "und-t-m0-true-c0-mixed"
},
"output": {
"type": "Locale",
"identifier": "und-t-c0-mixed-m0-true"
}
},
{
"input": {
"type": "Locale",
"identifier": "da-u-ca-gregory-ca-buddhist"
},
"output": {
"type": "Locale",
"identifier": "da-u-ca-gregory"
}
},
{
"input": {
"type": "Locale",
"identifier": "pt-u-attr2-attr1-ca-gregory"
},
"output": {
"type": "Locale",
"identifier": "pt-u-attr1-attr2-ca-gregory"
}
},
{
"input": {
"type": "Locale",
"identifier": "pt-u-attr1-attr2-attr1-ca-gregory"
},
"output": {
"type": "Locale",
"identifier": "pt-u-attr1-attr2-ca-gregory"
}
},
{
"input": {
"type": "Locale",
"identifier": "en-a-not-assigned"
},
"output": {
"type": "Locale",
"identifier": "en-a-not-assigned"
}
},
{
"input": {
"type": "Locale",
"identifier": "en-w-bar-u-foo-a-bar-x-u-foo"
},
"output": {
"type": "Locale",
"identifier": "en-a-bar-u-foo-w-bar-x-u-foo"
}
}
]

View File

@@ -0,0 +1,254 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
use std::collections::HashMap;
use std::convert::{TryFrom, TryInto};
use icu_locale_core::extensions::private;
use icu_locale_core::extensions::transform;
use icu_locale_core::extensions::unicode;
use icu_locale_core::extensions::Extensions;
use icu_locale_core::{subtags, LanguageIdentifier, Locale, ParseError};
use serde::Deserialize;
#[derive(Debug, Deserialize, Clone)]
pub struct LocaleIdentifier {
#[serde(rename = "type")]
pub field_type: String,
pub identifier: String,
}
#[derive(Debug, Deserialize, Clone)]
pub struct LocaleExtensionUnicode {
#[serde(default)]
keywords: HashMap<String, Option<String>>,
#[serde(default)]
attributes: Vec<String>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct LocaleExtensionTransform {
tlang: Option<String>,
#[serde(default)]
tfields: HashMap<String, Option<String>>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct LocaleExtensions {
unicode: Option<LocaleExtensionUnicode>,
transform: Option<LocaleExtensionTransform>,
#[serde(default)]
private: Vec<String>,
_other: Option<String>,
}
impl TryFrom<LocaleExtensions> for Extensions {
type Error = ParseError;
fn try_from(input: LocaleExtensions) -> Result<Self, Self::Error> {
let mut ext = Extensions::default();
if let Some(unicode) = input.unicode {
ext.unicode.keywords = unicode
.keywords
.iter()
.map(|(k, v)| {
(
unicode::Key::try_from_str(k).expect("Parsing key failed."),
v.as_ref().map_or(
unicode::Value::try_from_str("").expect("Failed to parse Value"),
|v| unicode::Value::try_from_str(v).expect("Parsing type failed."),
),
)
})
.collect();
let v: Vec<unicode::Attribute> = unicode
.attributes
.iter()
.map(|v| unicode::Attribute::try_from_str(v).expect("Parsing attribute failed."))
.collect();
ext.unicode.attributes = unicode::Attributes::from_vec_unchecked(v);
}
if let Some(transform) = input.transform {
ext.transform.fields = transform
.tfields
.iter()
.map(|(k, v)| {
(
transform::Key::try_from_str(k).expect("Parsing key failed."),
v.as_ref()
.map(|v| {
transform::Value::try_from_str(v).expect("Parsing value failed.")
})
.expect("Value cannot be empty."),
)
})
.collect();
if let Some(tlang) = transform.tlang {
ext.transform.lang = Some(tlang.parse().expect("Failed to parse tlang."));
}
}
let v: Vec<private::Subtag> = input
.private
.iter()
.map(|v| private::Subtag::try_from_str(v).expect("Failed to add field."))
.collect();
ext.private = private::Private::from_vec_unchecked(v);
Ok(ext)
}
}
#[derive(Debug, Deserialize, Clone)]
pub struct LocaleSubtags {
#[serde(rename = "type")]
pub field_type: String,
pub language: Option<String>,
pub script: Option<String>,
pub region: Option<String>,
#[serde(default)]
pub variants: Vec<String>,
pub extensions: Option<LocaleExtensions>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct LocaleError {
pub error: String,
pub text: String,
}
#[derive(Debug, Deserialize, Clone)]
#[serde(untagged)]
#[expect(clippy::large_enum_variant)] // test code
pub enum LocaleInfo {
String(String),
Error(LocaleError),
Identifier(LocaleIdentifier),
Object(LocaleSubtags),
}
impl TryFrom<LocaleInfo> for LanguageIdentifier {
type Error = ParseError;
fn try_from(input: LocaleInfo) -> Result<Self, Self::Error> {
match input {
LocaleInfo::String(s) => s.parse(),
LocaleInfo::Error(e) => Err(e.into()),
LocaleInfo::Identifier(ident) => ident.try_into(),
LocaleInfo::Object(o) => o.try_into(),
}
}
}
impl TryFrom<LocaleInfo> for Locale {
type Error = ParseError;
fn try_from(input: LocaleInfo) -> Result<Self, Self::Error> {
match input {
LocaleInfo::String(s) => s.parse(),
LocaleInfo::Error(e) => Err(e.into()),
LocaleInfo::Identifier(ident) => ident.try_into(),
LocaleInfo::Object(o) => o.try_into(),
}
}
}
impl TryFrom<LocaleIdentifier> for LanguageIdentifier {
type Error = ParseError;
fn try_from(input: LocaleIdentifier) -> Result<Self, Self::Error> {
LanguageIdentifier::try_from_locale_bytes(input.identifier.as_bytes())
}
}
impl TryFrom<LocaleIdentifier> for Locale {
type Error = ParseError;
fn try_from(input: LocaleIdentifier) -> Result<Self, Self::Error> {
Locale::try_from_str(&input.identifier)
}
}
impl TryFrom<LocaleSubtags> for LanguageIdentifier {
type Error = ParseError;
fn try_from(subtags: LocaleSubtags) -> Result<Self, Self::Error> {
let language = if let Some(lang) = subtags.language {
lang.parse().expect("Failed to parse language subtag")
} else {
subtags::Language::UNKNOWN
};
let script = subtags
.script
.map(|s| s.parse().expect("Failed to parse script subtag."));
let region = subtags
.region
.map(|s| s.parse().expect("Failed to parse region subtag."));
let variants = subtags
.variants
.iter()
.map(|v| v.parse().expect("Failed to parse variant subtag."))
.collect::<Vec<_>>();
Ok(LanguageIdentifier {
language,
script,
region,
variants: subtags::Variants::from_vec_unchecked(variants),
})
}
}
impl TryFrom<LocaleSubtags> for Locale {
type Error = ParseError;
fn try_from(subtags: LocaleSubtags) -> Result<Self, Self::Error> {
let language = if let Some(lang) = subtags.language {
lang.parse().expect("Failed to parse language subtag")
} else {
subtags::Language::UNKNOWN
};
let script = subtags
.script
.map(|s| s.parse().expect("Failed to parse script subtag."));
let region = subtags
.region
.map(|s| s.parse().expect("Failed to parse region subtag."));
let variants = subtags
.variants
.iter()
.map(|v| v.parse().expect("Failed to parse variant subtag."))
.collect::<Vec<_>>();
let extensions = if let Some(e) = subtags.extensions {
e.try_into().expect("Failed to parse extensions.")
} else {
Extensions::default()
};
Ok(Locale {
id: LanguageIdentifier {
language,
script,
region,
variants: subtags::Variants::from_vec_unchecked(variants),
},
extensions,
})
}
}
impl From<LocaleError> for ParseError {
fn from(e: LocaleError) -> Self {
match e.error.as_str() {
"InvalidLanguage" => ParseError::InvalidLanguage,
"InvalidSubtag" => ParseError::InvalidSubtag,
"InvalidExtension" => ParseError::InvalidExtension,
"DuplicatedExtension" => ParseError::DuplicatedExtension,
_ => unreachable!("Unknown error name"),
}
}
}
#[derive(Debug, Deserialize)]
pub struct LocaleTest {
pub input: LocaleInfo,
pub output: LocaleInfo,
}

156
vendor/icu_locale_core/tests/langid.rs vendored Normal file
View File

@@ -0,0 +1,156 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
mod fixtures;
use std::convert::TryInto;
use writeable::*;
use icu_locale_core::{subtags, LanguageIdentifier, ParseError};
type Result = std::result::Result<LanguageIdentifier, ParseError>;
fn test_langid_fixtures(tests: Vec<fixtures::LocaleTest>) {
for test in tests {
match test.output {
fixtures::LocaleInfo::String(s) => {
if let fixtures::LocaleInfo::Object(ref o) = &test.input {
if o.field_type == "Locale" {
continue;
}
}
let input: LanguageIdentifier = test.input.try_into().expect("Parsing failed.");
assert_writeable_eq!(input, s);
}
fixtures::LocaleInfo::Error(err) => {
let err: ParseError = err.into();
let input: Result = test.input.try_into();
assert_eq!(input, Err(err));
}
fixtures::LocaleInfo::Identifier(ident) => {
let input: LanguageIdentifier = test.input.try_into().expect("Parsing failed.");
let output: LanguageIdentifier = ident.try_into().expect("Parsing failed.");
assert_eq!(input, output);
}
fixtures::LocaleInfo::Object(o) => {
let input: LanguageIdentifier = test.input.try_into().expect("Parsing failed.");
let output: LanguageIdentifier = o.try_into().expect("Parsing failed.");
assert_eq!(input, output);
}
}
}
}
#[test]
fn test_langid_parsing() {
let data = serde_json::from_str(include_str!("fixtures/langid.json"))
.expect("Failed to read a fixture");
test_langid_fixtures(data);
}
#[test]
fn test_langid_invalid() {
let data = serde_json::from_str(include_str!("fixtures/invalid.json"))
.expect("Failed to read a fixture");
test_langid_fixtures(data);
}
#[test]
fn test_langid_canonicalize() {
let data = serde_json::from_str(include_str!("fixtures/canonicalize.json"))
.expect("Failed to read a fixture");
test_langid_fixtures(data);
}
#[test]
fn test_langid_from_locale() {
let data = serde_json::from_str(include_str!("fixtures/locale.json"))
.expect("Failed to read a fixture");
test_langid_fixtures(data);
}
#[test]
fn test_langid_subtag_language() {
let mut lang: subtags::Language = "en".parse().expect("Failed to parse a language.");
assert_eq!(lang.as_str(), "en");
lang = subtags::Language::UNKNOWN;
assert!(lang.is_unknown());
assert_writeable_eq!(lang, "und");
}
#[test]
fn test_langid_subtag_region() {
let region: subtags::Region = "en".parse().expect("Failed to parse a region.");
assert_eq!(region.as_str(), "EN");
assert_writeable_eq!(region, "EN");
}
#[test]
fn test_langid_subtag_script() {
let script: subtags::Script = "Latn".parse().expect("Failed to parse a script.");
assert_eq!(script.as_str(), "Latn");
assert_writeable_eq!(script, "Latn");
}
#[test]
fn test_langid_subtag_variant() {
let variant: subtags::Variant = "macos".parse().expect("Failed to parse a variant.");
assert_eq!(variant.as_str(), "macos");
assert_writeable_eq!(variant, "macos");
}
#[test]
fn test_langid_subtag_variants() {
let variant: subtags::Variant = "macos".parse().expect("Failed to parse a variant.");
let mut variants = subtags::Variants::from_vec_unchecked(vec![variant]);
assert_eq!(variants.first(), Some(&variant));
variants.clear();
assert_eq!(variants.len(), 0);
}
#[test]
fn test_langid_normalizing_eq_str() {
let tests: Vec<fixtures::LocaleTest> =
serde_json::from_str(include_str!("fixtures/langid.json"))
.expect("Failed to read a fixture");
for test in tests {
let parsed: LanguageIdentifier = test.input.try_into().expect("Parsing failed.");
assert!(parsed.normalizing_eq(&parsed.write_to_string()));
}
// Check that trailing characters are not ignored
let lang: LanguageIdentifier = "en".parse().expect("Parsing failed.");
assert!(!lang.normalizing_eq("en-US"));
}
#[test]
fn test_langid_strict_cmp() {
let tests: Vec<fixtures::LocaleTest> =
serde_json::from_str(include_str!("fixtures/langid.json"))
.expect("Failed to read a fixture");
let bcp47_strings = tests
.iter()
.map(|t| match t.input {
fixtures::LocaleInfo::String(ref s) => s.as_str(),
_ => panic!("Invalid fixture"),
})
.collect::<Vec<&str>>();
for a in bcp47_strings.iter() {
for b in bcp47_strings.iter() {
let a_langid = a
.parse::<LanguageIdentifier>()
.expect("Invalid BCP-47 in fixture");
let a_normalized = a_langid.write_to_string();
let string_cmp = a_normalized.as_bytes().cmp(b.as_bytes());
let test_cmp = a_langid.strict_cmp(b.as_bytes());
assert_eq!(string_cmp, test_cmp, "{a:?}/{b:?}");
}
}
}

119
vendor/icu_locale_core/tests/locale.rs vendored Normal file
View File

@@ -0,0 +1,119 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
mod fixtures;
use std::convert::TryInto;
use writeable::*;
use icu_locale_core::{LanguageIdentifier, Locale, ParseError};
type Result = std::result::Result<Locale, ParseError>;
fn test_langid_fixtures(tests: Vec<fixtures::LocaleTest>) {
for test in tests {
match test.output {
fixtures::LocaleInfo::String(s) => {
let input: Locale = test.input.try_into().expect("Parsing failed.");
assert_writeable_eq!(input, s);
}
fixtures::LocaleInfo::Error(err) => {
let err: ParseError = err.into();
let input: Result = test.input.try_into();
assert_eq!(input, Err(err));
}
fixtures::LocaleInfo::Identifier(ident) => {
let input: Locale = test.input.try_into().expect("Parsing failed.");
let output: Locale = ident.clone().try_into().expect("Parsing failed.");
assert_eq!(input, output);
assert_writeable_eq!(input, ident.identifier);
}
fixtures::LocaleInfo::Object(o) => {
let input: Locale = test.input.try_into().expect("Parsing failed.");
let output: Locale = o.try_into().expect("Parsing failed.");
assert_eq!(input, output);
}
}
}
}
#[test]
fn test_locale_parsing() {
let data = serde_json::from_str(include_str!("fixtures/locale.json"))
.expect("Failed to read a fixture");
test_langid_fixtures(data);
}
#[test]
fn test_locale_invalid() {
let data = serde_json::from_str(include_str!("fixtures/invalid-extensions.json"))
.expect("Failed to read a fixture");
test_langid_fixtures(data);
}
#[test]
fn test_locale_is_empty() {
let locale: Locale = Locale::UNKNOWN;
assert!(locale.extensions.is_empty());
assert_writeable_eq!(locale, "und");
}
#[test]
fn test_locale_conversions() {
let locale: Locale = Locale::UNKNOWN;
let langid: LanguageIdentifier = locale.clone().into();
let locale2: Locale = langid.into();
assert_eq!(locale, locale2);
}
#[test]
fn test_locale_canonicalize() {
let data = serde_json::from_str(include_str!("fixtures/canonicalize.json"))
.expect("Failed to read a fixture");
test_langid_fixtures(data);
}
#[test]
fn test_locale_normalizing_eq_str() {
let tests: Vec<fixtures::LocaleTest> =
serde_json::from_str(include_str!("fixtures/locale.json"))
.expect("Failed to read a fixture");
for test in tests {
let parsed: Locale = test.input.try_into().expect("Parsing failed.");
assert!(parsed.normalizing_eq(&parsed.write_to_string()));
}
// Check that trailing characters are not ignored
let locale: Locale = "en".parse().expect("Parsing failed.");
assert!(!locale.normalizing_eq("en-US"));
}
#[test]
fn test_locale_strict_cmp() {
let tests: Vec<fixtures::LocaleTest> =
serde_json::from_str(include_str!("fixtures/locale.json"))
.expect("Failed to read a fixture");
let bcp47_strings = tests
.iter()
.map(|t| match t.input {
fixtures::LocaleInfo::Identifier(ref s) => s.identifier.as_str(),
_ => match t.output {
fixtures::LocaleInfo::Identifier(ref s) => s.identifier.as_str(),
_ => panic!("No string in fixture input or output: {t:?}"),
},
})
.collect::<Vec<&str>>();
for a in bcp47_strings.iter() {
for b in bcp47_strings.iter() {
let a_langid = a.parse::<Locale>().expect("Invalid BCP-47 in fixture");
let a_normalized = a_langid.write_to_string();
let string_cmp = a_normalized.as_bytes().cmp(b.as_bytes());
let test_cmp = a_langid.strict_cmp(b.as_bytes());
assert_eq!(string_cmp, test_cmp, "{a:?}/{b:?}");
}
}
}