extern crate gettext_sys as ffi;
use std::ffi::{CStr, CString};
use std::io;
use std::path::PathBuf;
use std::ptr;
pub fn current_textdomain() -> Result<Vec<u8>, io::Error> {
unsafe {
let result = ffi::textdomain(ptr::null());
if result.is_null() {
Err(io::Error::last_os_error())
} else {
Ok(CStr::from_ptr(result).to_bytes().to_owned())
}
}
}
pub fn domain_directory<T: Into<Vec<u8>>>(domainname: T) -> Result<PathBuf, io::Error> {
let domainname = CString::new(domainname).expect("`domainname` contains an internal 0 byte");
#[cfg(windows)]
{
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;
unsafe {
let mut ptr = ffi::wbindtextdomain(domainname.as_ptr(), ptr::null());
if ptr.is_null() {
Err(io::Error::last_os_error())
} else {
let mut result = vec![];
while *ptr != 0_u16 {
result.push(*ptr);
ptr = ptr.offset(1);
}
Ok(PathBuf::from(OsString::from_wide(&result)))
}
}
}
#[cfg(not(windows))]
{
use std::ffi::OsString;
use std::os::unix::ffi::OsStringExt;
unsafe {
let result = ffi::bindtextdomain(domainname.as_ptr(), ptr::null());
if result.is_null() {
Err(io::Error::last_os_error())
} else {
let result = CStr::from_ptr(result);
Ok(PathBuf::from(OsString::from_vec(
result.to_bytes().to_vec(),
)))
}
}
}
}
pub fn textdomain_codeset<T: Into<Vec<u8>>>(domainname: T) -> Result<Option<String>, io::Error> {
let domainname = CString::new(domainname).expect("`domainname` contains an internal 0 byte");
unsafe {
let result = ffi::bind_textdomain_codeset(domainname.as_ptr(), ptr::null());
if result.is_null() {
let error = io::Error::last_os_error();
if let Some(0) = error.raw_os_error() {
return Ok(None);
} else {
return Err(error);
}
} else {
let result = CStr::from_ptr(result)
.to_str()
.expect("`bind_textdomain_codeset()` returned non-UTF-8 string")
.to_owned();
Ok(Some(result))
}
}
}