1use crate::memgraph::*;
17use crate::mgp::*;
18use crate::result::*;
19use crate::value::*;
20#[double]
22use crate::mgp::ffi;
23use mockall_double::double;
24
25pub struct List {
28 ptr: *mut mgp_list,
29 memgraph: Memgraph,
30}
31
32impl Drop for List {
33 fn drop(&mut self) {
34 unsafe {
35 if !self.ptr.is_null() {
36 ffi::mgp_list_destroy(self.ptr);
37 }
38 }
39 }
40}
41
42pub struct ListIterator<'a> {
43 list: &'a List,
44 position: u64,
45}
46
47impl<'a> Iterator for ListIterator<'a> {
48 type Item = Value;
49
50 fn next(&mut self) -> Option<Value> {
51 if self.position >= self.list.size() {
52 return None;
53 }
54 let value = match self.list.value_at(self.position) {
55 Ok(v) => v,
56 Err(_) => panic!("Unable to access the next list value."),
57 };
58 self.position += 1;
59 Some(value)
60 }
61}
62
63impl List {
64 pub(crate) fn new(ptr: *mut mgp_list, memgraph: &Memgraph) -> List {
65 #[cfg(not(test))]
66 assert!(
67 !ptr.is_null(),
68 "Unable to create list because the given pointer is null."
69 );
70
71 List {
72 ptr,
73 memgraph: memgraph.clone(),
74 }
75 }
76
77 pub fn make_empty(capacity: u64, memgraph: &Memgraph) -> MgpResult<List> {
78 unsafe {
79 let mgp_ptr = ffi::mgp_list_make_empty(capacity, memgraph.memory_ptr());
80 if mgp_ptr.is_null() {
81 return Err(MgpError::UnableToCreateEmptyList);
82 }
83 Ok(List::new(mgp_ptr, &memgraph))
84 }
85 }
86
87 pub(crate) unsafe fn mgp_copy(ptr: *const mgp_list, memgraph: &Memgraph) -> MgpResult<List> {
89 #[cfg(not(test))]
90 assert!(
91 !ptr.is_null(),
92 "Unable to create list copy because the given pointer is null."
93 );
94
95 let size = ffi::mgp_list_size(ptr);
96 let mgp_copy = ffi::mgp_list_make_empty(size, memgraph.memory_ptr());
97 if mgp_copy.is_null() {
98 return Err(MgpError::UnableToCopyList);
99 }
100 for index in 0..size {
101 let mgp_value = ffi::mgp_list_at(ptr, index);
102 if ffi::mgp_list_append(mgp_copy, mgp_value) == 0 {
103 ffi::mgp_list_destroy(mgp_copy);
104 return Err(MgpError::UnableToCopyList);
105 }
106 }
107 Ok(List::new(mgp_copy, &memgraph))
108 }
109
110 pub fn copy(&self) -> MgpResult<List> {
111 unsafe { List::mgp_copy(self.ptr, &self.memgraph) }
112 }
113
114 pub fn append(&self, value: &Value) -> MgpResult<()> {
116 unsafe {
117 let mgp_value = value.to_mgp_value(&self.memgraph)?;
118 if ffi::mgp_list_append(self.ptr, mgp_value.mgp_ptr()) == 0 {
119 return Err(MgpError::UnableToAppendListValue);
120 }
121 Ok(())
122 }
123 }
124
125 pub fn append_extend(&self, value: &Value) -> MgpResult<()> {
128 unsafe {
129 let mgp_value = value.to_mgp_value(&self.memgraph)?;
130 if ffi::mgp_list_append_extend(self.ptr, mgp_value.mgp_ptr()) == 0 {
131 return Err(MgpError::UnableToAppendExtendListValue);
132 }
133 Ok(())
134 }
135 }
136
137 pub fn size(&self) -> u64 {
138 unsafe { ffi::mgp_list_size(self.ptr) }
139 }
140
141 pub fn capacity(&self) -> u64 {
142 unsafe { ffi::mgp_list_capacity(self.ptr) }
143 }
144
145 pub fn value_at(&self, index: u64) -> MgpResult<Value> {
148 unsafe {
149 let c_value = ffi::mgp_list_at(self.ptr, index);
150 if c_value.is_null() {
151 return Err(MgpError::UnableToAccessListValueByIndex);
152 }
153 mgp_raw_value_to_value(c_value, &self.memgraph)
154 }
155 }
156
157 pub fn iter(&self) -> MgpResult<ListIterator> {
158 Ok(ListIterator {
159 list: self,
160 position: 0,
161 })
162 }
163}
164
165#[cfg(test)]
166mod tests;