gqlite 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/Cargo.toml +20 -0
- data/ext/gqlitedb/Cargo.toml +77 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/benches/common/pokec.rs +30 -20
- data/ext/gqlitedb/gqlite_bench_data/README.MD +6 -0
- data/ext/gqlitedb/gqlite_bench_data/scripts/generate_smaller_pokec.rb +85 -0
- data/ext/gqlitedb/gqlite_bench_data/scripts/to_efficient_pokec.rb +34 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/release.toml +2 -2
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators/arithmetic.rs +1 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators/stats.rs +27 -49
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators.rs +7 -7
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/capi.rs +34 -10
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/compiler/expression_analyser.rs +10 -4
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/compiler/variables_manager.rs +36 -39
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/compiler.rs +46 -41
- data/ext/gqlitedb/src/connection.rs +300 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/error.rs +113 -50
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/containers.rs +21 -26
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/edge.rs +3 -3
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/math.rs +3 -3
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/node.rs +2 -2
- data/ext/gqlitedb/src/functions/path.rs +75 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/scalar.rs +3 -3
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/string.rs +1 -1
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/value.rs +7 -7
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions.rs +29 -31
- data/ext/gqlitedb/src/graph.rs +11 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/interpreter/evaluators.rs +178 -224
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/interpreter/instructions.rs +8 -2
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/lib.rs +9 -5
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/parser/ast.rs +54 -76
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/parser/gql.pest +9 -4
- data/ext/{gqliterb/vendor/gqlitedb/src/parser/parser.rs → gqlitedb/src/parser/parser_impl.rs} +86 -34
- data/ext/gqlitedb/src/parser.rs +4 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/prelude.rs +3 -2
- data/ext/gqlitedb/src/query_result.rs +88 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/store/redb.rs +260 -170
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/store/sqlite.rs +157 -142
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/store.rs +30 -23
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/evaluators.rs +41 -85
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/store/redb.rs +12 -5
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/store/sqlite.rs +12 -5
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/store.rs +106 -114
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/templates/ast.rs +29 -29
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/templates/programs.rs +4 -4
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/value/compare.rs +13 -20
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/value/contains.rs +2 -2
- data/ext/gqlitedb/src/value.rs +225 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/value_table.rs +22 -18
- data/ext/gqliterb/Cargo.toml +12 -34
- data/ext/gqliterb/src/lib.rs +67 -39
- data/ext/graphcore/Cargo.toml +19 -0
- data/ext/graphcore/README.MD +4 -0
- data/ext/graphcore/release.toml +1 -0
- data/ext/graphcore/src/error.rs +28 -0
- data/ext/{gqliterb/vendor/gqlitedb → graphcore}/src/graph.rs +146 -35
- data/ext/graphcore/src/lib.rs +16 -0
- data/ext/graphcore/src/prelude.rs +4 -0
- data/ext/{gqliterb/vendor/gqlitedb → graphcore}/src/serialize_with.rs +2 -2
- data/ext/graphcore/src/table.rs +272 -0
- data/ext/{gqliterb/vendor/gqlitedb → graphcore}/src/value/value_map.rs +44 -49
- data/ext/graphcore/src/value.rs +413 -0
- metadata +94 -83
- data/ext/gqliterb/.cargo/config.toml +0 -2
- data/ext/gqliterb/Cargo.lock +0 -1109
- data/ext/gqliterb/vendor/gqlitedb/Cargo.lock +0 -2060
- data/ext/gqliterb/vendor/gqlitedb/Cargo.toml +0 -132
- data/ext/gqliterb/vendor/gqlitedb/src/connection.rs +0 -208
- data/ext/gqliterb/vendor/gqlitedb/src/functions/path.rs +0 -48
- data/ext/gqliterb/vendor/gqlitedb/src/parser.rs +0 -4
- data/ext/gqliterb/vendor/gqlitedb/src/value.rs +0 -559
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/askama.toml +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/benches/common/mod.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/benches/pokec_divan.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/benches/pokec_iai.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators/containers.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators/count.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/consts.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/interpreter/mod.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/store/pgql.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/compiler.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/parser.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/templates.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/utils.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/call_stats.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_count_for_node.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_create.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_delete.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_delete_by_nodes.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_select.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_update.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/graph_create.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/graph_delete.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/metadata_create_table.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/metadata_get.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/metadata_set.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/node_create.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/node_delete.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/node_select.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/node_update.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/table_exists.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/upgrade_from_1_01.sql +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/upgrade_graph_from_1_01.sql +0 -0
@@ -0,0 +1,272 @@
|
|
1
|
+
use crate::{prelude::*, Value, ValueTryIntoRef};
|
2
|
+
|
3
|
+
/// Table of values
|
4
|
+
#[derive(Debug, Default, Clone, PartialEq)]
|
5
|
+
pub struct Table
|
6
|
+
{
|
7
|
+
headers: Vec<String>,
|
8
|
+
data: Vec<crate::Value>,
|
9
|
+
}
|
10
|
+
|
11
|
+
impl Table
|
12
|
+
{
|
13
|
+
/// Create a new table, with the given headers and data.
|
14
|
+
/// It is assumed that number of column is equalt to headers, and the number
|
15
|
+
/// of row is equal to length of data divided by number of columns.
|
16
|
+
pub fn new(headers: Vec<String>, data: Vec<crate::Value>) -> Result<Table>
|
17
|
+
{
|
18
|
+
if data.len() % headers.len() != 0
|
19
|
+
{
|
20
|
+
Err(error::Error::InvalidTableDimensions)?;
|
21
|
+
}
|
22
|
+
Ok(Table { headers, data })
|
23
|
+
}
|
24
|
+
/// Create an empty table
|
25
|
+
pub fn empty() -> Table
|
26
|
+
{
|
27
|
+
Table {
|
28
|
+
headers: Default::default(),
|
29
|
+
data: Default::default(),
|
30
|
+
}
|
31
|
+
}
|
32
|
+
/// Return true is empty
|
33
|
+
pub fn is_empty(&self) -> bool
|
34
|
+
{
|
35
|
+
self.data.is_empty()
|
36
|
+
}
|
37
|
+
/// Access to the headers of the table
|
38
|
+
pub fn headers(&self) -> &Vec<String>
|
39
|
+
{
|
40
|
+
&self.headers
|
41
|
+
}
|
42
|
+
/// number of rows
|
43
|
+
pub fn rows(&self) -> usize
|
44
|
+
{
|
45
|
+
self.data.len() / self.headers.len()
|
46
|
+
}
|
47
|
+
/// number of columns
|
48
|
+
pub fn columns(&self) -> usize
|
49
|
+
{
|
50
|
+
self.headers.len()
|
51
|
+
}
|
52
|
+
/// value access
|
53
|
+
pub fn get<T>(&self, row: usize, column: usize) -> Result<&T>
|
54
|
+
where
|
55
|
+
Value: ValueTryIntoRef<T>,
|
56
|
+
{
|
57
|
+
let v = self.value(row, column)?;
|
58
|
+
v.try_into_ref()
|
59
|
+
}
|
60
|
+
/// value access
|
61
|
+
pub fn get_owned<T>(&self, row: usize, column: usize) -> Result<T>
|
62
|
+
where
|
63
|
+
Value: ValueTryIntoRef<T>,
|
64
|
+
T: Clone,
|
65
|
+
{
|
66
|
+
let v = self.value(row, column)?;
|
67
|
+
v.try_into_ref().map(T::to_owned)
|
68
|
+
}
|
69
|
+
/// value access
|
70
|
+
pub fn value(&self, row: usize, column: usize) -> Result<&Value>
|
71
|
+
{
|
72
|
+
if column > self.headers.len()
|
73
|
+
{
|
74
|
+
Err(error::Error::InvalidRange)
|
75
|
+
}
|
76
|
+
else
|
77
|
+
{
|
78
|
+
self
|
79
|
+
.data
|
80
|
+
.get(row * self.headers.len() + column)
|
81
|
+
.ok_or(error::Error::InvalidRange)
|
82
|
+
}
|
83
|
+
}
|
84
|
+
/// Create an iterator over the rows in the table
|
85
|
+
pub fn row_iter(&self) -> RowIter<'_>
|
86
|
+
{
|
87
|
+
RowIter {
|
88
|
+
data: &self.data,
|
89
|
+
columns: self.columns(),
|
90
|
+
index: 0,
|
91
|
+
row_count: self.rows(),
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
impl From<Table> for value::Value
|
97
|
+
{
|
98
|
+
fn from(val: Table) -> Self
|
99
|
+
{
|
100
|
+
let mut rows: Vec<value::Value> = Default::default();
|
101
|
+
let cl = val.headers.len();
|
102
|
+
rows.push(val.headers.into());
|
103
|
+
let mut it = val.data.into_iter();
|
104
|
+
loop
|
105
|
+
{
|
106
|
+
let first = it.next();
|
107
|
+
if let Some(first) = first
|
108
|
+
{
|
109
|
+
let mut row = Vec::with_capacity(cl);
|
110
|
+
row.push(first);
|
111
|
+
for _ in 1..cl
|
112
|
+
{
|
113
|
+
row.push(it.next().unwrap());
|
114
|
+
}
|
115
|
+
rows.push(row.into());
|
116
|
+
}
|
117
|
+
else
|
118
|
+
{
|
119
|
+
break;
|
120
|
+
}
|
121
|
+
}
|
122
|
+
rows.into()
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
/// View of a row
|
127
|
+
#[derive(Debug)]
|
128
|
+
pub struct RowView<'a>
|
129
|
+
{
|
130
|
+
row: &'a [value::Value], // length = columns.len()
|
131
|
+
}
|
132
|
+
|
133
|
+
impl<'a> RowView<'a>
|
134
|
+
{
|
135
|
+
/// Iterate over the value of the row view
|
136
|
+
pub fn iter(&self) -> std::slice::Iter<'a, value::Value>
|
137
|
+
{
|
138
|
+
self.row.iter()
|
139
|
+
}
|
140
|
+
/// value access
|
141
|
+
pub fn value(&self, column: usize) -> Result<&Value>
|
142
|
+
{
|
143
|
+
self.row.get(column).ok_or(error::Error::InvalidRange)
|
144
|
+
}
|
145
|
+
/// value access
|
146
|
+
pub fn get<T>(&self, column: usize) -> Result<&T>
|
147
|
+
where
|
148
|
+
Value: ValueTryIntoRef<T>,
|
149
|
+
{
|
150
|
+
let v = self.value(column)?;
|
151
|
+
v.try_into_ref()
|
152
|
+
}
|
153
|
+
/// value access
|
154
|
+
pub fn get_owned<T>(&self, column: usize) -> Result<T>
|
155
|
+
where
|
156
|
+
Value: ValueTryIntoRef<T>,
|
157
|
+
T: Clone,
|
158
|
+
{
|
159
|
+
let v = self.value(column)?;
|
160
|
+
v.try_into_ref().map(T::to_owned)
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
/// Iteratpr over rows of a table
|
165
|
+
pub struct RowIter<'a>
|
166
|
+
{
|
167
|
+
data: &'a Vec<value::Value>,
|
168
|
+
columns: usize,
|
169
|
+
index: usize,
|
170
|
+
row_count: usize,
|
171
|
+
}
|
172
|
+
|
173
|
+
impl<'a> Iterator for RowIter<'a>
|
174
|
+
{
|
175
|
+
type Item = RowView<'a>;
|
176
|
+
|
177
|
+
fn next(&mut self) -> Option<Self::Item>
|
178
|
+
{
|
179
|
+
if self.columns == 0
|
180
|
+
{
|
181
|
+
if self.index < self.row_count
|
182
|
+
{
|
183
|
+
self.index += 1;
|
184
|
+
Some(RowView {
|
185
|
+
row: &self.data[0..0],
|
186
|
+
})
|
187
|
+
}
|
188
|
+
else
|
189
|
+
{
|
190
|
+
None
|
191
|
+
}
|
192
|
+
}
|
193
|
+
else
|
194
|
+
{
|
195
|
+
let start = self.index * self.columns;
|
196
|
+
let end = start + self.columns;
|
197
|
+
|
198
|
+
if self.columns == 0 || end > self.data.len()
|
199
|
+
{
|
200
|
+
return None;
|
201
|
+
}
|
202
|
+
|
203
|
+
let rv = RowView {
|
204
|
+
row: &self.data[start..end],
|
205
|
+
};
|
206
|
+
|
207
|
+
self.index += 1;
|
208
|
+
|
209
|
+
Some(rv)
|
210
|
+
}
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
/// Convenient macro for creating tables.
|
215
|
+
///
|
216
|
+
/// Example:
|
217
|
+
///
|
218
|
+
/// ```rust
|
219
|
+
/// # use graphcore::{Table, table};
|
220
|
+
/// let table: Table = table!(("a", "b"), [["row0", "row0"], ["row1", "row2"]]);
|
221
|
+
/// ```
|
222
|
+
#[macro_export]
|
223
|
+
macro_rules! table {
|
224
|
+
() => (
|
225
|
+
$crate::Table::empty()
|
226
|
+
);
|
227
|
+
(($($header:expr),+ $(,)?), []) => (
|
228
|
+
$crate::Table::new(
|
229
|
+
vec![$($header.into()),+],
|
230
|
+
vec![]
|
231
|
+
).unwrap()
|
232
|
+
);
|
233
|
+
(($($header:expr),+ $(,)?), [$([$($x:expr),+ $(,)?]),*]) => (
|
234
|
+
{
|
235
|
+
let headers = vec![$($header.into()),+];
|
236
|
+
let mut data = Vec::new();
|
237
|
+
$(
|
238
|
+
data.extend(vec![$($x.into()),+]);
|
239
|
+
)*
|
240
|
+
$crate::Table::new(headers, data).unwrap()
|
241
|
+
}
|
242
|
+
);
|
243
|
+
}
|
244
|
+
|
245
|
+
#[cfg(test)]
|
246
|
+
mod tests
|
247
|
+
{
|
248
|
+
use crate::Table;
|
249
|
+
|
250
|
+
#[test]
|
251
|
+
fn test_table_macro()
|
252
|
+
{
|
253
|
+
let tb = table!();
|
254
|
+
assert_eq!(tb, Table::empty());
|
255
|
+
let tb = table!(("a", "b"), []);
|
256
|
+
assert_eq!(tb.rows(), 0);
|
257
|
+
assert_eq!(tb.columns(), 2);
|
258
|
+
assert_eq!(*tb.headers(), vec!["a".to_string(), "b".to_string()]);
|
259
|
+
let tb = table!(("a", "b"), [[1, 2], [3, 4]]);
|
260
|
+
assert_eq!(tb.rows(), 2);
|
261
|
+
assert_eq!(tb.columns(), 2);
|
262
|
+
assert_eq!(*tb.headers(), vec!["a".to_string(), "b".to_string()]);
|
263
|
+
assert_eq!(*tb.value(0, 0).unwrap(), 1.into());
|
264
|
+
assert_eq!(*tb.value(0, 1).unwrap(), 2.into());
|
265
|
+
assert_eq!(*tb.value(1, 0).unwrap(), 3.into());
|
266
|
+
assert_eq!(*tb.value(1, 1).unwrap(), 4.into());
|
267
|
+
assert_eq!(*tb.get::<i64>(0, 0).unwrap(), 1);
|
268
|
+
assert_eq!(*tb.get::<i64>(0, 1).unwrap(), 2);
|
269
|
+
assert_eq!(*tb.get::<i64>(1, 0).unwrap(), 3);
|
270
|
+
assert_eq!(*tb.get::<i64>(1, 1).unwrap(), 4);
|
271
|
+
}
|
272
|
+
}
|
@@ -28,11 +28,12 @@ impl ValueMap
|
|
28
28
|
.map(|(k, v)| (k, v.remove_null()))
|
29
29
|
.collect()
|
30
30
|
}
|
31
|
-
|
31
|
+
/// Remove a value in the given path.
|
32
|
+
pub fn remove_value<'a>(
|
32
33
|
&mut self,
|
33
34
|
field: Option<&'a String>,
|
34
35
|
mut path: impl Iterator<Item = &'a String>,
|
35
|
-
) ->
|
36
|
+
) -> Result<()>
|
36
37
|
{
|
37
38
|
if let Some(field) = field
|
38
39
|
{
|
@@ -47,9 +48,9 @@ impl ValueMap
|
|
47
48
|
}
|
48
49
|
None =>
|
49
50
|
{}
|
50
|
-
_ => Err(
|
51
|
-
|
52
|
-
)
|
51
|
+
_ => Err(Error::MissingKeyInPath {
|
52
|
+
key: field.to_owned(),
|
53
|
+
})?,
|
53
54
|
}
|
54
55
|
}
|
55
56
|
else
|
@@ -59,18 +60,17 @@ impl ValueMap
|
|
59
60
|
}
|
60
61
|
else
|
61
62
|
{
|
62
|
-
Err(
|
63
|
-
"remove_value should get a better error",
|
64
|
-
))? // TODO
|
63
|
+
Err(Error::MissingKey)?
|
65
64
|
}
|
66
65
|
Ok(())
|
67
66
|
}
|
68
|
-
|
67
|
+
/// Add a value at the given path.
|
68
|
+
pub fn add_values<'a>(
|
69
69
|
&mut self,
|
70
70
|
field: Option<&'a String>,
|
71
71
|
mut path: impl Iterator<Item = &'a String>,
|
72
72
|
value: ValueMap,
|
73
|
-
) ->
|
73
|
+
) -> Result<()>
|
74
74
|
{
|
75
75
|
if let Some(field) = field
|
76
76
|
{
|
@@ -90,38 +90,35 @@ impl ValueMap
|
|
90
90
|
o.set_value(Some(next_field), path, value.remove_null().into())?;
|
91
91
|
self.insert(field.to_owned(), o.into());
|
92
92
|
}
|
93
|
-
_ => Err(
|
94
|
-
|
95
|
-
)
|
93
|
+
_ => Err(Error::MissingKeyInPath {
|
94
|
+
key: field.to_owned(),
|
95
|
+
})?,
|
96
96
|
}
|
97
97
|
}
|
98
98
|
else
|
99
99
|
{
|
100
100
|
match v
|
101
101
|
{
|
102
|
-
Some(v) =>
|
102
|
+
Some(v) => match v
|
103
103
|
{
|
104
|
-
|
104
|
+
Value::Map(object) =>
|
105
105
|
{
|
106
|
-
|
106
|
+
for (k, v) in value.into_iter()
|
107
107
|
{
|
108
|
-
|
108
|
+
if v.is_null()
|
109
|
+
{
|
110
|
+
object.remove(&k);
|
111
|
+
}
|
112
|
+
else
|
109
113
|
{
|
110
|
-
|
111
|
-
{
|
112
|
-
object.remove(&k);
|
113
|
-
}
|
114
|
-
else
|
115
|
-
{
|
116
|
-
object.insert(k, v);
|
117
|
-
}
|
114
|
+
object.insert(k, v);
|
118
115
|
}
|
119
116
|
}
|
120
|
-
_ => Err(InternalError::Unimplemented(
|
121
|
-
"add_values should get a better error",
|
122
|
-
))?, // TODO
|
123
117
|
}
|
124
|
-
|
118
|
+
_ => Err(Error::MissingKeyInPath {
|
119
|
+
key: field.to_owned(),
|
120
|
+
})?,
|
121
|
+
},
|
125
122
|
None =>
|
126
123
|
{
|
127
124
|
self.insert(field.to_owned(), value.remove_null().into());
|
@@ -145,12 +142,13 @@ impl ValueMap
|
|
145
142
|
}
|
146
143
|
Ok(())
|
147
144
|
}
|
148
|
-
|
145
|
+
/// Set the value in the given path. Unlike add_value, it will complain if there is no existing value.
|
146
|
+
pub fn set_value<'a>(
|
149
147
|
&mut self,
|
150
148
|
field: Option<&'a String>,
|
151
149
|
mut path: impl Iterator<Item = &'a String>,
|
152
150
|
value: Value,
|
153
|
-
) ->
|
151
|
+
) -> Result<()>
|
154
152
|
{
|
155
153
|
if let Some(field) = field
|
156
154
|
{
|
@@ -173,29 +171,26 @@ impl ValueMap
|
|
173
171
|
self.insert(field.to_owned(), o.into());
|
174
172
|
}
|
175
173
|
}
|
176
|
-
_ => Err(
|
177
|
-
|
178
|
-
)
|
174
|
+
_ => Err(Error::MissingKeyInPath {
|
175
|
+
key: field.to_owned(),
|
176
|
+
})?,
|
179
177
|
}
|
180
178
|
}
|
179
|
+
else if value.is_null()
|
180
|
+
{
|
181
|
+
self.remove(field);
|
182
|
+
}
|
181
183
|
else
|
182
184
|
{
|
183
|
-
|
184
|
-
{
|
185
|
-
self.remove(field);
|
186
|
-
}
|
187
|
-
else
|
185
|
+
match v
|
188
186
|
{
|
189
|
-
|
187
|
+
Some(v) =>
|
190
188
|
{
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
{
|
197
|
-
self.insert(field.to_owned(), value);
|
198
|
-
}
|
189
|
+
*v = value;
|
190
|
+
}
|
191
|
+
None =>
|
192
|
+
{
|
193
|
+
self.insert(field.to_owned(), value);
|
199
194
|
}
|
200
195
|
}
|
201
196
|
}
|
@@ -211,7 +206,7 @@ impl ValueMap
|
|
211
206
|
*self = o;
|
212
207
|
Ok(())
|
213
208
|
}
|
214
|
-
_ => Err(
|
209
|
+
_ => Err(Error::MissingKey),
|
215
210
|
}
|
216
211
|
}
|
217
212
|
}
|