summaryrefslogtreecommitdiffstats
path: root/intl/locale/rust/fluent-langneg-ffi
diff options
context:
space:
mode:
Diffstat (limited to 'intl/locale/rust/fluent-langneg-ffi')
-rw-r--r--intl/locale/rust/fluent-langneg-ffi/Cargo.toml13
-rw-r--r--intl/locale/rust/fluent-langneg-ffi/cbindgen.toml17
-rw-r--r--intl/locale/rust/fluent-langneg-ffi/src/lib.rs79
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());
+ }
+}