move more constructor stuff into stringarray

This commit is contained in:
Pat Hickey
2020-09-02 17:16:39 -07:00
parent 39f1c9716c
commit 1d410d6559
2 changed files with 82 additions and 83 deletions

View File

@@ -1,12 +1,45 @@
use crate::Error;
use std::collections::HashMap;
use std::convert::TryInto;
use std::ffi::CString;
use std::ffi::{CString, OsString};
use wiggle::GuestPtr;
pub struct StringArray {
elems: Vec<CString>,
pub number_elements: u32,
pub cumulative_size: u32,
#[derive(Debug, Eq, Hash, PartialEq)]
pub enum PendingString {
Bytes(Vec<u8>),
OsString(OsString),
}
impl From<Vec<u8>> for PendingString {
fn from(bytes: Vec<u8>) -> Self {
Self::Bytes(bytes)
}
}
impl From<OsString> for PendingString {
fn from(s: OsString) -> Self {
Self::OsString(s)
}
}
impl PendingString {
pub fn into_string(self) -> Result<String, StringArrayError> {
let res = match self {
Self::Bytes(v) => String::from_utf8(v)?,
#[cfg(unix)]
Self::OsString(s) => {
use std::os::unix::ffi::OsStringExt;
String::from_utf8(s.into_vec())?
}
#[cfg(windows)]
Self::OsString(s) => {
use std::os::windows::ffi::OsStrExt;
let bytes: Vec<u16> = s.encode_wide().collect();
String::from_utf16(&bytes)?
}
};
Ok(res)
}
}
#[derive(Debug, thiserror::Error)]
@@ -23,10 +56,42 @@ pub enum StringArrayError {
/// Cumulative element size: must fit into u32
#[error("cumulative element size too big")]
CumElemSize,
/// Provided sequence of bytes was not a valid UTF-8.
#[error("provided sequence is not valid UTF-8: {0}")]
InvalidUtf8(#[from] std::string::FromUtf8Error),
/// Provided sequence of bytes was not a valid UTF-16.
///
/// This error is expected to only occur on Windows hosts.
#[error("provided sequence is not valid UTF-16: {0}")]
InvalidUtf16(#[from] std::string::FromUtf16Error),
}
pub struct StringArray {
elems: Vec<CString>,
pub number_elements: u32,
pub cumulative_size: u32,
}
impl StringArray {
pub fn new(elems: Vec<String>) -> Result<Self, StringArrayError> {
pub fn from_pending_vec(elems: Vec<PendingString>) -> Result<Self, StringArrayError> {
let elems = elems
.into_iter()
.map(|arg| arg.into_string())
.collect::<Result<Vec<String>, StringArrayError>>()?;
Self::from_strings(elems)
}
pub fn from_pending_map(
elems: HashMap<PendingString, PendingString>,
) -> Result<Self, StringArrayError> {
let mut pairs = Vec::new();
for (k, v) in elems.into_iter() {
let mut pair = k.into_string()?;
pair.push('=');
pair.push_str(&v.into_string()?);
pairs.push(pair);
}
Self::from_strings(pairs)
}
pub fn from_strings(elems: Vec<String>) -> Result<Self, StringArrayError> {
let elems = elems
.into_iter()
.map(|s| CString::new(s))