gqlite 1.2.3 → 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}/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 +10 -9
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/compiler/expression_analyser.rs +6 -4
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/compiler/variables_manager.rs +27 -31
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/compiler.rs +37 -41
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/connection.rs +42 -84
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/error.rs +105 -34
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/containers.rs +21 -26
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/edge.rs +2 -2
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/math.rs +2 -2
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/node.rs +1 -1
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/path.rs +15 -20
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/scalar.rs +2 -2
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/value.rs +6 -6
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions.rs +20 -20
- data/ext/gqlitedb/src/graph.rs +11 -0
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/interpreter/evaluators.rs +160 -194
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/interpreter/instructions.rs +2 -1
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/lib.rs +9 -4
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/parser/ast.rs +44 -52
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/parser/gql.pest +1 -1
- data/ext/{gqliterb/vendor/gqlitedb/src/parser/parser.rs → gqlitedb/src/parser/parser_impl.rs} +50 -28
- 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 +226 -148
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/store/sqlite.rs +111 -128
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/store.rs +22 -22
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/evaluators.rs +32 -76
- data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/store.rs +95 -111
- 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 +15 -5
- data/ext/gqliterb/Cargo.toml +12 -35
- data/ext/gqliterb/src/lib.rs +60 -38
- 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 +134 -38
- 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 -1116
- data/ext/gqliterb/vendor/gqlitedb/Cargo.lock +0 -2115
- data/ext/gqliterb/vendor/gqlitedb/Cargo.toml +0 -138
- data/ext/gqliterb/vendor/gqlitedb/src/parser.rs +0 -4
- data/ext/gqliterb/vendor/gqlitedb/src/value.rs +0 -609
- /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}/release.toml +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/functions/string.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/store/redb.rs +0 -0
- /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/store/sqlite.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
@@ -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
|
}
|
@@ -0,0 +1,413 @@
|
|
1
|
+
use itertools::Itertools as _;
|
2
|
+
use serde::{Deserialize, Serialize};
|
3
|
+
use std::{
|
4
|
+
hash::Hash,
|
5
|
+
ops::{Add, Div, Mul, Neg, Rem, Sub},
|
6
|
+
};
|
7
|
+
|
8
|
+
mod value_map;
|
9
|
+
|
10
|
+
pub(crate) use crate::prelude::*;
|
11
|
+
|
12
|
+
pub use value_map::ValueMap;
|
13
|
+
|
14
|
+
/// Represent a value in a properties for a Node or an Edge.
|
15
|
+
#[derive(Serialize, Deserialize, Debug, Default, PartialEq, Clone)]
|
16
|
+
#[serde(untagged)]
|
17
|
+
pub enum Value
|
18
|
+
{
|
19
|
+
/// Null value.
|
20
|
+
#[default]
|
21
|
+
Null,
|
22
|
+
/// A UUID Key in the graph.
|
23
|
+
Key(graph::Key),
|
24
|
+
/// Boolean value.
|
25
|
+
Boolean(bool),
|
26
|
+
/// Signed integer value.
|
27
|
+
Integer(i64),
|
28
|
+
#[serde(
|
29
|
+
serialize_with = "serialize_with::serialize_float",
|
30
|
+
deserialize_with = "serialize_with::deserialize_float"
|
31
|
+
)]
|
32
|
+
/// Floating point value.
|
33
|
+
Float(f64),
|
34
|
+
/// String value.
|
35
|
+
String(String),
|
36
|
+
/// Array of values.
|
37
|
+
Array(Vec<Value>),
|
38
|
+
/// Unordered map of values.
|
39
|
+
Map(ValueMap),
|
40
|
+
/// A node in the graph.
|
41
|
+
Node(graph::Node),
|
42
|
+
/// An edge in the graph.
|
43
|
+
Edge(graph::Edge),
|
44
|
+
/// A path in the graph.
|
45
|
+
Path(graph::SinglePath),
|
46
|
+
}
|
47
|
+
|
48
|
+
impl Value
|
49
|
+
{
|
50
|
+
/// Transform this value into a map. This function is guaranteed to succeed,
|
51
|
+
/// in case the value does not contains a map, it will create a default empty
|
52
|
+
/// map.
|
53
|
+
pub fn into_map(self) -> ValueMap
|
54
|
+
{
|
55
|
+
match self
|
56
|
+
{
|
57
|
+
Value::Map(o) => o.clone(),
|
58
|
+
_ => ValueMap::new(),
|
59
|
+
}
|
60
|
+
}
|
61
|
+
/// Return true if the value is null, false otherwise.
|
62
|
+
pub fn is_null(&self) -> bool
|
63
|
+
{
|
64
|
+
matches!(self, Value::Null)
|
65
|
+
}
|
66
|
+
/// Remove all elements of a map that are null. Walk through the map values recursively.
|
67
|
+
pub fn remove_null(self) -> Self
|
68
|
+
{
|
69
|
+
match self
|
70
|
+
{
|
71
|
+
Value::Map(object) => object.remove_null().into(),
|
72
|
+
o => o,
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
impl Hash for Value
|
77
|
+
{
|
78
|
+
fn hash<H: std::hash::Hasher>(&self, state: &mut H)
|
79
|
+
{
|
80
|
+
match self
|
81
|
+
{
|
82
|
+
Value::Null =>
|
83
|
+
{}
|
84
|
+
Value::Key(k) => k.hash(state),
|
85
|
+
Value::Boolean(b) => b.hash(state),
|
86
|
+
Value::Integer(i) => i.hash(state),
|
87
|
+
Value::Float(f) =>
|
88
|
+
{
|
89
|
+
let bits = if f.is_nan()
|
90
|
+
{
|
91
|
+
0x7ff8000000000000
|
92
|
+
}
|
93
|
+
else
|
94
|
+
{
|
95
|
+
f.to_bits()
|
96
|
+
};
|
97
|
+
bits.hash(state);
|
98
|
+
}
|
99
|
+
Value::String(s) => s.hash(state),
|
100
|
+
Value::Array(a) => a.hash(state),
|
101
|
+
Value::Map(m) => m.hash(state),
|
102
|
+
Value::Node(n) => n.hash(state),
|
103
|
+
Value::Edge(e) => e.hash(state),
|
104
|
+
Value::Path(p) => p.hash(state),
|
105
|
+
}
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
impl Add for Value
|
110
|
+
{
|
111
|
+
type Output = Result<Value>;
|
112
|
+
fn add(self, rhs: Self) -> Self::Output
|
113
|
+
{
|
114
|
+
match self
|
115
|
+
{
|
116
|
+
Value::Boolean(..)
|
117
|
+
| Value::Key(..)
|
118
|
+
| Value::Node(..)
|
119
|
+
| Value::Edge(..)
|
120
|
+
| Value::Map(..)
|
121
|
+
| Value::Path(..) => Err(Error::InvalidBinaryOperands),
|
122
|
+
Value::Null => Ok(Value::Null),
|
123
|
+
Self::Array(lhs) => match rhs
|
124
|
+
{
|
125
|
+
Self::Array(rhs) =>
|
126
|
+
{
|
127
|
+
let mut lhs = lhs.clone();
|
128
|
+
lhs.append(&mut rhs.clone());
|
129
|
+
Ok(lhs.into())
|
130
|
+
}
|
131
|
+
_ =>
|
132
|
+
{
|
133
|
+
let mut lhs = lhs.clone();
|
134
|
+
lhs.push(rhs.clone());
|
135
|
+
Ok(lhs.into())
|
136
|
+
}
|
137
|
+
},
|
138
|
+
Self::Float(lhs) => match rhs
|
139
|
+
{
|
140
|
+
Self::Float(rhs) => Ok((lhs + rhs).into()),
|
141
|
+
Self::Integer(rhs) => Ok((lhs + rhs as f64).into()),
|
142
|
+
Self::Null => Ok(Self::Null),
|
143
|
+
_ => Err(Error::InvalidBinaryOperands),
|
144
|
+
},
|
145
|
+
Self::Integer(lhs) => match rhs
|
146
|
+
{
|
147
|
+
Self::Float(rhs) => Ok((lhs as f64 + rhs).into()),
|
148
|
+
Self::Integer(rhs) => Ok((lhs + rhs).into()),
|
149
|
+
Self::Null => Ok(Self::Null),
|
150
|
+
_ => Err(Error::InvalidBinaryOperands),
|
151
|
+
},
|
152
|
+
Self::String(lhs) => match rhs
|
153
|
+
{
|
154
|
+
Self::String(rhs) => Ok((lhs + &rhs).into()),
|
155
|
+
Self::Null => Ok(Self::Null),
|
156
|
+
_ => Err(Error::InvalidBinaryOperands),
|
157
|
+
},
|
158
|
+
}
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
macro_rules! impl_mdsr {
|
163
|
+
($x:tt, $op:tt) => {
|
164
|
+
impl $x for Value
|
165
|
+
{
|
166
|
+
type Output = Result<Value>;
|
167
|
+
fn $op(self, rhs: Self) -> Self::Output
|
168
|
+
{
|
169
|
+
match self
|
170
|
+
{
|
171
|
+
Value::Boolean(..)
|
172
|
+
| Value::Key(..)
|
173
|
+
| Value::String(..)
|
174
|
+
| Value::Node(..)
|
175
|
+
| Value::Edge(..)
|
176
|
+
| Value::Array(..)
|
177
|
+
| Value::Map(..)
|
178
|
+
| Value::Path(..) => Err(Error::InvalidBinaryOperands.into()),
|
179
|
+
Value::Null => Ok(Value::Null),
|
180
|
+
Self::Float(lhs) => match rhs
|
181
|
+
{
|
182
|
+
Self::Float(rhs) => Ok(lhs.$op(rhs).into()),
|
183
|
+
Self::Integer(rhs) => Ok(lhs.$op(rhs as f64).into()),
|
184
|
+
Self::Null => Ok(Self::Null),
|
185
|
+
_ => Err(Error::InvalidBinaryOperands.into()),
|
186
|
+
},
|
187
|
+
Self::Integer(lhs) => match rhs
|
188
|
+
{
|
189
|
+
Self::Float(rhs) => Ok((lhs as f64).$op(rhs).into()),
|
190
|
+
Self::Integer(rhs) => Ok(lhs.$op(rhs).into()),
|
191
|
+
Self::Null => Ok(Self::Null),
|
192
|
+
_ => Err(Error::InvalidBinaryOperands.into()),
|
193
|
+
},
|
194
|
+
}
|
195
|
+
}
|
196
|
+
}
|
197
|
+
};
|
198
|
+
}
|
199
|
+
|
200
|
+
impl_mdsr!(Mul, mul);
|
201
|
+
impl_mdsr!(Sub, sub);
|
202
|
+
impl_mdsr!(Div, div);
|
203
|
+
impl_mdsr!(Rem, rem);
|
204
|
+
|
205
|
+
impl Value
|
206
|
+
{
|
207
|
+
/// Compute this value to the power of rhs. Return an error if called a non-number values.
|
208
|
+
pub fn pow(self, rhs: Value) -> Result<Value>
|
209
|
+
{
|
210
|
+
match self
|
211
|
+
{
|
212
|
+
Value::Boolean(..)
|
213
|
+
| Value::Key(..)
|
214
|
+
| Value::String(..)
|
215
|
+
| Value::Node(..)
|
216
|
+
| Value::Edge(..)
|
217
|
+
| Value::Array(..)
|
218
|
+
| Value::Map(..)
|
219
|
+
| Value::Path(..) => Err(Error::InvalidBinaryOperands),
|
220
|
+
Value::Null => Ok(Value::Null),
|
221
|
+
Self::Float(lhs) => match rhs
|
222
|
+
{
|
223
|
+
Self::Float(rhs) => Ok(lhs.powf(rhs).into()),
|
224
|
+
Self::Integer(rhs) => Ok(lhs.powf(rhs as f64).into()),
|
225
|
+
Self::Null => Ok(Self::Null),
|
226
|
+
_ => Err(Error::InvalidBinaryOperands),
|
227
|
+
},
|
228
|
+
Self::Integer(lhs) => match rhs
|
229
|
+
{
|
230
|
+
Self::Float(rhs) => Ok((lhs as f64).powf(rhs).into()),
|
231
|
+
Self::Integer(rhs) => match rhs.try_into()
|
232
|
+
{
|
233
|
+
Ok(rhs) => Ok(lhs.pow(rhs).into()),
|
234
|
+
Err(_) => Ok((lhs as f64).powf(rhs as f64).into()),
|
235
|
+
},
|
236
|
+
Self::Null => Ok(Self::Null),
|
237
|
+
_ => Err(Error::InvalidBinaryOperands),
|
238
|
+
},
|
239
|
+
}
|
240
|
+
}
|
241
|
+
}
|
242
|
+
|
243
|
+
impl Neg for Value
|
244
|
+
{
|
245
|
+
type Output = Result<Value>;
|
246
|
+
fn neg(self) -> Self::Output
|
247
|
+
{
|
248
|
+
match self
|
249
|
+
{
|
250
|
+
Self::Float(fl) => Ok((-fl).into()),
|
251
|
+
Self::Integer(i) => Ok((-i).into()),
|
252
|
+
Value::Null => Ok(Value::Null),
|
253
|
+
Value::Boolean(..)
|
254
|
+
| Value::Key(..)
|
255
|
+
| Value::String(..)
|
256
|
+
| Value::Node(..)
|
257
|
+
| Value::Edge(..)
|
258
|
+
| Value::Array(..)
|
259
|
+
| Value::Map(..)
|
260
|
+
| Value::Path(..) => Err(Error::InvalidNegationOperands),
|
261
|
+
}
|
262
|
+
}
|
263
|
+
}
|
264
|
+
|
265
|
+
impl std::fmt::Display for Value
|
266
|
+
{
|
267
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
268
|
+
{
|
269
|
+
match self
|
270
|
+
{
|
271
|
+
Value::Null => write!(f, "null"),
|
272
|
+
Value::Key(k) => write!(f, "<{}>", k.uuid()),
|
273
|
+
Value::Boolean(b) => write!(f, "{}", b),
|
274
|
+
Value::Integer(i) => write!(f, "{}", i),
|
275
|
+
Value::Float(fl) => write!(f, "{}", fl),
|
276
|
+
Value::String(s) => write!(f, "{}", s),
|
277
|
+
Value::Array(v) => write!(f, "[{}]", v.iter().map(|x| x.to_string()).join(", ")),
|
278
|
+
Value::Map(o) => write!(f, "{}", o),
|
279
|
+
Value::Node(n) => write!(f, "{}", n),
|
280
|
+
Value::Edge(e) => write!(f, "{}", e),
|
281
|
+
Value::Path(p) => write!(f, "{}", p),
|
282
|
+
}
|
283
|
+
}
|
284
|
+
}
|
285
|
+
|
286
|
+
/// Trait to return a reference to the underlying type
|
287
|
+
pub trait ValueTryIntoRef<T>
|
288
|
+
{
|
289
|
+
/// Return a reference to T
|
290
|
+
fn try_into_ref(&self) -> Result<&T, Error>;
|
291
|
+
}
|
292
|
+
|
293
|
+
impl ValueTryIntoRef<Value> for Value
|
294
|
+
{
|
295
|
+
fn try_into_ref(&self) -> Result<&Value, Error>
|
296
|
+
{
|
297
|
+
Ok(self)
|
298
|
+
}
|
299
|
+
}
|
300
|
+
|
301
|
+
macro_rules! impl_to_value {
|
302
|
+
($type:ty, $vn:tt) => {
|
303
|
+
impl From<$type> for Value
|
304
|
+
{
|
305
|
+
fn from(v: $type) -> Value
|
306
|
+
{
|
307
|
+
Value::$vn(v)
|
308
|
+
}
|
309
|
+
}
|
310
|
+
|
311
|
+
impl From<Vec<$type>> for Value
|
312
|
+
{
|
313
|
+
fn from(v: Vec<$type>) -> Value
|
314
|
+
{
|
315
|
+
Value::Array(v.into_iter().map(|v| v.into()).collect())
|
316
|
+
}
|
317
|
+
}
|
318
|
+
impl TryInto<$type> for Value
|
319
|
+
{
|
320
|
+
type Error = Error;
|
321
|
+
fn try_into(self) -> Result<$type, Self::Error>
|
322
|
+
{
|
323
|
+
match self
|
324
|
+
{
|
325
|
+
Value::$vn(v) => Ok(v),
|
326
|
+
_ => Err(
|
327
|
+
Error::InvalidValueCast {
|
328
|
+
value: Box::new(self),
|
329
|
+
typename: stringify!($type),
|
330
|
+
}
|
331
|
+
.into(),
|
332
|
+
),
|
333
|
+
}
|
334
|
+
}
|
335
|
+
}
|
336
|
+
|
337
|
+
impl ValueTryIntoRef<$type> for Value
|
338
|
+
{
|
339
|
+
fn try_into_ref(&self) -> Result<&$type, Error>
|
340
|
+
{
|
341
|
+
match self
|
342
|
+
{
|
343
|
+
Value::$vn(v) => Ok(v),
|
344
|
+
_ => Err(
|
345
|
+
Error::InvalidValueCast {
|
346
|
+
value: Box::new(self.clone()),
|
347
|
+
typename: stringify!($type),
|
348
|
+
}
|
349
|
+
.into(),
|
350
|
+
),
|
351
|
+
}
|
352
|
+
}
|
353
|
+
}
|
354
|
+
};
|
355
|
+
}
|
356
|
+
|
357
|
+
impl_to_value!(graph::Key, Key);
|
358
|
+
impl_to_value!(bool, Boolean);
|
359
|
+
impl_to_value!(i64, Integer);
|
360
|
+
impl_to_value!(f64, Float);
|
361
|
+
impl_to_value!(String, String);
|
362
|
+
impl_to_value!(graph::Node, Node);
|
363
|
+
impl_to_value!(graph::Edge, Edge);
|
364
|
+
impl_to_value!(graph::SinglePath, Path);
|
365
|
+
impl_to_value!(Vec<Value>, Array);
|
366
|
+
impl_to_value!(ValueMap, Map);
|
367
|
+
|
368
|
+
impl From<&str> for Value
|
369
|
+
{
|
370
|
+
fn from(val: &str) -> Self
|
371
|
+
{
|
372
|
+
Value::String(val.into())
|
373
|
+
}
|
374
|
+
}
|
375
|
+
|
376
|
+
/// Convenient macro for creating Array.
|
377
|
+
///
|
378
|
+
/// Example:
|
379
|
+
///
|
380
|
+
/// ```rust
|
381
|
+
/// # use graphcore::{Value, array};
|
382
|
+
/// let value_arr: Value = array!("hello", 12);
|
383
|
+
/// ```
|
384
|
+
#[macro_export]
|
385
|
+
macro_rules! array {
|
386
|
+
() => (
|
387
|
+
$crate::Value::Array(Default::default())
|
388
|
+
);
|
389
|
+
($($x:expr),+ $(,)?) => (
|
390
|
+
$crate::Value::Array(
|
391
|
+
vec![$($x.into()),+]
|
392
|
+
)
|
393
|
+
);
|
394
|
+
}
|
395
|
+
|
396
|
+
/// Convenient macro for creating ValueMap.
|
397
|
+
///
|
398
|
+
/// Example:
|
399
|
+
///
|
400
|
+
/// ```rust
|
401
|
+
/// # use graphcore::{ValueMap, value_map};
|
402
|
+
/// let value_map: ValueMap = value_map!("hello" => 12);
|
403
|
+
/// ```
|
404
|
+
#[macro_export]
|
405
|
+
macro_rules! value_map {
|
406
|
+
// map-like
|
407
|
+
($($k:expr => $v:expr),* $(,)?) => {
|
408
|
+
{
|
409
|
+
let value_map: $crate::ValueMap = core::convert::From::from([$(($k.to_string(), $v.into()),)*]);
|
410
|
+
value_map
|
411
|
+
}
|
412
|
+
};
|
413
|
+
}
|