gitql_std/array/
mod.rs

1use std::collections::HashMap;
2
3use gitql_ast::types::any::AnyType;
4use gitql_ast::types::array::ArrayType;
5use gitql_ast::types::dynamic::DynamicType;
6use gitql_ast::types::integer::IntType;
7use gitql_ast::types::text::TextType;
8use gitql_core::signature::Signature;
9use gitql_core::signature::StandardFunction;
10use gitql_core::values::array::ArrayValue;
11use gitql_core::values::integer::IntValue;
12use gitql_core::values::null::NullValue;
13use gitql_core::values::text::TextValue;
14use gitql_core::values::Value;
15
16use crate::meta_types::array_element_type;
17use crate::meta_types::array_of_type;
18use crate::meta_types::first_element_type;
19use crate::meta_types::second_element_type;
20
21use rand::seq::SliceRandom;
22
23#[inline(always)]
24pub fn register_std_array_functions(map: &mut HashMap<&'static str, StandardFunction>) {
25    map.insert("array_append", array_append);
26    map.insert("array_prepend", array_prepend);
27    map.insert("array_remove", array_remove);
28    map.insert("array_cat", array_cat);
29    map.insert("array_length", array_length);
30    map.insert("array_shuffle", array_shuffle);
31    map.insert("array_position", array_position);
32    map.insert("array_positions", array_positions);
33    map.insert("array_dims", array_dims);
34    map.insert("array_replace", array_replace);
35    map.insert("trim_array", array_trim);
36}
37
38#[inline(always)]
39pub fn register_std_array_function_signatures(map: &mut HashMap<&'static str, Signature>) {
40    map.insert(
41        "array_append",
42        Signature {
43            parameters: vec![
44                Box::new(ArrayType::new(Box::new(AnyType))),
45                Box::new(DynamicType {
46                    function: |elements| array_element_type(first_element_type(elements)),
47                }),
48            ],
49            return_type: Box::new(DynamicType::new(first_element_type)),
50        },
51    );
52    map.insert(
53        "array_prepend",
54        Signature {
55            parameters: vec![
56                Box::new(AnyType),
57                Box::new(DynamicType {
58                    function: |elements| array_of_type(first_element_type(elements)),
59                }),
60            ],
61            return_type: Box::new(DynamicType::new(second_element_type)),
62        },
63    );
64    map.insert(
65        "array_remove",
66        Signature {
67            parameters: vec![
68                Box::new(ArrayType::new(Box::new(AnyType))),
69                Box::new(DynamicType {
70                    function: |elements| array_element_type(first_element_type(elements)),
71                }),
72            ],
73            return_type: Box::new(DynamicType::new(first_element_type)),
74        },
75    );
76    map.insert(
77        "array_cat",
78        Signature {
79            parameters: vec![
80                Box::new(ArrayType::new(Box::new(AnyType))),
81                Box::new(DynamicType::new(first_element_type)),
82            ],
83            return_type: Box::new(DynamicType::new(first_element_type)),
84        },
85    );
86    map.insert(
87        "array_length",
88        Signature {
89            parameters: vec![Box::new(ArrayType {
90                base: Box::new(AnyType),
91            })],
92            return_type: Box::new(IntType),
93        },
94    );
95    map.insert(
96        "array_shuffle",
97        Signature {
98            parameters: vec![Box::new(ArrayType {
99                base: Box::new(AnyType),
100            })],
101            return_type: Box::new(DynamicType {
102                function: first_element_type,
103            }),
104        },
105    );
106    map.insert(
107        "array_position",
108        Signature {
109            parameters: vec![
110                Box::new(ArrayType {
111                    base: Box::new(AnyType),
112                }),
113                Box::new(DynamicType {
114                    function: |elements| array_element_type(first_element_type(elements)),
115                }),
116            ],
117            return_type: Box::new(IntType),
118        },
119    );
120    map.insert(
121        "array_dims",
122        Signature {
123            parameters: vec![Box::new(ArrayType {
124                base: Box::new(AnyType),
125            })],
126            return_type: Box::new(TextType),
127        },
128    );
129    map.insert(
130        "array_replace",
131        Signature {
132            parameters: vec![
133                Box::new(ArrayType {
134                    base: Box::new(AnyType),
135                }),
136                Box::new(DynamicType {
137                    function: |elements| array_element_type(first_element_type(elements)),
138                }),
139                Box::new(DynamicType {
140                    function: |elements| array_element_type(first_element_type(elements)),
141                }),
142            ],
143            return_type: Box::new(DynamicType {
144                function: first_element_type,
145            }),
146        },
147    );
148    map.insert(
149        "trim_array",
150        Signature {
151            parameters: vec![
152                Box::new(ArrayType {
153                    base: Box::new(AnyType),
154                }),
155                Box::new(IntType),
156            ],
157            return_type: Box::new(DynamicType {
158                function: first_element_type,
159            }),
160        },
161    );
162}
163
164pub fn array_append(inputs: &[Box<dyn Value>]) -> Box<dyn Value> {
165    let mut array = inputs[0].as_array().unwrap();
166    let element = &inputs[1];
167    array.push(element.to_owned());
168
169    let element_type = inputs[0].data_type().clone();
170    Box::new(ArrayValue::new(array, element_type))
171}
172
173pub fn array_prepend(inputs: &[Box<dyn Value>]) -> Box<dyn Value> {
174    let element = &inputs[0];
175    let mut array = inputs[1].as_array().unwrap();
176    array.insert(0, element.clone());
177
178    let element_type = inputs[0].data_type().clone();
179    Box::new(ArrayValue::new(array, element_type))
180}
181
182pub fn array_remove(inputs: &[Box<dyn Value>]) -> Box<dyn Value> {
183    let array = inputs[0].as_array().unwrap();
184    let element_to_remove = &inputs[1];
185    let array_after_remove = array
186        .into_iter()
187        .filter(|element| !element_to_remove.equals(element))
188        .collect();
189
190    let element_type = inputs[0].data_type().clone();
191    Box::new(ArrayValue::new(array_after_remove, element_type))
192}
193
194pub fn array_cat(inputs: &[Box<dyn Value>]) -> Box<dyn Value> {
195    let mut first = inputs[0].as_array().unwrap();
196    let mut other = inputs[1].as_array().unwrap();
197    let mut result = Vec::with_capacity(first.len() + other.len());
198    result.append(&mut first);
199    result.append(&mut other);
200
201    let element_type = inputs[0].data_type().clone();
202    Box::new(ArrayValue::new(result, element_type))
203}
204
205pub fn array_length(inputs: &[Box<dyn Value>]) -> Box<dyn Value> {
206    let array = inputs[0].as_array().unwrap();
207    let value = array.len() as i64;
208    Box::new(IntValue::new(value))
209}
210
211pub fn array_shuffle(inputs: &[Box<dyn Value>]) -> Box<dyn Value> {
212    let array_type = &inputs[0].data_type();
213    let element_type = &array_type
214        .as_any()
215        .downcast_ref::<ArrayType>()
216        .unwrap()
217        .base;
218    let mut array = inputs[0].as_array().unwrap();
219    array.shuffle(&mut rand::rng());
220    Box::new(ArrayValue::new(array, element_type.clone()))
221}
222
223pub fn array_position(inputs: &[Box<dyn Value>]) -> Box<dyn Value> {
224    let array = inputs[0].as_array().unwrap();
225    let elemnet = &inputs[1];
226    if let Some(index) = array.iter().position(|r| r.equals(elemnet)) {
227        return Box::new(IntValue::new((index + 1) as i64));
228    }
229    Box::new(NullValue)
230}
231
232pub fn array_positions(inputs: &[Box<dyn Value>]) -> Box<dyn Value> {
233    let array = inputs[0].as_array().unwrap();
234    let target = &inputs[1];
235    let mut positions: Vec<Box<dyn Value>> = vec![];
236    for (index, element) in array.into_iter().enumerate() {
237        if element.equals(target) {
238            positions.push(Box::new(IntValue::new((index + 1) as i64)));
239        }
240    }
241    Box::new(ArrayValue::new(positions, Box::new(IntType)))
242}
243
244pub fn array_dims(inputs: &[Box<dyn Value>]) -> Box<dyn Value> {
245    let array_type = inputs[0].data_type();
246    Box::new(TextValue::new(array_type.to_string()))
247}
248
249pub fn array_replace(inputs: &[Box<dyn Value>]) -> Box<dyn Value> {
250    let array_type = inputs[0].data_type();
251    let mut array_values = inputs[0].as_array().unwrap();
252    let from = &inputs[1];
253    let to = &inputs[2];
254    for element in &mut array_values {
255        if element.equals(from) {
256            *element = to.clone();
257        }
258    }
259    Box::new(ArrayValue::new(array_values, array_type))
260}
261
262pub fn array_trim(inputs: &[Box<dyn Value>]) -> Box<dyn Value> {
263    let mut array = inputs[0].as_array().unwrap();
264    let array_type = inputs[0].data_type();
265    let array_len = array.len();
266    let n = i64::min(array.len().try_into().unwrap(), inputs[1].as_int().unwrap());
267    array.truncate(array_len - n as usize);
268    Box::new(ArrayValue::new(array, array_type))
269}