hg: add osstring_to_local_bytes function to the encoding crate

Summary: Another convenience method that I plan to use in the `hgmain` later.

Reviewed By: quark-zju

Differential Revision: D9441426

fbshipit-source-id: 007e4932a344b9d1c8d4d654152bcca5c2362431
This commit is contained in:
Kostia Balytskyi 2018-08-22 08:55:54 -07:00 committed by Facebook Github Bot
parent 1175b6b1c6
commit 71baca5dfa
3 changed files with 56 additions and 4 deletions

View File

@ -21,6 +21,7 @@ mod unix;
pub use unix::{
local_bytes_to_osstring,
local_bytes_to_path,
osstring_to_local_bytes,
path_to_local_bytes
};
@ -28,6 +29,7 @@ pub use unix::{
pub use windows::{
local_bytes_to_osstring,
local_bytes_to_path,
osstring_to_local_bytes,
path_to_local_bytes
};

View File

@ -26,3 +26,8 @@ pub fn path_to_local_bytes(path: &Path) -> io::Result<&[u8]> {
pub fn local_bytes_to_path(bytes: &[u8]) -> io::Result<&Path> {
Ok(Path::new(local_bytes_to_osstring(bytes)?))
}
#[inline]
pub fn osstring_to_local_bytes<S: AsRef<OsStr>>(s: &S) -> io::Result<&[u8]> {
Ok(s.as_ref().as_bytes())
}

View File

@ -7,12 +7,13 @@ use std::io::ErrorKind::InvalidInput;
use winapi;
use kernel32;
use local_encoding::{Encoder, Encoding};
use std::os::windows::ffi::OsStringExt;
use std::ffi::OsString;
use std::os::windows::ffi::{OsStringExt, OsStrExt};
use std::ffi::{OsString, OsStr};
use std::path::{Path, PathBuf};
use winapi;
const MB_ERR_INVALID_CHARS: winapi::DWORD = 0x00000008;
const WC_COMPOSITECHECK: winapi::DWORD = 0x00000200;
/// Convert local bytes into an `OsString`
/// Since this is a Windows-specific version of this function,
@ -51,7 +52,7 @@ pub fn local_bytes_to_osstring(bytes: &[u8]) -> io::Result<OsString> {
len,
)
};
if len > 0 {
if len as usize == wide.len() {
Ok(OsString::from_wide(&wide))
} else {
Err(io::Error::last_os_error())
@ -79,4 +80,48 @@ pub fn path_to_local_bytes(path: &Path) -> io::Result<Vec<u8>> {
#[inline]
pub fn local_bytes_to_path(bytes: &[u8]) -> io::Result<PathBuf> {
Ok(PathBuf::from(local_bytes_to_osstring(bytes)?))
}
}
#[inline]
pub fn osstring_to_local_bytes<S: AsRef<OsStr>>(s: &S) -> io::Result<Vec<u8>> {
let codepage = winapi::CP_ACP;
let s: &OsStr = s.as_ref();
if s.len() == 0 {
return Ok(Vec::new());
}
let wstr: Vec<u16> = s.encode_wide().collect();
let len = unsafe {
kernel32::WideCharToMultiByte(
codepage,
WC_COMPOSITECHECK,
wstr.as_ptr(),
wstr.len() as i32,
std::ptr::null_mut(),
0,
std::ptr::null(),
std::ptr::null_mut(),
)
};
if len == 0 {
return Err(io::Error::last_os_error());
}
let mut astr: Vec<u8> = Vec::with_capacity(len as usize);
let len = unsafe {
astr.set_len(len as usize);
kernel32::WideCharToMultiByte(
codepage,
WC_COMPOSITECHECK,
wstr.as_ptr(),
wstr.len() as i32,
astr.as_mut_ptr() as winapi::LPSTR,
len,
std::ptr::null(),
std::ptr::null_mut(),
)
};
if len as usize == astr.len() {
Ok(astr)
} else {
Err(io::Error::last_os_error())
}
}