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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use holochain_core_types::error::{RibosomeErrorCode, RibosomeErrorReport};
use memory_allocation::{
decode_encoded_allocation, SinglePageAllocation, SinglePageStack, U16_MAX,
};
use serde::{Deserialize, Serialize};
use serde_json;
use std::{ffi::CStr, os::raw::c_char, slice};
fn load_str_from_raw<'a>(ptr_data: *mut c_char) -> &'a str {
let ptr_safe_c_str = unsafe { CStr::from_ptr(ptr_data) };
ptr_safe_c_str.to_str().unwrap()
}
fn write_in_wasm_memory(
stack: &mut SinglePageStack,
bytes: &[u8],
len: u16,
) -> Result<SinglePageAllocation, RibosomeErrorCode> {
if u32::from(len) + u32::from(stack.top()) > U16_MAX {
return Err(RibosomeErrorCode::OutOfMemory);
}
let ptr = stack.allocate(len) as *mut c_char;
let ptr_safe = unsafe { slice::from_raw_parts_mut(ptr, len as usize) };
for (i, byte) in bytes.iter().enumerate() {
ptr_safe[i] = *byte as i8;
}
SinglePageAllocation::new(ptr as u16, len)
}
pub fn store_string(
stack: &mut SinglePageStack,
s: &str,
) -> Result<SinglePageAllocation, RibosomeErrorCode> {
let bytes = s.as_bytes();
let len = bytes.len() as u32;
if len > U16_MAX {
return Err(RibosomeErrorCode::OutOfMemory);
}
return write_in_wasm_memory(stack, bytes, len as u16);
}
pub fn store_string_into_encoded_allocation(stack: &mut SinglePageStack, s: &str) -> i32 {
store_string(stack, s).unwrap().encode() as i32
}
pub fn load_string(encoded_allocation: u32) -> Result<String, String> {
let maybe_allocation = decode_encoded_allocation(encoded_allocation);
match maybe_allocation {
Err(return_code) => Err(return_code.to_string()),
Ok(allocation) => Ok(load_str_from_raw(allocation.offset() as *mut c_char).to_string()),
}
}
pub fn store_as_json<T: Serialize>(
stack: &mut SinglePageStack,
internal: T,
) -> Result<SinglePageAllocation, RibosomeErrorCode> {
let json_bytes = serde_json::to_vec(&internal).unwrap();
let json_bytes_len = json_bytes.len() as u32;
if json_bytes_len > U16_MAX {
return Err(RibosomeErrorCode::OutOfMemory);
}
return write_in_wasm_memory(stack, &json_bytes, json_bytes_len as u16);
}
pub fn store_json_into_encoded_allocation<T: Serialize>(
stack: &mut SinglePageStack,
internal: T,
) -> i32 {
store_as_json(stack, internal).unwrap().encode() as i32
}
pub fn load_json<'s, T: Deserialize<'s>>(encoded_allocation: u32) -> Result<T, String> {
let maybe_allocation = decode_encoded_allocation(encoded_allocation);
match maybe_allocation {
Err(return_code) => Err(return_code.to_string()),
Ok(allocation) => load_json_from_raw(allocation.offset() as *mut c_char),
}
}
#[allow(unknown_lints)]
#[allow(not_unsafe_ptr_arg_deref)]
pub fn load_json_from_raw<'s, T: Deserialize<'s>>(ptr_data: *mut c_char) -> Result<T, String> {
let stored_str = load_str_from_raw(ptr_data);
let maybe_obj: Result<T, serde_json::Error> = serde_json::from_str(stored_str);
match maybe_obj {
Ok(obj) => Ok(obj),
Err(_) => {
let maybe_error_report: Result<RibosomeErrorReport, serde_json::Error> =
serde_json::from_str(stored_str);
match maybe_error_report {
Err(_) => Err(RibosomeErrorCode::ArgumentDeserializationFailed.to_string()),
Ok(error_report) => Err(error_report.description),
}
}
}
}