use std::ffi::{CStr, CString};
use crate::memgraph::Memgraph;
use crate::mgp::*;
use crate::property::*;
use crate::result::*;
use crate::value::*;
use crate::vertex::Vertex;
#[double]
use crate::mgp::ffi;
use mockall_double::double;
pub struct EdgesIterator {
ptr: *mut mgp_edges_iterator,
is_first: bool,
memgraph: Memgraph,
}
impl EdgesIterator {
pub(crate) fn new(ptr: *mut mgp_edges_iterator, memgraph: &Memgraph) -> EdgesIterator {
#[cfg(not(test))]
assert!(
!ptr.is_null(),
"Unable to create edges iterator because the given pointer is null."
);
EdgesIterator {
ptr,
is_first: true,
memgraph: memgraph.clone(),
}
}
}
impl Drop for EdgesIterator {
fn drop(&mut self) {
unsafe {
if !self.ptr.is_null() {
ffi::mgp_edges_iterator_destroy(self.ptr);
}
}
}
}
impl Iterator for EdgesIterator {
type Item = Edge;
fn next(&mut self) -> Option<Edge> {
unsafe {
let data = if self.is_first {
self.is_first = false;
ffi::mgp_edges_iterator_get(self.ptr)
} else {
ffi::mgp_edges_iterator_next(self.ptr)
};
if data.is_null() {
None
} else {
Some(match Edge::mgp_copy(data, &self.memgraph) {
Ok(v) => v,
Err(_) => panic!("Unable to create edge during edges iteration."),
})
}
}
}
}
pub struct Edge {
ptr: *mut mgp_edge,
memgraph: Memgraph,
}
impl Drop for Edge {
fn drop(&mut self) {
unsafe {
if !self.ptr.is_null() {
ffi::mgp_edge_destroy(self.ptr);
}
}
}
}
impl Edge {
pub(crate) fn new(ptr: *mut mgp_edge, memgraph: &Memgraph) -> Edge {
#[cfg(not(test))]
assert!(
!ptr.is_null(),
"Unable to create edge because the given pointer is null."
);
Edge {
ptr,
memgraph: memgraph.clone(),
}
}
pub(crate) unsafe fn mgp_copy(ptr: *const mgp_edge, memgraph: &Memgraph) -> MgpResult<Edge> {
#[cfg(not(test))]
assert!(
!ptr.is_null(),
"Unable to create edge copy because the given pointer is null."
);
let mgp_copy = ffi::mgp_edge_copy(ptr, memgraph.memory_ptr());
if mgp_copy.is_null() {
return Err(MgpError::UnableToCopyEdge);
}
Ok(Edge::new(mgp_copy, &memgraph))
}
pub(crate) fn mgp_ptr(&self) -> *const mgp_edge {
self.ptr
}
pub fn copy(&self) -> MgpResult<Edge> {
unsafe { Edge::mgp_copy(self.ptr, &self.memgraph) }
}
pub fn id(&self) -> i64 {
unsafe { ffi::mgp_edge_get_id(self.ptr).as_int }
}
pub fn edge_type(&self) -> MgpResult<CString> {
unsafe {
let mgp_edge_type = ffi::mgp_edge_get_type(self.ptr);
create_cstring(mgp_edge_type.name)
}
}
pub fn from_vertex(&self) -> MgpResult<Vertex> {
unsafe {
let mgp_vertex = ffi::mgp_edge_get_from(self.ptr);
Vertex::mgp_copy(mgp_vertex, &self.memgraph)
}
}
pub fn to_vertex(&self) -> MgpResult<Vertex> {
unsafe {
let mgp_vertex = ffi::mgp_edge_get_to(self.ptr);
Vertex::mgp_copy(mgp_vertex, &self.memgraph)
}
}
pub fn property(&self, name: &CStr) -> MgpResult<Property> {
unsafe {
let mgp_value =
ffi::mgp_edge_get_property(self.ptr, name.as_ptr(), self.memgraph.memory_ptr());
if mgp_value.is_null() {
return Err(MgpError::UnableToReturnEdgePropertyValueAllocationError);
}
let value = match MgpValue::new(mgp_value, &self.memgraph).to_value() {
Ok(v) => v,
Err(_) => return Err(MgpError::UnableToReturnEdgePropertyValueCreationError),
};
match CString::new(name.to_bytes()) {
Ok(c_string) => Ok(Property {
name: c_string,
value,
}),
Err(_) => Err(MgpError::UnableToReturnEdgePropertyNameAllocationError),
}
}
}
pub fn properties(&self) -> MgpResult<PropertiesIterator> {
unsafe {
let mgp_iterator = ffi::mgp_edge_iter_properties(self.ptr, self.memgraph.memory_ptr());
if mgp_iterator.is_null() {
return Err(MgpError::UnableToReturnEdgePropertiesIterator);
}
Ok(PropertiesIterator::new(mgp_iterator, &self.memgraph))
}
}
}
#[cfg(test)]
mod tests;