1extern crate alloc;
2
3use alloc::string::String;
4use alloc::vec::Vec;
5
6use super::html::Node;
7
8use super::error::{Result, MochiError, PtrCastError};
9
10type MutRawBufPtr = *mut u8;
11type RawBufPtr = *const u8;
12pub(crate) type HostPtr = i32;
13
14#[link(wasm_import_module = "core")]
15extern "C" {
16 pub(crate) fn copy(ptr: HostPtr) -> HostPtr;
17 pub(crate) fn destroy(ptr: HostPtr);
18
19 fn create_array() -> HostPtr;
20 fn create_obj() -> HostPtr;
21 fn create_string(buf_raw_ptr: RawBufPtr, buf_len: i32) -> HostPtr;
22 fn create_bool(value: bool) -> HostPtr;
23 fn create_float(value: f64) -> HostPtr;
24 fn create_int(value: i64) -> HostPtr;
25 fn create_error() -> HostPtr;
26
27 pub(crate) fn ptr_kind(ptr: HostPtr) -> Kind;
28
29 fn string_len(ptr: HostPtr) -> i32;
30 fn read_string(ptr: HostPtr, buf_raw_ptr: MutRawBufPtr, buf_len: i32);
31 fn read_int(ptr: HostPtr) -> i64;
32 fn read_float(ptr: HostPtr) -> f64;
33 fn read_bool(ptr: HostPtr) -> bool;
34
35 fn obj_len(ptr: HostPtr) -> usize;
36 fn obj_get(ptr: HostPtr, key_raw_ptr: RawBufPtr, len: usize) -> HostPtr;
37 fn obj_set(ptr: HostPtr, key_raw_ptr: RawBufPtr, len: usize, value_ptr: HostPtr);
38 fn obj_remove(ptr: HostPtr, key_raw_ptr: RawBufPtr, len: usize);
39 fn obj_keys(ptr: HostPtr) -> HostPtr;
40 fn obj_values(ptr: HostPtr) -> HostPtr;
41
42 fn array_len(ptr: HostPtr) -> i32;
43 fn array_get(ptr: HostPtr, idx: i32) -> i32;
44 fn array_set(ptr: HostPtr, idx: i32, value_ptr: i32);
45 fn array_append(ptr: HostPtr, value_pre: i32);
46 fn array_remove(ptr: HostPtr, idx: i32);
47}
48
49pub fn print<T: AsRef<str>>(string: T) {
51 let string = string.as_ref();
52 extern "C" {
53 fn print(string: *const u8, size: usize);
54 }
55 unsafe {
56 print(string.as_ptr(), string.len());
57 }
58}
59
60#[repr(C)]
61#[derive(PartialEq, Eq, Debug, Clone, Copy)]
62pub enum Kind {
63 Unknown,
64 Null,
65 Object,
66 Array,
67 String,
68 Number,
69 Bool,
70 Node
71}
72
73#[derive(Debug)]
84pub struct PtrRef(HostPtr);
85
86impl PtrRef {
87 #[inline]
88 pub fn new(ptr: HostPtr) -> Self {
89 PtrRef(ptr)
90 }
91
92 #[inline]
93 pub fn pointer(&self) -> HostPtr {
94 self.0
95 }
96
97 #[inline]
98 pub fn kind(&self) -> Kind {
99 unsafe { ptr_kind(self.0) }
100 }
101
102 #[inline]
103 pub fn is_none(&self) -> bool {
104 self.kind() == Kind::Null
105 }
106
107 #[inline]
108 pub fn is_some(&self) -> bool {
109 !self.is_none()
110 }
111
112 pub fn as_string(&self) -> Result<String> {
113 match self.kind() {
114 Kind::String => {
115 let str_len = unsafe { string_len(self.0) };
116 let mut buf = alloc::vec::Vec::with_capacity(str_len as usize);
117 unsafe {
118 read_string(self.0, buf.as_mut_ptr(), str_len);
119 buf.set_len(str_len as usize);
120 }
121 String::from_utf8(buf).map_err(|_| MochiError::from(PtrCastError::Utf8NotValid))
122 },
123 Kind::Null => {
124 Err(MochiError::from(PtrCastError::NullPointer))
125 },
126 _ => {
127 Err(MochiError::from(PtrCastError::NotString))
128 }
129 }
130 }
131
132 pub fn as_object(self) -> Result<ObjectRef> {
133 match self.kind() {
134 Kind::Object => {
135 Ok(ObjectRef(self))
136 },
137 Kind::Null => {
138 Err(MochiError::from(PtrCastError::NullPointer))
139 },
140 _ => {
141 Err(MochiError::from(PtrCastError::NotObject))
142 }
143 }
144 }
145
146 pub fn as_array(self) -> Result<ArrayRef> {
147 match self.kind() {
148 Kind::Array => {
149 Ok(ArrayRef::from(self))
150 },
151 Kind::Null => {
152 Err(MochiError::from(PtrCastError::NullPointer))
153 },
154 _ => {
155 Err(MochiError::from(PtrCastError::NotArray))
156 }
157 }
158 }
159
160 pub fn as_int(&self) -> Result<i64> {
161 match self.kind() {
162 Kind::Number | Kind::Bool | Kind::String => {
163 Ok(unsafe { read_int(self.0) })
164 },
165 Kind::Null => {
166 Err(MochiError::from(PtrCastError::NullPointer))
167 },
168 _ => {
169 Err(MochiError::from(PtrCastError::NotNumber))
170 }
171 }
172 }
173
174 pub fn as_float(&self) -> Result<f64> {
175 match self.kind() {
176 Kind::Number | Kind::Bool | Kind::String => {
177 Ok(unsafe { read_float(self.0) })
178 },
179 Kind::Null => {
180 Err(MochiError::from(PtrCastError::NullPointer))
181 },
182 _ => {
183 Err(MochiError::from(PtrCastError::NotNumber))
184 }
185 }
186 }
187
188 pub fn as_bool(&self) -> Result<bool> {
189 match self.kind() {
190 Kind::Number | Kind::Bool => {
191 Ok(unsafe { read_bool(self.0) })
192 },
193 Kind::Null => {
194 Err(MochiError::from(PtrCastError::NullPointer))
195 },
196 _ => {
197 Err(MochiError::from(PtrCastError::NotNumber))
198 }
199 }
200 }
201
202 pub fn as_node(&self) -> Result<Node> {
204 match self.kind() {
205 Kind::Node => {
206 Ok(unsafe { Node::from(self.0) })
207 },
208 Kind::Null => {
209 Err(MochiError::from(PtrCastError::NullPointer))
210 },
211 _ => {
212 Err(MochiError::from(PtrCastError::NotArray))
213 }
214 }
215 }
216}
217
218impl Clone for PtrRef {
219 fn clone(&self) -> Self {
220 Self(unsafe { copy(self.0) })
221 }
222}
223
224impl Drop for PtrRef {
225 fn drop(&mut self) {
226 unsafe { destroy(self.0) }
227 }
228}
229
230impl From<i32> for PtrRef {
231 fn from(value: i32) -> Self {
232 PtrRef(unsafe { create_int(value as i64) })
233 }
234}
235
236impl From<i64> for PtrRef {
237 fn from(value: i64) -> Self {
238 PtrRef(unsafe { create_int(value as i64) })
239 }
240}
241
242impl From<f32> for PtrRef {
243 fn from(value: f32) -> Self {
244 PtrRef(unsafe { create_float(value as f64) })
245 }
246}
247
248impl From<f64> for PtrRef {
249 fn from(value: f64) -> Self {
250 PtrRef(unsafe { create_float(value as f64) })
251 }
252}
253
254impl From<bool> for PtrRef {
255 fn from(value: bool) -> Self {
256 PtrRef(unsafe { create_bool(value) })
257 }
258}
259
260impl From<String> for PtrRef {
261 fn from(value: String) -> Self {
262 PtrRef( unsafe { create_string(value.as_ptr(), value.len() as i32) })
263 }
264}
265
266impl From<&str> for PtrRef {
267 fn from(value: &str) -> Self {
268 PtrRef( unsafe { create_string(value.as_ptr(), value.len() as i32) })
269 }
270}
271
272impl<T> From<Result<T>> for PtrRef where PtrRef: From<T> {
273 fn from(value: Result<T>) -> Self {
274 match value {
275 Result::Ok(val) => val.into(),
276 Result::Err(_) => PtrRef(unsafe { create_error() }),
277 }
278 }
279}
280
281impl Into<String> for PtrRef {
282 fn into(self) -> String {
283 self.as_string().unwrap_or_default()
284 }
285}
286
287pub struct ObjectRef(PtrRef);
291
292impl ObjectRef {
293 pub fn new() -> Self {
294 let ptr: i32 = unsafe { create_obj() };
295 Self(PtrRef::new(ptr))
296 }
297
298 #[inline]
299 pub fn len(&self) -> usize {
300 unsafe { obj_len(self.0.0) }
301 }
302
303 #[inline]
304 pub fn is_empty(&self) -> bool {
305 self.len() == 0
306 }
307
308 pub fn get(&self, key: &str) -> PtrRef {
309 let ptr = unsafe { obj_get(self.0.0, key.as_ptr(), key.len()) };
310 PtrRef::new(ptr)
311 }
312
313 #[inline]
314 pub fn set(&mut self, key: &str, value: PtrRef) {
315 unsafe { obj_set(self.0.0, key.as_ptr(), key.len(), value.0) }
316 }
317
318 #[inline]
319 pub fn remove(&mut self, key: &str) {
320 unsafe { obj_remove(self.0.0, key.as_ptr(), key.len()) }
321 }
322
323 pub fn keys(&self) -> ArrayRef {
324 let rid = unsafe { obj_keys(self.0 .0) };
325 ArrayRef::from(PtrRef::new(rid))
326 }
327
328 pub fn values(&self) -> ArrayRef {
329 let rid = unsafe { obj_values(self.0 .0) };
330 ArrayRef::from(PtrRef::new(rid))
331 }
332
333 #[inline]
334 pub fn ptr(&self) -> i32 {
335 self.0.pointer()
336 }
337}
338
339impl Clone for ObjectRef {
340 fn clone(&self) -> Self {
341 Self(PtrRef::new(unsafe { copy(self.0.0) }))
342 }
343}
344
345impl Default for ObjectRef {
346 fn default() -> Self {
347 Self::new()
348 }
349}
350
351#[derive(Debug)]
352pub struct ArrayRef(
353 PtrRef,
354 i32,
355 i32
356);
357
358impl ArrayRef {
359 pub fn new() -> Self {
360 let pid = unsafe { create_array() };
361 Self(PtrRef::new(pid), 0, 0)
362 }
363
364 #[inline]
365 pub fn len(&self) -> i32 {
366 unsafe { array_len(self.0.0) }
367 }
368
369 #[inline]
370 pub fn is_empty(&self) -> bool {
371 self.len() == 0
372 }
373
374 pub fn get(&self, index: i32) -> PtrRef {
375 let rid = unsafe { array_get(self.0.0, index) };
376 PtrRef::new(rid)
377 }
378
379 #[inline]
380 pub fn set(&mut self, index: i32, object: PtrRef) {
381 unsafe { array_set(self.0.0, index, object.0) };
382 }
383
384 #[inline]
385 pub fn insert(&mut self, value: PtrRef) {
386 unsafe { array_append(self.0.0, value.0) };
387 self.2 += 1;
388 }
389
390 #[inline]
391 pub fn remove(&mut self, index: i32) {
392 unsafe { array_remove(self.0.0, index) };
393 self.2 -= 1;
394 }
395
396 #[inline]
397 pub fn ptr(&self) -> i32 {
398 self.0.pointer()
399 }
400}
401
402impl Iterator for ArrayRef {
403 type Item = PtrRef;
404
405 fn next(&mut self) -> Option<Self::Item> {
406 if self.1 > self.2 || self.2 == i32::MAX {
407 return None;
408 }
409 let value_ref = self.get(self.1);
410 self.1 += 1;
411 Some(value_ref)
412 }
413}
414
415impl DoubleEndedIterator for ArrayRef {
416 fn next_back(&mut self) -> Option<Self::Item> {
417 if self.1 > self.2 || self.2 == i32::MAX {
418 return None;
419 }
420 let value_ref = self.get(self.2);
421 self.2 = self.2.wrapping_sub(1);
422 Some(value_ref)
423 }
424}
425
426impl FromIterator<PtrRef> for ArrayRef {
427 fn from_iter<T: IntoIterator<Item = PtrRef>>(iter: T) -> Self {
428 let mut array = Self::new();
429 for value in iter {
430 array.insert(value);
431 }
432 array
433 }
434}
435
436impl From<PtrRef> for ArrayRef {
437 fn from(ptr: PtrRef) -> Self {
438 let length = unsafe { array_len(ptr.0) };
439 Self(ptr, 0, length.wrapping_sub(1))
440 }
441}
442
443impl<T: Into<PtrRef>> From<Vec<T>> for ArrayRef {
444 fn from(value: Vec<T>) -> Self {
445 let mut array = ArrayRef::new();
446 for item in value {
447 array.insert(item.into())
448 }
449 array
450 }
451}
452
453impl Clone for ArrayRef {
454 fn clone(&self) -> Self {
455 let ptr = unsafe { copy(self.0.0) };
456 Self(PtrRef::new(ptr), self.1, self.2)
457 }
458}
459
460impl Default for ArrayRef {
461 fn default() -> Self {
462 Self::new()
463 }
464}