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
@@ -3,19 +3,27 @@ use std::borrow::Borrow;
|
|
3
3
|
|
4
4
|
use crate::prelude::*;
|
5
5
|
|
6
|
-
|
7
|
-
pub(crate) enum EdgeDirectivity
|
8
|
-
{
|
9
|
-
Undirected,
|
10
|
-
Directed,
|
11
|
-
}
|
12
|
-
|
6
|
+
/// Uuid of a graph element (node, edge...).
|
13
7
|
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
|
14
8
|
pub struct Key
|
15
9
|
{
|
16
10
|
pub(crate) uuid: u128,
|
17
11
|
}
|
18
12
|
|
13
|
+
impl Key
|
14
|
+
{
|
15
|
+
/// New key from a given uuid
|
16
|
+
pub fn new(uuid: u128) -> Self
|
17
|
+
{
|
18
|
+
Self { uuid }
|
19
|
+
}
|
20
|
+
/// Return the 128bits uuid value.
|
21
|
+
pub fn uuid(&self) -> u128
|
22
|
+
{
|
23
|
+
self.uuid
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
19
27
|
impl Serialize for Key
|
20
28
|
{
|
21
29
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
@@ -79,6 +87,15 @@ pub struct Node
|
|
79
87
|
|
80
88
|
impl Node
|
81
89
|
{
|
90
|
+
/// Create a new node object
|
91
|
+
pub fn new(key: Key, labels: Vec<String>, properties: value::ValueMap) -> Node
|
92
|
+
{
|
93
|
+
Self {
|
94
|
+
key,
|
95
|
+
labels,
|
96
|
+
properties,
|
97
|
+
}
|
98
|
+
}
|
82
99
|
/// uuid for the Node.
|
83
100
|
pub fn key(&self) -> Key
|
84
101
|
{
|
@@ -89,11 +106,33 @@ impl Node
|
|
89
106
|
{
|
90
107
|
&self.labels
|
91
108
|
}
|
109
|
+
/// Mutable labels
|
110
|
+
pub fn labels_mut(&mut self) -> &mut Vec<String>
|
111
|
+
{
|
112
|
+
&mut self.labels
|
113
|
+
}
|
114
|
+
/// Edit labels
|
115
|
+
pub fn labels_edit(&mut self, editor: impl FnOnce(Vec<String>) -> Vec<String>)
|
116
|
+
{
|
117
|
+
let mut tmp = Default::default();
|
118
|
+
std::mem::swap(&mut self.labels, &mut tmp);
|
119
|
+
self.labels = editor(tmp);
|
120
|
+
}
|
92
121
|
/// Properties.
|
93
122
|
pub fn properties(&self) -> &value::ValueMap
|
94
123
|
{
|
95
124
|
&self.properties
|
96
125
|
}
|
126
|
+
/// Properties.
|
127
|
+
pub fn take_properties(self) -> value::ValueMap
|
128
|
+
{
|
129
|
+
self.properties
|
130
|
+
}
|
131
|
+
/// Properties.
|
132
|
+
pub fn properties_mut(&mut self) -> &mut value::ValueMap
|
133
|
+
{
|
134
|
+
&mut self.properties
|
135
|
+
}
|
97
136
|
/// Unpack Node in key, labels and properties.
|
98
137
|
pub fn unpack(self) -> (Key, Vec<String>, value::ValueMap)
|
99
138
|
{
|
@@ -102,7 +141,7 @@ impl Node
|
|
102
141
|
/// Convert into value map representation
|
103
142
|
pub fn into_value_map(self) -> value::ValueMap
|
104
143
|
{
|
105
|
-
crate::
|
144
|
+
crate::value_map!("key" => self.key, "labels" => self.labels, "properties" => self.properties, "type" => "node")
|
106
145
|
}
|
107
146
|
}
|
108
147
|
|
@@ -130,12 +169,6 @@ pub struct Edge
|
|
130
169
|
{
|
131
170
|
/// uuid for the Edge.
|
132
171
|
pub(crate) key: Key,
|
133
|
-
#[serde(skip_serializing)]
|
134
|
-
/// source node for the Edge, this property is used internally by the engine, but is not exported in query results, and not part of the public API.
|
135
|
-
pub(crate) source: Node,
|
136
|
-
/// destination node for the Edge, this property is used internally by the engine, but is not exported in query results, and not part of the public API.
|
137
|
-
#[serde(skip_serializing)]
|
138
|
-
pub(crate) destination: Node,
|
139
172
|
/// Labels for the Edge.
|
140
173
|
pub(crate) labels: Vec<String>,
|
141
174
|
/// Properties for the Edge.
|
@@ -144,6 +177,16 @@ pub struct Edge
|
|
144
177
|
|
145
178
|
impl Edge
|
146
179
|
{
|
180
|
+
/// Create a new node object
|
181
|
+
pub fn new(key: Key, labels: Vec<String>, properties: value::ValueMap) -> Edge
|
182
|
+
{
|
183
|
+
Self {
|
184
|
+
key,
|
185
|
+
labels,
|
186
|
+
properties,
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
147
190
|
/// uuid for the Node.
|
148
191
|
pub fn key(&self) -> Key
|
149
192
|
{
|
@@ -154,11 +197,33 @@ impl Edge
|
|
154
197
|
{
|
155
198
|
&self.labels
|
156
199
|
}
|
200
|
+
/// Mutable labels
|
201
|
+
pub fn labels_mut(&mut self) -> &mut Vec<String>
|
202
|
+
{
|
203
|
+
&mut self.labels
|
204
|
+
}
|
205
|
+
/// Edit labels
|
206
|
+
pub fn labels_edit(&mut self, editor: impl FnOnce(Vec<String>) -> Vec<String>)
|
207
|
+
{
|
208
|
+
let mut tmp = Default::default();
|
209
|
+
std::mem::swap(&mut self.labels, &mut tmp);
|
210
|
+
self.labels = editor(tmp);
|
211
|
+
}
|
157
212
|
/// Properties.
|
158
213
|
pub fn properties(&self) -> &value::ValueMap
|
159
214
|
{
|
160
215
|
&self.properties
|
161
216
|
}
|
217
|
+
/// Properties.
|
218
|
+
pub fn properties_mut(&mut self) -> &mut value::ValueMap
|
219
|
+
{
|
220
|
+
&mut self.properties
|
221
|
+
}
|
222
|
+
/// Properties.
|
223
|
+
pub fn take_properties(self) -> value::ValueMap
|
224
|
+
{
|
225
|
+
self.properties
|
226
|
+
}
|
162
227
|
/// Unpack Edge in key, labels and properties.
|
163
228
|
pub fn unpack(self) -> (Key, Vec<String>, value::ValueMap)
|
164
229
|
{
|
@@ -167,7 +232,7 @@ impl Edge
|
|
167
232
|
/// Convert into value map representation
|
168
233
|
pub fn into_value_map(self) -> value::ValueMap
|
169
234
|
{
|
170
|
-
crate::
|
235
|
+
crate::value_map!("key" => self.key, "labels" => self.labels, "properties" => self.properties, "type" => "edge")
|
171
236
|
}
|
172
237
|
}
|
173
238
|
|
@@ -181,24 +246,10 @@ impl std::fmt::Display for Edge
|
|
181
246
|
}
|
182
247
|
}
|
183
248
|
|
184
|
-
|
185
|
-
{
|
186
|
-
fn into(self) -> Path
|
187
|
-
{
|
188
|
-
Path {
|
189
|
-
key: self.key,
|
190
|
-
source: self.source,
|
191
|
-
destination: self.destination,
|
192
|
-
labels: self.labels,
|
193
|
-
properties: self.properties,
|
194
|
-
}
|
195
|
-
}
|
196
|
-
}
|
197
|
-
|
198
|
-
/// Path in the graph.
|
249
|
+
/// SinglePath in the graph. A SinglePath contains an edge, source and destination.
|
199
250
|
#[derive(Serialize, Deserialize, Debug, Default, PartialEq, Clone, Hash)]
|
200
251
|
#[serde(tag = "type", rename = "path")]
|
201
|
-
pub struct
|
252
|
+
pub struct SinglePath
|
202
253
|
{
|
203
254
|
/// uuid for the path.
|
204
255
|
pub(crate) key: Key,
|
@@ -212,8 +263,25 @@ pub struct Path
|
|
212
263
|
pub(crate) properties: value::ValueMap,
|
213
264
|
}
|
214
265
|
|
215
|
-
impl
|
266
|
+
impl SinglePath
|
216
267
|
{
|
268
|
+
/// Create new single path
|
269
|
+
pub fn new(
|
270
|
+
key: Key,
|
271
|
+
source: Node,
|
272
|
+
labels: Vec<String>,
|
273
|
+
properties: value::ValueMap,
|
274
|
+
destination: Node,
|
275
|
+
) -> SinglePath
|
276
|
+
{
|
277
|
+
SinglePath {
|
278
|
+
key,
|
279
|
+
source,
|
280
|
+
destination,
|
281
|
+
labels,
|
282
|
+
properties,
|
283
|
+
}
|
284
|
+
}
|
217
285
|
/// uuid for the Node.
|
218
286
|
pub fn key(&self) -> Key
|
219
287
|
{
|
@@ -250,14 +318,32 @@ impl Path
|
|
250
318
|
self.destination,
|
251
319
|
)
|
252
320
|
}
|
321
|
+
/// Convert into an Edge
|
322
|
+
pub fn to_edge(&self) -> Edge
|
323
|
+
{
|
324
|
+
Edge {
|
325
|
+
key: self.key,
|
326
|
+
labels: self.labels.clone(),
|
327
|
+
properties: self.properties.clone(),
|
328
|
+
}
|
329
|
+
}
|
330
|
+
/// Convert into an Edge
|
331
|
+
pub fn into_edge(self) -> Edge
|
332
|
+
{
|
333
|
+
Edge {
|
334
|
+
key: self.key,
|
335
|
+
labels: self.labels,
|
336
|
+
properties: self.properties,
|
337
|
+
}
|
338
|
+
}
|
253
339
|
/// Convert into value map representation
|
254
340
|
pub fn into_value_map(self) -> value::ValueMap
|
255
341
|
{
|
256
|
-
crate::
|
342
|
+
crate::value_map!("key" => self.key, "source" => self.source, "labels" => self.labels, "properties" => self.properties, "destination" => self.destination, "type" => "path")
|
257
343
|
}
|
258
344
|
}
|
259
345
|
|
260
|
-
impl std::fmt::Display for
|
346
|
+
impl std::fmt::Display for SinglePath
|
261
347
|
{
|
262
348
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
263
349
|
{
|
@@ -267,7 +353,20 @@ impl std::fmt::Display for Path
|
|
267
353
|
}
|
268
354
|
}
|
269
355
|
|
270
|
-
|
356
|
+
impl From<SinglePath> for Edge
|
357
|
+
{
|
358
|
+
fn from(val: SinglePath) -> Self
|
359
|
+
{
|
360
|
+
Edge {
|
361
|
+
key: val.key,
|
362
|
+
labels: val.labels,
|
363
|
+
properties: val.properties,
|
364
|
+
}
|
365
|
+
}
|
366
|
+
}
|
367
|
+
|
368
|
+
/// Convenient macro to create a vector of label, from &str.
|
369
|
+
#[macro_export]
|
271
370
|
macro_rules! labels {
|
272
371
|
// match a list of expressions separated by comma:
|
273
372
|
($($str:expr),*) => (
|
@@ -278,6 +377,3 @@ macro_rules! labels {
|
|
278
377
|
}
|
279
378
|
);
|
280
379
|
}
|
281
|
-
|
282
|
-
#[cfg(test)]
|
283
|
-
pub(crate) use labels;
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#![doc = include_str!("../README.MD")]
|
2
|
+
#![warn(missing_docs)]
|
3
|
+
#![deny(warnings)]
|
4
|
+
#![allow(clippy::result_large_err)]
|
5
|
+
|
6
|
+
mod error;
|
7
|
+
mod graph;
|
8
|
+
mod prelude;
|
9
|
+
mod serialize_with;
|
10
|
+
mod table;
|
11
|
+
mod value;
|
12
|
+
|
13
|
+
pub use error::Error;
|
14
|
+
pub use graph::{Edge, Key, Node, SinglePath};
|
15
|
+
pub use table::Table;
|
16
|
+
pub use value::{Value, ValueMap, ValueTryIntoRef};
|
@@ -2,7 +2,7 @@ use serde::de::{self, Visitor};
|
|
2
2
|
use serde::{Deserializer, Serializer};
|
3
3
|
use std::fmt;
|
4
4
|
|
5
|
-
const NAN: f64 =
|
5
|
+
const NAN: f64 = f64::NAN;
|
6
6
|
|
7
7
|
pub fn serialize_float<S>(x: &f64, serializer: S) -> Result<S::Ok, S::Error>
|
8
8
|
where
|
@@ -68,7 +68,7 @@ impl<'de> Visitor<'de> for FloatDeserializeVisitor
|
|
68
68
|
where
|
69
69
|
E: de::Error,
|
70
70
|
{
|
71
|
-
Ok(v
|
71
|
+
Ok(v)
|
72
72
|
}
|
73
73
|
|
74
74
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
@@ -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
|
+
}
|