-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjs_utils.rs
More file actions
121 lines (103 loc) · 3.49 KB
/
js_utils.rs
File metadata and controls
121 lines (103 loc) · 3.49 KB
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
use std::cell::RefCell;
use datex_core::{
dif::value::{DIFReferenceNotFoundError, DIFValueContainer},
runtime::memory::Memory,
serde::deserializer::from_value_container,
values::value_container::ValueContainer,
};
use log::info;
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use serde_wasm_bindgen::{Error, from_value};
use wasm_bindgen::{JsError, JsValue};
use web_sys::js_sys::{self, Array, ArrayBuffer, Object, Reflect};
pub trait TryAsByteSlice {
fn try_as_u8_slice(&self) -> Result<Vec<u8>, JsError>;
}
pub trait AsByteSlice {
fn as_u8_slice(&self) -> Vec<u8>;
}
impl TryAsByteSlice for JsValue {
fn try_as_u8_slice(&self) -> Result<Vec<u8>, JsError> {
let buffer: ArrayBuffer = self.clone().try_into().map_err(|_| {
JsError::new("Failed to convert JsValue to ArrayBuffer")
})?;
Ok(buffer.as_u8_slice())
}
}
impl AsByteSlice for ArrayBuffer {
fn as_u8_slice(&self) -> Vec<u8> {
let uint8_array = js_sys::Uint8Array::new(self);
let mut bytes = vec![0; uint8_array.length() as usize];
uint8_array.copy_to(&mut bytes);
bytes
}
}
pub fn js_object<T: Into<JsValue>>(values: Vec<(&str, T)>) -> Object {
let obj = Object::new();
for (key, value) in values {
let js_value: JsValue = value.into();
let _ = Reflect::set(&obj, &key.into(), &js_value);
}
obj
}
pub fn js_array<T>(values: &[T]) -> JsValue
where
T: Into<JsValue> + Clone,
{
// FIXME TODO can we avoid clone here?
let js_array = values
.iter()
.map(|x| <T as Into<JsValue>>::into(x.clone()))
.collect::<Array>();
JsValue::from(js_array)
}
pub fn js_error<T: std::fmt::Display>(err: T) -> JsError {
JsError::new(&err.to_string())
}
trait ToJsError<T> {
fn js(self) -> Result<T, JsError>;
}
impl<T, E: std::error::Error + 'static> ToJsError<T> for Result<T, E> {
fn js(self) -> Result<T, JsError> {
self.map_err(js_error)
}
}
/// Deserialize a JsValue into a Rust type T using DIFValueContainer as an intermediary,
pub fn cast_from_dif_js_value<T>(
value: JsValue,
memory: &RefCell<Memory>,
) -> Result<T, ()>
where
T: DeserializeOwned,
{
let unresolved_value_container: DIFValueContainer = from_value(value)
.expect("Failed to deserialize JsValue to DIFValueContainer");
let value_container = unresolved_value_container
.to_value_container(memory)
.map_err(|_| ())?;
from_value_container::<T>(&value_container).map_err(|e| {
info!("Deserialization error: {}", e);
()
})
}
/// Converts a JsValue to a DIFValueContainer using the provided Memory instance.
pub fn dif_js_value_to_value_container(
value: JsValue,
memory: &RefCell<Memory>,
) -> Result<ValueContainer, DIFReferenceNotFoundError> {
let unresolved_value_container: DIFValueContainer = from_value(value)
.expect("Failed to deserialize JsValue to DIFValueContainer");
unresolved_value_container.to_value_container(memory)
}
pub fn value_container_to_dif_js_value(
value_container: &ValueContainer,
) -> JsValue {
let dif_value_container =
DIFValueContainer::from_value_container(&value_container);
to_js_value(&dif_value_container)
.expect("Failed to serialize DIFValueContainer to JsValue")
}
/// Convert a serializable value to a JsValue (JSON compatible)
pub fn to_js_value<T: Serialize>(value: &T) -> Result<JsValue, Error> {
value.serialize(&serde_wasm_bindgen::Serializer::json_compatible())
}