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
use super::JSValue;
use anyhow::anyhow;
use std::collections::HashMap;

/// A macro for implementing `TryFrom<JSValue>` for multiple types at once.
/// Takes a list of type-variant pairs and generates a `TryFrom<JSValue>` implementation for each type.
///
/// # Type-Variant Pairs
///
/// * `$t:ty` - The type for which the implementation is generated
/// * `$variant:ident` - The corresponding variant of `JSValue` that is expected when converting
macro_rules! impl_try_from_jsvalue {
    ($($t:ty, $variant:ident),+ $(,)?) => {
        $(impl TryFrom<JSValue> for $t {
            type Error = anyhow::Error;

            fn try_from(value: JSValue) -> Result<Self, Self::Error> {
                match value {
                    JSValue::$variant(val) => Ok(val),
                    _ => Err(anyhow!("Error: could not convert JSValue to {}", std::any::type_name::<$t>())),
                }
            }
        })+
    };
}

impl_try_from_jsvalue!(
    bool, Bool,
    i32, Int,
    f64, Float,
    String, String,
    Vec<JSValue>, Array,
    HashMap<String, JSValue>, Object,
    Vec<u8>, ArrayBuffer,
);

impl TryFrom<JSValue> for usize {
    type Error = anyhow::Error;

    fn try_from(value: JSValue) -> Result<Self, Self::Error> {
        match value {
            JSValue::Int(val) => Ok(val as usize),
            _ => Err(anyhow!("Error: could not convert JSValue to usize")),
        }
    }
}