gqlite 1.2.0 → 1.2.3
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/gqliterb/.cargo/config.toml +2 -0
- data/ext/gqliterb/Cargo.lock +152 -135
- data/ext/gqliterb/Cargo.toml +4 -6
- data/ext/gqliterb/src/lib.rs +8 -2
- data/ext/gqliterb/vendor/gqlitedb/Cargo.lock +2115 -0
- data/ext/gqliterb/vendor/gqlitedb/Cargo.toml +138 -0
- data/ext/gqliterb/vendor/gqlitedb/askama.toml +3 -0
- data/ext/gqliterb/vendor/gqlitedb/benches/common/mod.rs +25 -0
- data/ext/gqliterb/vendor/gqlitedb/benches/common/pokec.rs +185 -0
- data/ext/gqliterb/vendor/gqlitedb/benches/pokec_divan.rs +137 -0
- data/ext/gqliterb/vendor/gqlitedb/benches/pokec_iai.rs +122 -0
- data/ext/gqliterb/vendor/gqlitedb/release.toml +7 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators/arithmetic.rs +96 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators/containers.rs +33 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators/count.rs +35 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators/stats.rs +168 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators.rs +74 -0
- data/ext/gqliterb/vendor/gqlitedb/src/capi.rs +259 -0
- data/ext/gqliterb/vendor/gqlitedb/src/compiler/expression_analyser.rs +431 -0
- data/ext/gqliterb/vendor/gqlitedb/src/compiler/variables_manager.rs +621 -0
- data/ext/gqliterb/vendor/gqlitedb/src/compiler.rs +1115 -0
- data/ext/gqliterb/vendor/gqlitedb/src/connection.rs +342 -0
- data/ext/gqliterb/vendor/gqlitedb/src/consts.rs +10 -0
- data/ext/gqliterb/vendor/gqlitedb/src/error.rs +613 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/containers.rs +115 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/edge.rs +20 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/math.rs +44 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/node.rs +16 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/path.rs +80 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/scalar.rs +86 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/string.rs +28 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/value.rs +99 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions.rs +410 -0
- data/ext/gqliterb/vendor/gqlitedb/src/graph.rs +283 -0
- data/ext/gqliterb/vendor/gqlitedb/src/interpreter/evaluators.rs +1776 -0
- data/ext/gqliterb/vendor/gqlitedb/src/interpreter/instructions.rs +267 -0
- data/ext/gqliterb/vendor/gqlitedb/src/interpreter/mod.rs +4 -0
- data/ext/gqliterb/vendor/gqlitedb/src/lib.rs +41 -0
- data/ext/gqliterb/vendor/gqlitedb/src/parser/ast.rs +611 -0
- data/ext/gqliterb/vendor/gqlitedb/src/parser/gql.pest +196 -0
- data/ext/gqliterb/vendor/gqlitedb/src/parser/parser.rs +1183 -0
- data/ext/gqliterb/vendor/gqlitedb/src/parser.rs +4 -0
- data/ext/gqliterb/vendor/gqlitedb/src/prelude.rs +8 -0
- data/ext/gqliterb/vendor/gqlitedb/src/serialize_with.rs +94 -0
- data/ext/gqliterb/vendor/gqlitedb/src/store/pgql.rs +121 -0
- data/ext/gqliterb/vendor/gqlitedb/src/store/redb.rs +1262 -0
- data/ext/gqliterb/vendor/gqlitedb/src/store/sqlite.rs +1026 -0
- data/ext/gqliterb/vendor/gqlitedb/src/store.rs +439 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/compiler.rs +92 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/evaluators.rs +227 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/parser.rs +81 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/store/redb.rs +46 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/store/sqlite.rs +46 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/store.rs +470 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/templates/ast.rs +356 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/templates/programs.rs +455 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/templates.rs +2 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests.rs +39 -0
- data/ext/gqliterb/vendor/gqlitedb/src/utils.rs +28 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value/compare.rs +212 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value/contains.rs +47 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value/value_map.rs +298 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value.rs +609 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value_table.rs +610 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/call_stats.sql +22 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_count_for_node.sql +3 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_create.sql +6 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_delete.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_delete_by_nodes.sql +2 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_select.sql +139 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_update.sql +4 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/graph_create.sql +16 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/graph_delete.sql +3 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_create_table.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_get.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_set.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_create.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_delete.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_select.sql +42 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_update.sql +4 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/table_exists.sql +5 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/upgrade_from_1_01.sql +2 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/upgrade_graph_from_1_01.sql +65 -0
- metadata +82 -2
@@ -0,0 +1,212 @@
|
|
1
|
+
use std::cmp;
|
2
|
+
|
3
|
+
use itertools::Itertools;
|
4
|
+
|
5
|
+
use crate::prelude::*;
|
6
|
+
|
7
|
+
pub(crate) enum Ordering
|
8
|
+
{
|
9
|
+
Equal,
|
10
|
+
Different,
|
11
|
+
Less,
|
12
|
+
Greater,
|
13
|
+
ComparedNull,
|
14
|
+
Null,
|
15
|
+
}
|
16
|
+
|
17
|
+
impl From<cmp::Ordering> for Ordering
|
18
|
+
{
|
19
|
+
fn from(value: cmp::Ordering) -> Self
|
20
|
+
{
|
21
|
+
match value
|
22
|
+
{
|
23
|
+
cmp::Ordering::Equal => Ordering::Equal,
|
24
|
+
cmp::Ordering::Greater => Ordering::Greater,
|
25
|
+
cmp::Ordering::Less => Ordering::Less,
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
fn compare_map(lhs: &value::ValueMap, rhs: &value::ValueMap) -> Ordering
|
31
|
+
{
|
32
|
+
if lhs.len() == rhs.len()
|
33
|
+
{
|
34
|
+
lhs
|
35
|
+
.iter()
|
36
|
+
.sorted_by(|(lk, _), (rk, _)| lk.cmp(rk))
|
37
|
+
.zip(rhs.iter().sorted_by(|(lk, _), (rk, _)| lk.cmp(rk)))
|
38
|
+
.map(|((lhs_k, lhs_v), (rhs_k, rhs_v))| {
|
39
|
+
let cmp = lhs_k.cmp(rhs_k);
|
40
|
+
match cmp
|
41
|
+
{
|
42
|
+
std::cmp::Ordering::Equal => compare(lhs_v, rhs_v),
|
43
|
+
o => o.into(),
|
44
|
+
}
|
45
|
+
})
|
46
|
+
.find(|p| match p
|
47
|
+
{
|
48
|
+
Ordering::Equal => false,
|
49
|
+
_ => true,
|
50
|
+
})
|
51
|
+
.unwrap_or(Ordering::Equal)
|
52
|
+
}
|
53
|
+
else if lhs.len() < rhs.len()
|
54
|
+
{
|
55
|
+
Ordering::Less
|
56
|
+
}
|
57
|
+
else
|
58
|
+
{
|
59
|
+
Ordering::Greater
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
fn compare_f64(lhs: &f64, rhs: &f64) -> Ordering
|
64
|
+
{
|
65
|
+
if lhs.is_nan() || rhs.is_nan()
|
66
|
+
{
|
67
|
+
Ordering::Different
|
68
|
+
}
|
69
|
+
else
|
70
|
+
{
|
71
|
+
lhs.total_cmp(rhs).into()
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
fn compare_node(lhs: &graph::Node, rhs: &graph::Node) -> Ordering
|
76
|
+
{
|
77
|
+
lhs.key.uuid.cmp(&rhs.key.uuid).into()
|
78
|
+
}
|
79
|
+
|
80
|
+
pub(crate) fn compare(lhs: &value::Value, rhs: &value::Value) -> Ordering
|
81
|
+
{
|
82
|
+
use value::Value;
|
83
|
+
match lhs
|
84
|
+
{
|
85
|
+
Value::Null => Ordering::ComparedNull,
|
86
|
+
Value::Boolean(bl) => match rhs
|
87
|
+
{
|
88
|
+
Value::Boolean(br) => bl.cmp(br).into(),
|
89
|
+
Value::Null => Ordering::ComparedNull,
|
90
|
+
_ => Ordering::Null,
|
91
|
+
},
|
92
|
+
Value::Integer(il) => match rhs
|
93
|
+
{
|
94
|
+
Value::Integer(ir) => il.cmp(ir).into(),
|
95
|
+
Value::Float(fr) => compare_f64(&(*il as f64), fr),
|
96
|
+
Value::Null => Ordering::ComparedNull,
|
97
|
+
_ => Ordering::Null,
|
98
|
+
},
|
99
|
+
Value::Float(fl) => match rhs
|
100
|
+
{
|
101
|
+
Value::Integer(ir) => compare_f64(fl, &(*ir as f64)),
|
102
|
+
Value::Float(fr) => compare_f64(fl, fr),
|
103
|
+
Value::Null => Ordering::ComparedNull,
|
104
|
+
_ => Ordering::Null,
|
105
|
+
},
|
106
|
+
Value::String(sl) => match rhs
|
107
|
+
{
|
108
|
+
Value::String(sr) => sl.cmp(sr).into(),
|
109
|
+
Value::Null => Ordering::ComparedNull,
|
110
|
+
_ => Ordering::Null,
|
111
|
+
},
|
112
|
+
Value::Array(al) => match rhs
|
113
|
+
{
|
114
|
+
Value::Array(ar) =>
|
115
|
+
{
|
116
|
+
if al.len() < ar.len()
|
117
|
+
{
|
118
|
+
Ordering::Less
|
119
|
+
}
|
120
|
+
else if al.len() > ar.len()
|
121
|
+
{
|
122
|
+
Ordering::Greater
|
123
|
+
}
|
124
|
+
else
|
125
|
+
{
|
126
|
+
let mut comp_to_null = false;
|
127
|
+
let mut compare_equal = true;
|
128
|
+
let comp = al
|
129
|
+
.iter()
|
130
|
+
.zip(ar.iter())
|
131
|
+
.find_map(|(l, r)| match compare(l, r)
|
132
|
+
{
|
133
|
+
Ordering::Equal => None,
|
134
|
+
Ordering::Null | Ordering::Different =>
|
135
|
+
{
|
136
|
+
compare_equal = false;
|
137
|
+
None
|
138
|
+
}
|
139
|
+
Ordering::Greater => Some(Ordering::Greater),
|
140
|
+
Ordering::Less => Some(Ordering::Less),
|
141
|
+
Ordering::ComparedNull =>
|
142
|
+
{
|
143
|
+
comp_to_null = true;
|
144
|
+
None
|
145
|
+
}
|
146
|
+
});
|
147
|
+
|
148
|
+
// Due to opencypher madness, if you compare [nil, 2] with [1, 2] this should return null because of the nil/1 comparison,
|
149
|
+
// however [nil, 2] with [1, "2"] should return false because 2 != "2" 🤦
|
150
|
+
match (comp, comp_to_null, compare_equal)
|
151
|
+
{
|
152
|
+
// Some imply either greater or lesser, in which case, return the value unless a comparison to null was made
|
153
|
+
(Some(o), false, _) => o,
|
154
|
+
(Some(_), true, _) => Ordering::ComparedNull,
|
155
|
+
// If equal, check if a comparison to null was made
|
156
|
+
(None, true, true) => Ordering::ComparedNull,
|
157
|
+
(None, false, true) => Ordering::Equal,
|
158
|
+
// If false, ignore comparison to null
|
159
|
+
(None, _, false) => Ordering::Null,
|
160
|
+
}
|
161
|
+
}
|
162
|
+
}
|
163
|
+
Value::Null => Ordering::ComparedNull,
|
164
|
+
_ => Ordering::Null,
|
165
|
+
},
|
166
|
+
Value::Map(lhs) => match rhs
|
167
|
+
{
|
168
|
+
Value::Map(rhs) => compare_map(lhs, rhs),
|
169
|
+
_ => Ordering::Null,
|
170
|
+
},
|
171
|
+
Value::Node(lhs) => match rhs
|
172
|
+
{
|
173
|
+
Value::Node(rhs) => compare_node(lhs, rhs),
|
174
|
+
_ => Ordering::Null,
|
175
|
+
},
|
176
|
+
Value::Edge(lhs) => match rhs
|
177
|
+
{
|
178
|
+
Value::Edge(rhs) =>
|
179
|
+
{
|
180
|
+
lhs.key.uuid.cmp(&rhs.key.uuid).into()
|
181
|
+
// let labels_cmp = lhs.labels.cmp(&rhs.labels);
|
182
|
+
// match labels_cmp
|
183
|
+
// {
|
184
|
+
// std::cmp::Ordering::Equal => compare_map(&lhs.properties, &rhs.properties),
|
185
|
+
// o => o.into(),
|
186
|
+
// }
|
187
|
+
}
|
188
|
+
_ => Ordering::Null,
|
189
|
+
},
|
190
|
+
Value::Path(lhs) => match rhs
|
191
|
+
{
|
192
|
+
Value::Path(rhs) =>
|
193
|
+
{
|
194
|
+
let labels_cmp = lhs.labels.cmp(&rhs.labels);
|
195
|
+
match labels_cmp
|
196
|
+
{
|
197
|
+
std::cmp::Ordering::Equal => match compare_map(&lhs.properties, &rhs.properties)
|
198
|
+
{
|
199
|
+
Ordering::Equal => match compare_node(&lhs.source, &rhs.source)
|
200
|
+
{
|
201
|
+
Ordering::Equal => compare_node(&lhs.destination, &rhs.destination),
|
202
|
+
o => o,
|
203
|
+
},
|
204
|
+
o => o,
|
205
|
+
},
|
206
|
+
o => o.into(),
|
207
|
+
}
|
208
|
+
}
|
209
|
+
_ => Ordering::Null,
|
210
|
+
},
|
211
|
+
}
|
212
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
use crate::prelude::*;
|
2
|
+
|
3
|
+
pub(crate) enum ContainResult
|
4
|
+
{
|
5
|
+
True,
|
6
|
+
False,
|
7
|
+
ComparedNull,
|
8
|
+
}
|
9
|
+
|
10
|
+
/// Compute contains, according to OpenCypher specification, specifically handling the comparison with null.
|
11
|
+
pub(crate) fn contains(container: &Vec<value::Value>, value: &value::Value) -> ContainResult
|
12
|
+
{
|
13
|
+
if value.is_null()
|
14
|
+
{
|
15
|
+
if container.is_empty()
|
16
|
+
{
|
17
|
+
ContainResult::False
|
18
|
+
}
|
19
|
+
else
|
20
|
+
{
|
21
|
+
ContainResult::ComparedNull
|
22
|
+
}
|
23
|
+
}
|
24
|
+
else
|
25
|
+
{
|
26
|
+
let mut has_compared_to_null = false;
|
27
|
+
for v_c in container.iter()
|
28
|
+
{
|
29
|
+
use value::ContainResult;
|
30
|
+
match value::compare(v_c, &value)
|
31
|
+
{
|
32
|
+
value::Ordering::Equal => return ContainResult::True,
|
33
|
+
value::Ordering::ComparedNull => has_compared_to_null = true,
|
34
|
+
_ =>
|
35
|
+
{}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
if has_compared_to_null
|
39
|
+
{
|
40
|
+
ContainResult::ComparedNull
|
41
|
+
}
|
42
|
+
else
|
43
|
+
{
|
44
|
+
ContainResult::False
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
@@ -0,0 +1,298 @@
|
|
1
|
+
use itertools::Itertools;
|
2
|
+
use serde::{Deserialize, Serialize};
|
3
|
+
use std::{
|
4
|
+
hash::Hash,
|
5
|
+
ops::{Deref, DerefMut},
|
6
|
+
};
|
7
|
+
|
8
|
+
use crate::{prelude::*, Value};
|
9
|
+
|
10
|
+
type ValueMapInner = std::collections::HashMap<String, Value>;
|
11
|
+
|
12
|
+
/// A map of values.
|
13
|
+
#[derive(Debug, PartialEq, Default, Clone, Deserialize, Serialize)]
|
14
|
+
pub struct ValueMap(ValueMapInner);
|
15
|
+
|
16
|
+
impl ValueMap
|
17
|
+
{
|
18
|
+
/// Create a default value map.
|
19
|
+
pub fn new() -> Self
|
20
|
+
{
|
21
|
+
Self::default()
|
22
|
+
}
|
23
|
+
pub(crate) fn remove_null(self) -> Self
|
24
|
+
{
|
25
|
+
self
|
26
|
+
.into_iter()
|
27
|
+
.filter(|(_, v)| !v.is_null())
|
28
|
+
.map(|(k, v)| (k, v.remove_null()))
|
29
|
+
.collect()
|
30
|
+
}
|
31
|
+
pub(crate) fn remove_value<'a>(
|
32
|
+
&mut self,
|
33
|
+
field: Option<&'a String>,
|
34
|
+
mut path: impl Iterator<Item = &'a String>,
|
35
|
+
) -> crate::Result<()>
|
36
|
+
{
|
37
|
+
if let Some(field) = field
|
38
|
+
{
|
39
|
+
if let Some(next_field) = path.next()
|
40
|
+
{
|
41
|
+
let v = self.get_mut(field);
|
42
|
+
match v
|
43
|
+
{
|
44
|
+
Some(Value::Map(o)) =>
|
45
|
+
{
|
46
|
+
o.remove_value(Some(next_field), path)?;
|
47
|
+
}
|
48
|
+
None =>
|
49
|
+
{}
|
50
|
+
_ => Err(InternalError::Unimplemented(
|
51
|
+
"remove_value should get a better error",
|
52
|
+
))?, // TODO
|
53
|
+
}
|
54
|
+
}
|
55
|
+
else
|
56
|
+
{
|
57
|
+
self.remove(field);
|
58
|
+
}
|
59
|
+
}
|
60
|
+
else
|
61
|
+
{
|
62
|
+
Err(InternalError::Unimplemented(
|
63
|
+
"remove_value should get a better error",
|
64
|
+
))? // TODO
|
65
|
+
}
|
66
|
+
Ok(())
|
67
|
+
}
|
68
|
+
pub(crate) fn add_values<'a>(
|
69
|
+
&mut self,
|
70
|
+
field: Option<&'a String>,
|
71
|
+
mut path: impl Iterator<Item = &'a String>,
|
72
|
+
value: ValueMap,
|
73
|
+
) -> crate::Result<()>
|
74
|
+
{
|
75
|
+
if let Some(field) = field
|
76
|
+
{
|
77
|
+
let v = self.get_mut(field);
|
78
|
+
|
79
|
+
if let Some(next_field) = path.next()
|
80
|
+
{
|
81
|
+
match v
|
82
|
+
{
|
83
|
+
Some(Value::Map(o)) =>
|
84
|
+
{
|
85
|
+
o.add_values(Some(next_field), path, value)?;
|
86
|
+
}
|
87
|
+
None =>
|
88
|
+
{
|
89
|
+
let mut o = ValueMap::new();
|
90
|
+
o.set_value(Some(next_field), path, value.remove_null().into())?;
|
91
|
+
self.insert(field.to_owned(), o.into());
|
92
|
+
}
|
93
|
+
_ => Err(InternalError::Unimplemented(
|
94
|
+
"add_values should get a better error",
|
95
|
+
))?, // TODO
|
96
|
+
}
|
97
|
+
}
|
98
|
+
else
|
99
|
+
{
|
100
|
+
match v
|
101
|
+
{
|
102
|
+
Some(v) =>
|
103
|
+
{
|
104
|
+
match v
|
105
|
+
{
|
106
|
+
Value::Map(object) =>
|
107
|
+
{
|
108
|
+
for (k, v) in value.into_iter()
|
109
|
+
{
|
110
|
+
if v.is_null()
|
111
|
+
{
|
112
|
+
object.remove(&k);
|
113
|
+
}
|
114
|
+
else
|
115
|
+
{
|
116
|
+
object.insert(k, v);
|
117
|
+
}
|
118
|
+
}
|
119
|
+
}
|
120
|
+
_ => Err(InternalError::Unimplemented(
|
121
|
+
"add_values should get a better error",
|
122
|
+
))?, // TODO
|
123
|
+
}
|
124
|
+
}
|
125
|
+
None =>
|
126
|
+
{
|
127
|
+
self.insert(field.to_owned(), value.remove_null().into());
|
128
|
+
}
|
129
|
+
}
|
130
|
+
}
|
131
|
+
}
|
132
|
+
else
|
133
|
+
{
|
134
|
+
for (k, v) in value.into_iter()
|
135
|
+
{
|
136
|
+
if v.is_null()
|
137
|
+
{
|
138
|
+
self.remove(&k);
|
139
|
+
}
|
140
|
+
else
|
141
|
+
{
|
142
|
+
self.insert(k, v);
|
143
|
+
}
|
144
|
+
}
|
145
|
+
}
|
146
|
+
Ok(())
|
147
|
+
}
|
148
|
+
pub(crate) fn set_value<'a>(
|
149
|
+
&mut self,
|
150
|
+
field: Option<&'a String>,
|
151
|
+
mut path: impl Iterator<Item = &'a String>,
|
152
|
+
value: Value,
|
153
|
+
) -> crate::Result<()>
|
154
|
+
{
|
155
|
+
if let Some(field) = field
|
156
|
+
{
|
157
|
+
let v = self.get_mut(field);
|
158
|
+
|
159
|
+
if let Some(next_field) = path.next()
|
160
|
+
{
|
161
|
+
match v
|
162
|
+
{
|
163
|
+
Some(Value::Map(o)) =>
|
164
|
+
{
|
165
|
+
o.set_value(Some(next_field), path, value)?;
|
166
|
+
}
|
167
|
+
None =>
|
168
|
+
{
|
169
|
+
if !value.is_null()
|
170
|
+
{
|
171
|
+
let mut o = ValueMap::new();
|
172
|
+
o.set_value(Some(next_field), path, value)?;
|
173
|
+
self.insert(field.to_owned(), o.into());
|
174
|
+
}
|
175
|
+
}
|
176
|
+
_ => Err(InternalError::Unimplemented(
|
177
|
+
"update_value should get a better error",
|
178
|
+
))?, // TODO
|
179
|
+
}
|
180
|
+
}
|
181
|
+
else
|
182
|
+
{
|
183
|
+
if value.is_null()
|
184
|
+
{
|
185
|
+
self.remove(field);
|
186
|
+
}
|
187
|
+
else
|
188
|
+
{
|
189
|
+
match v
|
190
|
+
{
|
191
|
+
Some(v) =>
|
192
|
+
{
|
193
|
+
*v = value;
|
194
|
+
}
|
195
|
+
None =>
|
196
|
+
{
|
197
|
+
self.insert(field.to_owned(), value);
|
198
|
+
}
|
199
|
+
}
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
Ok(())
|
204
|
+
}
|
205
|
+
else
|
206
|
+
{
|
207
|
+
match value
|
208
|
+
{
|
209
|
+
Value::Map(o) =>
|
210
|
+
{
|
211
|
+
*self = o;
|
212
|
+
Ok(())
|
213
|
+
}
|
214
|
+
_ => Err(InternalError::Unimplemented("set_value should get a better error").into()), // TODO
|
215
|
+
}
|
216
|
+
}
|
217
|
+
}
|
218
|
+
}
|
219
|
+
|
220
|
+
impl Hash for ValueMap
|
221
|
+
{
|
222
|
+
fn hash<H: std::hash::Hasher>(&self, state: &mut H)
|
223
|
+
{
|
224
|
+
for (k, v) in self.0.iter().sorted_by(|(lk, _), (rk, _)| lk.cmp(rk))
|
225
|
+
{
|
226
|
+
k.hash(state);
|
227
|
+
v.hash(state);
|
228
|
+
}
|
229
|
+
}
|
230
|
+
}
|
231
|
+
|
232
|
+
impl Deref for ValueMap
|
233
|
+
{
|
234
|
+
type Target = ValueMapInner;
|
235
|
+
fn deref(&self) -> &Self::Target
|
236
|
+
{
|
237
|
+
&self.0
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
impl DerefMut for ValueMap
|
242
|
+
{
|
243
|
+
fn deref_mut(&mut self) -> &mut Self::Target
|
244
|
+
{
|
245
|
+
&mut self.0
|
246
|
+
}
|
247
|
+
}
|
248
|
+
|
249
|
+
impl FromIterator<(String, Value)> for ValueMap
|
250
|
+
{
|
251
|
+
/// Constructs a `HashMap<K, V>` from an iterator of key-value pairs.
|
252
|
+
///
|
253
|
+
/// If the iterator produces any pairs with equal keys,
|
254
|
+
/// all but one of the corresponding values will be dropped.
|
255
|
+
fn from_iter<T: IntoIterator<Item = (String, Value)>>(iter: T) -> ValueMap
|
256
|
+
{
|
257
|
+
let mut map = ValueMapInner::with_hasher(Default::default());
|
258
|
+
map.extend(iter);
|
259
|
+
ValueMap(map)
|
260
|
+
}
|
261
|
+
}
|
262
|
+
|
263
|
+
impl IntoIterator for ValueMap
|
264
|
+
{
|
265
|
+
type Item = (String, Value);
|
266
|
+
type IntoIter = <ValueMapInner as IntoIterator>::IntoIter;
|
267
|
+
fn into_iter(self) -> Self::IntoIter
|
268
|
+
{
|
269
|
+
self.0.into_iter()
|
270
|
+
}
|
271
|
+
}
|
272
|
+
|
273
|
+
impl<const N: usize> From<[(String, Value); N]> for ValueMap
|
274
|
+
{
|
275
|
+
fn from(arr: [(String, Value); N]) -> Self
|
276
|
+
{
|
277
|
+
Self(ValueMapInner::from_iter(arr))
|
278
|
+
}
|
279
|
+
}
|
280
|
+
|
281
|
+
impl std::fmt::Display for ValueMap
|
282
|
+
{
|
283
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
284
|
+
{
|
285
|
+
write!(f, "{{")?;
|
286
|
+
self.iter().enumerate().for_each(|(n, (k, v))| {
|
287
|
+
if n == 0
|
288
|
+
{
|
289
|
+
write!(f, "{}: {}", k, v).unwrap();
|
290
|
+
}
|
291
|
+
else
|
292
|
+
{
|
293
|
+
write!(f, ", {}: {}", k, v).unwrap();
|
294
|
+
}
|
295
|
+
});
|
296
|
+
write!(f, "}}")
|
297
|
+
}
|
298
|
+
}
|