rsmgp_sys/property/mod.rs
1// Copyright (c) 2016-2021 Memgraph Ltd. [https://memgraph.com]
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//! All related to the property graph property (data key-value pair).
15
16use std::ffi::CString;
17
18use crate::memgraph::*;
19use crate::mgp::*;
20use crate::value::*;
21// Required here, if not present tests linking fails.
22#[double]
23use crate::mgp::ffi;
24use mockall_double::double;
25
26/// All related to the property graph property (data key-value pair).
27///
28/// Property is used in the following contexts:
29/// * return Property from [PropertiesIterator]
30/// * return Property directly from [crate::vertex::Vertex] or [crate::edge::Edge].
31///
32/// Property owns [CString] and [Value] bacause the underlying C string or value could be deleted
33/// during the lifetime of the property. In other words, Property stores copies of underlying name
34/// and value.
35pub struct Property {
36 pub name: CString,
37 pub value: Value,
38}
39
40pub struct PropertiesIterator {
41 ptr: *mut mgp_properties_iterator,
42 is_first: bool,
43 memgraph: Memgraph,
44}
45
46impl PropertiesIterator {
47 pub(crate) fn new(
48 ptr: *mut mgp_properties_iterator,
49 memgraph: &Memgraph,
50 ) -> PropertiesIterator {
51 #[cfg(not(test))]
52 assert!(
53 !ptr.is_null(),
54 "Unable to create properties iterator because the given pointer is null."
55 );
56
57 PropertiesIterator {
58 ptr,
59 is_first: true,
60 memgraph: memgraph.clone(),
61 }
62 }
63}
64
65impl Drop for PropertiesIterator {
66 fn drop(&mut self) {
67 unsafe {
68 if !self.ptr.is_null() {
69 ffi::mgp_properties_iterator_destroy(self.ptr);
70 }
71 }
72 }
73}
74
75impl Iterator for PropertiesIterator {
76 type Item = Property;
77
78 fn next(&mut self) -> Option<Property> {
79 unsafe {
80 let data = if self.is_first {
81 self.is_first = false;
82 ffi::mgp_properties_iterator_get(self.ptr)
83 } else {
84 ffi::mgp_properties_iterator_next(self.ptr)
85 };
86
87 if data.is_null() {
88 None
89 } else {
90 // Unwrap/panic is I think the only option here because if something fails the
91 // whole procedure should be stopped. Returning empty Option is not an option
92 // because it's not correct. The same applies in case of the property value.
93 let data_ref = data.as_ref().unwrap();
94 Some(Property {
95 name: match create_cstring(data_ref.name) {
96 Ok(v) => v,
97 Err(_) => panic!("Unable to provide next property. Name creation problem."),
98 },
99 value: match mgp_raw_value_to_value(data_ref.value, &self.memgraph) {
100 Ok(v) => v,
101 Err(_) => panic!("Unable to provide next property. Value create problem."),
102 },
103 })
104 }
105 }
106 }
107}
108
109#[cfg(test)]
110mod tests;