port in args and env. slightly different style

building up a bunch of deferred errors in the CtxBuilder sucks. so does
reporting errors right away. Idk what to do here?
This commit is contained in:
Pat Hickey
2020-12-11 15:33:15 -08:00
parent aef8be560f
commit d586574b1f
5 changed files with 86 additions and 8 deletions

View File

@@ -25,7 +25,7 @@ pub fn instantiate(
// Additionally register any preopened directories if we have them.
let mut builder = wasi_c2::WasiCtx::builder();
builder.arg(bin_name).arg(".").inherit_stdio();
builder.arg(bin_name)?.arg(".")?.inherit_stdio();
/*
if let Some(workspace) = workspace {

View File

@@ -1,5 +1,6 @@
use crate::dir::{DirCaps, DirEntry, WasiDir};
use crate::file::{FileCaps, FileEntry, WasiFile};
use crate::string_array::{StringArray, StringArrayError};
use crate::table::Table;
use crate::Error;
use std::cell::{RefCell, RefMut};
@@ -7,6 +8,8 @@ use std::path::PathBuf;
use std::rc::Rc;
pub struct WasiCtx {
pub(crate) args: StringArray,
pub(crate) env: StringArray,
table: Rc<RefCell<Table>>,
}
@@ -17,6 +20,8 @@ impl WasiCtx {
pub fn new() -> Self {
WasiCtx {
args: StringArray::new(),
env: StringArray::new(),
table: Rc::new(RefCell::new(Table::new())),
}
}
@@ -64,9 +69,9 @@ impl WasiCtxBuilder {
pub fn build(self) -> Result<WasiCtx, Error> {
Ok(self.0)
}
pub fn arg(&mut self, _arg: &str) -> &mut Self {
// Intentionally left blank. We do not handle arguments yet.
self
pub fn arg(&mut self, arg: &str) -> Result<&mut Self, StringArrayError> {
self.0.args.push(arg.to_owned())?;
Ok(self)
}
pub fn inherit_stdio(&mut self) -> &mut Self {
self.0.insert_file(

View File

@@ -6,9 +6,11 @@ mod error;
mod file;
pub mod snapshots;
pub mod stdio;
mod string_array;
pub mod table;
pub use ctx::WasiCtx;
pub use dir::{DirCaps, WasiDir};
pub use error::Error;
pub use file::{FileCaps, WasiFile};
pub use string_array::StringArrayError;

View File

@@ -106,11 +106,11 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
argv: &GuestPtr<'b, GuestPtr<'b, u8>>,
argv_buf: &GuestPtr<'b, u8>,
) -> Result<(), Error> {
unimplemented!()
self.args.write_to_guest(argv_buf, argv)
}
fn args_sizes_get(&self) -> Result<(types::Size, types::Size), Error> {
unimplemented!()
Ok((self.args.number_elements(), self.args.cumulative_size()))
}
fn environ_get<'b>(
@@ -118,11 +118,11 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
environ: &GuestPtr<'b, GuestPtr<'b, u8>>,
environ_buf: &GuestPtr<'b, u8>,
) -> Result<(), Error> {
unimplemented!()
self.env.write_to_guest(environ_buf, environ)
}
fn environ_sizes_get(&self) -> Result<(types::Size, types::Size), Error> {
unimplemented!()
Ok((self.env.number_elements(), self.env.cumulative_size()))
}
fn clock_res_get(&self, id: types::Clockid) -> Result<types::Timestamp, Error> {

View File

@@ -0,0 +1,71 @@
use crate::Error;
use wiggle::GuestPtr;
pub struct StringArray {
elems: Vec<String>,
}
#[derive(Debug, thiserror::Error)]
pub enum StringArrayError {
#[error("Number of elements exceeds 2^32")]
NumberElements,
#[error("Element size exceeds 2^32")]
ElementSize,
#[error("Cumulative size exceeds 2^32")]
CumulativeSize,
}
impl StringArray {
pub fn new() -> Self {
StringArray { elems: Vec::new() }
}
pub fn push(&mut self, elem: String) -> Result<(), StringArrayError> {
if self.elems.len() + 1 > std::u32::MAX as usize {
return Err(StringArrayError::NumberElements);
}
if elem.as_bytes().len() + 1 > std::u32::MAX as usize {
return Err(StringArrayError::ElementSize);
}
if self.cumulative_size() as usize + elem.as_bytes().len() + 1 > std::u32::MAX as usize {
return Err(StringArrayError::CumulativeSize);
}
self.elems.push(elem);
Ok(())
}
pub fn number_elements(&self) -> u32 {
self.elems.len() as u32
}
pub fn cumulative_size(&self) -> u32 {
self.elems
.iter()
.map(|e| e.as_bytes().len() + 1)
.sum::<usize>() as u32
}
pub fn write_to_guest<'a>(
&self,
buffer: &GuestPtr<'a, u8>,
element_heads: &GuestPtr<'a, GuestPtr<'a, u8>>,
) -> Result<(), Error> {
let element_heads = element_heads.as_array(self.number_elements());
let buffer = buffer.as_array(self.cumulative_size());
let mut cursor = 0;
for (elem, head) in self.elems.iter().zip(element_heads.iter()) {
let bytes = elem.as_bytes();
let len = bytes.len() as u32;
{
let elem_buffer = buffer
.get_range(cursor..(cursor + len))
.ok_or(Error::Inval)?; // Elements don't fit in buffer provided
elem_buffer.copy_from_slice(bytes)?;
}
buffer.get(cursor + len).ok_or(Error::Inval)?.write(0)?; // 0 terminate
head?.write(buffer.get(cursor).expect("already validated"))?;
cursor += len + 1;
}
Ok(())
}
}