From 1d410d655995e1116958c6752fecb02c53145f1e Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Wed, 2 Sep 2020 17:16:39 -0700 Subject: [PATCH] move more constructor stuff into stringarray --- crates/wasi-common/src/ctx.rs | 88 ++++---------------------- crates/wasi-common/src/string_array.rs | 77 ++++++++++++++++++++-- 2 files changed, 82 insertions(+), 83 deletions(-) diff --git a/crates/wasi-common/src/ctx.rs b/crates/wasi-common/src/ctx.rs index db7e617097..1b77b093c4 100644 --- a/crates/wasi-common/src/ctx.rs +++ b/crates/wasi-common/src/ctx.rs @@ -1,22 +1,21 @@ use crate::entry::{Entry, EntryHandle}; use crate::fdpool::FdPool; use crate::handle::Handle; -use crate::string_array::{StringArray, StringArrayError}; +use crate::string_array::{PendingString, StringArray, StringArrayError}; use crate::sys::osdir::OsDir; use crate::sys::stdio::NullDevice; use crate::sys::stdio::{Stderr, StderrExt, Stdin, StdinExt, Stdout, StdoutExt}; use crate::virtfs::{VirtualDir, VirtualDirEntry}; use crate::wasi::types; -use crate::{Error, Result}; +use crate::Error; use std::borrow::Borrow; use std::cell::RefCell; use std::collections::HashMap; use std::convert::TryFrom; -use std::ffi::OsString; use std::fs::File; use std::path::{Path, PathBuf}; use std::rc::Rc; -use std::{env, io, string}; +use std::{env, io}; /// Possible errors when `WasiCtxBuilder` fails building /// `WasiCtx`. @@ -25,14 +24,6 @@ pub enum WasiCtxBuilderError { /// General I/O error was encountered. #[error("general I/O error encountered: {0}")] Io(#[from] io::Error), - /// Provided sequence of bytes was not a valid UTF-8. - #[error("provided sequence is not valid UTF-8: {0}")] - InvalidUtf8(#[from] 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] string::FromUtf16Error), /// Error constructing arguments #[error("while constructing arguments: {0}")] Args(#[source] StringArrayError), @@ -67,44 +58,6 @@ impl std::fmt::Debug for PendingEntry { } } -#[derive(Debug, Eq, Hash, PartialEq)] -enum PendingString { - Bytes(Vec), - OsString(OsString), -} - -impl From> for PendingString { - fn from(bytes: Vec) -> Self { - Self::Bytes(bytes) - } -} - -impl From for PendingString { - fn from(s: OsString) -> Self { - Self::OsString(s) - } -} - -impl PendingString { - fn into_string(self) -> WasiCtxBuilderResult { - 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 = s.encode_wide().collect(); - String::from_utf16(&bytes)? - } - }; - Ok(res) - } -} - struct PendingPreopen(Box WasiCtxBuilderResult>>); impl PendingPreopen { @@ -322,30 +275,11 @@ impl WasiCtxBuilder { pub fn build(&mut self) -> WasiCtxBuilderResult { // Process arguments and environment variables into `String`s, failing quickly if they // contain any NUL bytes, or if conversion from `OsString` fails. - let args = self - .args - .take() - .unwrap() - .into_iter() - .map(|arg| arg.into_string()) - .collect::>>()?; - let args = StringArray::new(args).map_err(WasiCtxBuilderError::Args)?; - let env = self - .env - .take() - .unwrap() - .into_iter() - .map(|(k, v)| { - k.into_string().and_then(|mut pair| { - v.into_string().and_then(|v| { - pair.push('='); - pair.push_str(v.as_str()); - Ok(pair) - }) - }) - }) - .collect::>>()?; - let env = StringArray::new(env).map_err(WasiCtxBuilderError::Env)?; + let args = + StringArray::from_pending_vec(self.args.take().expect("WasiCtxBuilder has args")) + .map_err(WasiCtxBuilderError::Args)?; + let env = StringArray::from_pending_map(self.env.take().expect("WasiCtxBuilder has env")) + .map_err(WasiCtxBuilderError::Env)?; let mut entries = EntryTable::new(); // Populate the non-preopen entries. @@ -461,7 +395,7 @@ impl WasiCtx { } /// Get an immutable `Entry` corresponding to the specified raw WASI `fd`. - pub(crate) fn get_entry(&self, fd: types::Fd) -> Result> { + pub(crate) fn get_entry(&self, fd: types::Fd) -> Result, Error> { match self.entries.borrow().get(&fd) { Some(entry) => Ok(entry), None => Err(Error::Badf), @@ -472,7 +406,7 @@ impl WasiCtx { /// /// The `Entry` will automatically get another free raw WASI `fd` assigned. Note that /// the two subsequent free raw WASI `fd`s do not have to be stored contiguously. - pub(crate) fn insert_entry(&self, entry: Entry) -> Result { + pub(crate) fn insert_entry(&self, entry: Entry) -> Result { self.entries.borrow_mut().insert(entry).ok_or(Error::Mfile) } @@ -483,7 +417,7 @@ impl WasiCtx { } /// Remove `Entry` corresponding to the specified raw WASI `fd` from the `WasiCtx` object. - pub(crate) fn remove_entry(&self, fd: types::Fd) -> Result> { + pub(crate) fn remove_entry(&self, fd: types::Fd) -> Result, Error> { self.entries.borrow_mut().remove(fd).ok_or(Error::Badf) } diff --git a/crates/wasi-common/src/string_array.rs b/crates/wasi-common/src/string_array.rs index a671f6a2a1..cfb3d75af2 100644 --- a/crates/wasi-common/src/string_array.rs +++ b/crates/wasi-common/src/string_array.rs @@ -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, - pub number_elements: u32, - pub cumulative_size: u32, +#[derive(Debug, Eq, Hash, PartialEq)] +pub enum PendingString { + Bytes(Vec), + OsString(OsString), +} + +impl From> for PendingString { + fn from(bytes: Vec) -> Self { + Self::Bytes(bytes) + } +} + +impl From for PendingString { + fn from(s: OsString) -> Self { + Self::OsString(s) + } +} + +impl PendingString { + pub fn into_string(self) -> Result { + 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 = 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, + pub number_elements: u32, + pub cumulative_size: u32, +} impl StringArray { - pub fn new(elems: Vec) -> Result { + pub fn from_pending_vec(elems: Vec) -> Result { + let elems = elems + .into_iter() + .map(|arg| arg.into_string()) + .collect::, StringArrayError>>()?; + Self::from_strings(elems) + } + pub fn from_pending_map( + elems: HashMap, + ) -> Result { + 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) -> Result { let elems = elems .into_iter() .map(|s| CString::new(s))