Path: blob/main/crates/wasi-common/src/string_array.rs
1692 views
use crate::{Error, ErrorExt};1use wiggle::{GuestMemory, GuestPtr};23pub struct StringArray {4elems: Vec<String>,5}67#[derive(Debug, thiserror::Error)]8pub enum StringArrayError {9#[error("Number of elements exceeds 2^32")]10NumberElements,11#[error("Element size exceeds 2^32")]12ElementSize,13#[error("Cumulative size exceeds 2^32")]14CumulativeSize,15}1617impl StringArray {18pub fn new() -> Self {19StringArray { elems: Vec::new() }20}2122pub fn push(&mut self, elem: String) -> Result<(), StringArrayError> {23if self.elems.len() + 1 > std::u32::MAX as usize {24return Err(StringArrayError::NumberElements);25}26if elem.as_bytes().len() + 1 > std::u32::MAX as usize {27return Err(StringArrayError::ElementSize);28}29if self.cumulative_size() as usize + elem.as_bytes().len() + 1 > std::u32::MAX as usize {30return Err(StringArrayError::CumulativeSize);31}32self.elems.push(elem);33Ok(())34}3536pub fn number_elements(&self) -> u32 {37self.elems.len() as u3238}3940pub fn cumulative_size(&self) -> u32 {41self.elems42.iter()43.map(|e| e.as_bytes().len() + 1)44.sum::<usize>() as u3245}4647pub fn write_to_guest(48&self,49memory: &mut GuestMemory<'_>,50buffer: GuestPtr<u8>,51element_heads: GuestPtr<GuestPtr<u8>>,52) -> Result<(), Error> {53let element_heads = element_heads.as_array(self.number_elements());54let buffer = buffer.as_array(self.cumulative_size());55let mut cursor = 0;56for (elem, head) in self.elems.iter().zip(element_heads.iter()) {57let bytes = elem.as_bytes();58let len = bytes.len() as u32;59{60let elem_buffer = buffer61.get_range(cursor..(cursor + len))62.ok_or(Error::invalid_argument())?; // Elements don't fit in buffer provided63memory.copy_from_slice(bytes, elem_buffer)?;64}65memory.write(66buffer.get(cursor + len).ok_or(Error::invalid_argument())?,670,68)?; // 0 terminate69memory.write(head?, buffer.get(cursor).expect("already validated"))?;70cursor += len + 1;71}72Ok(())73}74}757677