diff options
Diffstat (limited to 'intl/locale/rust/fluent-langneg-ffi')
-rw-r--r-- | intl/locale/rust/fluent-langneg-ffi/Cargo.toml | 13 | ||||
-rw-r--r-- | intl/locale/rust/fluent-langneg-ffi/cbindgen.toml | 17 | ||||
-rw-r--r-- | intl/locale/rust/fluent-langneg-ffi/src/lib.rs | 79 |
3 files changed, 109 insertions, 0 deletions
diff --git a/intl/locale/rust/fluent-langneg-ffi/Cargo.toml b/intl/locale/rust/fluent-langneg-ffi/Cargo.toml new file mode 100644 index 0000000000..88d6bad4d4 --- /dev/null +++ b/intl/locale/rust/fluent-langneg-ffi/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "fluent-langneg-ffi" +version = "0.1.0" +license = "MPL-2.0" +authors = ["Zibi Braniecki <zibi@braniecki.net>"] +edition = "2018" + +[dependencies] +nsstring = { path = "../../../../xpcom/rust/nsstring" } +thin-vec = { version = "0.2.1", features = ["gecko-ffi"] } +fluent-langneg = { version = "0.13", features = ["cldr"] } +unic-langid = "0.9" +unic-langid-ffi = { path = "../unic-langid-ffi" } diff --git a/intl/locale/rust/fluent-langneg-ffi/cbindgen.toml b/intl/locale/rust/fluent-langneg-ffi/cbindgen.toml new file mode 100644 index 0000000000..98ec15d389 --- /dev/null +++ b/intl/locale/rust/fluent-langneg-ffi/cbindgen.toml @@ -0,0 +1,17 @@ +header = """/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */""" +autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen. See RunCbindgen.py */ +#ifndef mozilla_intl_locale_MozLocaleBindings_h +#error "Don't include this file directly, instead include MozLocaleBindings.h" +#endif +""" +include_version = true +braces = "SameLine" +line_length = 100 +tab_width = 2 +language = "C++" +namespaces = ["mozilla", "intl", "ffi"] + +[export.rename] +"ThinVec" = "nsTArray" diff --git a/intl/locale/rust/fluent-langneg-ffi/src/lib.rs b/intl/locale/rust/fluent-langneg-ffi/src/lib.rs new file mode 100644 index 0000000000..591e9ef861 --- /dev/null +++ b/intl/locale/rust/fluent-langneg-ffi/src/lib.rs @@ -0,0 +1,79 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use fluent_langneg::negotiate::NegotiationStrategy as LangNegNegotiationStrategy; +use fluent_langneg::negotiate_languages; +use nsstring::nsACString; +use nsstring::nsCString; +use thin_vec::ThinVec; +use unic_langid::{LanguageIdentifier, LanguageIdentifierError}; +use unic_langid_ffi::new_langid_for_mozilla; + +/// We want to return the exact strings that were passed to us out of the +/// available and default pool. Since for the negotiation we canonicalize them +/// in `LanguageIdentifier`, this struct will preserve the original, non-canonicalized +/// string, and then use it to populate return array. +#[derive(Debug, PartialEq)] +struct LangIdString<'l> { + pub source: &'l nsCString, + pub langid: LanguageIdentifier, +} + +impl<'l> LangIdString<'l> { + pub fn try_new(s: &'l nsCString) -> Result<Self, LanguageIdentifierError> { + new_langid_for_mozilla(s).map(|l| LangIdString { + source: s, + langid: l, + }) + } +} + +impl<'l> AsRef<LanguageIdentifier> for LangIdString<'l> { + fn as_ref(&self) -> &LanguageIdentifier { + &self.langid + } +} + +#[repr(C)] +pub enum NegotiationStrategy { + Filtering, + Matching, + Lookup, +} + +fn get_strategy(input: NegotiationStrategy) -> LangNegNegotiationStrategy { + match input { + NegotiationStrategy::Filtering => LangNegNegotiationStrategy::Filtering, + NegotiationStrategy::Matching => LangNegNegotiationStrategy::Matching, + NegotiationStrategy::Lookup => LangNegNegotiationStrategy::Lookup, + } +} + +#[no_mangle] +pub extern "C" fn fluent_langneg_negotiate_languages( + requested: &ThinVec<nsCString>, + available: &ThinVec<nsCString>, + default: &nsACString, + strategy: NegotiationStrategy, + result: &mut ThinVec<nsCString>, +) { + let requested = requested + .iter() + .filter_map(|s| new_langid_for_mozilla(s).ok()) + .collect::<Vec<_>>(); + + let available = available + .iter() + .filter_map(|s| LangIdString::try_new(s).ok()) + .collect::<Vec<_>>(); + + let d: nsCString = default.into(); + let default = LangIdString::try_new(&d).ok(); + + let strategy = get_strategy(strategy); + + for l in negotiate_languages(&requested, &available, default.as_ref(), strategy) { + result.push(l.source.clone()); + } +} |