1use std::convert::From;
17use std::ffi::{CStr, CString};
18
19use crate::edge::*;
20use crate::list::*;
21use crate::map::*;
22use crate::memgraph::*;
23use crate::mgp::*;
24use crate::path::*;
25use crate::result::*;
26use crate::vertex::*;
27#[double]
29use crate::mgp::ffi;
30use mockall_double::double;
31
32pub(crate) unsafe fn create_cstring(c_char_ptr: *const i8) -> MgpResult<CString> {
38 match CString::new(CStr::from_ptr(c_char_ptr).to_bytes()) {
39 Ok(v) => Ok(v),
40 Err(_) => Err(MgpError::UnableToCreateCString),
41 }
42}
43
44pub struct MgpValue {
74 ptr: *mut mgp_value,
77 memgraph: Memgraph,
78}
79
80impl Drop for MgpValue {
81 fn drop(&mut self) {
82 unsafe {
83 if !self.ptr.is_null() {
84 ffi::mgp_value_destroy(self.ptr);
85 }
86 }
87 }
88}
89
90impl MgpValue {
91 pub(crate) fn new(ptr: *mut mgp_value, memgraph: &Memgraph) -> MgpValue {
92 #[cfg(not(test))]
93 assert!(
94 !ptr.is_null(),
95 "Unable to create Memgraph value because the given pointer is null."
96 );
97
98 MgpValue {
99 ptr,
100 memgraph: memgraph.clone(),
101 }
102 }
103
104 pub(crate) fn mgp_ptr(&self) -> *const mgp_value {
105 self.ptr
106 }
107
108 pub fn to_value(&self) -> MgpResult<Value> {
109 unsafe { mgp_raw_value_to_value(self.mgp_ptr(), &self.memgraph) }
110 }
111
112 pub fn make_null(memgraph: &Memgraph) -> MgpResult<MgpValue> {
113 unsafe {
114 let mgp_ptr = ffi::mgp_value_make_null(memgraph.memory_ptr());
115 if mgp_ptr.is_null() {
116 return Err(MgpError::UnableToMakeNullValue);
117 }
118 Ok(MgpValue::new(mgp_ptr, &memgraph))
119 }
120 }
121
122 pub fn is_null(&self) -> bool {
123 unsafe { ffi::mgp_value_is_null(self.ptr) != 0 }
124 }
125
126 pub fn make_bool(value: bool, memgraph: &Memgraph) -> MgpResult<MgpValue> {
127 unsafe {
128 let mgp_ptr =
129 ffi::mgp_value_make_bool(if !value { 0 } else { 1 }, memgraph.memory_ptr());
130 if mgp_ptr.is_null() {
131 return Err(MgpError::UnableToMakeBoolValue);
132 }
133 Ok(MgpValue::new(mgp_ptr, &memgraph))
134 }
135 }
136
137 pub fn is_bool(&self) -> bool {
138 unsafe { ffi::mgp_value_is_bool(self.ptr) != 0 }
139 }
140
141 pub fn make_int(value: i64, memgraph: &Memgraph) -> MgpResult<MgpValue> {
142 unsafe {
143 let mgp_ptr = ffi::mgp_value_make_int(value, memgraph.memory_ptr());
144 if mgp_ptr.is_null() {
145 return Err(MgpError::UnableToMakeIntegerValue);
146 }
147 Ok(MgpValue::new(mgp_ptr, &memgraph))
148 }
149 }
150
151 pub fn is_int(&self) -> bool {
152 unsafe { ffi::mgp_value_is_int(self.ptr) != 0 }
153 }
154
155 pub fn make_double(value: f64, memgraph: &Memgraph) -> MgpResult<MgpValue> {
156 unsafe {
157 let mgp_ptr = ffi::mgp_value_make_double(value, memgraph.memory_ptr());
158 if mgp_ptr.is_null() {
159 return Err(MgpError::UnableToMakeDoubleValue);
160 }
161 Ok(MgpValue::new(mgp_ptr, &memgraph))
162 }
163 }
164
165 pub fn is_double(&self) -> bool {
166 unsafe { ffi::mgp_value_is_double(self.ptr) != 0 }
167 }
168
169 pub fn make_string(value: &CStr, memgraph: &Memgraph) -> MgpResult<MgpValue> {
170 unsafe {
171 let mgp_ptr = ffi::mgp_value_make_string(value.as_ptr(), memgraph.memory_ptr());
172 if mgp_ptr.is_null() {
173 return Err(MgpError::UnableToMakeMemgraphStringValue);
174 }
175 Ok(MgpValue::new(mgp_ptr, &memgraph))
176 }
177 }
178
179 pub fn is_string(&self) -> bool {
180 unsafe { ffi::mgp_value_is_string(self.ptr) != 0 }
181 }
182
183 pub fn make_list(list: &List, memgraph: &Memgraph) -> MgpResult<MgpValue> {
186 unsafe {
187 let mgp_list = ffi::mgp_list_make_empty(list.size(), memgraph.memory_ptr());
190 for item in list.iter()? {
191 let mgp_value = item.to_mgp_value(&memgraph)?;
192 if ffi::mgp_list_append(mgp_list, mgp_value.ptr) == 0 {
193 ffi::mgp_list_destroy(mgp_list);
194 return Err(MgpError::UnableToMakeListValue);
195 }
196 }
197 let mgp_value = ffi::mgp_value_make_list(mgp_list);
198 if mgp_value.is_null() {
199 ffi::mgp_list_destroy(mgp_list);
200 return Err(MgpError::UnableToMakeListValue);
201 }
202 Ok(MgpValue::new(mgp_value, &memgraph))
203 }
204 }
205
206 pub fn is_list(&self) -> bool {
207 unsafe { ffi::mgp_value_is_list(self.ptr) != 0 }
208 }
209
210 pub fn make_map(map: &Map, memgraph: &Memgraph) -> MgpResult<MgpValue> {
213 unsafe {
214 let mgp_map = ffi::mgp_map_make_empty(memgraph.memory_ptr());
217 for item in map.iter()? {
218 let mgp_value = match item.value.to_mgp_value(&memgraph) {
219 Ok(v) => v,
220 Err(_) => {
221 ffi::mgp_map_destroy(mgp_map);
222 return Err(MgpError::UnableToMakeMapValue);
223 }
224 };
225 if ffi::mgp_map_insert(mgp_map, item.key.as_ptr(), mgp_value.ptr) == 0 {
226 ffi::mgp_map_destroy(mgp_map);
227 return Err(MgpError::UnableToMakeMapValue);
228 }
229 }
230 let mgp_value = ffi::mgp_value_make_map(mgp_map);
231 if mgp_value.is_null() {
232 ffi::mgp_map_destroy(mgp_map);
233 return Err(MgpError::UnableToMakeMapValue);
234 }
235 Ok(MgpValue::new(mgp_value, &memgraph))
236 }
237 }
238
239 pub fn is_map(&self) -> bool {
240 unsafe { ffi::mgp_value_is_map(self.ptr) != 0 }
241 }
242
243 pub fn make_vertex(vertex: &Vertex, memgraph: &Memgraph) -> MgpResult<MgpValue> {
246 unsafe {
247 let mgp_copy = ffi::mgp_vertex_copy(vertex.mgp_ptr(), memgraph.memory_ptr());
250 if mgp_copy.is_null() {
251 return Err(MgpError::UnableToMakeVertexValue);
252 }
253 let mgp_value = ffi::mgp_value_make_vertex(mgp_copy);
254 if mgp_value.is_null() {
255 ffi::mgp_vertex_destroy(mgp_copy);
256 return Err(MgpError::UnableToMakeVertexValue);
257 }
258 Ok(MgpValue::new(mgp_value, &memgraph))
259 }
260 }
261
262 pub fn is_vertex(&self) -> bool {
263 unsafe { ffi::mgp_value_is_vertex(self.ptr) != 0 }
264 }
265
266 pub fn make_edge(edge: &Edge, memgraph: &Memgraph) -> MgpResult<MgpValue> {
269 unsafe {
270 let mgp_copy = ffi::mgp_edge_copy(edge.mgp_ptr(), memgraph.memory_ptr());
273 if mgp_copy.is_null() {
274 return Err(MgpError::UnableToMakeEdgeValue);
275 }
276 let mgp_value = ffi::mgp_value_make_edge(mgp_copy);
277 if mgp_value.is_null() {
278 ffi::mgp_edge_destroy(mgp_copy);
279 return Err(MgpError::UnableToMakeEdgeValue);
280 }
281 Ok(MgpValue::new(mgp_value, &memgraph))
282 }
283 }
284
285 pub fn is_edge(&self) -> bool {
286 unsafe { ffi::mgp_value_is_edge(self.ptr) != 0 }
287 }
288
289 pub fn make_path(path: &Path, memgraph: &Memgraph) -> MgpResult<MgpValue> {
292 unsafe {
293 let mgp_copy = ffi::mgp_path_copy(path.mgp_ptr(), memgraph.memory_ptr());
296 if mgp_copy.is_null() {
297 return Err(MgpError::UnableToMakePathValue);
298 }
299 let mgp_value = ffi::mgp_value_make_path(mgp_copy);
300 if mgp_value.is_null() {
301 ffi::mgp_path_destroy(mgp_copy);
302 return Err(MgpError::UnableToMakePathValue);
303 }
304 Ok(MgpValue::new(mgp_value, &memgraph))
305 }
306 }
307
308 pub fn is_path(&self) -> bool {
309 unsafe { ffi::mgp_value_is_path(self.ptr) != 0 }
310 }
311}
312
313pub enum Value {
317 Null,
318 Bool(bool),
319 Int(i64),
320 Float(f64),
321 String(CString),
322 Vertex(Vertex),
323 Edge(Edge),
324 Path(Path),
325 List(List),
326 Map(Map),
327}
328
329impl Value {
330 pub fn to_mgp_value(&self, memgraph: &Memgraph) -> MgpResult<MgpValue> {
331 match self {
332 Value::Null => MgpValue::make_null(&memgraph),
333 Value::Bool(x) => MgpValue::make_bool(*x, &memgraph),
334 Value::Int(x) => MgpValue::make_int(*x, &memgraph),
335 Value::Float(x) => MgpValue::make_double(*x, &memgraph),
336 Value::String(x) => MgpValue::make_string(&*x.as_c_str(), &memgraph),
337 Value::List(x) => MgpValue::make_list(&x, &memgraph),
338 Value::Map(x) => MgpValue::make_map(&x, &memgraph),
339 Value::Vertex(x) => MgpValue::make_vertex(&x, &memgraph),
340 Value::Edge(x) => MgpValue::make_edge(&x, &memgraph),
341 Value::Path(x) => MgpValue::make_path(&x, &memgraph),
342 }
343 }
344}
345
346impl From<MgpValue> for Value {
347 fn from(item: MgpValue) -> Self {
348 match item.to_value() {
349 Ok(v) => v,
350 Err(_) => panic!("Unable to create Value from MgpValue."),
351 }
352 }
353}
354
355pub(crate) unsafe fn mgp_raw_value_to_value(
369 value: *const mgp_value,
370 memgraph: &Memgraph,
371) -> MgpResult<Value> {
372 #[allow(non_upper_case_globals)]
373 match ffi::mgp_value_get_type(value) {
374 mgp_value_type_MGP_VALUE_TYPE_NULL => Ok(Value::Null),
375 mgp_value_type_MGP_VALUE_TYPE_BOOL => Ok(Value::Bool(ffi::mgp_value_get_bool(value) == 0)),
376 mgp_value_type_MGP_VALUE_TYPE_INT => Ok(Value::Int(ffi::mgp_value_get_int(value))),
377 mgp_value_type_MGP_VALUE_TYPE_STRING => {
378 let mgp_string = ffi::mgp_value_get_string(value);
379 match create_cstring(mgp_string) {
380 Ok(value) => Ok(Value::String(value)),
381 Err(_) => Err(MgpError::UnableToMakeValueString),
382 }
383 }
384 mgp_value_type_MGP_VALUE_TYPE_DOUBLE => Ok(Value::Float(ffi::mgp_value_get_double(value))),
385 mgp_value_type_MGP_VALUE_TYPE_VERTEX => {
386 let mgp_vertex = ffi::mgp_value_get_vertex(value);
387 Ok(Value::Vertex(Vertex::mgp_copy(mgp_vertex, &memgraph)?))
388 }
389 mgp_value_type_MGP_VALUE_TYPE_EDGE => {
390 let mgp_edge = ffi::mgp_value_get_edge(value);
391 Ok(Value::Edge(Edge::mgp_copy(mgp_edge, &memgraph)?))
392 }
393 mgp_value_type_MGP_VALUE_TYPE_PATH => {
394 let mgp_path = ffi::mgp_value_get_path(value);
395 Ok(Value::Path(Path::mgp_copy(mgp_path, &memgraph)?))
396 }
397 mgp_value_type_MGP_VALUE_TYPE_LIST => {
398 let mgp_list = ffi::mgp_value_get_list(value);
399 Ok(Value::List(List::mgp_copy(mgp_list, &memgraph)?))
400 }
401 mgp_value_type_MGP_VALUE_TYPE_MAP => {
402 let mgp_map = ffi::mgp_value_get_map(value);
403 Ok(Value::Map(Map::mgp_copy(mgp_map, &memgraph)?))
404 }
405 _ => {
406 panic!("Unable to create value object because of uncovered mgp_value type.");
407 }
408 }
409}
410
411#[cfg(test)]
412mod tests;