gqlite 1.2.0 → 1.2.2

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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/ext/gqliterb/.cargo/config.toml +2 -0
  3. data/ext/gqliterb/Cargo.lock +133 -123
  4. data/ext/gqliterb/Cargo.toml +3 -6
  5. data/ext/gqliterb/src/lib.rs +2 -2
  6. data/ext/gqliterb/vendor/gqlitedb/Cargo.lock +2060 -0
  7. data/ext/gqliterb/vendor/gqlitedb/Cargo.toml +132 -0
  8. data/ext/gqliterb/vendor/gqlitedb/askama.toml +3 -0
  9. data/ext/gqliterb/vendor/gqlitedb/benches/common/mod.rs +25 -0
  10. data/ext/gqliterb/vendor/gqlitedb/benches/common/pokec.rs +185 -0
  11. data/ext/gqliterb/vendor/gqlitedb/benches/pokec_divan.rs +137 -0
  12. data/ext/gqliterb/vendor/gqlitedb/benches/pokec_iai.rs +122 -0
  13. data/ext/gqliterb/vendor/gqlitedb/release.toml +7 -0
  14. data/ext/gqliterb/vendor/gqlitedb/src/aggregators/arithmetic.rs +96 -0
  15. data/ext/gqliterb/vendor/gqlitedb/src/aggregators/containers.rs +33 -0
  16. data/ext/gqliterb/vendor/gqlitedb/src/aggregators/count.rs +35 -0
  17. data/ext/gqliterb/vendor/gqlitedb/src/aggregators/stats.rs +168 -0
  18. data/ext/gqliterb/vendor/gqlitedb/src/aggregators.rs +74 -0
  19. data/ext/gqliterb/vendor/gqlitedb/src/capi.rs +236 -0
  20. data/ext/gqliterb/vendor/gqlitedb/src/compiler/expression_analyser.rs +427 -0
  21. data/ext/gqliterb/vendor/gqlitedb/src/compiler/variables_manager.rs +620 -0
  22. data/ext/gqliterb/vendor/gqlitedb/src/compiler.rs +1106 -0
  23. data/ext/gqliterb/vendor/gqlitedb/src/connection.rs +208 -0
  24. data/ext/gqliterb/vendor/gqlitedb/src/consts.rs +10 -0
  25. data/ext/gqliterb/vendor/gqlitedb/src/error.rs +621 -0
  26. data/ext/gqliterb/vendor/gqlitedb/src/functions/containers.rs +115 -0
  27. data/ext/gqliterb/vendor/gqlitedb/src/functions/edge.rs +20 -0
  28. data/ext/gqliterb/vendor/gqlitedb/src/functions/math.rs +44 -0
  29. data/ext/gqliterb/vendor/gqlitedb/src/functions/node.rs +16 -0
  30. data/ext/gqliterb/vendor/gqlitedb/src/functions/path.rs +48 -0
  31. data/ext/gqliterb/vendor/gqlitedb/src/functions/scalar.rs +86 -0
  32. data/ext/gqliterb/vendor/gqlitedb/src/functions/string.rs +28 -0
  33. data/ext/gqliterb/vendor/gqlitedb/src/functions/value.rs +99 -0
  34. data/ext/gqliterb/vendor/gqlitedb/src/functions.rs +412 -0
  35. data/ext/gqliterb/vendor/gqlitedb/src/graph.rs +268 -0
  36. data/ext/gqliterb/vendor/gqlitedb/src/interpreter/evaluators.rs +1788 -0
  37. data/ext/gqliterb/vendor/gqlitedb/src/interpreter/instructions.rs +262 -0
  38. data/ext/gqliterb/vendor/gqlitedb/src/interpreter/mod.rs +4 -0
  39. data/ext/gqliterb/vendor/gqlitedb/src/lib.rs +42 -0
  40. data/ext/gqliterb/vendor/gqlitedb/src/parser/ast.rs +625 -0
  41. data/ext/gqliterb/vendor/gqlitedb/src/parser/gql.pest +191 -0
  42. data/ext/gqliterb/vendor/gqlitedb/src/parser/parser.rs +1153 -0
  43. data/ext/gqliterb/vendor/gqlitedb/src/parser.rs +4 -0
  44. data/ext/gqliterb/vendor/gqlitedb/src/prelude.rs +8 -0
  45. data/ext/gqliterb/vendor/gqlitedb/src/serialize_with.rs +94 -0
  46. data/ext/gqliterb/vendor/gqlitedb/src/store/pgql.rs +121 -0
  47. data/ext/gqliterb/vendor/gqlitedb/src/store/redb.rs +1250 -0
  48. data/ext/gqliterb/vendor/gqlitedb/src/store/sqlite.rs +994 -0
  49. data/ext/gqliterb/vendor/gqlitedb/src/store.rs +432 -0
  50. data/ext/gqliterb/vendor/gqlitedb/src/tests/compiler.rs +92 -0
  51. data/ext/gqliterb/vendor/gqlitedb/src/tests/evaluators.rs +227 -0
  52. data/ext/gqliterb/vendor/gqlitedb/src/tests/parser.rs +81 -0
  53. data/ext/gqliterb/vendor/gqlitedb/src/tests/store/redb.rs +39 -0
  54. data/ext/gqliterb/vendor/gqlitedb/src/tests/store/sqlite.rs +39 -0
  55. data/ext/gqliterb/vendor/gqlitedb/src/tests/store.rs +462 -0
  56. data/ext/gqliterb/vendor/gqlitedb/src/tests/templates/ast.rs +356 -0
  57. data/ext/gqliterb/vendor/gqlitedb/src/tests/templates/programs.rs +455 -0
  58. data/ext/gqliterb/vendor/gqlitedb/src/tests/templates.rs +2 -0
  59. data/ext/gqliterb/vendor/gqlitedb/src/tests.rs +39 -0
  60. data/ext/gqliterb/vendor/gqlitedb/src/utils.rs +28 -0
  61. data/ext/gqliterb/vendor/gqlitedb/src/value/compare.rs +212 -0
  62. data/ext/gqliterb/vendor/gqlitedb/src/value/contains.rs +47 -0
  63. data/ext/gqliterb/vendor/gqlitedb/src/value/value_map.rs +298 -0
  64. data/ext/gqliterb/vendor/gqlitedb/src/value.rs +559 -0
  65. data/ext/gqliterb/vendor/gqlitedb/src/value_table.rs +616 -0
  66. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/call_stats.sql +22 -0
  67. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_count_for_node.sql +3 -0
  68. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_create.sql +6 -0
  69. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_delete.sql +1 -0
  70. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_delete_by_nodes.sql +2 -0
  71. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_select.sql +139 -0
  72. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_update.sql +4 -0
  73. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/graph_create.sql +16 -0
  74. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/graph_delete.sql +3 -0
  75. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_create_table.sql +1 -0
  76. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_get.sql +1 -0
  77. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_set.sql +1 -0
  78. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_create.sql +1 -0
  79. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_delete.sql +1 -0
  80. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_select.sql +42 -0
  81. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_update.sql +4 -0
  82. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/table_exists.sql +5 -0
  83. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/upgrade_from_1_01.sql +2 -0
  84. data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/upgrade_graph_from_1_01.sql +65 -0
  85. metadata +82 -2
@@ -0,0 +1,33 @@
1
+ use super::AggregatorState;
2
+
3
+ use crate::{value::Value, Result};
4
+
5
+ #[derive(Debug)]
6
+ struct CollectState
7
+ {
8
+ value: Vec<Value>,
9
+ }
10
+
11
+ impl CollectState
12
+ {
13
+ fn new() -> Result<Self>
14
+ {
15
+ Ok(Self {
16
+ value: Default::default(),
17
+ })
18
+ }
19
+ }
20
+ impl AggregatorState for CollectState
21
+ {
22
+ fn next(&mut self, value: Value) -> crate::Result<()>
23
+ {
24
+ self.value.push(value);
25
+ Ok(())
26
+ }
27
+ fn finalise(self: Box<Self>) -> crate::Result<crate::value::Value>
28
+ {
29
+ Ok(self.value.into())
30
+ }
31
+ }
32
+
33
+ super::declare_aggregator!(collect, Collect, CollectState, () -> i64);
@@ -0,0 +1,35 @@
1
+ use super::AggregatorState;
2
+
3
+ use crate::Result;
4
+
5
+ #[derive(Debug)]
6
+ struct CountState
7
+ {
8
+ count: i64,
9
+ }
10
+
11
+ impl CountState
12
+ {
13
+ fn new() -> Result<Self>
14
+ {
15
+ Ok(Self { count: 0 })
16
+ }
17
+ }
18
+
19
+ impl AggregatorState for CountState
20
+ {
21
+ fn next(&mut self, value: crate::value::Value) -> crate::Result<()>
22
+ {
23
+ if !value.is_null()
24
+ {
25
+ self.count += 1;
26
+ }
27
+ Ok(())
28
+ }
29
+ fn finalise(self: Box<Self>) -> crate::Result<crate::value::Value>
30
+ {
31
+ Ok(self.count.into())
32
+ }
33
+ }
34
+
35
+ super::declare_aggregator!(count, Count, CountState, () -> i64);
@@ -0,0 +1,168 @@
1
+ use std::fmt::Debug;
2
+
3
+ use super::AggregatorState;
4
+
5
+ use crate::{
6
+ error::{InternalError, RunTimeError},
7
+ value::Value,
8
+ Result,
9
+ };
10
+
11
+ #[derive(Debug)]
12
+ struct AvgState
13
+ {
14
+ value: Value,
15
+ count: usize,
16
+ }
17
+
18
+ impl AvgState
19
+ {
20
+ fn new() -> Result<Self>
21
+ {
22
+ Ok(Self {
23
+ value: Value::Null,
24
+ count: 0,
25
+ })
26
+ }
27
+ }
28
+
29
+ impl AggregatorState for AvgState
30
+ {
31
+ fn next(&mut self, value: Value) -> crate::Result<()>
32
+ {
33
+ if self.value.is_null()
34
+ {
35
+ self.value = value;
36
+ }
37
+ else
38
+ {
39
+ match value
40
+ {
41
+ Value::Null =>
42
+ {}
43
+ Value::Integer(i) =>
44
+ {
45
+ self.count += 1;
46
+ match self.value
47
+ {
48
+ Value::Integer(vi) => self.value = (vi + i).into(),
49
+ Value::Float(vf) => self.value = (vf + i as f64).into(),
50
+ _ => Err(InternalError::InvalidAggregationState)?,
51
+ }
52
+ }
53
+ Value::Float(f) =>
54
+ {
55
+ self.count += 1;
56
+ match self.value
57
+ {
58
+ Value::Integer(vi) => self.value = (vi as f64 + f).into(),
59
+ Value::Float(vf) => self.value = (vf + f).into(),
60
+ _ => Err(InternalError::InvalidAggregationState)?,
61
+ }
62
+ }
63
+ _ => Err(RunTimeError::InvalidArgumentType)?,
64
+ }
65
+ }
66
+ Ok(())
67
+ }
68
+ fn finalise(self: Box<Self>) -> crate::Result<crate::value::Value>
69
+ {
70
+ match self.value
71
+ {
72
+ Value::Null => Ok(Value::Null),
73
+ Value::Integer(vi) => Ok((vi / self.count as i64).into()),
74
+ Value::Float(vf) => Ok((vf / self.count as f64).into()),
75
+ _ => Err(InternalError::InvalidAggregationState)?,
76
+ }
77
+ }
78
+ }
79
+
80
+ super::declare_aggregator!(avg, Avg, AvgState, () -> Value);
81
+
82
+ #[derive(Debug)]
83
+ struct MinState
84
+ {
85
+ value: Value,
86
+ }
87
+
88
+ impl MinState
89
+ {
90
+ fn new() -> Result<Self>
91
+ {
92
+ Ok(Self { value: Value::Null })
93
+ }
94
+ }
95
+
96
+ impl AggregatorState for MinState
97
+ {
98
+ fn next(&mut self, value: Value) -> crate::Result<()>
99
+ {
100
+ if self.value.is_null()
101
+ {
102
+ self.value = value;
103
+ }
104
+ else if !value.is_null()
105
+ {
106
+ match value.orderability(&self.value)
107
+ {
108
+ std::cmp::Ordering::Less =>
109
+ {
110
+ self.value = value;
111
+ }
112
+ _ =>
113
+ {}
114
+ }
115
+ }
116
+ Ok(())
117
+ }
118
+ fn finalise(self: Box<Self>) -> crate::Result<crate::value::Value>
119
+ {
120
+ Ok(self.value)
121
+ }
122
+ }
123
+
124
+ super::declare_aggregator!(min, Min, MinState, () -> i64);
125
+
126
+ #[derive(Debug)]
127
+ struct MaxState
128
+ {
129
+ value: Value,
130
+ }
131
+
132
+ impl MaxState
133
+ {
134
+ fn new() -> Result<Self>
135
+ {
136
+ Ok(Self { value: Value::Null })
137
+ }
138
+ }
139
+
140
+ impl AggregatorState for MaxState
141
+ {
142
+ fn next(&mut self, value: Value) -> crate::Result<()>
143
+ {
144
+ if self.value.is_null()
145
+ {
146
+ self.value = value;
147
+ }
148
+ else if !value.is_null()
149
+ {
150
+ match value.orderability(&self.value)
151
+ {
152
+ std::cmp::Ordering::Greater =>
153
+ {
154
+ self.value = value;
155
+ }
156
+ _ =>
157
+ {}
158
+ }
159
+ }
160
+ Ok(())
161
+ }
162
+ fn finalise(self: Box<Self>) -> crate::Result<crate::value::Value>
163
+ {
164
+ Ok(self.value)
165
+ }
166
+ }
167
+
168
+ super::declare_aggregator!(max, Max, MaxState, () -> i64);
@@ -0,0 +1,74 @@
1
+ mod arithmetic;
2
+ mod containers;
3
+ mod count;
4
+ mod stats;
5
+
6
+ use std::{fmt::Debug, sync::Arc};
7
+
8
+ use crate::prelude::*;
9
+ use compiler::expression_analyser::ExpressionType;
10
+
11
+ pub(crate) trait AggregatorState: Debug
12
+ {
13
+ fn next(&mut self, expression: value::Value) -> Result<()>;
14
+ fn finalise(self: Box<Self>) -> Result<value::Value>;
15
+ }
16
+
17
+ pub(crate) trait AggregatorTrait: Debug + Sync + Send
18
+ {
19
+ fn create(&self, arguments: Vec<value::Value>) -> Result<Box<dyn AggregatorState>>;
20
+ fn validate_arguments(&self, arguments: Vec<ExpressionType>) -> Result<ExpressionType>;
21
+ }
22
+
23
+ pub(crate) type Aggregator = Arc<Box<dyn AggregatorTrait>>;
24
+
25
+ macro_rules! declare_aggregator {
26
+ ($function_name: ident, $type_name: ident, $state_type_name: tt, ( $( $arg_type: ty $(,)? )* ) -> $ret_type: ty) => {
27
+ #[derive(Debug)]
28
+ pub(super) struct $type_name {}
29
+ impl $type_name
30
+ {
31
+ pub(crate) fn new() -> (String, crate::aggregators::Aggregator)
32
+ {
33
+ (
34
+ stringify!($function_name).to_string(),
35
+ std::sync::Arc::new(Box::new(Self {})),
36
+ )
37
+ }
38
+ }
39
+ impl crate::aggregators::AggregatorTrait for $type_name
40
+ {
41
+ #[allow(unused_variables)]
42
+ fn create(&self, arguments: Vec<crate::value::Value>) -> Result<Box<dyn AggregatorState>>
43
+ {
44
+ Ok(Box::new($crate::functions::make_function_call!($function_name, $state_type_name::new, arguments, $( $arg_type,)*)?))
45
+ }
46
+ #[allow(unused_variables)]
47
+ fn validate_arguments(
48
+ &self,
49
+ arguments: Vec<$crate::compiler::expression_analyser::ExpressionType>,
50
+ ) -> Result<$crate::compiler::expression_analyser::ExpressionType>
51
+ {
52
+ use crate::functions::FunctionTypeTrait;
53
+ // TODO
54
+ Ok(<$ret_type>::result_type())
55
+ }
56
+
57
+ }
58
+ };
59
+ }
60
+
61
+ pub(crate) use declare_aggregator;
62
+
63
+ pub(crate) fn init_aggregators() -> std::collections::HashMap<String, Aggregator>
64
+ {
65
+ [
66
+ count::Count::new(),
67
+ arithmetic::Sum::new(),
68
+ containers::Collect::new(),
69
+ stats::Avg::new(),
70
+ stats::Min::new(),
71
+ stats::Max::new(),
72
+ ]
73
+ .into()
74
+ }
@@ -0,0 +1,236 @@
1
+ use std::borrow::Borrow;
2
+
3
+ fn handle_error<T, E: std::borrow::Borrow<E> + ToString>(
4
+ context: *mut GqliteApiContextT,
5
+ result: Result<T, E>,
6
+ ) -> Result<T, E>
7
+ {
8
+ match &result
9
+ {
10
+ Ok(_) =>
11
+ {}
12
+ Err(e) =>
13
+ {
14
+ let mut context = unsafe { Box::from_raw(context) };
15
+ context.string = std::ffi::CString::new(e.borrow().to_string()).unwrap();
16
+ context.has_error = true;
17
+ let _ = Box::into_raw(context);
18
+ }
19
+ }
20
+ result
21
+ }
22
+
23
+ fn get_value(value: *mut GqliteValueT) -> crate::value::Value
24
+ {
25
+ if value.is_null()
26
+ {
27
+ crate::value::Value::default()
28
+ }
29
+ else
30
+ {
31
+ let value = unsafe { Box::from_raw(value) };
32
+ let v = value.value.clone();
33
+ let _ = Box::into_raw(value);
34
+ v
35
+ }
36
+ }
37
+
38
+ fn check_error(context: *mut GqliteApiContextT)
39
+ {
40
+ if unsafe { (*context).has_error }
41
+ {
42
+ let context = unsafe { Box::from_raw(context) };
43
+ let stri = context.string.to_str().unwrap();
44
+ println!("Error message '{stri:?}' was not cleared from context!");
45
+ let _ = Box::into_raw(context);
46
+ }
47
+ }
48
+
49
+ #[repr(C)]
50
+ pub struct GqliteApiContextT
51
+ {
52
+ string: std::ffi::CString,
53
+ has_error: bool,
54
+ }
55
+
56
+ #[repr(C)]
57
+ pub struct GqliteConnectionT
58
+ {
59
+ connection: crate::Connection,
60
+ }
61
+
62
+ #[repr(C)]
63
+ pub struct GqliteValueT
64
+ {
65
+ value: crate::value::Value,
66
+ }
67
+
68
+ #[no_mangle]
69
+ pub extern "C" fn gqlite_api_context_create() -> *mut GqliteApiContextT
70
+ {
71
+ Box::into_raw(Box::new(GqliteApiContextT {
72
+ string: std::ffi::CString::new("").unwrap(),
73
+ has_error: false,
74
+ }))
75
+ }
76
+
77
+ #[no_mangle]
78
+ pub extern "C" fn gqlite_api_context_destroy(context: *mut GqliteApiContextT)
79
+ {
80
+ unsafe {
81
+ let _ = Box::from_raw(context);
82
+ }
83
+ }
84
+
85
+ #[no_mangle]
86
+ pub extern "C" fn gqlite_api_context_get_message(
87
+ context: *mut GqliteApiContextT,
88
+ ) -> *const std::ffi::c_char
89
+ {
90
+ unsafe { (*context).string.as_ptr() }
91
+ }
92
+
93
+ #[no_mangle]
94
+ pub extern "C" fn gqlite_api_context_has_error(context: *mut GqliteApiContextT) -> bool
95
+ {
96
+ unsafe { (*context).has_error }
97
+ }
98
+
99
+ #[no_mangle]
100
+ pub extern "C" fn gqlite_api_context_clear_error(context: *mut GqliteApiContextT)
101
+ {
102
+ let mut context = unsafe { Box::from_raw(context) };
103
+ context.has_error = false;
104
+ let _ = Box::into_raw(context);
105
+ }
106
+
107
+ #[no_mangle]
108
+ pub extern "C" fn gqlite_connection_create_from_file(
109
+ context: *mut GqliteApiContextT,
110
+ filename: *const std::ffi::c_char,
111
+ options: *mut GqliteValueT,
112
+ ) -> *mut GqliteConnectionT
113
+ {
114
+ check_error(context);
115
+ let options = get_value(options);
116
+ let path = unsafe { std::ffi::CStr::from_ptr(filename) };
117
+ if let Ok(path) = handle_error(context, path.to_str())
118
+ {
119
+ if let Ok(c) = handle_error(context, crate::Connection::open(path, options.into_map()))
120
+ {
121
+ return Box::into_raw(Box::new(GqliteConnectionT { connection: c }));
122
+ }
123
+ }
124
+ std::ptr::null::<GqliteConnectionT>() as *mut GqliteConnectionT
125
+ }
126
+
127
+ #[no_mangle]
128
+ pub extern "C" fn gqlite_connection_destroy(
129
+ _context: *mut GqliteApiContextT,
130
+ connection: *mut GqliteConnectionT,
131
+ )
132
+ {
133
+ unsafe {
134
+ let _ = Box::from_raw(connection);
135
+ }
136
+ }
137
+
138
+ #[no_mangle]
139
+ pub extern "C" fn gqlite_connection_query(
140
+ context: *mut GqliteApiContextT,
141
+ connection: *mut GqliteConnectionT,
142
+ query: *const std::ffi::c_char,
143
+ bindings: *mut GqliteValueT,
144
+ ) -> *mut GqliteValueT
145
+ {
146
+ check_error(context);
147
+ let query = unsafe { std::ffi::CStr::from_ptr(query) };
148
+ if let Ok(query) = handle_error(context, query.to_str())
149
+ {
150
+ let conn = unsafe { Box::from_raw(connection) };
151
+ let result = conn
152
+ .connection
153
+ .execute_query(query, get_value(bindings).into_map());
154
+ let _ = Box::into_raw(conn);
155
+ if let Ok(v) = handle_error(context, result)
156
+ {
157
+ return Box::into_raw(Box::new(GqliteValueT { value: v }));
158
+ }
159
+ }
160
+ std::ptr::null::<GqliteValueT>() as *mut GqliteValueT
161
+ }
162
+
163
+ #[no_mangle]
164
+ pub extern "C" fn gqlite_value_create(context: *mut GqliteApiContextT) -> *mut GqliteValueT
165
+ {
166
+ check_error(context);
167
+ Box::into_raw(Box::new(GqliteValueT {
168
+ value: crate::value::Value::default(),
169
+ }))
170
+ }
171
+
172
+ #[no_mangle]
173
+ pub extern "C" fn gqlite_value_destroy(context: *mut GqliteApiContextT, value: *mut GqliteValueT)
174
+ {
175
+ check_error(context);
176
+ unsafe {
177
+ let _ = Box::from_raw(value);
178
+ }
179
+ }
180
+
181
+ #[no_mangle]
182
+ pub extern "C" fn gqlite_value_to_json(
183
+ context: *mut GqliteApiContextT,
184
+ value: *mut GqliteValueT,
185
+ ) -> *const std::ffi::c_char
186
+ {
187
+ check_error(context);
188
+
189
+ let value = unsafe { Box::from_raw(value) };
190
+
191
+ if let Ok(v) = handle_error(context, serde_json::to_string(value.value.borrow()))
192
+ {
193
+ let mut context = unsafe { Box::from_raw(context) };
194
+ context.string = std::ffi::CString::new(v).unwrap();
195
+ context.has_error = false;
196
+ let r = context.string.as_ptr();
197
+ let _ = Box::into_raw(context);
198
+ let _ = Box::into_raw(value);
199
+ return r;
200
+ }
201
+ let _ = Box::into_raw(value);
202
+ return std::ptr::null();
203
+ }
204
+
205
+ #[no_mangle]
206
+ pub extern "C" fn gqlite_value_from_json(
207
+ context: *mut GqliteApiContextT,
208
+ json: *const std::ffi::c_char,
209
+ ) -> *mut GqliteValueT
210
+ {
211
+ check_error(context);
212
+
213
+ let json = unsafe { std::ffi::CStr::from_ptr(json) };
214
+ if let Ok(json) = handle_error(context, json.to_str())
215
+ {
216
+ if let Ok(v) = handle_error(context, serde_json::from_str::<crate::value::Value>(json))
217
+ {
218
+ return Box::into_raw(Box::new(GqliteValueT { value: v }));
219
+ }
220
+ }
221
+ return std::ptr::null::<GqliteValueT>() as *mut GqliteValueT;
222
+ }
223
+
224
+ #[no_mangle]
225
+ pub extern "C" fn gqlite_value_is_valid(
226
+ context: *mut GqliteApiContextT,
227
+ value: *mut GqliteValueT,
228
+ ) -> bool
229
+ {
230
+ check_error(context);
231
+ match unsafe { (*value).value.borrow() }
232
+ {
233
+ crate::value::Value::Null => false,
234
+ _ => true,
235
+ }
236
+ }