1use std::ops;
2
3use crate::document::Document;
4use crate::key::Key;
5use crate::table::TableKeyValue;
6use crate::{value, InlineTable, InternalString, Item, Table, Value};
7
8// copied from
9// https://github.com/serde-rs/json/blob/master/src/value/index.rs
10
11pub trait Index: crate::private::Sealed {
12 #[doc(hidden)]
13 fn index<'v>(&self, val: &'v Item) -> Option<&'v Item>;
14 #[doc(hidden)]
15 fn index_mut<'v>(&self, val: &'v mut Item) -> Option<&'v mut Item>;
16}
17
18impl Index for usize {
19 fn index<'v>(&self, v: &'v Item) -> Option<&'v Item> {
20 match *v {
21 Item::ArrayOfTables(ref aot: &ArrayOfTables) => aot.values.get(*self),
22 Item::Value(ref a: &Value) if a.is_array() => a.as_array().and_then(|a: &Array| a.values.get(*self)),
23 _ => None,
24 }
25 }
26 fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> {
27 match *v {
28 Item::ArrayOfTables(ref mut vec: &mut ArrayOfTables) => vec.values.get_mut(*self),
29 Item::Value(ref mut a: &mut Value) => a.as_array_mut().and_then(|a: &mut Array| a.values.get_mut(*self)),
30 _ => None,
31 }
32 }
33}
34
35impl Index for str {
36 fn index<'v>(&self, v: &'v Item) -> Option<&'v Item> {
37 match *v {
38 Item::Table(ref t) => t.get(self),
39 Item::Value(ref v) => v
40 .as_inline_table()
41 .and_then(|t| t.items.get(self))
42 .and_then(|kv| {
43 if !kv.value.is_none() {
44 Some(&kv.value)
45 } else {
46 None
47 }
48 }),
49 _ => None,
50 }
51 }
52 fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> {
53 if let Item::None = *v {
54 let mut t = InlineTable::default();
55 t.items.insert(
56 InternalString::from(self),
57 TableKeyValue::new(Key::new(self), Item::None),
58 );
59 *v = value(Value::InlineTable(t));
60 }
61 match *v {
62 Item::Table(ref mut t) => Some(t.entry(self).or_insert(Item::None)),
63 Item::Value(ref mut v) => v.as_inline_table_mut().map(|t| {
64 &mut t
65 .items
66 .entry(InternalString::from(self))
67 .or_insert_with(|| TableKeyValue::new(Key::new(self), Item::None))
68 .value
69 }),
70 _ => None,
71 }
72 }
73}
74
75impl Index for String {
76 fn index<'v>(&self, v: &'v Item) -> Option<&'v Item> {
77 self[..].index(val:v)
78 }
79 fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> {
80 self[..].index_mut(val:v)
81 }
82}
83
84impl<'a, T: ?Sized> Index for &'a T
85where
86 T: Index,
87{
88 fn index<'v>(&self, v: &'v Item) -> Option<&'v Item> {
89 (**self).index(val:v)
90 }
91 fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> {
92 (**self).index_mut(val:v)
93 }
94}
95
96impl<I> ops::Index<I> for Item
97where
98 I: Index,
99{
100 type Output = Item;
101
102 fn index(&self, index: I) -> &Item {
103 index.index(self).expect(msg:"index not found")
104 }
105}
106
107impl<I> ops::IndexMut<I> for Item
108where
109 I: Index,
110{
111 fn index_mut(&mut self, index: I) -> &mut Item {
112 index.index_mut(self).expect(msg:"index not found")
113 }
114}
115
116impl<'s> ops::Index<&'s str> for Table {
117 type Output = Item;
118
119 fn index(&self, key: &'s str) -> &Item {
120 self.get(key).expect(msg:"index not found")
121 }
122}
123
124impl<'s> ops::IndexMut<&'s str> for Table {
125 fn index_mut(&mut self, key: &'s str) -> &mut Item {
126 self.entry(key).or_insert(default:Item::None)
127 }
128}
129
130impl<'s> ops::Index<&'s str> for InlineTable {
131 type Output = Value;
132
133 fn index(&self, key: &'s str) -> &Value {
134 self.get(key).expect(msg:"index not found")
135 }
136}
137
138impl<'s> ops::IndexMut<&'s str> for InlineTable {
139 fn index_mut(&mut self, key: &'s str) -> &mut Value {
140 self.get_mut(key).expect(msg:"index not found")
141 }
142}
143
144impl<'s> ops::Index<&'s str> for Document {
145 type Output = Item;
146
147 fn index(&self, key: &'s str) -> &Item {
148 self.root.index(key)
149 }
150}
151
152impl<'s> ops::IndexMut<&'s str> for Document {
153 fn index_mut(&mut self, key: &'s str) -> &mut Item {
154 self.root.index_mut(index:key)
155 }
156}
157