1use 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#[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 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 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;