toml_edit/
index.rs

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) => aot.values.get(*self),
22            Item::Value(ref a) if a.is_array() => a.as_array().and_then(|a| 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) => vec.values.get_mut(*self),
29            Item::Value(ref mut a) => a.as_array_mut().and_then(|a| 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(v)
78    }
79    fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> {
80        self[..].index_mut(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(v)
90    }
91    fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> {
92        (**self).index_mut(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("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("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("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(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("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("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(key)
155    }
156}