#![cfg(target_os = "windows")]
use std;
use std::mem;
use super::{WideStr, WideString};
use std::ffi::{OsString, OsStr};
use std::os::windows::ffi::{OsStringExt, OsStrExt};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WideCString {
inner: Vec<u16>,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WideCStr {
inner: [u16],
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NulError(usize, Vec<u16>);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MissingNulError(Option<Vec<u16>>);
impl WideCString {
pub fn new() -> WideCString {
WideCString { inner: vec![0] }
}
pub fn from_vec<T: Into<Vec<u16>>>(v: T) -> Result<WideCString, NulError> {
let v = v.into();
match v.iter().position(|&val| val == 0) {
None => Ok(unsafe { WideCString::from_vec_unchecked(v) }),
Some(pos) => Err(NulError(pos, v)),
}
}
pub fn from_vec_with_nul<T: Into<Vec<u16>>>(v: T) -> Result<WideCString, MissingNulError> {
let mut v = v.into();
match v.iter().position(|&val| val == 0) {
None => Err(MissingNulError(Some(v))),
Some(pos) => {
v.truncate(pos + 1);
Ok(unsafe { WideCString::from_vec_with_nul_unchecked(v) })
}
}
}
pub unsafe fn from_vec_unchecked(v: Vec<u16>) -> WideCString {
let mut v = v;
match v.last() {
None => v.push(0),
Some(&c) if c != 0 => v.push(0),
Some(_) => (),
}
WideCString::from_vec_with_nul_unchecked(v)
}
pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u16>) -> WideCString {
WideCString { inner: v }
}
pub fn from_str<T: AsRef<OsStr>>(s: T) -> Result<WideCString, NulError> {
let v: Vec<u16> = s.as_ref().encode_wide().collect();
WideCString::from_vec(v)
}
pub fn from_str_with_nul<T: AsRef<OsStr>>(s: T) -> Result<WideCString, MissingNulError> {
let v: Vec<u16> = s.as_ref().encode_wide().collect();
WideCString::from_vec_with_nul(v)
}
pub fn from_wide_str<T: AsRef<WideStr>>(s: T) -> Result<WideCString, NulError> {
WideCString::from_vec(s.as_ref().as_slice())
}
pub fn from_wide_str_with_nul<T: AsRef<WideStr>>(s: T) -> Result<WideCString, MissingNulError> {
WideCString::from_vec_with_nul(s.as_ref().as_slice())
}
pub unsafe fn from_ptr_str<'a>(p: *const u16) -> WideCString {
assert!(!p.is_null());
let mut i: isize = 0;
while *p.offset(i) != 0 {
i = i + 1;
}
let slice = std::slice::from_raw_parts(p, i as usize + 1);
WideCString::from_vec_with_nul_unchecked(slice.into())
}
pub unsafe fn from_ptr(p: *const u16, len: usize) -> Result<WideCString, NulError> {
if len == 0 {
return Ok(WideCString::new());
}
assert!(!p.is_null());
let slice = std::slice::from_raw_parts(p, len);
WideCString::from_vec(slice)
}
pub unsafe fn from_ptr_with_nul(p: *const u16,
len: usize)
-> Result<WideCString, MissingNulError> {
if len == 0 {
return Ok(WideCString::new());
}
assert!(!p.is_null());
let slice = std::slice::from_raw_parts(p, len);
WideCString::from_vec_with_nul(slice)
}
pub fn as_wide_c_str(&self) -> &WideCStr {
self
}
pub fn into_vec(self) -> Vec<u16> {
let mut v = self.inner;
v.pop();
v
}
pub fn into_vec_with_nul(self) -> Vec<u16> {
self.inner
}
}
impl Into<Vec<u16>> for WideCString {
fn into(self) -> Vec<u16> {
self.into_vec()
}
}
impl From<WideCString> for OsString {
fn from(s: WideCString) -> OsString {
s.to_os_string()
}
}
impl From<WideCString> for WideString {
fn from(s: WideCString) -> WideString {
s.to_wide_string()
}
}
impl<'a, T: ?Sized + AsRef<WideCStr>> From<&'a T> for WideCString {
fn from(s: &'a T) -> WideCString {
s.as_ref().to_wide_c_string()
}
}
impl std::ops::Index<std::ops::RangeFull> for WideCString {
type Output = WideCStr;
#[inline]
fn index(&self, _index: std::ops::RangeFull) -> &WideCStr {
WideCStr::from_inner(&self.inner)
}
}
impl std::ops::Deref for WideCString {
type Target = WideCStr;
#[inline]
fn deref(&self) -> &WideCStr {
&self[..]
}
}
impl WideCStr {
pub fn new<'a, S: AsRef<WideCStr> + ?Sized>(s: &'a S) -> &'a WideCStr {
s.as_ref()
}
fn from_inner(slice: &[u16]) -> &WideCStr {
unsafe { mem::transmute(slice) }
}
pub unsafe fn from_ptr_str<'a>(p: *const u16) -> &'a WideCStr {
assert!(!p.is_null());
let mut i: isize = 0;
while *p.offset(i) != 0 {
i = i + 1;
}
mem::transmute(std::slice::from_raw_parts(p, i as usize + 1))
}
pub unsafe fn from_ptr_with_nul<'a>(p: *const u16, len: usize) -> &'a WideCStr {
assert!(*p.offset(len as isize) == 0);
mem::transmute(std::slice::from_raw_parts(p, len + 1))
}
pub fn from_slice_with_nul<'a>(slice: &'a [u16]) -> Result<&'a WideCStr, MissingNulError> {
match slice.iter().position(|x| *x == 0) {
None => Err(MissingNulError(None)),
Some(i) => Ok(unsafe { std::mem::transmute(&slice[..i + 1]) }),
}
}
pub fn to_wide_c_string(&self) -> WideCString {
unsafe { WideCString::from_vec_with_nul_unchecked(self.inner.to_owned()) }
}
pub fn to_os_string(&self) -> OsString {
OsString::from_wide(self.as_slice())
}
pub fn to_wide_string(&self) -> WideString {
WideString::from_vec(self.as_slice())
}
pub fn to_string(&self) -> Result<String, std::string::FromUtf16Error> {
String::from_utf16(self.as_slice())
}
pub fn to_string_lossy(&self) -> String {
String::from_utf16_lossy(self.as_slice())
}
pub fn as_slice(&self) -> &[u16] {
&self.inner[..self.len()]
}
pub fn as_slice_with_nul(&self) -> &[u16] {
&self.inner
}
pub fn as_ptr(&self) -> *const u16 {
self.inner.as_ptr()
}
pub fn len(&self) -> usize {
self.inner.len() - 1
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl std::borrow::Borrow<WideCStr> for WideCString {
fn borrow(&self) -> &WideCStr {
&self[..]
}
}
impl ToOwned for WideCStr {
type Owned = WideCString;
fn to_owned(&self) -> WideCString {
self.to_wide_c_string()
}
}
impl AsRef<WideCStr> for WideCStr {
fn as_ref(&self) -> &WideCStr {
self
}
}
impl AsRef<WideCStr> for WideCString {
fn as_ref(&self) -> &WideCStr {
self
}
}
impl AsRef<[u16]> for WideCStr {
fn as_ref(&self) -> &[u16] {
self.as_slice()
}
}
impl AsRef<[u16]> for WideCString {
fn as_ref(&self) -> &[u16] {
self.as_slice()
}
}
impl NulError {
pub fn nul_position(&self) -> usize {
self.0
}
pub fn into_vec(self) -> Vec<u16> {
self.1
}
}
impl Into<Vec<u16>> for NulError {
fn into(self) -> Vec<u16> {
self.into_vec()
}
}
impl std::fmt::Display for NulError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "nul value found at position {}", self.0)
}
}
impl std::error::Error for NulError {
fn description(&self) -> &str {
"nul value found"
}
}
impl MissingNulError {
pub fn into_vec(self) -> Option<Vec<u16>> {
self.0
}
}
impl std::fmt::Display for MissingNulError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "missing terminating nul value")
}
}
impl std::error::Error for MissingNulError {
fn description(&self) -> &str {
"missing terminating nul value"
}
}