1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use context::Context;
use holochain_core_types::error::RibosomeReturnCode;
use holochain_wasm_utils::memory_allocation::decode_encoded_allocation;
use nucleus::{
ribosome::{api::ZomeApiFunction, memory::SinglePageManager, Defn},
ZomeFnCall,
};
use std::sync::Arc;
use wasmi::{Externals, RuntimeArgs, RuntimeValue, Trap, TrapKind};
#[derive(Clone)]
pub struct Runtime {
pub memory_manager: SinglePageManager,
pub context: Arc<Context>,
pub dna_name: String,
pub zome_call: ZomeFnCall,
}
impl Runtime {
pub fn load_utf8_from_args(&self, args: &RuntimeArgs) -> String {
assert_eq!(1, args.len());
let encoded_allocation: u32 = args.nth(0);
let maybe_allocation = decode_encoded_allocation(encoded_allocation);
let allocation = match maybe_allocation {
Err(RibosomeReturnCode::Success) => return String::new(),
Err(_) => panic!("received error code instead of valid encoded allocation"),
Ok(allocation) => allocation,
};
let bin_arg = self.memory_manager.read(allocation);
String::from_utf8(bin_arg)
.unwrap()
}
pub fn store_utf8(&mut self, json_str: &str) -> Result<Option<RuntimeValue>, Trap> {
let mut s_bytes: Vec<_> = json_str.to_string().into_bytes();
s_bytes.push(0);
let allocation_of_result = self.memory_manager.write(&s_bytes);
if allocation_of_result.is_err() {
return Err(Trap::new(TrapKind::MemoryAccessOutOfBounds));
}
let encoded_allocation = allocation_of_result.unwrap().encode();
Ok(Some(RuntimeValue::I32(encoded_allocation as i32)))
}
}
impl Externals for Runtime {
fn invoke_index(
&mut self,
index: usize,
args: RuntimeArgs,
) -> Result<Option<RuntimeValue>, Trap> {
let zf = ZomeApiFunction::from_index(index);
match zf {
ZomeApiFunction::MissingNo => panic!("unknown function index"),
_ => zf.as_fn()(self, &args),
}
}
}