diff --git a/Cargo.toml b/Cargo.toml index f6b73f6..e246679 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,6 +71,7 @@ serde_json = "1" mysql-common-derive = { path = "derive", version = "0.30.2", optional = true } btoi = "0.4.3" zstd = "0.13" +unic-langid = { version = "0.9.4", optional = true } [dev-dependencies] proptest = "1.0" @@ -104,6 +105,7 @@ test = ["derive"] derive = ["mysql-common-derive"] binlog = ["bitvec"] nightly = ["test"] +unic-langid = ["dep:unic-langid"] [package.metadata.docs.rs] rustdoc-args = ["--cfg", "docsrs"] @@ -119,4 +121,5 @@ features = [ "bigdecimal", "derive", "binlog", + "unic-langid", ] diff --git a/src/value/convert/mod.rs b/src/value/convert/mod.rs index 2816a72..157122f 100644 --- a/src/value/convert/mod.rs +++ b/src/value/convert/mod.rs @@ -31,6 +31,7 @@ pub mod decimal; pub mod time; pub mod time02; pub mod uuid; +pub mod unic_langid; lazy_static::lazy_static! { static ref DATETIME_RE_YMD: Regex = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap(); diff --git a/src/value/convert/unic_langid.rs b/src/value/convert/unic_langid.rs new file mode 100644 index 0000000..43f7bd6 --- /dev/null +++ b/src/value/convert/unic_langid.rs @@ -0,0 +1,60 @@ +//! This module implements conversion to ISO language-locale identifiers +//! See [unic-locale](https://github.com/zbraniecki/unic-locale) + +#![cfg(feature = "unic-langid")] + +use std::convert::TryFrom; +use unic_langid::LanguageIdentifier; + +use super::{FromValue, FromValueError, ParseIr, Value}; + +#[cfg_attr(docsrs, doc(cfg(feature = "unic-langid")))] +impl TryFrom for ParseIr { + type Error = FromValueError; + + fn try_from(value: Value) -> Result { + match &value { + Value::Bytes(b) => match LanguageIdentifier::from_bytes(b) { + Ok(ident) => Ok(ParseIr(ident, value)), + Err(_) => Err(FromValueError(value)), + }, + _ => Err(FromValueError(value)), + } + } +} + +#[cfg_attr(docsrs, doc(cfg(feature = "unic-langid")))] +impl From> for LanguageIdentifier { + fn from(value: ParseIr) -> Self { + value.commit() + } +} + +#[cfg_attr(docsrs, doc(cfg(feature = "unic-langid")))] +impl From> for Value { + fn from(value: ParseIr) -> Self { + value.rollback() + } +} + +#[cfg_attr(docsrs, doc(cfg(feature = "unic-langid")))] +impl FromValue for LanguageIdentifier { + type Intermediate = ParseIr; +} + +#[cfg_attr(docsrs, doc(cfg(feature = "unic-langid")))] +impl From for Value { + fn from(lang_ident: LanguageIdentifier) -> Value { + Value::Bytes(lang_ident.to_string().into()) + } +} + +#[test] +fn can_convert_sql_locale_to_ident() { + let value = Value::Bytes(String::from("en-US").into_bytes()); + + let ident = LanguageIdentifier::from_value(value); + + assert_eq!(ident.language.to_string().as_str(), "en"); + assert_eq!(ident.to_string().as_str(), "en-US"); +}