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}