Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wasi-common/src/string_array.rs
1692 views
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 {
19
pub fn new() -> Self {
20
StringArray { elems: Vec::new() }
21
}
22
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
37
pub fn number_elements(&self) -> u32 {
38
self.elems.len() as u32
39
}
40
41
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
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
77