rsmgp_sys/edge/
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 edge (relationship) related.
15
16use std::ffi::{CStr, CString};
17
18use crate::memgraph::Memgraph;
19use crate::mgp::*;
20use crate::property::*;
21use crate::result::*;
22use crate::value::*;
23use crate::vertex::Vertex;
24// Required here, if not present tests linking fails.
25#[double]
26use crate::mgp::ffi;
27use mockall_double::double;
28
29pub struct EdgesIterator {
30    ptr: *mut mgp_edges_iterator,
31    is_first: bool,
32    memgraph: Memgraph,
33}
34
35impl EdgesIterator {
36    pub(crate) fn new(ptr: *mut mgp_edges_iterator, memgraph: &Memgraph) -> EdgesIterator {
37        #[cfg(not(test))]
38        assert!(
39            !ptr.is_null(),
40            "Unable to create edges iterator because the given pointer is null."
41        );
42
43        EdgesIterator {
44            ptr,
45            is_first: true,
46            memgraph: memgraph.clone(),
47        }
48    }
49}
50
51impl Drop for EdgesIterator {
52    fn drop(&mut self) {
53        unsafe {
54            if !self.ptr.is_null() {
55                ffi::mgp_edges_iterator_destroy(self.ptr);
56            }
57        }
58    }
59}
60
61impl Iterator for EdgesIterator {
62    type Item = Edge;
63
64    fn next(&mut self) -> Option<Edge> {
65        unsafe {
66            let data = if self.is_first {
67                self.is_first = false;
68                ffi::mgp_edges_iterator_get(self.ptr)
69            } else {
70                ffi::mgp_edges_iterator_next(self.ptr)
71            };
72
73            if data.is_null() {
74                None
75            } else {
76                Some(match Edge::mgp_copy(data, &self.memgraph) {
77                    Ok(v) => v,
78                    Err(_) => panic!("Unable to create edge during edges iteration."),
79                })
80            }
81        }
82    }
83}
84
85pub struct Edge {
86    ptr: *mut mgp_edge,
87    memgraph: Memgraph,
88}
89
90impl Drop for Edge {
91    fn drop(&mut self) {
92        unsafe {
93            if !self.ptr.is_null() {
94                ffi::mgp_edge_destroy(self.ptr);
95            }
96        }
97    }
98}
99
100impl Edge {
101    pub(crate) fn new(ptr: *mut mgp_edge, memgraph: &Memgraph) -> Edge {
102        #[cfg(not(test))]
103        assert!(
104            !ptr.is_null(),
105            "Unable to create edge because the given pointer is null."
106        );
107
108        Edge {
109            ptr,
110            memgraph: memgraph.clone(),
111        }
112    }
113
114    /// Creates a new Edge based on [mgp_edge].
115    pub(crate) unsafe fn mgp_copy(ptr: *const mgp_edge, memgraph: &Memgraph) -> MgpResult<Edge> {
116        #[cfg(not(test))]
117        assert!(
118            !ptr.is_null(),
119            "Unable to create edge copy because the given pointer is null."
120        );
121
122        let mgp_copy = ffi::mgp_edge_copy(ptr, memgraph.memory_ptr());
123        if mgp_copy.is_null() {
124            return Err(MgpError::UnableToCopyEdge);
125        }
126        Ok(Edge::new(mgp_copy, &memgraph))
127    }
128
129    /// Returns the underlying [mgp_edge] pointer.
130    pub(crate) fn mgp_ptr(&self) -> *const mgp_edge {
131        self.ptr
132    }
133
134    pub fn copy(&self) -> MgpResult<Edge> {
135        unsafe { Edge::mgp_copy(self.ptr, &self.memgraph) }
136    }
137
138    pub fn id(&self) -> i64 {
139        unsafe { ffi::mgp_edge_get_id(self.ptr).as_int }
140    }
141
142    pub fn edge_type(&self) -> MgpResult<CString> {
143        unsafe {
144            let mgp_edge_type = ffi::mgp_edge_get_type(self.ptr);
145            create_cstring(mgp_edge_type.name)
146        }
147    }
148
149    pub fn from_vertex(&self) -> MgpResult<Vertex> {
150        unsafe {
151            let mgp_vertex = ffi::mgp_edge_get_from(self.ptr);
152            Vertex::mgp_copy(mgp_vertex, &self.memgraph)
153        }
154    }
155
156    pub fn to_vertex(&self) -> MgpResult<Vertex> {
157        unsafe {
158            let mgp_vertex = ffi::mgp_edge_get_to(self.ptr);
159            Vertex::mgp_copy(mgp_vertex, &self.memgraph)
160        }
161    }
162
163    pub fn property(&self, name: &CStr) -> MgpResult<Property> {
164        unsafe {
165            let mgp_value =
166                ffi::mgp_edge_get_property(self.ptr, name.as_ptr(), self.memgraph.memory_ptr());
167            if mgp_value.is_null() {
168                return Err(MgpError::UnableToReturnEdgePropertyValueAllocationError);
169            }
170            let value = match MgpValue::new(mgp_value, &self.memgraph).to_value() {
171                Ok(v) => v,
172                Err(_) => return Err(MgpError::UnableToReturnEdgePropertyValueCreationError),
173            };
174            match CString::new(name.to_bytes()) {
175                Ok(c_string) => Ok(Property {
176                    name: c_string,
177                    value,
178                }),
179                Err(_) => Err(MgpError::UnableToReturnEdgePropertyNameAllocationError),
180            }
181        }
182    }
183
184    pub fn properties(&self) -> MgpResult<PropertiesIterator> {
185        unsafe {
186            let mgp_iterator = ffi::mgp_edge_iter_properties(self.ptr, self.memgraph.memory_ptr());
187            if mgp_iterator.is_null() {
188                return Err(MgpError::UnableToReturnEdgePropertiesIterator);
189            }
190            Ok(PropertiesIterator::new(mgp_iterator, &self.memgraph))
191        }
192    }
193}
194
195#[cfg(test)]
196mod tests;