1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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());
}
}
|