1use std::fmt::{self, Display};
2
3use yasi::InternedString;
4
5use crate::{InOMap, Value};
6
7struct Type<'a>(&'a Value);
9
10impl<'a> Display for Type<'a> {
11 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
12 match *self.0 {
13 Value::Null => formatter.write_str("null"),
14 Value::Bool(_) => formatter.write_str("boolean"),
15 Value::Number(_) => formatter.write_str("number"),
16 Value::String(_) => formatter.write_str("string"),
17 Value::Array(_) => formatter.write_str("array"),
18 Value::Object(_) => formatter.write_str("object"),
19 }
20 }
21}
22pub trait Index {
23 #[doc(hidden)]
25 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;
26
27 #[doc(hidden)]
29 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;
30
31 #[doc(hidden)]
33 fn index_into_owned(&self, v: Value) -> Option<Value>;
34
35 #[doc(hidden)]
40 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
41}
42
43impl Index for usize {
44 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
45 match v {
46 Value::Array(vec) => vec.get(*self),
47 _ => None,
48 }
49 }
50 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
51 match v {
52 Value::Array(vec) => vec.get_mut(*self),
53 _ => None,
54 }
55 }
56 fn index_into_owned(&self, v: Value) -> Option<Value> {
57 match v {
58 Value::Array(mut vec) => {
59 if vec.len() > *self {
60 Some(vec.remove(*self))
61 } else {
62 None
63 }
64 }
65 _ => None,
66 }
67 }
68 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
69 match v {
70 Value::Array(vec) => {
71 let len = vec.len();
72 vec.get_mut(*self).unwrap_or_else(|| {
73 panic!(
74 "cannot access index {} of JSON array of length {}",
75 self, len
76 )
77 })
78 }
79 _ => panic!("cannot access index {} of JSON {}", self, Type(v)),
80 }
81 }
82}
83
84impl Index for str {
85 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
86 match v {
87 Value::Object(map) => map.get(self),
88 _ => None,
89 }
90 }
91 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
92 match v {
93 Value::Object(map) => map.get_mut(self),
94 _ => None,
95 }
96 }
97 fn index_into_owned(&self, v: Value) -> Option<Value> {
98 match v {
99 Value::Object(mut map) => map.remove(self),
100 _ => None,
101 }
102 }
103 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
104 if let Value::Null = v {
105 *v = Value::Object(InOMap::new());
106 }
107 match v {
108 Value::Object(map) => map
109 .entry(InternedString::intern(self))
110 .or_insert(Value::Null),
111 _ => panic!("cannot access key {:?} in JSON {}", self, Type(v)),
112 }
113 }
114}
115
116impl Index for String {
117 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
118 self[..].index_into(v)
119 }
120 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
121 self[..].index_into_mut(v)
122 }
123 fn index_into_owned(&self, v: Value) -> Option<Value> {
124 self[..].index_into_owned(v)
125 }
126 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
127 self[..].index_or_insert(v)
128 }
129}
130
131impl<'a, T> Index for &'a T
132where
133 T: ?Sized + Index,
134{
135 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
136 (**self).index_into(v)
137 }
138 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
139 (**self).index_into_mut(v)
140 }
141 fn index_into_owned(&self, v: Value) -> Option<Value> {
142 (**self).index_into_owned(v)
143 }
144 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
145 (**self).index_or_insert(v)
146 }
147}
148
149impl<I> std::ops::Index<I> for Value
150where
151 I: Index,
152{
153 type Output = Value;
154
155 fn index(&self, index: I) -> &Value {
184 static NULL: Value = Value::Null;
185 index.index_into(self).unwrap_or(&NULL)
186 }
187}
188
189impl<I> std::ops::IndexMut<I> for Value
190where
191 I: Index,
192{
193 fn index_mut(&mut self, index: I) -> &mut Value {
227 index.index_or_insert(self)
228 }
229}