1use crate::ops::{OpsIndex, OpsIndexMut, Value};
2use rbson::Document;
3
4pub trait Index: private::Sealed {
5 #[doc(hidden)]
7 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;
8
9 #[doc(hidden)]
11 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;
12
13 #[doc(hidden)]
18 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
19}
20
21impl Index for usize {
22 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
23 match *v {
24 Value::Array(ref vec) => vec.get(*self),
25 _ => None,
26 }
27 }
28 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
29 match *v {
30 Value::Array(ref mut vec) => vec.get_mut(*self),
31 _ => None,
32 }
33 }
34 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
35 match *v {
36 Value::Array(ref mut vec) => {
37 let len = vec.len();
38 vec.get_mut(*self).unwrap_or_else(|| {
39 panic!(
40 "cannot access index {} of JSON array of length {}",
41 self, len
42 )
43 })
44 }
45 _ => panic!("cannot access index {} of JSON {}", self, Type(v)),
46 }
47 }
48}
49
50impl Index for str {
51 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
52 match *v {
53 Value::Document(ref map) => map.get(self),
54 _ => None,
55 }
56 }
57 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
58 match *v {
59 Value::Document(ref mut map) => map.get_mut(self),
60 _ => None,
61 }
62 }
63 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
64 if let Value::Null = *v {
65 *v = Value::Document(Document::new());
66 }
67 match *v {
68 Value::Document(ref mut map) => map.entry(self.to_owned()).or_insert(Value::Null),
69 _ => panic!("cannot access key {:?} in JSON {}", self, Type(v)),
70 }
71 }
72}
73
74impl Index for String {
75 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
76 self[..].index_into(v)
77 }
78 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
79 self[..].index_into_mut(v)
80 }
81 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
82 self[..].index_or_insert(v)
83 }
84}
85
86impl<'a, T> Index for &'a T
87where
88 T: ?Sized + Index,
89{
90 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
91 (**self).index_into(v)
92 }
93 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
94 (**self).index_into_mut(v)
95 }
96 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
97 (**self).index_or_insert(v)
98 }
99}
100
101mod private {
103 pub trait Sealed {}
104 impl Sealed for usize {}
105 impl Sealed for str {}
106 impl Sealed for String {}
107 impl<'a, T> Sealed for &'a T where T: ?Sized + Sealed {}
108}
109
110struct Type<'a>(&'a Value);
112
113impl<'a> std::fmt::Display for Type<'a> {
114 fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
115 match *self.0 {
116 Value::Null => formatter.write_str("Null"),
117 Value::Boolean(_) => formatter.write_str("Boolean"),
118 Value::Int32(_) => formatter.write_str("Int32"),
119 Value::Int64(_) => formatter.write_str("Int64"),
120 Value::Double(_) => formatter.write_str("Double"),
121 Value::String(_) => formatter.write_str("String"),
122 Value::Array(_) => formatter.write_str("Array"),
123 Value::Document(_) => formatter.write_str("Document"),
124 _ => formatter.write_str("Other"),
125 }
126 }
127}
128
129impl<I> OpsIndex<I> for Value
149where
150 I: Index,
151{
152 type Output = Value;
153
154 fn index(&self, index: I) -> &Value {
155 static NULL: Value = Value::Null;
156 index.index_into(self).unwrap_or(&NULL)
157 }
158}
159
160impl<I> OpsIndexMut<I> for Value
161where
162 I: Index,
163{
164 fn index_mut(&mut self, index: I) -> &mut Value {
165 index.index_or_insert(self)
166 }
167}