Skip to main content

graphrecords_python/graphrecord/querying/
mod.rs

1pub mod attributes;
2pub mod edges;
3pub mod nodes;
4pub mod values;
5
6use super::{
7    Lut, PyNodeIndex, attribute::PyGraphRecordAttribute, errors::PyGraphRecordError,
8    traits::DeepFrom, value::PyGraphRecordValue,
9};
10use crate::{
11    conversion_lut::ConversionLut,
12    graphrecord::querying::{
13        attributes::{
14            PyEdgeSingleAttributeWithoutIndexGroupOperand,
15            PyNodeSingleAttributeWithoutIndexGroupOperand,
16        },
17        edges::{PyEdgeIndexGroupOperand, PyEdgeIndicesGroupOperand},
18        nodes::{PyNodeIndexGroupOperand, PyNodeIndicesGroupOperand},
19        values::{
20            PyEdgeSingleValueWithoutIndexGroupOperand, PyNodeSingleValueWithoutIndexGroupOperand,
21        },
22    },
23};
24use attributes::{
25    PyEdgeAttributesTreeGroupOperand, PyEdgeAttributesTreeOperand,
26    PyEdgeMultipleAttributesWithIndexGroupOperand, PyEdgeMultipleAttributesWithIndexOperand,
27    PyEdgeMultipleAttributesWithoutIndexOperand, PyEdgeSingleAttributeWithIndexGroupOperand,
28    PyEdgeSingleAttributeWithIndexOperand, PyEdgeSingleAttributeWithoutIndexOperand,
29    PyNodeAttributesTreeGroupOperand, PyNodeAttributesTreeOperand,
30    PyNodeMultipleAttributesWithIndexGroupOperand, PyNodeMultipleAttributesWithIndexOperand,
31    PyNodeMultipleAttributesWithoutIndexOperand, PyNodeSingleAttributeWithIndexGroupOperand,
32    PyNodeSingleAttributeWithIndexOperand, PyNodeSingleAttributeWithoutIndexOperand,
33};
34use edges::{PyEdgeIndexOperand, PyEdgeIndicesOperand};
35use graphrecords_core::{
36    GraphRecord,
37    errors::{GraphRecordError, GraphRecordResult},
38    graphrecord::{
39        GraphRecordAttribute,
40        querying::{
41            ReturnOperand,
42            attributes::{
43                EdgeAttributesTreeOperand, EdgeMultipleAttributesWithIndexOperand,
44                EdgeMultipleAttributesWithoutIndexOperand, EdgeSingleAttributeWithIndexOperand,
45                EdgeSingleAttributeWithoutIndexOperand, NodeAttributesTreeOperand,
46                NodeMultipleAttributesWithIndexOperand, NodeMultipleAttributesWithoutIndexOperand,
47                NodeSingleAttributeWithIndexOperand, NodeSingleAttributeWithoutIndexOperand,
48            },
49            edges::{EdgeIndexOperand, EdgeIndicesOperand},
50            group_by::{GroupKey, GroupOperand},
51            nodes::{NodeIndexOperand, NodeIndicesOperand},
52            values::{
53                EdgeMultipleValuesWithIndexOperand, EdgeMultipleValuesWithoutIndexOperand,
54                EdgeSingleValueWithIndexOperand, EdgeSingleValueWithoutIndexOperand,
55                NodeMultipleValuesWithIndexOperand, NodeMultipleValuesWithoutIndexOperand,
56                NodeSingleValueWithIndexOperand, NodeSingleValueWithoutIndexOperand,
57            },
58            wrapper::{CardinalityWrapper, MatchMode, Wrapper},
59        },
60    },
61};
62use nodes::{PyNodeIndexOperand, PyNodeIndicesOperand};
63use pyo3::{
64    Borrowed, Bound, FromPyObject, IntoPyObject, IntoPyObjectExt, PyAny, PyErr, PyResult, Python,
65    pyclass,
66    types::{PyAnyMethods, PyList},
67};
68use std::collections::HashMap;
69use values::{
70    PyEdgeMultipleValuesWithIndexGroupOperand, PyEdgeMultipleValuesWithIndexOperand,
71    PyEdgeMultipleValuesWithoutIndexOperand, PyEdgeSingleValueWithIndexGroupOperand,
72    PyEdgeSingleValueWithIndexOperand, PyEdgeSingleValueWithoutIndexOperand,
73    PyNodeMultipleValuesWithIndexGroupOperand, PyNodeMultipleValuesWithIndexOperand,
74    PyNodeMultipleValuesWithoutIndexOperand, PyNodeSingleValueWithIndexGroupOperand,
75    PyNodeSingleValueWithIndexOperand, PyNodeSingleValueWithoutIndexOperand,
76};
77
78#[pyclass(frozen)]
79#[derive(Debug, Clone, Copy)]
80pub enum PyMatchMode {
81    Any,
82    All,
83}
84
85impl From<MatchMode> for PyMatchMode {
86    fn from(mode: MatchMode) -> Self {
87        match mode {
88            MatchMode::Any => Self::Any,
89            MatchMode::All => Self::All,
90        }
91    }
92}
93
94impl From<PyMatchMode> for MatchMode {
95    fn from(mode: PyMatchMode) -> Self {
96        match mode {
97            PyMatchMode::Any => Self::Any,
98            PyMatchMode::All => Self::All,
99        }
100    }
101}
102
103#[derive(Debug, Clone)]
104pub enum PyGroupKey {
105    NodeIndex(PyNodeIndex),
106    Value(PyGraphRecordValue),
107    OptionalValue(Option<PyGraphRecordValue>),
108    TupleKey((Box<Self>, Box<Self>)),
109}
110
111impl From<GroupKey<'_>> for PyGroupKey {
112    fn from(key: GroupKey<'_>) -> Self {
113        match key {
114            GroupKey::NodeIndex(index) => Self::NodeIndex(PyNodeIndex::from(index.clone())),
115            GroupKey::Value(value) => Self::Value(PyGraphRecordValue::from(value.clone())),
116            GroupKey::OptionalValue(value) => {
117                Self::OptionalValue(value.cloned().map(PyGraphRecordValue::from))
118            }
119            GroupKey::TupleKey((left, right)) => {
120                Self::TupleKey((Box::new(Self::from(*left)), Box::new(Self::from(*right))))
121            }
122        }
123    }
124}
125
126impl<'py> IntoPyObject<'py> for PyGroupKey {
127    type Target = pyo3::PyAny;
128    type Output = Bound<'py, Self::Target>;
129    type Error = PyErr;
130
131    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
132        match self {
133            Self::NodeIndex(index) => index.into_pyobject(py),
134            Self::Value(value) => value.into_pyobject(py),
135            Self::OptionalValue(value) => value.into_pyobject(py),
136            Self::TupleKey((left, right)) => {
137                let left = left.into_pyobject(py)?;
138                let right = right.into_pyobject(py)?;
139                (left, right).into_bound_py_any(py)
140            }
141        }
142    }
143}
144
145pub enum PyReturnOperand {
146    NodeAttributesTree(PyNodeAttributesTreeOperand),
147    NodeAttributesTreeGroup(PyNodeAttributesTreeGroupOperand),
148    EdgeAttributesTree(PyEdgeAttributesTreeOperand),
149    EdgeAttributesTreeGroup(PyEdgeAttributesTreeGroupOperand),
150    NodeMultipleAttributesWithIndex(PyNodeMultipleAttributesWithIndexOperand),
151    NodeMultipleAttributesWithIndexGroup(PyNodeMultipleAttributesWithIndexGroupOperand),
152    NodeMultipleAttributesWithoutIndex(PyNodeMultipleAttributesWithoutIndexOperand),
153    EdgeMultipleAttributesWithIndex(PyEdgeMultipleAttributesWithIndexOperand),
154    EdgeMultipleAttributesWithIndexGroup(PyEdgeMultipleAttributesWithIndexGroupOperand),
155    EdgeMultipleAttributesWithoutIndex(PyEdgeMultipleAttributesWithoutIndexOperand),
156    NodeSingleAttributeWithIndex(PyNodeSingleAttributeWithIndexOperand),
157    NodeSingleAttributeWithIndexGroup(PyNodeSingleAttributeWithIndexGroupOperand),
158    NodeSingleAttributeWithoutIndex(PyNodeSingleAttributeWithoutIndexOperand),
159    NodeSingleAttributeWithoutIndexGroup(PyNodeSingleAttributeWithoutIndexGroupOperand),
160    EdgeSingleAttributeWithIndex(PyEdgeSingleAttributeWithIndexOperand),
161    EdgeSingleAttributeWithIndexGroup(PyEdgeSingleAttributeWithIndexGroupOperand),
162    EdgeSingleAttributeWithoutIndex(PyEdgeSingleAttributeWithoutIndexOperand),
163    EdgeSingleAttributeWithoutIndexGroup(PyEdgeSingleAttributeWithoutIndexGroupOperand),
164    EdgeIndices(PyEdgeIndicesOperand),
165    EdgeIndicesGroup(PyEdgeIndicesGroupOperand),
166    EdgeIndex(PyEdgeIndexOperand),
167    EdgeIndexGroup(PyEdgeIndexGroupOperand),
168    NodeIndices(PyNodeIndicesOperand),
169    NodeIndicesGroup(PyNodeIndicesGroupOperand),
170    NodeIndex(PyNodeIndexOperand),
171    NodeIndexGroup(PyNodeIndexGroupOperand),
172    NodeMultipleValuesWithIndex(PyNodeMultipleValuesWithIndexOperand),
173    NodeMultipleValuesWithIndexGroup(PyNodeMultipleValuesWithIndexGroupOperand),
174    NodeMultipleValuesWithoutIndex(PyNodeMultipleValuesWithoutIndexOperand),
175    EdgeMultipleValuesWithIndex(PyEdgeMultipleValuesWithIndexOperand),
176    EdgeMultipleValuesWithIndexGroup(PyEdgeMultipleValuesWithIndexGroupOperand),
177    EdgeMultipleValuesWithoutIndex(PyEdgeMultipleValuesWithoutIndexOperand),
178    NodeSingleValueWithIndex(PyNodeSingleValueWithIndexOperand),
179    NodeSingleValueWithIndexGroup(PyNodeSingleValueWithIndexGroupOperand),
180    NodeSingleValueWithoutIndex(PyNodeSingleValueWithoutIndexOperand),
181    NodeSingleValueWithoutIndexGroup(PyNodeSingleValueWithoutIndexGroupOperand),
182    EdgeSingleValueWithIndex(PyEdgeSingleValueWithIndexOperand),
183    EdgeSingleValueWithIndexGroup(PyEdgeSingleValueWithIndexGroupOperand),
184    EdgeSingleValueWithoutIndex(PyEdgeSingleValueWithoutIndexOperand),
185    EdgeSingleValueWithoutIndexGroup(PyEdgeSingleValueWithoutIndexGroupOperand),
186    Vector(Vec<Self>),
187}
188
189impl<'a> ReturnOperand<'a> for PyReturnOperand {
190    type ReturnValue = PyReturnValue<'a>;
191
192    #[allow(clippy::too_many_lines)]
193    fn evaluate(&self, graphrecord: &'a GraphRecord) -> GraphRecordResult<Self::ReturnValue> {
194        match self {
195            Self::NodeAttributesTree(operand) => operand
196                .evaluate(graphrecord)
197                .map(PyReturnValue::NodeAttributesTree),
198            Self::NodeAttributesTreeGroup(operand) => operand
199                .evaluate(graphrecord)
200                .map(PyReturnValue::NodeAttributesTreeGroup),
201            Self::EdgeAttributesTree(operand) => operand
202                .evaluate(graphrecord)
203                .map(PyReturnValue::EdgeAttributesTree),
204            Self::EdgeAttributesTreeGroup(operand) => operand
205                .evaluate(graphrecord)
206                .map(PyReturnValue::EdgeAttributesTreeGroup),
207            Self::NodeMultipleAttributesWithIndex(operand) => operand
208                .evaluate(graphrecord)
209                .map(PyReturnValue::NodeMultipleAttributesWithIndex),
210            Self::NodeMultipleAttributesWithIndexGroup(operand) => operand
211                .evaluate(graphrecord)
212                .map(PyReturnValue::NodeMultipleAttributesWithIndexGroup),
213            Self::NodeMultipleAttributesWithoutIndex(operand) => operand
214                .evaluate(graphrecord)
215                .map(PyReturnValue::NodeMultipleAttributesWithoutIndex),
216            Self::EdgeMultipleAttributesWithIndex(operand) => operand
217                .evaluate(graphrecord)
218                .map(PyReturnValue::EdgeMultipleAttributesWithIndex),
219            Self::EdgeMultipleAttributesWithIndexGroup(operand) => operand
220                .evaluate(graphrecord)
221                .map(PyReturnValue::EdgeMultipleAttributesWithIndexGroup),
222            Self::EdgeMultipleAttributesWithoutIndex(operand) => operand
223                .evaluate(graphrecord)
224                .map(PyReturnValue::EdgeMultipleAttributesWithoutIndex),
225            Self::NodeSingleAttributeWithIndex(operand) => operand
226                .evaluate(graphrecord)
227                .map(PyReturnValue::NodeSingleAttributeWithIndex),
228            Self::NodeSingleAttributeWithIndexGroup(operand) => operand
229                .evaluate(graphrecord)
230                .map(PyReturnValue::NodeSingleAttributeWithIndexGroup),
231            Self::NodeSingleAttributeWithoutIndex(operand) => operand
232                .evaluate(graphrecord)
233                .map(PyReturnValue::NodeSingleAttributeWithoutIndex),
234            Self::NodeSingleAttributeWithoutIndexGroup(operand) => operand
235                .evaluate(graphrecord)
236                .map(PyReturnValue::NodeSingleAttributeWithoutIndexGroup),
237            Self::EdgeSingleAttributeWithIndex(operand) => operand
238                .evaluate(graphrecord)
239                .map(PyReturnValue::EdgeSingleAttributeWithIndex),
240            Self::EdgeSingleAttributeWithIndexGroup(operand) => operand
241                .evaluate(graphrecord)
242                .map(PyReturnValue::EdgeSingleAttributeWithIndexGroup),
243            Self::EdgeSingleAttributeWithoutIndex(operand) => operand
244                .evaluate(graphrecord)
245                .map(PyReturnValue::EdgeSingleAttributeWithoutIndex),
246            Self::EdgeSingleAttributeWithoutIndexGroup(operand) => operand
247                .evaluate(graphrecord)
248                .map(PyReturnValue::EdgeSingleAttributeWithoutIndexGroup),
249            Self::EdgeIndices(operand) => operand
250                .evaluate(graphrecord)
251                .map(PyReturnValue::EdgeIndices),
252            Self::EdgeIndicesGroup(operand) => operand
253                .evaluate(graphrecord)
254                .map(PyReturnValue::EdgeIndicesGroup),
255            Self::EdgeIndex(operand) => operand.evaluate(graphrecord).map(PyReturnValue::EdgeIndex),
256            Self::EdgeIndexGroup(operand) => operand
257                .evaluate(graphrecord)
258                .map(PyReturnValue::EdgeIndexGroup),
259            Self::NodeIndices(operand) => operand
260                .evaluate(graphrecord)
261                .map(PyReturnValue::NodeIndices),
262            Self::NodeIndicesGroup(operand) => operand
263                .evaluate(graphrecord)
264                .map(PyReturnValue::NodeIndicesGroup),
265            Self::NodeIndex(operand) => operand.evaluate(graphrecord).map(PyReturnValue::NodeIndex),
266            Self::NodeIndexGroup(operand) => operand
267                .evaluate(graphrecord)
268                .map(PyReturnValue::NodeIndexGroup),
269            Self::NodeMultipleValuesWithIndex(operand) => operand
270                .evaluate(graphrecord)
271                .map(PyReturnValue::NodeMultipleValuesWithIndex),
272            Self::NodeMultipleValuesWithIndexGroup(operand) => operand
273                .evaluate(graphrecord)
274                .map(PyReturnValue::NodeMultipleValuesWithIndexGroup),
275            Self::NodeMultipleValuesWithoutIndex(operand) => operand
276                .evaluate(graphrecord)
277                .map(PyReturnValue::NodeMultipleValuesWithoutIndex),
278            Self::EdgeMultipleValuesWithIndex(operand) => operand
279                .evaluate(graphrecord)
280                .map(PyReturnValue::EdgeMultipleValuesWithIndex),
281            Self::EdgeMultipleValuesWithIndexGroup(operand) => operand
282                .evaluate(graphrecord)
283                .map(PyReturnValue::EdgeMultipleValuesWithIndexGroup),
284            Self::EdgeMultipleValuesWithoutIndex(operand) => operand
285                .evaluate(graphrecord)
286                .map(PyReturnValue::EdgeMultipleValuesWithoutIndex),
287            Self::NodeSingleValueWithIndex(operand) => operand
288                .evaluate(graphrecord)
289                .map(PyReturnValue::NodeSingleValueWithIndex),
290            Self::NodeSingleValueWithIndexGroup(operand) => operand
291                .evaluate(graphrecord)
292                .map(PyReturnValue::NodeSingleValueWithIndexGroup),
293            Self::NodeSingleValueWithoutIndex(operand) => operand
294                .evaluate(graphrecord)
295                .map(PyReturnValue::NodeSingleValueWithoutIndex),
296            Self::NodeSingleValueWithoutIndexGroup(operand) => operand
297                .evaluate(graphrecord)
298                .map(PyReturnValue::NodeSingleValueWithoutIndexGroup),
299            Self::EdgeSingleValueWithIndex(operand) => operand
300                .evaluate(graphrecord)
301                .map(PyReturnValue::EdgeSingleValueWithIndex),
302            Self::EdgeSingleValueWithIndexGroup(operand) => operand
303                .evaluate(graphrecord)
304                .map(PyReturnValue::EdgeSingleValueWithIndexGroup),
305            Self::EdgeSingleValueWithoutIndex(operand) => operand
306                .evaluate(graphrecord)
307                .map(PyReturnValue::EdgeSingleValueWithoutIndex),
308            Self::EdgeSingleValueWithoutIndexGroup(operand) => operand
309                .evaluate(graphrecord)
310                .map(PyReturnValue::EdgeSingleValueWithoutIndexGroup),
311            Self::Vector(operand) => operand
312                .iter()
313                .map(|item| item.evaluate(graphrecord))
314                .collect::<GraphRecordResult<Vec<_>>>()
315                .map(PyReturnValue::Vector),
316        }
317    }
318}
319
320static RETURNOPERAND_CONVERSION_LUT: Lut<PyReturnOperand> = ConversionLut::new();
321
322#[allow(clippy::unnecessary_wraps, clippy::too_many_lines)]
323pub(crate) fn convert_pyobject_to_pyreturnoperand(
324    ob: &Bound<'_, PyAny>,
325) -> PyResult<PyReturnOperand> {
326    fn convert_py_node_attributes_tree_operand(ob: &Bound<'_, PyAny>) -> PyResult<PyReturnOperand> {
327        Ok(PyReturnOperand::NodeAttributesTree(
328            ob.extract::<PyNodeAttributesTreeOperand>()
329                .expect("Extraction must succeed"),
330        ))
331    }
332    fn convert_py_node_attributes_tree_group_operand(
333        ob: &Bound<'_, PyAny>,
334    ) -> PyResult<PyReturnOperand> {
335        Ok(PyReturnOperand::NodeAttributesTreeGroup(
336            ob.extract::<PyNodeAttributesTreeGroupOperand>()
337                .expect("Extraction must succeed"),
338        ))
339    }
340
341    fn convert_py_edge_attributes_tree_operand(ob: &Bound<'_, PyAny>) -> PyResult<PyReturnOperand> {
342        Ok(PyReturnOperand::EdgeAttributesTree(
343            ob.extract::<PyEdgeAttributesTreeOperand>()
344                .expect("Extraction must succeed"),
345        ))
346    }
347
348    fn convert_py_edge_attributes_tree_group_operand(
349        ob: &Bound<'_, PyAny>,
350    ) -> PyResult<PyReturnOperand> {
351        Ok(PyReturnOperand::EdgeAttributesTreeGroup(
352            ob.extract::<PyEdgeAttributesTreeGroupOperand>()
353                .expect("Extraction must succeed"),
354        ))
355    }
356
357    fn convert_py_node_multiple_attributes_with_index_operand(
358        ob: &Bound<'_, PyAny>,
359    ) -> PyResult<PyReturnOperand> {
360        Ok(PyReturnOperand::NodeMultipleAttributesWithIndex(
361            ob.extract::<PyNodeMultipleAttributesWithIndexOperand>()
362                .expect("Extraction must succeed"),
363        ))
364    }
365
366    fn convert_py_node_multiple_attributes_with_index_group_operand(
367        ob: &Bound<'_, PyAny>,
368    ) -> PyResult<PyReturnOperand> {
369        Ok(PyReturnOperand::NodeMultipleAttributesWithIndexGroup(
370            ob.extract::<PyNodeMultipleAttributesWithIndexGroupOperand>()
371                .expect("Extraction must succeed"),
372        ))
373    }
374
375    fn convert_py_node_multiple_attributes_without_index_operand(
376        ob: &Bound<'_, PyAny>,
377    ) -> PyResult<PyReturnOperand> {
378        Ok(PyReturnOperand::NodeMultipleAttributesWithoutIndex(
379            ob.extract::<PyNodeMultipleAttributesWithoutIndexOperand>()
380                .expect("Extraction must succeed"),
381        ))
382    }
383
384    fn convert_py_edge_multiple_attributes_with_index_operand(
385        ob: &Bound<'_, PyAny>,
386    ) -> PyResult<PyReturnOperand> {
387        Ok(PyReturnOperand::EdgeMultipleAttributesWithIndex(
388            ob.extract::<PyEdgeMultipleAttributesWithIndexOperand>()
389                .expect("Extraction must succeed"),
390        ))
391    }
392
393    fn convert_py_edge_multiple_attributes_with_index_group_operand(
394        ob: &Bound<'_, PyAny>,
395    ) -> PyResult<PyReturnOperand> {
396        Ok(PyReturnOperand::EdgeMultipleAttributesWithIndexGroup(
397            ob.extract::<PyEdgeMultipleAttributesWithIndexGroupOperand>()
398                .expect("Extraction must succeed"),
399        ))
400    }
401
402    fn convert_py_edge_multiple_attributes_without_index_operand(
403        ob: &Bound<'_, PyAny>,
404    ) -> PyResult<PyReturnOperand> {
405        Ok(PyReturnOperand::EdgeMultipleAttributesWithoutIndex(
406            ob.extract::<PyEdgeMultipleAttributesWithoutIndexOperand>()
407                .expect("Extraction must succeed"),
408        ))
409    }
410
411    fn convert_py_node_single_attribute_with_index_operand(
412        ob: &Bound<'_, PyAny>,
413    ) -> PyResult<PyReturnOperand> {
414        Ok(PyReturnOperand::NodeSingleAttributeWithIndex(
415            ob.extract::<PyNodeSingleAttributeWithIndexOperand>()
416                .expect("Extraction must succeed"),
417        ))
418    }
419
420    fn convert_py_node_single_attribute_with_index_group_operand(
421        ob: &Bound<'_, PyAny>,
422    ) -> PyResult<PyReturnOperand> {
423        Ok(PyReturnOperand::NodeSingleAttributeWithIndexGroup(
424            ob.extract::<PyNodeSingleAttributeWithIndexGroupOperand>()
425                .expect("Extraction must succeed"),
426        ))
427    }
428
429    fn convert_py_node_single_attribute_without_index_operand(
430        ob: &Bound<'_, PyAny>,
431    ) -> PyResult<PyReturnOperand> {
432        Ok(PyReturnOperand::NodeSingleAttributeWithoutIndex(
433            ob.extract::<PyNodeSingleAttributeWithoutIndexOperand>()
434                .expect("Extraction must succeed"),
435        ))
436    }
437
438    fn convert_py_node_single_attribute_without_index_group_operand(
439        ob: &Bound<'_, PyAny>,
440    ) -> PyResult<PyReturnOperand> {
441        Ok(PyReturnOperand::NodeSingleAttributeWithoutIndexGroup(
442            ob.extract::<PyNodeSingleAttributeWithoutIndexGroupOperand>()
443                .expect("Extraction must succeed"),
444        ))
445    }
446
447    fn convert_py_edge_single_attribute_with_index_operand(
448        ob: &Bound<'_, PyAny>,
449    ) -> PyResult<PyReturnOperand> {
450        Ok(PyReturnOperand::EdgeSingleAttributeWithIndex(
451            ob.extract::<PyEdgeSingleAttributeWithIndexOperand>()
452                .expect("Extraction must succeed"),
453        ))
454    }
455
456    fn convert_py_edge_single_attribute_with_index_group_operand(
457        ob: &Bound<'_, PyAny>,
458    ) -> PyResult<PyReturnOperand> {
459        Ok(PyReturnOperand::EdgeSingleAttributeWithIndexGroup(
460            ob.extract::<PyEdgeSingleAttributeWithIndexGroupOperand>()
461                .expect("Extraction must succeed"),
462        ))
463    }
464
465    fn convert_py_edge_single_attribute_without_index_operand(
466        ob: &Bound<'_, PyAny>,
467    ) -> PyResult<PyReturnOperand> {
468        Ok(PyReturnOperand::EdgeSingleAttributeWithoutIndex(
469            ob.extract::<PyEdgeSingleAttributeWithoutIndexOperand>()
470                .expect("Extraction must succeed"),
471        ))
472    }
473
474    fn convert_py_edge_single_attribute_without_index_group_operand(
475        ob: &Bound<'_, PyAny>,
476    ) -> PyResult<PyReturnOperand> {
477        Ok(PyReturnOperand::EdgeSingleAttributeWithoutIndexGroup(
478            ob.extract::<PyEdgeSingleAttributeWithoutIndexGroupOperand>()
479                .expect("Extraction must succeed"),
480        ))
481    }
482
483    fn convert_py_edge_indices_operand(ob: &Bound<'_, PyAny>) -> PyResult<PyReturnOperand> {
484        Ok(PyReturnOperand::EdgeIndices(
485            ob.extract::<PyEdgeIndicesOperand>()
486                .expect("Extraction must succeed"),
487        ))
488    }
489
490    fn convert_py_edge_indices_group_operand(ob: &Bound<'_, PyAny>) -> PyResult<PyReturnOperand> {
491        Ok(PyReturnOperand::EdgeIndicesGroup(
492            ob.extract::<PyEdgeIndicesGroupOperand>()
493                .expect("Extraction must succeed"),
494        ))
495    }
496
497    fn convert_py_edge_index_operand(ob: &Bound<'_, PyAny>) -> PyResult<PyReturnOperand> {
498        Ok(PyReturnOperand::EdgeIndex(
499            ob.extract::<PyEdgeIndexOperand>()
500                .expect("Extraction must succeed"),
501        ))
502    }
503
504    fn convert_py_edge_index_group_operand(ob: &Bound<'_, PyAny>) -> PyResult<PyReturnOperand> {
505        Ok(PyReturnOperand::EdgeIndexGroup(
506            ob.extract::<PyEdgeIndexGroupOperand>()
507                .expect("Extraction must succeed"),
508        ))
509    }
510
511    fn convert_py_node_indices_operand(ob: &Bound<'_, PyAny>) -> PyResult<PyReturnOperand> {
512        Ok(PyReturnOperand::NodeIndices(
513            ob.extract::<PyNodeIndicesOperand>()
514                .expect("Extraction must succeed"),
515        ))
516    }
517
518    fn convert_py_node_indices_group_operand(ob: &Bound<'_, PyAny>) -> PyResult<PyReturnOperand> {
519        Ok(PyReturnOperand::NodeIndicesGroup(
520            ob.extract::<PyNodeIndicesGroupOperand>()
521                .expect("Extraction must succeed"),
522        ))
523    }
524
525    fn convert_py_node_index_operand(ob: &Bound<'_, PyAny>) -> PyResult<PyReturnOperand> {
526        Ok(PyReturnOperand::NodeIndex(
527            ob.extract::<PyNodeIndexOperand>()
528                .expect("Extraction must succeed"),
529        ))
530    }
531
532    fn convert_py_node_index_group_operand(ob: &Bound<'_, PyAny>) -> PyResult<PyReturnOperand> {
533        Ok(PyReturnOperand::NodeIndexGroup(
534            ob.extract::<PyNodeIndexGroupOperand>()
535                .expect("Extraction must succeed"),
536        ))
537    }
538
539    fn convert_py_node_multiple_values_with_index_operand(
540        ob: &Bound<'_, PyAny>,
541    ) -> PyResult<PyReturnOperand> {
542        Ok(PyReturnOperand::NodeMultipleValuesWithIndex(
543            ob.extract::<PyNodeMultipleValuesWithIndexOperand>()
544                .expect("Extraction must succeed"),
545        ))
546    }
547
548    fn convert_py_node_multiple_values_with_index_group_operand(
549        ob: &Bound<'_, PyAny>,
550    ) -> PyResult<PyReturnOperand> {
551        Ok(PyReturnOperand::NodeMultipleValuesWithIndexGroup(
552            ob.extract::<PyNodeMultipleValuesWithIndexGroupOperand>()
553                .expect("Extraction must succeed"),
554        ))
555    }
556
557    fn convert_py_node_multiple_values_without_index_operand(
558        ob: &Bound<'_, PyAny>,
559    ) -> PyResult<PyReturnOperand> {
560        Ok(PyReturnOperand::NodeMultipleValuesWithoutIndex(
561            ob.extract::<PyNodeMultipleValuesWithoutIndexOperand>()
562                .expect("Extraction must succeed"),
563        ))
564    }
565
566    fn convert_py_edge_multiple_values_with_index_operand(
567        ob: &Bound<'_, PyAny>,
568    ) -> PyResult<PyReturnOperand> {
569        Ok(PyReturnOperand::EdgeMultipleValuesWithIndex(
570            ob.extract::<PyEdgeMultipleValuesWithIndexOperand>()
571                .expect("Extraction must succeed"),
572        ))
573    }
574
575    fn convert_py_edge_multiple_values_with_index_group_operand(
576        ob: &Bound<'_, PyAny>,
577    ) -> PyResult<PyReturnOperand> {
578        Ok(PyReturnOperand::EdgeMultipleValuesWithIndexGroup(
579            ob.extract::<PyEdgeMultipleValuesWithIndexGroupOperand>()
580                .expect("Extraction must succeed"),
581        ))
582    }
583
584    fn convert_py_edge_multiple_values_without_index_operand(
585        ob: &Bound<'_, PyAny>,
586    ) -> PyResult<PyReturnOperand> {
587        Ok(PyReturnOperand::EdgeMultipleValuesWithoutIndex(
588            ob.extract::<PyEdgeMultipleValuesWithoutIndexOperand>()
589                .expect("Extraction must succeed"),
590        ))
591    }
592
593    fn convert_py_node_single_value_with_index_operand(
594        ob: &Bound<'_, PyAny>,
595    ) -> PyResult<PyReturnOperand> {
596        Ok(PyReturnOperand::NodeSingleValueWithIndex(
597            ob.extract::<PyNodeSingleValueWithIndexOperand>()
598                .expect("Extraction must succeed"),
599        ))
600    }
601
602    fn convert_py_node_single_value_with_index_group_operand(
603        ob: &Bound<'_, PyAny>,
604    ) -> PyResult<PyReturnOperand> {
605        Ok(PyReturnOperand::NodeSingleValueWithIndexGroup(
606            ob.extract::<PyNodeSingleValueWithIndexGroupOperand>()
607                .expect("Extraction must succeed"),
608        ))
609    }
610
611    fn convert_py_node_single_value_without_index_operand(
612        ob: &Bound<'_, PyAny>,
613    ) -> PyResult<PyReturnOperand> {
614        Ok(PyReturnOperand::NodeSingleValueWithoutIndex(
615            ob.extract::<PyNodeSingleValueWithoutIndexOperand>()
616                .expect("Extraction must succeed"),
617        ))
618    }
619
620    fn convert_py_node_single_value_without_index_group_operand(
621        ob: &Bound<'_, PyAny>,
622    ) -> PyResult<PyReturnOperand> {
623        Ok(PyReturnOperand::NodeSingleValueWithoutIndexGroup(
624            ob.extract::<PyNodeSingleValueWithoutIndexGroupOperand>()
625                .expect("Extraction must succeed"),
626        ))
627    }
628
629    fn convert_py_edge_single_value_with_index_operand(
630        ob: &Bound<'_, PyAny>,
631    ) -> PyResult<PyReturnOperand> {
632        Ok(PyReturnOperand::EdgeSingleValueWithIndex(
633            ob.extract::<PyEdgeSingleValueWithIndexOperand>()
634                .expect("Extraction must succeed"),
635        ))
636    }
637
638    fn convert_py_edge_single_value_with_index_group_operand(
639        ob: &Bound<'_, PyAny>,
640    ) -> PyResult<PyReturnOperand> {
641        Ok(PyReturnOperand::EdgeSingleValueWithIndexGroup(
642            ob.extract::<PyEdgeSingleValueWithIndexGroupOperand>()
643                .expect("Extraction must succeed"),
644        ))
645    }
646
647    fn convert_py_edge_single_value_without_index_operand(
648        ob: &Bound<'_, PyAny>,
649    ) -> PyResult<PyReturnOperand> {
650        Ok(PyReturnOperand::EdgeSingleValueWithoutIndex(
651            ob.extract::<PyEdgeSingleValueWithoutIndexOperand>()
652                .expect("Extraction must succeed"),
653        ))
654    }
655
656    fn convert_py_edge_single_value_without_index_group_operand(
657        ob: &Bound<'_, PyAny>,
658    ) -> PyResult<PyReturnOperand> {
659        Ok(PyReturnOperand::EdgeSingleValueWithoutIndexGroup(
660            ob.extract::<PyEdgeSingleValueWithoutIndexGroupOperand>()
661                .expect("Extraction must succeed"),
662        ))
663    }
664
665    fn convert_py_list(ob: &Bound<'_, PyAny>) -> PyResult<PyReturnOperand> {
666        Ok(PyReturnOperand::Vector(
667            ob.extract::<Vec<PyReturnOperand>>()?,
668        ))
669    }
670
671    fn throw_error(ob: &Bound<'_, PyAny>) -> PyResult<PyReturnOperand> {
672        Err(
673            PyGraphRecordError::from(GraphRecordError::ConversionError(format!(
674                "Failed to convert {ob} into query ReturnOperand",
675            )))
676            .into(),
677        )
678    }
679
680    let type_pointer = ob.get_type_ptr() as usize;
681
682    let conversion_function = RETURNOPERAND_CONVERSION_LUT.get_or_insert(type_pointer, || {
683        if ob.is_instance_of::<PyNodeAttributesTreeOperand>() {
684            convert_py_node_attributes_tree_operand
685        } else if ob.is_instance_of::<PyNodeAttributesTreeGroupOperand>() {
686            convert_py_node_attributes_tree_group_operand
687        } else if ob.is_instance_of::<PyEdgeAttributesTreeOperand>() {
688            convert_py_edge_attributes_tree_operand
689        } else if ob.is_instance_of::<PyEdgeAttributesTreeGroupOperand>() {
690            convert_py_edge_attributes_tree_group_operand
691        } else if ob.is_instance_of::<PyNodeMultipleAttributesWithIndexOperand>() {
692            convert_py_node_multiple_attributes_with_index_operand
693        } else if ob.is_instance_of::<PyNodeMultipleAttributesWithIndexGroupOperand>() {
694            convert_py_node_multiple_attributes_with_index_group_operand
695        } else if ob.is_instance_of::<PyNodeMultipleAttributesWithoutIndexOperand>() {
696            convert_py_node_multiple_attributes_without_index_operand
697        } else if ob.is_instance_of::<PyEdgeMultipleAttributesWithIndexOperand>() {
698            convert_py_edge_multiple_attributes_with_index_operand
699        } else if ob.is_instance_of::<PyEdgeMultipleAttributesWithIndexGroupOperand>() {
700            convert_py_edge_multiple_attributes_with_index_group_operand
701        } else if ob.is_instance_of::<PyEdgeMultipleAttributesWithoutIndexOperand>() {
702            convert_py_edge_multiple_attributes_without_index_operand
703        } else if ob.is_instance_of::<PyNodeSingleAttributeWithIndexOperand>() {
704            convert_py_node_single_attribute_with_index_operand
705        } else if ob.is_instance_of::<PyNodeSingleAttributeWithIndexGroupOperand>() {
706            convert_py_node_single_attribute_with_index_group_operand
707        } else if ob.is_instance_of::<PyNodeSingleAttributeWithoutIndexOperand>() {
708            convert_py_node_single_attribute_without_index_operand
709        } else if ob.is_instance_of::<PyNodeSingleAttributeWithoutIndexGroupOperand>() {
710            convert_py_node_single_attribute_without_index_group_operand
711        } else if ob.is_instance_of::<PyEdgeSingleAttributeWithIndexOperand>() {
712            convert_py_edge_single_attribute_with_index_operand
713        } else if ob.is_instance_of::<PyEdgeSingleAttributeWithIndexGroupOperand>() {
714            convert_py_edge_single_attribute_with_index_group_operand
715        } else if ob.is_instance_of::<PyEdgeSingleAttributeWithoutIndexOperand>() {
716            convert_py_edge_single_attribute_without_index_operand
717        } else if ob.is_instance_of::<PyEdgeSingleAttributeWithoutIndexGroupOperand>() {
718            convert_py_edge_single_attribute_without_index_group_operand
719        } else if ob.is_instance_of::<PyEdgeIndicesOperand>() {
720            convert_py_edge_indices_operand
721        } else if ob.is_instance_of::<PyEdgeIndicesGroupOperand>() {
722            convert_py_edge_indices_group_operand
723        } else if ob.is_instance_of::<PyEdgeIndexOperand>() {
724            convert_py_edge_index_operand
725        } else if ob.is_instance_of::<PyEdgeIndexGroupOperand>() {
726            convert_py_edge_index_group_operand
727        } else if ob.is_instance_of::<PyNodeIndicesOperand>() {
728            convert_py_node_indices_operand
729        } else if ob.is_instance_of::<PyNodeIndicesGroupOperand>() {
730            convert_py_node_indices_group_operand
731        } else if ob.is_instance_of::<PyNodeIndexOperand>() {
732            convert_py_node_index_operand
733        } else if ob.is_instance_of::<PyNodeIndexGroupOperand>() {
734            convert_py_node_index_group_operand
735        } else if ob.is_instance_of::<PyNodeMultipleValuesWithIndexOperand>() {
736            convert_py_node_multiple_values_with_index_operand
737        } else if ob.is_instance_of::<PyNodeMultipleValuesWithIndexGroupOperand>() {
738            convert_py_node_multiple_values_with_index_group_operand
739        } else if ob.is_instance_of::<PyNodeMultipleValuesWithoutIndexOperand>() {
740            convert_py_node_multiple_values_without_index_operand
741        } else if ob.is_instance_of::<PyEdgeMultipleValuesWithIndexOperand>() {
742            convert_py_edge_multiple_values_with_index_operand
743        } else if ob.is_instance_of::<PyEdgeMultipleValuesWithIndexGroupOperand>() {
744            convert_py_edge_multiple_values_with_index_group_operand
745        } else if ob.is_instance_of::<PyEdgeMultipleValuesWithoutIndexOperand>() {
746            convert_py_edge_multiple_values_without_index_operand
747        } else if ob.is_instance_of::<PyNodeSingleValueWithIndexOperand>() {
748            convert_py_node_single_value_with_index_operand
749        } else if ob.is_instance_of::<PyNodeSingleValueWithIndexGroupOperand>() {
750            convert_py_node_single_value_with_index_group_operand
751        } else if ob.is_instance_of::<PyNodeSingleValueWithoutIndexOperand>() {
752            convert_py_node_single_value_without_index_operand
753        } else if ob.is_instance_of::<PyNodeSingleValueWithoutIndexGroupOperand>() {
754            convert_py_node_single_value_without_index_group_operand
755        } else if ob.is_instance_of::<PyEdgeSingleValueWithIndexOperand>() {
756            convert_py_edge_single_value_with_index_operand
757        } else if ob.is_instance_of::<PyEdgeSingleValueWithIndexGroupOperand>() {
758            convert_py_edge_single_value_with_index_group_operand
759        } else if ob.is_instance_of::<PyEdgeSingleValueWithoutIndexOperand>() {
760            convert_py_edge_single_value_without_index_operand
761        } else if ob.is_instance_of::<PyEdgeSingleValueWithoutIndexGroupOperand>() {
762            convert_py_edge_single_value_without_index_group_operand
763        } else if ob.is_instance_of::<PyList>() {
764            convert_py_list
765        } else {
766            throw_error
767        }
768    });
769
770    conversion_function(ob)
771}
772
773impl FromPyObject<'_, '_> for PyReturnOperand {
774    type Error = PyErr;
775
776    fn extract(ob: Borrowed<'_, '_, PyAny>) -> PyResult<Self> {
777        convert_pyobject_to_pyreturnoperand(&ob)
778    }
779}
780
781pub enum PyReturnValue<'a> {
782    NodeAttributesTree(<Wrapper<NodeAttributesTreeOperand> as ReturnOperand<'a>>::ReturnValue),
783    NodeAttributesTreeGroup(<Wrapper<GroupOperand<NodeAttributesTreeOperand>> as ReturnOperand<'a>>::ReturnValue),
784    EdgeAttributesTree(<Wrapper<EdgeAttributesTreeOperand> as ReturnOperand<'a>>::ReturnValue),
785    EdgeAttributesTreeGroup(<Wrapper<GroupOperand<EdgeAttributesTreeOperand>> as ReturnOperand<'a>>::ReturnValue),
786    NodeMultipleAttributesWithIndex(
787        <Wrapper<NodeMultipleAttributesWithIndexOperand> as ReturnOperand<'a>>::ReturnValue,
788    ),
789    NodeMultipleAttributesWithIndexGroup(
790        <Wrapper<GroupOperand<NodeMultipleAttributesWithIndexOperand>> as ReturnOperand<'a>>::ReturnValue,
791    ),
792    NodeMultipleAttributesWithoutIndex(
793        <Wrapper<NodeMultipleAttributesWithoutIndexOperand> as ReturnOperand<'a>>::ReturnValue,
794    ),
795    EdgeMultipleAttributesWithIndex(
796        <Wrapper<EdgeMultipleAttributesWithIndexOperand> as ReturnOperand<'a>>::ReturnValue,
797    ),
798    EdgeMultipleAttributesWithIndexGroup(
799        <Wrapper<GroupOperand<EdgeMultipleAttributesWithIndexOperand>> as ReturnOperand<'a>>::ReturnValue,
800    ),
801    EdgeMultipleAttributesWithoutIndex(
802        <Wrapper<EdgeMultipleAttributesWithoutIndexOperand> as ReturnOperand<'a>>::ReturnValue,
803    ),
804    NodeSingleAttributeWithIndex(
805        <Wrapper<NodeSingleAttributeWithIndexOperand> as ReturnOperand<'a>>::ReturnValue,
806    ),
807    NodeSingleAttributeWithIndexGroup(
808        <Wrapper<GroupOperand<NodeSingleAttributeWithIndexOperand>> as ReturnOperand<'a>>::ReturnValue,
809    ),
810    NodeSingleAttributeWithoutIndex(
811        <Wrapper<NodeSingleAttributeWithoutIndexOperand> as ReturnOperand<'a>>::ReturnValue,
812    ),
813    NodeSingleAttributeWithoutIndexGroup(
814        <Wrapper<GroupOperand<NodeSingleAttributeWithoutIndexOperand>> as ReturnOperand<'a>>::ReturnValue,
815    ),
816    EdgeSingleAttributeWithIndex(
817        <Wrapper<EdgeSingleAttributeWithIndexOperand> as ReturnOperand<'a>>::ReturnValue,
818    ),
819    EdgeSingleAttributeWithIndexGroup(
820        <Wrapper<GroupOperand<EdgeSingleAttributeWithIndexOperand>> as ReturnOperand<'a>>::ReturnValue,
821    ),
822    EdgeSingleAttributeWithoutIndex(
823        <Wrapper<EdgeSingleAttributeWithoutIndexOperand> as ReturnOperand<'a>>::ReturnValue,
824    ),
825    EdgeSingleAttributeWithoutIndexGroup(
826        <Wrapper<GroupOperand<EdgeSingleAttributeWithoutIndexOperand>> as ReturnOperand<'a>>::ReturnValue,
827    ),
828    EdgeIndices(<Wrapper<EdgeIndicesOperand> as ReturnOperand<'a>>::ReturnValue),
829    EdgeIndicesGroup(<Wrapper<GroupOperand<EdgeIndicesOperand>> as ReturnOperand<'a>>::ReturnValue),
830    EdgeIndex(<Wrapper<EdgeIndexOperand> as ReturnOperand<'a>>::ReturnValue),
831    EdgeIndexGroup(<Wrapper<GroupOperand<EdgeIndexOperand>> as ReturnOperand<'a>>::ReturnValue),
832    NodeIndices(<Wrapper<NodeIndicesOperand> as ReturnOperand<'a>>::ReturnValue),
833    NodeIndicesGroup(<Wrapper<GroupOperand<NodeIndicesOperand>> as ReturnOperand<'a>>::ReturnValue),
834    NodeIndex(<Wrapper<NodeIndexOperand> as ReturnOperand<'a>>::ReturnValue),
835    NodeIndexGroup(<Wrapper<GroupOperand<NodeIndexOperand>> as ReturnOperand<'a>>::ReturnValue),
836    NodeMultipleValuesWithIndex(
837        <Wrapper<NodeMultipleValuesWithIndexOperand> as ReturnOperand<'a>>::ReturnValue,
838    ),
839    NodeMultipleValuesWithIndexGroup(
840        <Wrapper<GroupOperand<NodeMultipleValuesWithIndexOperand>> as ReturnOperand<'a>>::ReturnValue,
841    ),
842    NodeMultipleValuesWithoutIndex(
843        <Wrapper<NodeMultipleValuesWithoutIndexOperand> as ReturnOperand<'a>>::ReturnValue,
844    ),
845    EdgeMultipleValuesWithIndex(
846        <Wrapper<EdgeMultipleValuesWithIndexOperand> as ReturnOperand<'a>>::ReturnValue,
847    ),
848    EdgeMultipleValuesWithIndexGroup(
849        <Wrapper<GroupOperand<EdgeMultipleValuesWithIndexOperand>> as ReturnOperand<'a>>::ReturnValue,
850    ),
851    EdgeMultipleValuesWithoutIndex(
852        <Wrapper<EdgeMultipleValuesWithoutIndexOperand> as ReturnOperand<'a>>::ReturnValue,
853    ),
854    NodeSingleValueWithIndex(
855        <Wrapper<NodeSingleValueWithIndexOperand> as ReturnOperand<'a>>::ReturnValue,
856    ),
857    NodeSingleValueWithIndexGroup(
858        <Wrapper<GroupOperand<NodeSingleValueWithIndexOperand>> as ReturnOperand<'a>>::ReturnValue,
859    ),
860    NodeSingleValueWithoutIndex(
861        <Wrapper<NodeSingleValueWithoutIndexOperand> as ReturnOperand<'a>>::ReturnValue,
862    ),
863    NodeSingleValueWithoutIndexGroup(
864        <Wrapper<GroupOperand<NodeSingleValueWithoutIndexOperand>> as ReturnOperand<'a>>::ReturnValue,
865    ),
866    EdgeSingleValueWithIndex(
867        <Wrapper<EdgeSingleValueWithIndexOperand> as ReturnOperand<'a>>::ReturnValue,
868    ),
869    EdgeSingleValueWithIndexGroup(
870        <Wrapper<GroupOperand<EdgeSingleValueWithIndexOperand>> as ReturnOperand<'a>>::ReturnValue,
871    ),
872    EdgeSingleValueWithoutIndex(
873        <Wrapper<EdgeSingleValueWithoutIndexOperand> as ReturnOperand<'a>>::ReturnValue,
874    ),
875    EdgeSingleValueWithoutIndexGroup(
876        <Wrapper<GroupOperand<EdgeSingleValueWithoutIndexOperand>> as ReturnOperand<'a>>::ReturnValue,
877    ),
878    Vector(Vec<Self>),
879}
880
881impl<'py> IntoPyObject<'py> for PyReturnValue<'_> {
882    type Target = PyAny;
883    type Output = Bound<'py, Self::Target>;
884    type Error = PyErr;
885
886    #[allow(clippy::too_many_lines)]
887    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
888        match self {
889            PyReturnValue::NodeAttributesTree(iterator) => iterator
890                .map(|item| {
891                    (
892                        PyNodeIndex::from(item.0.clone()),
893                        Vec::<PyGraphRecordAttribute>::deep_from(item.1),
894                    )
895                })
896                .collect::<HashMap<_, _>>()
897                .into_bound_py_any(py),
898            PyReturnValue::NodeAttributesTreeGroup(iterator) => iterator
899                .map(|(key, items)| {
900                    (
901                        PyGroupKey::from(key),
902                        items
903                            .map(|item| {
904                                (
905                                    PyNodeIndex::from(item.0.clone()),
906                                    Vec::<PyGraphRecordAttribute>::deep_from(item.1),
907                                )
908                            })
909                            .collect::<HashMap<_, _>>(),
910                    )
911                })
912                .collect::<Vec<_>>()
913                .into_bound_py_any(py),
914            PyReturnValue::EdgeAttributesTree(iterator) => iterator
915                .map(|item| (item.0, Vec::<PyGraphRecordAttribute>::deep_from(item.1)))
916                .collect::<HashMap<_, _>>()
917                .into_bound_py_any(py),
918            PyReturnValue::EdgeAttributesTreeGroup(iterator) => iterator
919                .map(|(key, items)| {
920                    (
921                        PyGroupKey::from(key),
922                        items
923                            .map(|item| (item.0, Vec::<PyGraphRecordAttribute>::deep_from(item.1)))
924                            .collect::<HashMap<_, _>>(),
925                    )
926                })
927                .collect::<Vec<_>>()
928                .into_bound_py_any(py),
929            PyReturnValue::NodeMultipleAttributesWithIndex(iterator) => iterator
930                .map(|item| {
931                    (
932                        PyNodeIndex::from(item.0.clone()),
933                        PyGraphRecordAttribute::from(item.1),
934                    )
935                })
936                .collect::<HashMap<_, _>>()
937                .into_bound_py_any(py),
938            PyReturnValue::NodeMultipleAttributesWithIndexGroup(iterator) => iterator
939                .map(|(key, items)| {
940                    (
941                        PyGroupKey::from(key),
942                        items
943                            .map(|item| {
944                                (
945                                    PyNodeIndex::from(item.0.clone()),
946                                    PyGraphRecordAttribute::from(item.1),
947                                )
948                            })
949                            .collect::<HashMap<_, _>>(),
950                    )
951                })
952                .collect::<Vec<_>>()
953                .into_bound_py_any(py),
954            PyReturnValue::NodeMultipleAttributesWithoutIndex(iterator)
955            | PyReturnValue::EdgeMultipleAttributesWithoutIndex(iterator)
956            | PyReturnValue::NodeIndices(iterator) => iterator
957                .map(PyGraphRecordAttribute::from)
958                .collect::<Vec<_>>()
959                .into_bound_py_any(py),
960            PyReturnValue::EdgeMultipleAttributesWithIndex(iterator) => iterator
961                .map(|item| (item.0, PyGraphRecordAttribute::from(item.1)))
962                .collect::<HashMap<_, _>>()
963                .into_bound_py_any(py),
964            PyReturnValue::EdgeMultipleAttributesWithIndexGroup(iterator) => iterator
965                .map(|(key, items)| {
966                    (
967                        PyGroupKey::from(key),
968                        items
969                            .map(|item| (item.0, PyGraphRecordAttribute::from(item.1)))
970                            .collect::<HashMap<_, _>>(),
971                    )
972                })
973                .collect::<Vec<_>>()
974                .into_bound_py_any(py),
975            PyReturnValue::NodeSingleAttributeWithIndex(attribute) => attribute
976                .map(|item| {
977                    (
978                        PyGraphRecordAttribute::from(item.0.clone()),
979                        PyGraphRecordAttribute::from(item.1),
980                    )
981                })
982                .into_bound_py_any(py),
983            PyReturnValue::NodeSingleAttributeWithIndexGroup(attribute) => attribute
984                .map(|(key, items)| {
985                    (
986                        PyGroupKey::from(key),
987                        items.map(|item| {
988                            (
989                                PyGraphRecordAttribute::from(item.0.clone()),
990                                PyGraphRecordAttribute::from(item.1),
991                            )
992                        }),
993                    )
994                })
995                .collect::<Vec<_>>()
996                .into_bound_py_any(py),
997            PyReturnValue::NodeSingleAttributeWithoutIndex(attribute)
998            | PyReturnValue::EdgeSingleAttributeWithoutIndex(attribute) => attribute
999                .map(PyGraphRecordAttribute::from)
1000                .into_bound_py_any(py),
1001            PyReturnValue::NodeSingleAttributeWithoutIndexGroup(attribute) => attribute
1002                .map(|(key, item)| {
1003                    (
1004                        PyGroupKey::from(key),
1005                        item.map(PyGraphRecordAttribute::from),
1006                    )
1007                })
1008                .collect::<Vec<_>>()
1009                .into_bound_py_any(py),
1010            PyReturnValue::EdgeSingleAttributeWithIndex(attribute) => attribute
1011                .map(|item| (item.0, PyGraphRecordAttribute::from(item.1)))
1012                .into_bound_py_any(py),
1013            PyReturnValue::EdgeSingleAttributeWithIndexGroup(attribute) => attribute
1014                .map(|(key, items)| {
1015                    (
1016                        PyGroupKey::from(key),
1017                        items.map(|item| (item.0, PyGraphRecordAttribute::from(item.1))),
1018                    )
1019                })
1020                .collect::<Vec<_>>()
1021                .into_bound_py_any(py),
1022            PyReturnValue::EdgeSingleAttributeWithoutIndexGroup(attribute) => attribute
1023                .map(|(key, item)| {
1024                    (
1025                        PyGroupKey::from(key),
1026                        item.map(PyGraphRecordAttribute::from),
1027                    )
1028                })
1029                .collect::<Vec<_>>()
1030                .into_bound_py_any(py),
1031            PyReturnValue::EdgeIndices(iterator) => {
1032                iterator.collect::<Vec<_>>().into_bound_py_any(py)
1033            }
1034            PyReturnValue::EdgeIndicesGroup(iterator) => iterator
1035                .map(|(key, iterator)| (PyGroupKey::from(key), iterator.collect::<Vec<_>>()))
1036                .collect::<Vec<_>>()
1037                .into_bound_py_any(py),
1038            PyReturnValue::EdgeIndex(index) => index.into_bound_py_any(py),
1039            PyReturnValue::EdgeIndexGroup(index) => index
1040                .map(|(key, index)| (PyGroupKey::from(key), index))
1041                .collect::<Vec<_>>()
1042                .into_bound_py_any(py),
1043            PyReturnValue::NodeIndicesGroup(iterator) => iterator
1044                .map(|(key, iterator)| {
1045                    (
1046                        PyGroupKey::from(key),
1047                        iterator
1048                            .map(PyGraphRecordAttribute::from)
1049                            .collect::<Vec<_>>(),
1050                    )
1051                })
1052                .collect::<Vec<_>>()
1053                .into_bound_py_any(py),
1054            PyReturnValue::NodeIndex(index) => {
1055                Option::<PyNodeIndex>::deep_from(index).into_bound_py_any(py)
1056            }
1057            PyReturnValue::NodeIndexGroup(index) => index
1058                .map(|(key, index)| {
1059                    (
1060                        PyGroupKey::from(key),
1061                        Option::<PyNodeIndex>::deep_from(index),
1062                    )
1063                })
1064                .collect::<Vec<_>>()
1065                .into_bound_py_any(py),
1066            PyReturnValue::NodeMultipleValuesWithIndex(iterator) => iterator
1067                .map(|item| {
1068                    (
1069                        PyNodeIndex::from(item.0.clone()),
1070                        PyGraphRecordValue::from(item.1),
1071                    )
1072                })
1073                .collect::<HashMap<_, _>>()
1074                .into_bound_py_any(py),
1075            PyReturnValue::NodeMultipleValuesWithIndexGroup(iterator) => iterator
1076                .map(|(key, items)| {
1077                    (
1078                        PyGroupKey::from(key),
1079                        items
1080                            .map(|item| {
1081                                (
1082                                    PyNodeIndex::from(item.0.clone()),
1083                                    PyGraphRecordValue::from(item.1),
1084                                )
1085                            })
1086                            .collect::<HashMap<_, _>>(),
1087                    )
1088                })
1089                .collect::<Vec<_>>()
1090                .into_bound_py_any(py),
1091            PyReturnValue::NodeMultipleValuesWithoutIndex(iterator)
1092            | PyReturnValue::EdgeMultipleValuesWithoutIndex(iterator) => iterator
1093                .map(PyGraphRecordValue::from)
1094                .collect::<Vec<_>>()
1095                .into_bound_py_any(py),
1096            PyReturnValue::EdgeMultipleValuesWithIndex(iterator) => iterator
1097                .map(|item| (item.0, PyGraphRecordValue::from(item.1)))
1098                .collect::<HashMap<_, _>>()
1099                .into_bound_py_any(py),
1100            PyReturnValue::EdgeMultipleValuesWithIndexGroup(iterator) => iterator
1101                .map(|(key, items)| {
1102                    (
1103                        PyGroupKey::from(key),
1104                        items
1105                            .map(|item| (item.0, PyGraphRecordValue::from(item.1)))
1106                            .collect::<HashMap<_, _>>(),
1107                    )
1108                })
1109                .collect::<Vec<_>>()
1110                .into_bound_py_any(py),
1111            PyReturnValue::NodeSingleValueWithIndex(value) => value
1112                .map(|item| {
1113                    (
1114                        PyGraphRecordAttribute::from(item.0.clone()),
1115                        PyGraphRecordValue::from(item.1),
1116                    )
1117                })
1118                .into_bound_py_any(py),
1119            PyReturnValue::NodeSingleValueWithIndexGroup(value) => value
1120                .map(|(key, items)| {
1121                    (
1122                        PyGroupKey::from(key),
1123                        items.map(|item| {
1124                            (
1125                                PyGraphRecordAttribute::from(item.0.clone()),
1126                                PyGraphRecordValue::from(item.1),
1127                            )
1128                        }),
1129                    )
1130                })
1131                .collect::<Vec<_>>()
1132                .into_bound_py_any(py),
1133            PyReturnValue::NodeSingleValueWithoutIndex(value)
1134            | PyReturnValue::EdgeSingleValueWithoutIndex(value) => {
1135                value.map(PyGraphRecordValue::from).into_bound_py_any(py)
1136            }
1137            PyReturnValue::NodeSingleValueWithoutIndexGroup(value) => value
1138                .map(|(key, item)| (PyGroupKey::from(key), item.map(PyGraphRecordValue::from)))
1139                .collect::<Vec<_>>()
1140                .into_bound_py_any(py),
1141            PyReturnValue::EdgeSingleValueWithIndex(value) => value
1142                .map(|item| (item.0, PyGraphRecordValue::from(item.1)))
1143                .into_bound_py_any(py),
1144            PyReturnValue::EdgeSingleValueWithIndexGroup(value) => value
1145                .map(|(key, items)| {
1146                    (
1147                        PyGroupKey::from(key),
1148                        items.map(|item| (item.0, PyGraphRecordValue::from(item.1))),
1149                    )
1150                })
1151                .collect::<Vec<_>>()
1152                .into_bound_py_any(py),
1153            PyReturnValue::EdgeSingleValueWithoutIndexGroup(value) => value
1154                .map(|(key, item)| (PyGroupKey::from(key), item.map(PyGraphRecordValue::from)))
1155                .collect::<Vec<_>>()
1156                .into_bound_py_any(py),
1157            PyReturnValue::Vector(vector) => vector.into_bound_py_any(py),
1158        }
1159    }
1160}
1161
1162#[repr(transparent)]
1163pub struct PyGraphRecordAttributeCardinalityWrapper(CardinalityWrapper<GraphRecordAttribute>);
1164
1165impl From<CardinalityWrapper<GraphRecordAttribute>> for PyGraphRecordAttributeCardinalityWrapper {
1166    fn from(attribute: CardinalityWrapper<GraphRecordAttribute>) -> Self {
1167        Self(attribute)
1168    }
1169}
1170
1171impl From<PyGraphRecordAttributeCardinalityWrapper> for CardinalityWrapper<GraphRecordAttribute> {
1172    fn from(attribute: PyGraphRecordAttributeCardinalityWrapper) -> Self {
1173        attribute.0
1174    }
1175}
1176
1177impl FromPyObject<'_, '_> for PyGraphRecordAttributeCardinalityWrapper {
1178    type Error = PyErr;
1179
1180    fn extract(ob: Borrowed<'_, '_, PyAny>) -> PyResult<Self> {
1181        match ob.extract::<PyGraphRecordAttribute>() { Ok(attribute) => {
1182            Ok(CardinalityWrapper::Single(GraphRecordAttribute::from(attribute)).into())
1183        } _ => { match ob.extract::<Vec<PyGraphRecordAttribute>>() { Ok(attributes) => {
1184            Ok(CardinalityWrapper::from(
1185                attributes
1186                    .into_iter()
1187                    .map(GraphRecordAttribute::from)
1188                    .collect::<Vec<_>>(),
1189            )
1190            .into())
1191        } _ => { match ob.extract::<(Vec<PyGraphRecordAttribute>, PyMatchMode)>() { Ok(attributes) => {
1192            Ok(CardinalityWrapper::from((
1193                attributes
1194                    .0
1195                    .into_iter()
1196                    .map(GraphRecordAttribute::from)
1197                    .collect::<Vec<_>>(),
1198                attributes.1.into(),
1199            ))
1200            .into())
1201        } _ => {
1202            Err(
1203                PyGraphRecordError::from(GraphRecordError::ConversionError(format!(
1204                    "Failed to convert {} into GraphRecordAttribute, List[GraphRecordAttribute] or (List[GraphRecordAttribute], MatchMode)",
1205                    ob.to_owned()
1206                )))
1207                .into(),
1208            )
1209        }}}}}}
1210    }
1211}
1212
1213type PyGroupCardinalityWrapper = PyGraphRecordAttributeCardinalityWrapper;