Skip to main content

myriad/
value.rs

1use polka::Value;
2use alloc::{string::String, vec::Vec};
3use crate::memory::Heap;
4
5// String <-> heap cell ABI.
6// A String is stored as a heap cell whose first slot is the byte length
7// (plain u64) and whose remaining cell-data words pack the UTF-8 bytes 8 per
8// word, little-endian. mask is all zeros.
9
10#[inline]
11pub fn string_word_count(byte_len: usize) -> usize {
12    1 + (byte_len + 7) / 8
13}
14
15pub fn alloc_string(heap: &mut Heap, s: &str) -> Result<Value, String> {
16    let bytes = s.as_bytes();
17    let size = string_word_count(bytes.len());
18    let (slot, gen_) = heap.try_alloc(size)?;
19    let dst = heap.cell_data_mut(slot, gen_)?;
20    dst[0] = bytes.len() as u64;
21    if !bytes.is_empty() {
22        let dst_ptr = dst[1..].as_mut_ptr() as *mut u8;
23        unsafe { core::ptr::copy_nonoverlapping(bytes.as_ptr(), dst_ptr, bytes.len()); }
24    }
25    Ok(Value::from_handle(slot, gen_))
26}
27
28pub fn read_string(heap: &Heap, val: Value) -> Option<String> {
29    if val.is_handle_none() { return None; }
30    let (slot, gen_) = val.as_handle();
31    let data = heap.cell_data(slot, gen_).ok()?;
32    if data.is_empty() { return None; }
33    let len = data[0] as usize;
34    let mut out = Vec::with_capacity(len);
35    let mut remaining = len;
36    for i in 1..data.len() {
37        if remaining == 0 { break; }
38        let word = data[i].to_le_bytes();
39        let take = remaining.min(8);
40        out.extend_from_slice(&word[..take]);
41        remaining -= take;
42    }
43    String::from_utf8(out).ok()
44}