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
use std::{ffi::CString, os::raw::c_char};
extern "C" {
fn icu_get_default_locale(output: *mut c_char, output_len: usize) -> usize;
fn icu_set_default_locale(locale: *const c_char);
fn udata_setCommonData_71(this: *const u8, error_code: *mut i32);
}
/// This function bypasses the normal ICU data loading process and allows you to force ICU's system
/// data to come out of a user-specified area in memory.
///
/// ICU data must be at least 8-aligned, and should be 16-aligned. See
/// https://unicode-org.github.io/icu/userguide/icudata
///
/// The format of this data is that of the icu common data file, as is generated by the pkgdata
/// tool with mode=common or mode=dll. You can read in a whole common mode file and pass the
/// address to the start of the data, or (with the appropriate link options) pass in the pointer to
/// the data that has been loaded from a dll by the operating system, as shown in this code:
///
/// ```c++
/// extern const char U_IMPORT U_ICUDATA_ENTRY_POINT [];
/// // U_ICUDATA_ENTRY_POINT is same as entry point specified to pkgdata tool
/// UErrorCode status = U_ZERO_ERROR;
///
/// udata_setCommonData(&U_ICUDATA_ENTRY_POINT, &status);
/// ```
///
/// It is important that the declaration be as above. The entry point must not be declared as an
/// extern void*.
///
/// Starting with ICU 4.4, it is possible to set several data packages, one per call to this
/// function. udata_open() will look for data in the multiple data packages in the order in which
/// they were set. The position of the linked-in or default-name ICU .data package in the search
/// list depends on when the first data item is loaded that is not contained in the already
/// explicitly set packages. If data was loaded implicitly before the first call to this function
/// (for example, via opening a converter, constructing a UnicodeString from default-codepage data,
/// using formatting or collation APIs, etc.), then the default data will be first in the list.
///
/// This function has no effect on application (non ICU) data. See udata_setAppData() for similar
/// functionality for application data.
// TODO(ry) Map error code to something useful.
#[inline(always)]
pub fn set_common_data_71(data: &'static [u8]) -> Result<(), i32> {
let mut error_code = 0i32;
unsafe {
udata_setCommonData_71(data.as_ptr(), &mut error_code);
}
if error_code == 0 {
Ok(())
} else {
Err(error_code)
}
}
/// Returns BCP47 language tag.
pub fn get_language_tag() -> String {
let mut output = [0u8; 1024];
let len = unsafe {
icu_get_default_locale(output.as_mut_ptr() as *mut c_char, output.len())
};
std::str::from_utf8(&output[..len]).unwrap().to_owned()
}
pub fn set_default_locale(locale: &str) {
unsafe {
let c_str = CString::new(locale).expect("Invalid locale");
icu_set_default_locale(c_str.as_ptr());
}
}