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
use crate::{lazyvalue::LazyValue, value::Value};
use core::ops;

pub trait Index: private::Sealed {
    /// Return None if the index is not already in the array or object.
    #[doc(hidden)]
    fn value_index_into<'dom, 'v>(self, v: &'v Value<'dom>) -> Option<&'v Value<'dom>>;

    /// Return None if the index is not already in the array or object lazy_value.
    #[doc(hidden)]
    fn lazyvalue_index_into<'de>(self, v: &'de LazyValue<'de>) -> Option<LazyValue<'de>>;
}

pub trait IndexMut: private::Sealed {
    /// Return None if the key is not already in the array or object.
    #[doc(hidden)]
    fn index_into_mut<'dom, 'v>(self, v: &'v mut Value<'dom>) -> Option<&'v mut Value<'dom>>;
}

impl Index for usize {
    fn value_index_into<'dom, 'v>(self, v: &'v Value<'dom>) -> Option<&'v Value<'dom>> {
        v.get_index(self)
    }

    fn lazyvalue_index_into<'de>(self, v: &'de LazyValue<'de>) -> Option<LazyValue<'de>> {
        v.get_index(self)
    }
}

impl IndexMut for usize {
    fn index_into_mut<'dom, 'v>(self, v: &'v mut Value<'dom>) -> Option<&'v mut Value<'dom>> {
        v.get_index_mut(self)
    }
}

impl Index for &str {
    fn value_index_into<'dom, 'v>(self, v: &'v Value<'dom>) -> Option<&'v Value<'dom>> {
        v.get_key(self)
    }

    fn lazyvalue_index_into<'de>(self, v: &'de LazyValue<'de>) -> Option<LazyValue<'de>> {
        v.get_key(self)
    }
}

impl IndexMut for &str {
    fn index_into_mut<'dom, 'v>(self, v: &'v mut Value<'dom>) -> Option<&'v mut Value<'dom>> {
        v.get_key_mut(self)
    }
}

// Prevent users from implementing the Index trait.
mod private {
    pub trait Sealed {}
    impl Sealed for usize {}
    impl Sealed for str {}
    impl Sealed for std::string::String {}
    impl<'a, T> Sealed for &'a T where T: ?Sized + Sealed {}
}

impl<'dom, I> ops::Index<I> for Value<'dom>
where
    I: Index,
{
    type Output = Value<'dom>;

    fn index(&self, index: I) -> &Value<'dom> {
        // if not found, return NULL value
        thread_local! {
            pub static NULL: Value<'static> = const { Value::new_uinit() };
        }
        index.value_index_into(self).unwrap()
    }
}