lib.rs (2494B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 use fluent_langneg::negotiate::NegotiationStrategy as LangNegNegotiationStrategy; 6 use fluent_langneg::negotiate_languages; 7 use nsstring::nsACString; 8 use nsstring::nsCString; 9 use thin_vec::ThinVec; 10 use unic_langid::{LanguageIdentifier, LanguageIdentifierError}; 11 use unic_langid_ffi::new_langid_for_mozilla; 12 13 /// We want to return the exact strings that were passed to us out of the 14 /// available and default pool. Since for the negotiation we canonicalize them 15 /// in `LanguageIdentifier`, this struct will preserve the original, non-canonicalized 16 /// string, and then use it to populate return array. 17 #[derive(Debug, PartialEq)] 18 struct LangIdString<'l> { 19 pub source: &'l nsCString, 20 pub langid: LanguageIdentifier, 21 } 22 23 impl<'l> LangIdString<'l> { 24 pub fn try_new(s: &'l nsCString) -> Result<Self, LanguageIdentifierError> { 25 new_langid_for_mozilla(s).map(|l| LangIdString { 26 source: s, 27 langid: l, 28 }) 29 } 30 } 31 32 impl<'l> AsRef<LanguageIdentifier> for LangIdString<'l> { 33 fn as_ref(&self) -> &LanguageIdentifier { 34 &self.langid 35 } 36 } 37 38 #[repr(C)] 39 pub enum NegotiationStrategy { 40 Filtering, 41 Matching, 42 Lookup, 43 } 44 45 fn get_strategy(input: NegotiationStrategy) -> LangNegNegotiationStrategy { 46 match input { 47 NegotiationStrategy::Filtering => LangNegNegotiationStrategy::Filtering, 48 NegotiationStrategy::Matching => LangNegNegotiationStrategy::Matching, 49 NegotiationStrategy::Lookup => LangNegNegotiationStrategy::Lookup, 50 } 51 } 52 53 #[no_mangle] 54 pub extern "C" fn fluent_langneg_negotiate_languages( 55 requested: &ThinVec<nsCString>, 56 available: &ThinVec<nsCString>, 57 default: &nsACString, 58 strategy: NegotiationStrategy, 59 result: &mut ThinVec<nsCString>, 60 ) { 61 let requested = requested 62 .iter() 63 .filter_map(|s| new_langid_for_mozilla(s).ok()) 64 .collect::<Vec<_>>(); 65 66 let available = available 67 .iter() 68 .filter_map(|s| LangIdString::try_new(s).ok()) 69 .collect::<Vec<_>>(); 70 71 let d: nsCString = default.into(); 72 let default = LangIdString::try_new(&d).ok(); 73 74 let strategy = get_strategy(strategy); 75 76 for l in negotiate_languages(&requested, &available, default.as_ref(), strategy) { 77 result.push(l.source.clone()); 78 } 79 }