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;