use crate::memgraph::*;
use crate::mgp::*;
use crate::result::*;
use crate::value::*;
#[double]
use crate::mgp::ffi;
use mockall_double::double;
pub struct List {
ptr: *mut mgp_list,
memgraph: Memgraph,
}
impl Drop for List {
fn drop(&mut self) {
unsafe {
if !self.ptr.is_null() {
ffi::mgp_list_destroy(self.ptr);
}
}
}
}
pub struct ListIterator<'a> {
list: &'a List,
position: u64,
}
impl<'a> Iterator for ListIterator<'a> {
type Item = Value;
fn next(&mut self) -> Option<Value> {
if self.position >= self.list.size() {
return None;
}
let value = match self.list.value_at(self.position) {
Ok(v) => v,
Err(_) => panic!("Unable to access the next list value."),
};
self.position += 1;
Some(value)
}
}
impl List {
pub(crate) fn new(ptr: *mut mgp_list, memgraph: &Memgraph) -> List {
#[cfg(not(test))]
assert!(
!ptr.is_null(),
"Unable to create list because the given pointer is null."
);
List {
ptr,
memgraph: memgraph.clone(),
}
}
pub fn make_empty(capacity: u64, memgraph: &Memgraph) -> MgpResult<List> {
unsafe {
let mgp_ptr = ffi::mgp_list_make_empty(capacity, memgraph.memory_ptr());
if mgp_ptr.is_null() {
return Err(MgpError::UnableToCreateEmptyList);
}
Ok(List::new(mgp_ptr, &memgraph))
}
}
pub(crate) unsafe fn mgp_copy(ptr: *const mgp_list, memgraph: &Memgraph) -> MgpResult<List> {
#[cfg(not(test))]
assert!(
!ptr.is_null(),
"Unable to create list copy because the given pointer is null."
);
let size = ffi::mgp_list_size(ptr);
let mgp_copy = ffi::mgp_list_make_empty(size, memgraph.memory_ptr());
if mgp_copy.is_null() {
return Err(MgpError::UnableToCopyList);
}
for index in 0..size {
let mgp_value = ffi::mgp_list_at(ptr, index);
if ffi::mgp_list_append(mgp_copy, mgp_value) == 0 {
ffi::mgp_list_destroy(mgp_copy);
return Err(MgpError::UnableToCopyList);
}
}
Ok(List::new(mgp_copy, &memgraph))
}
pub fn copy(&self) -> MgpResult<List> {
unsafe { List::mgp_copy(self.ptr, &self.memgraph) }
}
pub fn append(&self, value: &Value) -> MgpResult<()> {
unsafe {
let mgp_value = value.to_mgp_value(&self.memgraph)?;
if ffi::mgp_list_append(self.ptr, mgp_value.mgp_ptr()) == 0 {
return Err(MgpError::UnableToAppendListValue);
}
Ok(())
}
}
pub fn append_extend(&self, value: &Value) -> MgpResult<()> {
unsafe {
let mgp_value = value.to_mgp_value(&self.memgraph)?;
if ffi::mgp_list_append_extend(self.ptr, mgp_value.mgp_ptr()) == 0 {
return Err(MgpError::UnableToAppendExtendListValue);
}
Ok(())
}
}
pub fn size(&self) -> u64 {
unsafe { ffi::mgp_list_size(self.ptr) }
}
pub fn capacity(&self) -> u64 {
unsafe { ffi::mgp_list_capacity(self.ptr) }
}
pub fn value_at(&self, index: u64) -> MgpResult<Value> {
unsafe {
let c_value = ffi::mgp_list_at(self.ptr, index);
if c_value.is_null() {
return Err(MgpError::UnableToAccessListValueByIndex);
}
mgp_raw_value_to_value(c_value, &self.memgraph)
}
}
pub fn iter(&self) -> MgpResult<ListIterator> {
Ok(ListIterator {
list: self,
position: 0,
})
}
}
#[cfg(test)]
mod tests;