1 use crate::{Error, ErrorExt}; 2 use wiggle::{GuestMemory, GuestPtr}; 3 4 pub struct StringArray { 5 elems: Vec<String>, 6 } 7 8 #[derive(Debug, thiserror::Error)] 9 pub enum StringArrayError { 10 #[error("Number of elements exceeds 2^32")] 11 NumberElements, 12 #[error("Element size exceeds 2^32")] 13 ElementSize, 14 #[error("Cumulative size exceeds 2^32")] 15 CumulativeSize, 16 } 17 18 impl StringArray { new() -> Self19 pub fn new() -> Self { 20 StringArray { elems: Vec::new() } 21 } 22 push(&mut self, elem: String) -> Result<(), StringArrayError>23 pub fn push(&mut self, elem: String) -> Result<(), StringArrayError> { 24 if self.elems.len() + 1 > std::u32::MAX as usize { 25 return Err(StringArrayError::NumberElements); 26 } 27 if elem.as_bytes().len() + 1 > std::u32::MAX as usize { 28 return Err(StringArrayError::ElementSize); 29 } 30 if self.cumulative_size() as usize + elem.as_bytes().len() + 1 > std::u32::MAX as usize { 31 return Err(StringArrayError::CumulativeSize); 32 } 33 self.elems.push(elem); 34 Ok(()) 35 } 36 number_elements(&self) -> u3237 pub fn number_elements(&self) -> u32 { 38 self.elems.len() as u32 39 } 40 cumulative_size(&self) -> u3241 pub fn cumulative_size(&self) -> u32 { 42 self.elems 43 .iter() 44 .map(|e| e.as_bytes().len() + 1) 45 .sum::<usize>() as u32 46 } 47 write_to_guest( &self, memory: &mut GuestMemory<'_>, buffer: GuestPtr<u8>, element_heads: GuestPtr<GuestPtr<u8>>, ) -> Result<(), Error>48 pub fn write_to_guest( 49 &self, 50 memory: &mut GuestMemory<'_>, 51 buffer: GuestPtr<u8>, 52 element_heads: GuestPtr<GuestPtr<u8>>, 53 ) -> Result<(), Error> { 54 let element_heads = element_heads.as_array(self.number_elements()); 55 let buffer = buffer.as_array(self.cumulative_size()); 56 let mut cursor = 0; 57 for (elem, head) in self.elems.iter().zip(element_heads.iter()) { 58 let bytes = elem.as_bytes(); 59 let len = bytes.len() as u32; 60 { 61 let elem_buffer = buffer 62 .get_range(cursor..(cursor + len)) 63 .ok_or(Error::invalid_argument())?; // Elements don't fit in buffer provided 64 memory.copy_from_slice(bytes, elem_buffer)?; 65 } 66 memory.write( 67 buffer.get(cursor + len).ok_or(Error::invalid_argument())?, 68 0, 69 )?; // 0 terminate 70 memory.write(head?, buffer.get(cursor).expect("already validated"))?; 71 cursor += len + 1; 72 } 73 Ok(()) 74 } 75 } 76