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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/ext/Cargo.toml +20 -0
  3. data/ext/gqlitedb/Cargo.toml +77 -0
  4. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/benches/common/pokec.rs +30 -20
  5. data/ext/gqlitedb/gqlite_bench_data/README.MD +6 -0
  6. data/ext/gqlitedb/gqlite_bench_data/scripts/generate_smaller_pokec.rb +85 -0
  7. data/ext/gqlitedb/gqlite_bench_data/scripts/to_efficient_pokec.rb +34 -0
  8. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators/arithmetic.rs +1 -0
  9. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators/stats.rs +27 -49
  10. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators.rs +7 -7
  11. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/capi.rs +10 -9
  12. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/compiler/expression_analyser.rs +6 -4
  13. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/compiler/variables_manager.rs +27 -31
  14. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/compiler.rs +37 -41
  15. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/connection.rs +42 -84
  16. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/error.rs +105 -34
  17. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/containers.rs +21 -26
  18. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/edge.rs +2 -2
  19. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/math.rs +2 -2
  20. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/node.rs +1 -1
  21. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/path.rs +15 -20
  22. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/scalar.rs +2 -2
  23. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/value.rs +6 -6
  24. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions.rs +20 -20
  25. data/ext/gqlitedb/src/graph.rs +11 -0
  26. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/interpreter/evaluators.rs +160 -194
  27. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/interpreter/instructions.rs +2 -1
  28. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/lib.rs +9 -4
  29. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/parser/ast.rs +44 -52
  30. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/parser/gql.pest +1 -1
  31. data/ext/{gqliterb/vendor/gqlitedb/src/parser/parser.rs → gqlitedb/src/parser/parser_impl.rs} +50 -28
  32. data/ext/gqlitedb/src/parser.rs +4 -0
  33. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/prelude.rs +3 -2
  34. data/ext/gqlitedb/src/query_result.rs +88 -0
  35. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/store/redb.rs +226 -148
  36. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/store/sqlite.rs +111 -128
  37. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/store.rs +22 -22
  38. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/evaluators.rs +32 -76
  39. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/store.rs +95 -111
  40. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/templates/ast.rs +29 -29
  41. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/templates/programs.rs +4 -4
  42. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/value/compare.rs +13 -20
  43. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/value/contains.rs +2 -2
  44. data/ext/gqlitedb/src/value.rs +225 -0
  45. data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/value_table.rs +15 -5
  46. data/ext/gqliterb/Cargo.toml +12 -35
  47. data/ext/gqliterb/src/lib.rs +60 -38
  48. data/ext/graphcore/Cargo.toml +19 -0
  49. data/ext/graphcore/README.MD +4 -0
  50. data/ext/graphcore/release.toml +1 -0
  51. data/ext/graphcore/src/error.rs +28 -0
  52. data/ext/{gqliterb/vendor/gqlitedb → graphcore}/src/graph.rs +134 -38
  53. data/ext/graphcore/src/lib.rs +16 -0
  54. data/ext/graphcore/src/prelude.rs +4 -0
  55. data/ext/{gqliterb/vendor/gqlitedb → graphcore}/src/serialize_with.rs +2 -2
  56. data/ext/graphcore/src/table.rs +272 -0
  57. data/ext/{gqliterb/vendor/gqlitedb → graphcore}/src/value/value_map.rs +44 -49
  58. data/ext/graphcore/src/value.rs +413 -0
  59. metadata +94 -83
  60. data/ext/gqliterb/.cargo/config.toml +0 -2
  61. data/ext/gqliterb/Cargo.lock +0 -1116
  62. data/ext/gqliterb/vendor/gqlitedb/Cargo.lock +0 -2115
  63. data/ext/gqliterb/vendor/gqlitedb/Cargo.toml +0 -138
  64. data/ext/gqliterb/vendor/gqlitedb/src/parser.rs +0 -4
  65. data/ext/gqliterb/vendor/gqlitedb/src/value.rs +0 -609
  66. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/askama.toml +0 -0
  67. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/benches/common/mod.rs +0 -0
  68. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/benches/pokec_divan.rs +0 -0
  69. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/benches/pokec_iai.rs +0 -0
  70. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/release.toml +0 -0
  71. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators/containers.rs +0 -0
  72. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/aggregators/count.rs +0 -0
  73. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/consts.rs +0 -0
  74. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/functions/string.rs +0 -0
  75. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/interpreter/mod.rs +0 -0
  76. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/store/pgql.rs +0 -0
  77. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/compiler.rs +0 -0
  78. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/parser.rs +0 -0
  79. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/store/redb.rs +0 -0
  80. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/store/sqlite.rs +0 -0
  81. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests/templates.rs +0 -0
  82. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/tests.rs +0 -0
  83. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/src/utils.rs +0 -0
  84. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/call_stats.sql +0 -0
  85. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_count_for_node.sql +0 -0
  86. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_create.sql +0 -0
  87. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_delete.sql +0 -0
  88. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_delete_by_nodes.sql +0 -0
  89. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_select.sql +0 -0
  90. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/edge_update.sql +0 -0
  91. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/graph_create.sql +0 -0
  92. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/graph_delete.sql +0 -0
  93. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/metadata_create_table.sql +0 -0
  94. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/metadata_get.sql +0 -0
  95. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/metadata_set.sql +0 -0
  96. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/node_create.sql +0 -0
  97. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/node_delete.sql +0 -0
  98. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/node_select.sql +0 -0
  99. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/node_update.sql +0 -0
  100. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/table_exists.sql +0 -0
  101. /data/ext/{gqliterb/vendor/gqlitedb → gqlitedb}/templates/sql/sqlite/upgrade_from_1_01.sql +0 -0
  102. /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
- #[derive(Debug, Clone, Copy)]
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::map!("labels" => self.labels, "properties" => self.properties, "type" => "node")
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::map!( "labels" => self.labels, "properties" => self.properties, "type" => "edge")
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
- impl Into<Path> for Edge
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 Path
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 Path
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::map!( "source" => self.source, "labels" => self.labels, "properties" => self.properties, "destination" => self.destination, "type" => "path")
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 Path
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
- #[cfg(test)]
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};
@@ -0,0 +1,4 @@
1
+ pub(crate) use crate::{error, graph, serialize_with, value};
2
+ pub(crate) use error::Error;
3
+
4
+ pub type Result<T, E = Error> = std::result::Result<T, E>;
@@ -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 = std::f64::NAN;
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 as f64)
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
+ }