shape_ext_typescript/
marshaling.rs1use deno_core::v8;
6
7pub fn shape_type_to_ts_hint(shape_type: &str) -> String {
13 match shape_type {
14 "number" => "number".to_string(),
15 "int" => "number".to_string(),
16 "bool" => "boolean".to_string(),
17 "string" => "string".to_string(),
18 "none" => "void".to_string(),
19 s if s.starts_with("Array<") => {
20 let inner = &s[6..s.len() - 1];
21 format!("Array<{}>", shape_type_to_ts_hint(inner))
22 }
23 _ => "object".to_string(),
24 }
25}
26
27pub fn msgpack_to_v8<'s>(
36 scope: &mut v8::HandleScope<'s>,
37 bytes: &[u8],
38) -> Result<Vec<v8::Local<'s, v8::Value>>, String> {
39 if bytes.is_empty() {
40 return Ok(Vec::new());
41 }
42
43 let values: Vec<rmpv::Value> =
44 rmp_serde::from_slice(bytes).map_err(|e| format!("Failed to deserialize args: {}", e))?;
45
46 values
47 .iter()
48 .map(|v| rmpv_to_v8(scope, v))
49 .collect::<Result<Vec<_>, _>>()
50}
51
52fn rmpv_to_v8<'s>(
54 scope: &mut v8::HandleScope<'s>,
55 value: &rmpv::Value,
56) -> Result<v8::Local<'s, v8::Value>, String> {
57 match value {
58 rmpv::Value::Nil => Ok(v8::null(scope).into()),
59
60 rmpv::Value::Boolean(b) => Ok(v8::Boolean::new(scope, *b).into()),
61
62 rmpv::Value::Integer(i) => {
63 if let Some(n) = i.as_i64() {
64 if n >= i32::MIN as i64 && n <= i32::MAX as i64 {
66 Ok(v8::Integer::new(scope, n as i32).into())
67 } else {
68 Ok(v8::Number::new(scope, n as f64).into())
69 }
70 } else if let Some(n) = i.as_u64() {
71 if n <= i32::MAX as u64 {
72 Ok(v8::Integer::new_from_unsigned(scope, n as u32).into())
73 } else {
74 Ok(v8::Number::new(scope, n as f64).into())
75 }
76 } else {
77 Ok(v8::null(scope).into())
78 }
79 }
80
81 rmpv::Value::F32(f) => Ok(v8::Number::new(scope, *f as f64).into()),
82
83 rmpv::Value::F64(f) => Ok(v8::Number::new(scope, *f).into()),
84
85 rmpv::Value::String(s) => {
86 if let Some(s) = s.as_str() {
87 let v8_str = v8::String::new(scope, s)
88 .ok_or_else(|| "Failed to create V8 string".to_string())?;
89 Ok(v8_str.into())
90 } else {
91 Ok(v8::null(scope).into())
92 }
93 }
94
95 rmpv::Value::Array(arr) => {
96 let v8_arr = v8::Array::new(scope, arr.len() as i32);
97 for (i, elem) in arr.iter().enumerate() {
98 let v8_val = rmpv_to_v8(scope, elem)?;
99 v8_arr.set_index(scope, i as u32, v8_val);
100 }
101 Ok(v8_arr.into())
102 }
103
104 rmpv::Value::Map(entries) => {
105 let v8_obj = v8::Object::new(scope);
106 for (k, v) in entries {
107 let v8_key = rmpv_to_v8(scope, k)?;
108 let v8_val = rmpv_to_v8(scope, v)?;
109 v8_obj.set(scope, v8_key, v8_val);
110 }
111 Ok(v8_obj.into())
112 }
113
114 rmpv::Value::Binary(_) | rmpv::Value::Ext(_, _) => Ok(v8::null(scope).into()),
115 }
116}
117
118pub fn v8_to_msgpack(
124 scope: &mut v8::HandleScope,
125 value: v8::Local<v8::Value>,
126) -> Result<Vec<u8>, String> {
127 let rmpv_val = v8_to_rmpv(scope, value)?;
128 rmp_serde::to_vec(&rmpv_val).map_err(|e| format!("Failed to serialize result: {}", e))
129}
130
131fn v8_to_rmpv(
133 scope: &mut v8::HandleScope,
134 value: v8::Local<v8::Value>,
135) -> Result<rmpv::Value, String> {
136 if value.is_null_or_undefined() {
137 return Ok(rmpv::Value::Nil);
138 }
139
140 if value.is_boolean() {
141 let b = value.boolean_value(scope);
142 return Ok(rmpv::Value::Boolean(b));
143 }
144
145 if value.is_int32() {
147 let i = value.int32_value(scope).unwrap_or(0);
148 return Ok(rmpv::Value::Integer(rmpv::Integer::from(i as i64)));
149 }
150
151 if value.is_uint32() {
152 let u = value.uint32_value(scope).unwrap_or(0);
153 return Ok(rmpv::Value::Integer(rmpv::Integer::from(u as i64)));
154 }
155
156 if value.is_number() {
157 let f = value.number_value(scope).unwrap_or(0.0);
158 if f.fract() == 0.0 && f >= i64::MIN as f64 && f <= i64::MAX as f64 {
160 return Ok(rmpv::Value::Integer(rmpv::Integer::from(f as i64)));
161 }
162 return Ok(rmpv::Value::F64(f));
163 }
164
165 if value.is_string() {
166 let s = value.to_rust_string_lossy(scope);
167 return Ok(rmpv::Value::String(rmpv::Utf8String::from(s)));
168 }
169
170 if value.is_array() {
171 let arr = v8::Local::<v8::Array>::try_from(value)
172 .map_err(|_| "Failed to cast to Array".to_string())?;
173 let len = arr.length();
174 let mut items = Vec::with_capacity(len as usize);
175 for i in 0..len {
176 if let Some(elem) = arr.get_index(scope, i) {
177 items.push(v8_to_rmpv(scope, elem)?);
178 } else {
179 items.push(rmpv::Value::Nil);
180 }
181 }
182 return Ok(rmpv::Value::Array(items));
183 }
184
185 if value.is_object() {
186 let obj = value.to_object(scope).unwrap();
187 let property_names = obj
188 .get_own_property_names(scope, v8::GetPropertyNamesArgs::default())
189 .ok_or_else(|| "Failed to get property names".to_string())?;
190 let len = property_names.length();
191 let mut entries = Vec::with_capacity(len as usize);
192 for i in 0..len {
193 let key = property_names.get_index(scope, i).unwrap();
194 let val = obj
195 .get(scope, key)
196 .unwrap_or_else(|| v8::null(scope).into());
197 let rmpv_key = v8_to_rmpv(scope, key)?;
198 let rmpv_val = v8_to_rmpv(scope, val)?;
199 entries.push((rmpv_key, rmpv_val));
200 }
201 return Ok(rmpv::Value::Map(entries));
202 }
203
204 Ok(rmpv::Value::Nil)
206}