Skip to main content

surrealdb_expr/expr/idiom/
recursion.rs

1use crate::expr::Part;
2use crate::expr::part::{RecurseInstruction, RecursionPlan};
3use crate::val::{Array, Value};
4
5#[derive(Clone, Copy, Debug)]
6pub struct Recursion<'a> {
7	pub min: u32,
8	pub max: Option<u32>,
9	pub iterated: u32,
10	pub current: &'a Value,
11	pub path: &'a [Part],
12	pub plan: Option<&'a RecursionPlan>,
13	pub instruction: Option<&'a RecurseInstruction>,
14}
15
16impl<'a> Recursion<'a> {
17	pub fn with_iterated(self, iterated: u32) -> Self {
18		Self {
19			iterated,
20			..self
21		}
22	}
23
24	pub fn with_current(self, current: &'a Value) -> Self {
25		Self {
26			current,
27			..self
28		}
29	}
30}
31
32// Method used to check if the value
33// inside a recursed idiom path is final
34pub fn is_final(v: &Value) -> bool {
35	match v {
36		Value::None => true,
37		Value::Null => true,
38		Value::Array(v) => v.is_empty() || v.is_all_none_or_null(),
39		_ => false,
40	}
41}
42
43pub fn get_final(v: &Value) -> Value {
44	match v {
45		Value::Array(_) => Value::Array(Array(vec![])),
46		Value::Null => Value::Null,
47		_ => Value::None,
48	}
49}
50
51pub fn clean_iteration(v: Value) -> Value {
52	if let Value::Array(v) = v {
53		Value::from(v.0.into_iter().filter(|v| !is_final(v)).collect::<Vec<Value>>()).flatten()
54	} else {
55		v
56	}
57}