• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gluesql / gluesql / 20406697944

21 Dec 2025 07:44AM UTC coverage: 98.085% (-0.02%) from 98.105%
20406697944

push

github

web-flow
Add Expr::Value variant for direct runtime value injection (#1860)

Add Expr::Value(Value) variant to enable direct runtime value injection into expressions, eliminating unnecessary conversions and simplifying the AST.

478 of 483 new or added lines in 26 files covered. (98.96%)

1 existing line in 1 file now uncovered.

39434 of 40204 relevant lines covered (98.08%)

65128.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.76
/core/src/executor/evaluate/function.rs
1
use {
2
    super::{EvaluateError, Evaluated},
3
    crate::{
4
        ast::DateTimeField,
5
        data::{Key, Point, Value},
6
        result::{Error, Result},
7
    },
8
    chrono::{Datelike, Duration, Months},
9
    md5::{Digest, Md5},
10
    rand::{Rng, SeedableRng, rngs::StdRng},
11
    std::{
12
        borrow::Cow,
13
        fmt::Write,
14
        ops::ControlFlow::{self as StdControlFlow, Break, Continue},
15
    },
16
    uuid::Uuid,
17
};
18

19
type ControlFlow<T> = std::ops::ControlFlow<BreakCase, T>;
20

21
pub enum BreakCase {
22
    Null,
23
    Err(Error),
24
}
25

26
trait ContinueOrBreak<T> {
27
    fn continue_or_break(self, err: Error) -> ControlFlow<T>;
28
}
29

30
impl<T> ContinueOrBreak<T> for Option<T> {
31
    fn continue_or_break(self, err: Error) -> ControlFlow<T> {
101,094✔
32
        match self {
101,094✔
33
            Some(v) => Continue(v),
96,222✔
34
            None => Break(BreakCase::Err(err)),
4,872✔
35
        }
36
    }
101,094✔
37
}
38

39
trait BreakIfNull<T> {
40
    fn break_if_null(self) -> ControlFlow<T>;
41
}
42

43
impl<'a> BreakIfNull<Evaluated<'a>> for Result<Evaluated<'a>> {
44
    fn break_if_null(self) -> ControlFlow<Evaluated<'a>> {
×
45
        match self {
×
46
            Err(err) => Break(BreakCase::Err(err)),
×
47
            Ok(value) if value.is_null() => Break(BreakCase::Null),
×
48
            Ok(value) => Continue(value),
×
49
        }
50
    }
×
51
}
52

53
impl<'a> BreakIfNull<Evaluated<'a>> for Evaluated<'a> {
54
    fn break_if_null(self) -> ControlFlow<Evaluated<'a>> {
9,744✔
55
        if self.is_null() {
9,744✔
56
            Break(BreakCase::Null)
1,218✔
57
        } else {
58
            Continue(self)
8,526✔
59
        }
60
    }
9,744✔
61
}
62

63
impl BreakIfNull<Value> for Result<Value> {
64
    fn break_if_null(self) -> ControlFlow<Value> {
1,256,197✔
65
        match self {
1,256,197✔
66
            Err(err) => Break(BreakCase::Err(err)),
×
67
            Ok(value) if value.is_null() => Break(BreakCase::Null),
1,256,197✔
68
            Ok(value) => Continue(value),
1,177,027✔
69
        }
70
    }
1,256,197✔
71
}
72

73
trait ControlFlowMapErr<T, F> {
74
    fn map_err(self, f: F) -> ControlFlow<T>
75
    where
76
        F: FnOnce(Error) -> Error;
77
}
78

79
impl<T, F> ControlFlowMapErr<T, F> for ControlFlow<T> {
80
    fn map_err(self, f: F) -> ControlFlow<T>
58,464✔
81
    where
58,464✔
82
        F: FnOnce(Error) -> Error,
58,464✔
83
    {
84
        match self {
4,872✔
85
            Continue(v) => Continue(v),
53,592✔
86
            Break(BreakCase::Null) => Break(BreakCase::Null),
3,654✔
87
            Break(BreakCase::Err(err)) => Break(BreakCase::Err(f(err))),
1,218✔
88
        }
89
    }
58,464✔
90
}
91

92
pub trait IntoControlFlow<T> {
93
    fn into_control_flow(self) -> ControlFlow<T>;
94
}
95

96
impl<T> IntoControlFlow<T> for Result<T> {
97
    fn into_control_flow(self) -> ControlFlow<T> {
346,350✔
98
        match self {
346,350✔
99
            Err(err) => Break(BreakCase::Err(err)),
79,170✔
100
            Ok(value) => Continue(value),
267,180✔
101
        }
102
    }
346,350✔
103
}
104

105
fn eval_to_str(name: &str, evaluated: Evaluated<'_>) -> ControlFlow<String> {
377,582✔
106
    match evaluated.try_into().break_if_null()? {
377,582✔
107
        Value::Str(value) => Continue(value),
338,606✔
108
        _ => Break(BreakCase::Err(
10,962✔
109
            EvaluateError::FunctionRequiresStringValue(name.to_owned()).into(),
10,962✔
110
        )),
10,962✔
111
    }
112
}
377,582✔
113

114
fn eval_to_int(name: &str, evaluated: Evaluated<'_>) -> ControlFlow<i64> {
260,652✔
115
    match evaluated.try_into().break_if_null()? {
260,652✔
116
        Value::I64(num) => Continue(num),
232,638✔
117
        _ => Break(BreakCase::Err(
17,052✔
118
            EvaluateError::FunctionRequiresIntegerValue(name.to_owned()).into(),
17,052✔
119
        )),
17,052✔
120
    }
121
}
260,652✔
122

123
fn eval_to_float(name: &str, evaluated: Evaluated<'_>) -> ControlFlow<f64> {
333,732✔
124
    match evaluated.try_into().break_if_null()? {
333,732✔
125
        Value::I64(v) => Continue(v as f64),
88,914✔
126
        Value::F32(v) => Continue(v.into()),
×
127
        Value::F64(v) => Continue(v),
160,776✔
128
        _ => Break(BreakCase::Err(
52,374✔
129
            EvaluateError::FunctionRequiresFloatValue(name.to_owned()).into(),
52,374✔
130
        )),
52,374✔
131
    }
132
}
333,732✔
133

134
fn eval_to_point(name: &str, evaluated: Evaluated<'_>) -> ControlFlow<Point> {
7,308✔
135
    match evaluated.try_into().break_if_null()? {
7,308✔
136
        Value::Point(v) => Continue(v),
4,872✔
137
        _ => Break(BreakCase::Err(
1,218✔
138
            EvaluateError::FunctionRequiresPointValue(name.to_owned()).into(),
1,218✔
139
        )),
1,218✔
140
    }
141
}
7,308✔
142

143
// --- text ---
144
pub fn concat(exprs: Vec<Evaluated<'_>>) -> ControlFlow<Evaluated<'_>> {
7,308✔
145
    let value = exprs
7,308✔
146
        .into_iter()
7,308✔
147
        .try_fold(None, |left: Option<Evaluated>, right| match left {
15,834✔
148
            None => Continue(Some(right)),
6,090✔
149
            Some(left) => left.concat(right).break_if_null().map_continue(Some),
9,744✔
150
        })?;
15,834✔
151

152
    value.continue_or_break(EvaluateError::EmptyArgNotAllowedInConcat.into())
6,090✔
153
}
7,308✔
154

155
pub fn concat_ws<'a>(
9,744✔
156
    name: &str,
9,744✔
157
    separator: Evaluated<'a>,
9,744✔
158
    exprs: Vec<Evaluated<'a>>,
9,744✔
159
) -> ControlFlow<Evaluated<'a>> {
9,744✔
160
    let separator = eval_to_str(name, separator)?;
9,744✔
161

162
    let result = exprs
9,744✔
163
        .into_iter()
9,744✔
164
        .map(Value::try_from)
9,744✔
165
        .filter(|value| !matches!(value, Ok(Value::Null)))
30,450✔
166
        .map(|value| Ok(String::from(value?)))
28,014✔
167
        .collect::<Result<Vec<_>>>()
9,744✔
168
        .into_control_flow()?
9,744✔
169
        .join(&separator);
9,744✔
170

171
    Continue(Evaluated::Value(Cow::Owned(Value::Str(result))))
9,744✔
172
}
9,744✔
173

174
pub fn lower<'a>(name: &str, expr: Evaluated<'a>) -> ControlFlow<Evaluated<'a>> {
46,284✔
175
    eval_to_str(name, expr)
46,284✔
176
        .map_continue(|value| value.to_lowercase())
46,284✔
177
        .map_continue(Value::Str)
46,284✔
178
        .map_continue(|v| Evaluated::Value(Cow::Owned(v)))
46,284✔
179
}
46,284✔
180

181
pub fn initcap<'a>(name: &str, expr: Evaluated<'a>) -> ControlFlow<Evaluated<'a>> {
12,180✔
182
    let string = eval_to_str(name, expr)?
12,180✔
183
        .chars()
7,308✔
184
        .scan(true, |state, c| {
43,848✔
185
            let c = if *state {
43,848✔
186
                c.to_ascii_uppercase()
21,924✔
187
            } else {
188
                c.to_ascii_lowercase()
21,924✔
189
            };
190
            *state = !c.is_alphanumeric();
43,848✔
191
            Some(c)
43,848✔
192
        })
43,848✔
193
        .collect();
7,308✔
194

195
    Continue(Evaluated::Value(Cow::Owned(Value::Str(string))))
7,308✔
196
}
12,180✔
197

198
pub fn upper<'a>(name: &str, expr: Evaluated<'a>) -> ControlFlow<Evaluated<'a>> {
29,232✔
199
    eval_to_str(name, expr)
29,232✔
200
        .map_continue(|value| value.to_uppercase())
29,232✔
201
        .map_continue(Value::Str)
29,232✔
202
        .map_continue(|v| Evaluated::Value(Cow::Owned(v)))
29,232✔
203
}
29,232✔
204

205
pub fn left_or_right<'a>(
25,578✔
206
    name: &str,
25,578✔
207
    expr: Evaluated<'_>,
25,578✔
208
    size: Evaluated<'_>,
25,578✔
209
) -> ControlFlow<Evaluated<'a>> {
25,578✔
210
    let string = eval_to_str(name, expr)?;
25,578✔
211
    let size = eval_to_int(name, size)
21,924✔
212
        .map_continue(usize::try_from)?
21,924✔
213
        .map_err(|_| EvaluateError::FunctionRequiresUSizeValue(name.to_owned()).into())
19,488✔
214
        .into_control_flow()?;
19,488✔
215

216
    let converted = if name == "LEFT" {
18,270✔
217
        string.get(..size).map(ToOwned::to_owned).unwrap_or(string)
13,398✔
218
    } else {
219
        let start_pos = if size > string.len() {
4,872✔
220
            0
1,218✔
221
        } else {
222
            string.len() - size
3,654✔
223
        };
224

225
        string
4,872✔
226
            .get(start_pos..)
4,872✔
227
            .map(ToOwned::to_owned)
4,872✔
228
            .unwrap_or(string)
4,872✔
229
    };
230

231
    Continue(Evaluated::Value(Cow::Owned(Value::Str(converted))))
18,270✔
232
}
25,578✔
233

234
pub fn lpad_or_rpad<'a>(
38,976✔
235
    name: &str,
38,976✔
236
    expr: Evaluated<'_>,
38,976✔
237
    size: Evaluated<'_>,
38,976✔
238
    fill: Option<Evaluated<'_>>,
38,976✔
239
) -> ControlFlow<Evaluated<'a>> {
38,976✔
240
    let string = eval_to_str(name, expr)?;
38,976✔
241
    let size = eval_to_int(name, size)
31,668✔
242
        .map_continue(usize::try_from)?
31,668✔
243
        .map_err(|_| EvaluateError::FunctionRequiresUSizeValue(name.to_owned()).into())
26,796✔
244
        .into_control_flow()?;
26,796✔
245

246
    let fill = match fill {
24,360✔
247
        Some(expr) => eval_to_str(name, expr)?,
12,180✔
248
        None => " ".to_owned(),
12,180✔
249
    };
250

251
    let result = if size > string.len() {
21,924✔
252
        let padding_size = size - string.len();
12,180✔
253
        let repeat_count = padding_size / fill.len();
12,180✔
254
        let plus_count = padding_size % fill.len();
12,180✔
255
        let fill = fill.repeat(repeat_count) + &fill[0..plus_count];
12,180✔
256

257
        if name == "LPAD" {
12,180✔
258
            fill + &string
7,308✔
259
        } else {
260
            string + &fill
4,872✔
261
        }
262
    } else {
263
        string[0..size].to_owned()
9,744✔
264
    };
265

266
    Continue(Evaluated::Value(Cow::Owned(Value::Str(result))))
21,924✔
267
}
38,976✔
268

269
pub fn reverse<'a>(name: &str, expr: Evaluated<'a>) -> ControlFlow<Evaluated<'a>> {
4,872✔
270
    let value = eval_to_str(name, expr)?.chars().rev().collect::<String>();
4,872✔
271

272
    Continue(Evaluated::Value(Cow::Owned(Value::Str(value))))
2,436✔
273
}
4,872✔
274

275
pub fn repeat<'a>(
6,090✔
276
    name: &str,
6,090✔
277
    expr: Evaluated<'_>,
6,090✔
278
    num: Evaluated<'_>,
6,090✔
279
) -> ControlFlow<Evaluated<'a>> {
6,090✔
280
    let expr = eval_to_str(name, expr)?;
6,090✔
281
    let num = eval_to_int(name, num)? as usize;
3,654✔
282
    let value = expr.repeat(num);
2,436✔
283

284
    Continue(Evaluated::Value(Cow::Owned(Value::Str(value))))
2,436✔
285
}
6,090✔
286

287
pub fn replace<'a>(
6,090✔
288
    name: &str,
6,090✔
289
    expr: Evaluated<'_>,
6,090✔
290
    old: Evaluated<'_>,
6,090✔
291
    new: Evaluated<'_>,
6,090✔
292
) -> ControlFlow<Evaluated<'a>> {
6,090✔
293
    let expr = eval_to_str(name, expr)?;
6,090✔
294
    let old = eval_to_str(name, old)?;
3,654✔
295
    let new = eval_to_str(name, new)?;
2,436✔
296
    let value = expr.replace(&old, &new);
2,436✔
297

298
    Continue(Evaluated::Value(Cow::Owned(Value::Str(value))))
2,436✔
299
}
6,090✔
300

301
pub fn ascii<'a>(name: &str, expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
30,450✔
302
    let string = eval_to_str(name, expr)?;
30,450✔
303
    let mut iter = string.chars();
29,232✔
304

305
    match (iter.next(), iter.next()) {
29,232✔
306
        (Some(c), None) => {
21,924✔
307
            if c.is_ascii() {
21,924✔
308
                Continue(Evaluated::Value(Cow::Owned(Value::U8(c as u8))))
20,706✔
309
            } else {
310
                Err(EvaluateError::NonAsciiCharacterNotAllowed.into()).into_control_flow()
1,218✔
311
            }
312
        }
313
        _ => {
314
            Err(EvaluateError::AsciiFunctionRequiresSingleCharacterValue.into()).into_control_flow()
7,308✔
315
        }
316
    }
317
}
30,450✔
318

319
pub fn chr<'a>(name: &str, expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
24,360✔
320
    let expr = eval_to_int(name, expr)?;
24,360✔
321

322
    match expr {
23,142✔
323
        0..=255 => {
23,142✔
324
            let expr = expr as u8;
19,488✔
325

326
            Continue(Evaluated::Value(Cow::Owned(Value::Str(
19,488✔
327
                (expr as char).to_string(),
19,488✔
328
            ))))
19,488✔
329
        }
330
        _ => Err(EvaluateError::ChrFunctionRequiresIntegerValueInRange0To255.into())
3,654✔
331
            .into_control_flow(),
3,654✔
332
    }
333
}
24,360✔
334

335
pub fn md5<'a>(name: &str, expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
3,654✔
336
    let string = eval_to_str(name, expr)?;
3,654✔
337
    let mut hasher = Md5::new();
2,436✔
338
    hasher.update(string.as_bytes());
2,436✔
339
    let result = hasher.finalize();
2,436✔
340
    let result = format!("{result:x}");
2,436✔
341

342
    Continue(Evaluated::Value(Cow::Owned(Value::Str(result))))
2,436✔
343
}
3,654✔
344

345
pub fn hex<'a>(name: &str, expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
10,962✔
346
    match expr.try_into().break_if_null()? {
10,962✔
347
        Value::I64(number) => {
3,654✔
348
            let result = format!("{number:X}");
3,654✔
349
            Continue(Evaluated::Value(Cow::Owned(Value::Str(result))))
3,654✔
350
        }
351
        Value::Str(string) => {
4,872✔
352
            let result = string.as_bytes().iter().fold(String::new(), |mut acc, b| {
20,706✔
353
                let _ = write!(acc, "{b:02X}");
20,706✔
354
                acc
20,706✔
355
            });
20,706✔
356

357
            Continue(Evaluated::Value(Cow::Owned(Value::Str(result))))
4,872✔
358
        }
359
        _ => Break(BreakCase::Err(
1,218✔
360
            EvaluateError::FunctionRequiresIntegerOrStringValue(name.to_owned()).into(),
1,218✔
361
        )),
1,218✔
362
    }
363
}
10,962✔
364

365
// --- float ---
366

367
pub fn abs<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
29,232✔
368
    let value = match n.try_into().break_if_null()? {
29,232✔
369
        Value::I8(v) => Value::I8(v.abs()),
1,218✔
370
        Value::I32(v) => Value::I32(v.abs()),
×
371
        Value::I64(v) => Value::I64(v.abs()),
18,270✔
372
        Value::I128(v) => Value::I128(v.abs()),
×
373
        Value::Decimal(v) => Value::Decimal(v.abs()),
1,218✔
374
        Value::F32(v) => Value::F32(v.abs()),
×
375
        Value::F64(v) => Value::F64(v.abs()),
3,654✔
376
        _ => {
377
            return Err(EvaluateError::FunctionRequiresFloatValue(name.to_owned()).into())
3,654✔
378
                .into_control_flow();
3,654✔
379
        }
380
    };
381

382
    Continue(Evaluated::Value(Cow::Owned(value)))
24,360✔
383
}
29,232✔
384

385
pub fn ifnull<'a>(expr: Evaluated<'a>, then: Evaluated<'a>) -> ControlFlow<Evaluated<'a>> {
35,322✔
386
    Continue(if expr.is_null() { then } else { expr })
35,322✔
387
}
35,322✔
388

389
pub fn nullif<'a>(expr1: Evaluated<'a>, expr2: &Evaluated<'a>) -> ControlFlow<Evaluated<'a>> {
7,308✔
390
    Continue(if &expr1 == expr2 {
7,308✔
391
        Evaluated::Value(Cow::Owned(Value::Null))
3,654✔
392
    } else {
393
        expr1
3,654✔
394
    })
395
}
7,308✔
396

397
pub fn sign<'a>(name: &str, n: Evaluated<'a>) -> ControlFlow<Evaluated<'a>> {
19,488✔
398
    let x = eval_to_float(name, n)?;
19,488✔
399
    if x == 0.0 {
14,616✔
400
        return Continue(Evaluated::Value(Cow::Owned(Value::I8(0))));
7,308✔
401
    }
7,308✔
402

403
    Continue(Evaluated::Value(Cow::Owned(Value::I8(x.signum() as i8))))
7,308✔
404
}
19,488✔
405

406
pub fn sqrt<'a>(n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
7,308✔
407
    Value::try_from(n)
7,308✔
408
        .and_then(|v| v.sqrt())
7,308✔
409
        .into_control_flow()
7,308✔
410
        .map_continue(|v| Evaluated::Value(Cow::Owned(v)))
7,308✔
411
}
7,308✔
412

413
pub fn power<'a>(
13,398✔
414
    name: &str,
13,398✔
415
    expr: Evaluated<'_>,
13,398✔
416
    power: Evaluated<'_>,
13,398✔
417
) -> ControlFlow<Evaluated<'a>> {
13,398✔
418
    let expr = eval_to_float(name, expr)?;
13,398✔
419
    let power = eval_to_float(name, power)?;
8,526✔
420

421
    Continue(Evaluated::Value(Cow::Owned(Value::F64(expr.powf(power)))))
6,090✔
422
}
13,398✔
423

424
pub fn ceil<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
19,488✔
425
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.ceil()))))
19,488✔
426
}
19,488✔
427

428
pub fn rand<'a>(name: &str, seed: Option<Evaluated<'_>>) -> ControlFlow<Evaluated<'a>> {
9,744✔
429
    let seed = if let Some(v) = seed {
9,744✔
430
        StdRng::seed_from_u64(eval_to_float(name, v)? as u64).r#gen()
8,526✔
431
    } else {
432
        rand::random()
1,218✔
433
    };
434
    Continue(Evaluated::Value(Cow::Owned(Value::F64(seed))))
4,872✔
435
}
9,744✔
436

437
pub fn round<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
21,924✔
438
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.round()))))
21,924✔
439
}
21,924✔
440

441
pub fn trunc<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
19,488✔
442
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.trunc()))))
19,488✔
443
}
19,488✔
444

445
pub fn floor<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
19,488✔
446
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.floor()))))
19,488✔
447
}
19,488✔
448

449
pub fn radians<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
21,924✔
450
    eval_to_float(name, n)
21,924✔
451
        .map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.to_radians()))))
21,924✔
452
}
21,924✔
453

454
pub fn degrees<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
19,488✔
455
    eval_to_float(name, n)
19,488✔
456
        .map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.to_degrees()))))
19,488✔
457
}
19,488✔
458

459
pub fn exp<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
6,090✔
460
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.exp()))))
6,090✔
461
}
6,090✔
462

463
pub fn log<'a>(
8,526✔
464
    name: &str,
8,526✔
465
    antilog: Evaluated<'_>,
8,526✔
466
    base: Evaluated<'_>,
8,526✔
467
) -> ControlFlow<Evaluated<'a>> {
8,526✔
468
    let antilog = eval_to_float(name, antilog)?;
8,526✔
469
    let base = eval_to_float(name, base)?;
6,090✔
470

471
    Continue(Evaluated::Value(Cow::Owned(Value::F64(antilog.log(base)))))
3,654✔
472
}
8,526✔
473

474
pub fn ln<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
6,090✔
475
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.ln()))))
6,090✔
476
}
6,090✔
477

478
pub fn log2<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
6,090✔
479
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.log2()))))
6,090✔
480
}
6,090✔
481

482
pub fn log10<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
6,090✔
483
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.log10()))))
6,090✔
484
}
6,090✔
485

486
pub fn sin<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
7,308✔
487
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.sin()))))
7,308✔
488
}
7,308✔
489

490
pub fn cos<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
7,308✔
491
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.cos()))))
7,308✔
492
}
7,308✔
493

494
pub fn tan<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
7,308✔
495
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.tan()))))
7,308✔
496
}
7,308✔
497

498
pub fn asin<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
4,872✔
499
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.asin()))))
4,872✔
500
}
4,872✔
501

502
pub fn acos<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
6,090✔
503
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.acos()))))
6,090✔
504
}
6,090✔
505

506
pub fn atan<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
7,308✔
507
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Cow::Owned(Value::F64(n.atan()))))
7,308✔
508
}
7,308✔
509

510
// --- integer ---
511

512
pub fn div<'a>(
30,450✔
513
    name: &str,
30,450✔
514
    dividend: Evaluated<'_>,
30,450✔
515
    divisor: Evaluated<'_>,
30,450✔
516
) -> ControlFlow<Evaluated<'a>> {
30,450✔
517
    let dividend = eval_to_float(name, dividend)
30,450✔
518
        .map_err(|_| EvaluateError::FunctionRequiresFloatOrIntegerValue(name.to_owned()).into())?;
30,450✔
519
    let divisor = eval_to_float(name, divisor)
28,014✔
520
        .map_err(|_| EvaluateError::FunctionRequiresFloatOrIntegerValue(name.to_owned()).into())?;
28,014✔
521

522
    if divisor == 0.0 {
25,578✔
523
        return Err(EvaluateError::DivisorShouldNotBeZero.into()).into_control_flow();
2,436✔
524
    }
23,142✔
525

526
    Continue(Evaluated::Value(Cow::Owned(Value::I64(
23,142✔
527
        (dividend / divisor) as i64,
23,142✔
528
    ))))
23,142✔
529
}
30,450✔
530

531
pub fn gcd<'a>(
28,014✔
532
    name: &str,
28,014✔
533
    left: Evaluated<'_>,
28,014✔
534
    right: Evaluated<'_>,
28,014✔
535
) -> ControlFlow<Evaluated<'a>> {
28,014✔
536
    let left = eval_to_int(name, left)?;
28,014✔
537
    let right = eval_to_int(name, right)?;
24,360✔
538

539
    gcd_i64(left, right).map_continue(|gcd| Evaluated::Value(Cow::Owned(Value::I64(gcd))))
21,924✔
540
}
28,014✔
541

542
pub fn lcm<'a>(
28,014✔
543
    name: &str,
28,014✔
544
    left: Evaluated<'_>,
28,014✔
545
    right: Evaluated<'_>,
28,014✔
546
) -> ControlFlow<Evaluated<'a>> {
28,014✔
547
    fn lcm(a: i64, b: i64) -> ControlFlow<i64> {
23,142✔
548
        let gcd_val: i128 = gcd_i64(a, b)?.into();
23,142✔
549

550
        let a: i128 = a.into();
21,924✔
551
        let b: i128 = b.into();
21,924✔
552

553
        // lcm(a, b) = abs(a * b) / gcd(a, b)   if gcd(a, b) != 0
554
        // lcm(a, b) = 0                        if gcd(a, b) == 0
555
        let result = (a * b).abs().checked_div(gcd_val).unwrap_or(0);
21,924✔
556

557
        i64::try_from(result)
21,924✔
558
            .map_err(|_| EvaluateError::LcmResultOutOfRange.into())
21,924✔
559
            .into_control_flow()
21,924✔
560
    }
23,142✔
561

562
    let left = eval_to_int(name, left)?;
28,014✔
563
    let right = eval_to_int(name, right)?;
25,578✔
564

565
    lcm(left, right).map_continue(|lcm| Evaluated::Value(Cow::Owned(Value::I64(lcm))))
23,142✔
566
}
28,014✔
567

568
fn gcd_i64(a: i64, b: i64) -> ControlFlow<i64> {
45,066✔
569
    let mut a = a
45,066✔
570
        .checked_abs()
45,066✔
571
        .continue_or_break(EvaluateError::GcdLcmOverflow(a).into())?;
45,066✔
572
    let mut b = b
42,630✔
573
        .checked_abs()
42,630✔
574
        .continue_or_break(EvaluateError::GcdLcmOverflow(b).into())?;
42,630✔
575

576
    while b > 0 {
127,890✔
577
        (a, b) = (b, a % b);
85,260✔
578
    }
85,260✔
579

580
    Continue(a)
42,630✔
581
}
45,066✔
582

583
// --- list ---
584
pub fn append<'a>(expr: Evaluated<'_>, value: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
4,872✔
585
    let expr = expr.try_into().break_if_null()?;
4,872✔
586
    let value = value.try_into().break_if_null()?;
4,872✔
587

588
    match (expr, value) {
4,872✔
589
        (Value::List(mut l), v) => {
3,654✔
590
            l.push(v);
3,654✔
591
            Continue(Evaluated::Value(Cow::Owned(Value::List(l))))
3,654✔
592
        }
593
        _ => Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
594
    }
595
}
4,872✔
596

597
pub fn prepend<'a>(expr: Evaluated<'_>, value: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
4,872✔
598
    let expr = expr.try_into().break_if_null()?;
4,872✔
599
    let value = value.try_into().break_if_null()?;
4,872✔
600

601
    match (expr, value) {
4,872✔
602
        (Value::List(mut l), v) => {
3,654✔
603
            l.insert(0, v);
3,654✔
604
            Continue(Evaluated::Value(Cow::Owned(Value::List(l))))
3,654✔
605
        }
606
        _ => Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
607
    }
608
}
4,872✔
609

610
pub fn skip<'a>(
8,526✔
611
    name: &str,
8,526✔
612
    expr: Evaluated<'_>,
8,526✔
613
    size: Evaluated<'_>,
8,526✔
614
) -> ControlFlow<Evaluated<'a>> {
8,526✔
615
    let expr = expr.try_into().break_if_null()?;
8,526✔
616
    let size: usize = match size.try_into().break_if_null()? {
7,308✔
617
        Value::I64(number) => usize::try_from(number)
4,872✔
618
            .map_err(|_| EvaluateError::FunctionRequiresUSizeValue(name.to_owned()).into()),
4,872✔
619
        _ => Err(EvaluateError::FunctionRequiresIntegerValue(name.to_owned()).into()),
1,218✔
620
    }
621
    .into_control_flow()?;
6,090✔
622

623
    match expr {
3,654✔
624
        Value::List(l) => {
2,436✔
625
            let l = l.into_iter().skip(size).collect();
2,436✔
626
            Continue(Evaluated::Value(Cow::Owned(Value::List(l))))
2,436✔
627
        }
628
        _ => Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
629
    }
630
}
8,526✔
631

632
pub fn sort<'a>(expr: Evaluated<'_>, order: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
12,180✔
633
    let expr = expr.try_into().break_if_null()?;
12,180✔
634
    let order = order.try_into().break_if_null()?;
12,180✔
635

636
    match expr {
12,180✔
637
        Value::List(l) => {
10,962✔
638
            let mut l: Vec<(Key, Value)> = l
10,962✔
639
                .into_iter()
10,962✔
640
                .map(|v| match Key::try_from(&v) {
38,976✔
641
                    Ok(key) => Ok((key, v)),
37,758✔
642
                    Err(_) => Err(EvaluateError::InvalidSortType.into()),
1,218✔
643
                })
38,976✔
644
                .collect::<Result<Vec<(Key, Value)>>>()
10,962✔
645
                .into_control_flow()?;
10,962✔
646

647
            let asc = match order {
9,744✔
648
                Value::Str(s) => match s.to_uppercase().as_str() {
8,526✔
649
                    "ASC" => true,
8,526✔
650
                    "DESC" => false,
3,654✔
651
                    _ => return Err(EvaluateError::InvalidSortOrder.into()).into_control_flow(),
1,218✔
652
                },
653
                _ => return Err(EvaluateError::InvalidSortOrder.into()).into_control_flow(),
1,218✔
654
            };
655

656
            l.sort_by(|a, b| if asc { a.0.cmp(&b.0) } else { b.0.cmp(&a.0) });
25,578✔
657

658
            Continue(Evaluated::Value(Cow::Owned(Value::List(
659
                l.into_iter().map(|(_, v)| v).collect(),
7,308✔
660
            ))))
661
        }
662
        _ => Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
663
    }
664
}
12,180✔
665

666
pub fn slice<'a>(
14,616✔
667
    name: &str,
14,616✔
668
    expr: Evaluated<'_>,
14,616✔
669
    start: Evaluated<'_>,
14,616✔
670
    length: Evaluated<'_>,
14,616✔
671
) -> ControlFlow<Evaluated<'a>> {
14,616✔
672
    let expr = expr.try_into().break_if_null()?;
14,616✔
673
    let mut start = eval_to_int(name, start)?;
14,616✔
674
    let length = eval_to_int(name, length)
13,398✔
675
        .map_continue(usize::try_from)?
13,398✔
676
        .map_err(|_| EvaluateError::FunctionRequiresUSizeValue(name.to_owned()).into())
12,180✔
677
        .into_control_flow()?;
12,180✔
678

679
    match expr {
12,180✔
680
        Value::List(l) => {
10,962✔
681
            if start < 0 {
10,962✔
682
                start += l.len() as i64;
3,654✔
683
            }
7,308✔
684
            if start < 0 {
10,962✔
685
                start = 0;
1,218✔
686
            }
9,744✔
687

688
            let start_usize = start as usize;
10,962✔
689

690
            let l = l.into_iter().skip(start_usize).take(length).collect();
10,962✔
691
            Continue(Evaluated::Value(Cow::Owned(Value::List(l))))
10,962✔
692
        }
693
        _ => Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
694
    }
695
}
14,616✔
696

697
pub fn take<'a>(
12,180✔
698
    name: &str,
12,180✔
699
    expr: Evaluated<'_>,
12,180✔
700
    size: Evaluated<'_>,
12,180✔
701
) -> ControlFlow<Evaluated<'a>> {
12,180✔
702
    let expr = expr.try_into().break_if_null()?;
12,180✔
703
    let size = eval_to_int(name, size)
10,962✔
704
        .map_continue(usize::try_from)?
10,962✔
705
        .map_err(|_| EvaluateError::FunctionRequiresUSizeValue(name.to_owned()).into())
8,526✔
706
        .into_control_flow()?;
8,526✔
707

708
    match expr {
7,308✔
709
        Value::List(l) => {
6,090✔
710
            let l = l.into_iter().take(size).collect();
6,090✔
711
            Continue(Evaluated::Value(Cow::Owned(Value::List(l))))
6,090✔
712
        }
713
        _ => Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
714
    }
715
}
12,180✔
716

717
pub fn is_empty<'a>(expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
13,398✔
718
    let expr = expr.try_into().break_if_null()?;
13,398✔
719
    let length = match expr {
13,398✔
720
        Value::List(l) => l.len(),
6,090✔
721
        Value::Map(m) => m.len(),
6,090✔
722
        _ => {
723
            return Err(EvaluateError::MapOrListTypeRequired.into()).into_control_flow();
1,218✔
724
        }
725
    };
726

727
    Continue(Evaluated::Value(Cow::Owned(Value::Bool(length == 0))))
12,180✔
728
}
13,398✔
729

730
// --- etc ---
731

732
pub fn unwrap<'a>(
42,630✔
733
    name: &str,
42,630✔
734
    expr: Evaluated<'a>,
42,630✔
735
    selector: Evaluated<'_>,
42,630✔
736
) -> ControlFlow<Evaluated<'a>> {
42,630✔
737
    let value = match expr {
40,194✔
738
        _ if expr.is_null() => return Continue(expr),
42,630✔
739
        Evaluated::Value(value) => value,
38,976✔
740
        _ => {
741
            return Err(EvaluateError::FunctionRequiresMapValue(name.to_owned()).into())
1,218✔
742
                .into_control_flow();
1,218✔
743
        }
744
    };
745
    let selector = eval_to_str(name, selector)?;
38,976✔
746

747
    value
37,758✔
748
        .selector(&selector)
37,758✔
749
        .into_control_flow()
37,758✔
750
        .map_continue(|v| Evaluated::Value(Cow::Owned(v)))
37,758✔
751
}
42,630✔
752

753
pub fn generate_uuid<'a>() -> Evaluated<'a> {
10,963✔
754
    Evaluated::Value(Cow::Owned(Value::Uuid(Uuid::new_v4().as_u128())))
10,963✔
755
}
10,963✔
756

757
pub fn greatest<'a>(name: &str, exprs: Vec<Evaluated<'a>>) -> Result<Evaluated<'a>> {
9,744✔
758
    exprs
9,744✔
759
        .into_iter()
9,744✔
760
        .try_fold(None, |greatest, expr| -> Result<_> {
35,322✔
761
            let Some(greatest) = greatest else {
35,322✔
762
                return Ok(Some(expr));
9,744✔
763
            };
764

765
            match greatest.evaluate_cmp(&expr) {
25,578✔
766
                Some(std::cmp::Ordering::Less) => Ok(Some(expr)),
12,180✔
767
                Some(_) => Ok(Some(greatest)),
9,744✔
768
                None => Err(EvaluateError::NonComparableArgumentError(name.to_owned()).into()),
3,654✔
769
            }
770
        })?
35,322✔
771
        .ok_or(EvaluateError::FunctionRequiresAtLeastOneArgument(name.to_owned()).into())
6,090✔
772
}
9,744✔
773

774
pub fn format<'a>(
24,360✔
775
    name: &str,
24,360✔
776
    expr: Evaluated<'_>,
24,360✔
777
    format: Evaluated<'_>,
24,360✔
778
) -> ControlFlow<Evaluated<'a>> {
24,360✔
779
    match expr.try_into().break_if_null()? {
24,360✔
780
        Value::Date(expr) => eval_to_str(name, format)
7,308✔
781
            .map_continue(|format| chrono::NaiveDate::format(&expr, &format).to_string()),
7,308✔
782
        Value::Timestamp(expr) => eval_to_str(name, format)
9,744✔
783
            .map_continue(|format| chrono::NaiveDateTime::format(&expr, &format).to_string()),
9,744✔
784
        Value::Time(expr) => eval_to_str(name, format)
6,090✔
785
            .map_continue(|format| chrono::NaiveTime::format(&expr, &format).to_string()),
6,090✔
786
        value => Err(EvaluateError::UnsupportedExprForFormatFunction(value.into()).into())
1,218✔
787
            .into_control_flow(),
1,218✔
788
    }
789
    .map_continue(Value::Str)
24,360✔
790
    .map_continue(|v| Evaluated::Value(Cow::Owned(v)))
24,360✔
791
}
24,360✔
792

793
pub fn last_day<'a>(name: &str, expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
6,090✔
794
    let date = match expr.try_into().break_if_null()? {
6,090✔
795
        Value::Date(date) => date,
2,436✔
796
        Value::Timestamp(timestamp) => timestamp.date(),
2,436✔
797
        _ => {
798
            return Err(EvaluateError::FunctionRequiresDateOrDateTimeValue(name.to_owned()).into())
1,218✔
799
                .into_control_flow();
1,218✔
800
        }
801
    };
802

803
    Continue(Evaluated::Value(Cow::Owned(Value::Date(
4,872✔
804
        date + Months::new(1) - Duration::days(i64::from(date.day())),
4,872✔
805
    ))))
4,872✔
806
}
6,090✔
807

808
pub fn to_date<'a>(
15,834✔
809
    name: &str,
15,834✔
810
    expr: Evaluated<'_>,
15,834✔
811
    format: Evaluated<'_>,
15,834✔
812
) -> ControlFlow<Evaluated<'a>> {
15,834✔
813
    match expr.try_into().break_if_null()? {
15,834✔
814
        Value::Str(expr) => {
14,616✔
815
            let format = eval_to_str(name, format)?;
14,616✔
816

817
            chrono::NaiveDate::parse_from_str(&expr, &format)
14,616✔
818
                .map(Value::Date)
14,616✔
819
                .map(|v| Evaluated::Value(Cow::Owned(v)))
14,616✔
820
                .map_err(|err| {
14,616✔
821
                    let err: EvaluateError = err.into();
1,218✔
822
                    err.into()
1,218✔
823
                })
1,218✔
824
        }
825
        _ => Err(EvaluateError::FunctionRequiresStringValue(name.to_owned()).into()),
1,218✔
826
    }
827
    .into_control_flow()
15,834✔
828
}
15,834✔
829

830
pub fn to_timestamp<'a>(
15,834✔
831
    name: &str,
15,834✔
832
    expr: Evaluated<'_>,
15,834✔
833
    format: Evaluated<'_>,
15,834✔
834
) -> ControlFlow<Evaluated<'a>> {
15,834✔
835
    match expr.try_into().break_if_null()? {
15,834✔
836
        Value::Str(expr) => {
14,616✔
837
            let format = eval_to_str(name, format)?;
14,616✔
838

839
            chrono::NaiveDateTime::parse_from_str(&expr, &format)
14,616✔
840
                .map(Value::Timestamp)
14,616✔
841
                .map(|v| Evaluated::Value(Cow::Owned(v)))
14,616✔
842
                .map_err(|err| {
14,616✔
843
                    let err: EvaluateError = err.into();
7,308✔
844
                    err.into()
7,308✔
845
                })
7,308✔
846
        }
847
        _ => Err(EvaluateError::FunctionRequiresStringValue(name.to_owned()).into()),
1,218✔
848
    }
849
    .into_control_flow()
15,834✔
850
}
15,834✔
851

852
pub fn add_month<'a>(
13,398✔
853
    name: &str,
13,398✔
854
    expr: Evaluated<'_>,
13,398✔
855
    size: Evaluated<'_>,
13,398✔
856
) -> ControlFlow<Evaluated<'a>> {
13,398✔
857
    let size = eval_to_int(name, size)?;
13,398✔
858
    let expr = eval_to_str(name, expr)?;
12,180✔
859
    let expr = chrono::NaiveDate::parse_from_str(&expr, "%Y-%m-%d")
12,180✔
860
        .map_err(EvaluateError::from)
12,180✔
861
        .map_err(Error::from)
12,180✔
862
        .into_control_flow()?;
12,180✔
863
    let date = {
6,090✔
864
        let size_as_u32 = size
8,526✔
865
            .abs()
8,526✔
866
            .try_into()
8,526✔
867
            .map_err(|_| EvaluateError::I64ToU32ConversionFailure(name.to_owned()).into())
8,526✔
868
            .into_control_flow()?;
8,526✔
869
        let new_months = chrono::Months::new(size_as_u32);
7,308✔
870

871
        if size <= 0 {
7,308✔
872
            expr.checked_sub_months(new_months)
2,436✔
873
        } else {
874
            expr.checked_add_months(new_months)
4,872✔
875
        }
876
        .continue_or_break(EvaluateError::ChrFunctionRequiresIntegerValueInRange0To255.into())?
7,308✔
877
    };
878
    Continue(Evaluated::Value(Cow::Owned(Value::Date(date))))
6,090✔
879
}
13,398✔
880

881
pub fn to_time<'a>(
9,744✔
882
    name: &str,
9,744✔
883
    expr: Evaluated<'_>,
9,744✔
884
    format: Evaluated<'_>,
9,744✔
885
) -> ControlFlow<Evaluated<'a>> {
9,744✔
886
    match expr.try_into().break_if_null()? {
9,744✔
887
        Value::Str(expr) => {
8,526✔
888
            let format = eval_to_str(name, format)?;
8,526✔
889

890
            chrono::NaiveTime::parse_from_str(&expr, &format)
8,526✔
891
                .map(Value::Time)
8,526✔
892
                .map(|v| Evaluated::Value(Cow::Owned(v)))
8,526✔
893
                .map_err(|err| {
8,526✔
894
                    let err: EvaluateError = err.into();
1,218✔
895
                    err.into()
1,218✔
896
                })
1,218✔
897
        }
898
        _ => Err(EvaluateError::FunctionRequiresStringValue(name.to_owned()).into()),
1,218✔
899
    }
900
    .into_control_flow()
9,744✔
901
}
9,744✔
902

903
pub fn position<'a>(
7,309✔
904
    from_expr: Evaluated<'_>,
7,309✔
905
    sub_expr: Evaluated<'_>,
7,309✔
906
) -> ControlFlow<Evaluated<'a>> {
7,309✔
907
    let from: Value = from_expr.try_into().break_if_null()?;
7,309✔
908
    let sub = sub_expr.try_into().break_if_null()?;
7,309✔
909

910
    from.position(&sub)
6,091✔
911
        .map(|v| Evaluated::Value(Cow::Owned(v)))
6,091✔
912
        .into_control_flow()
6,091✔
913
}
7,309✔
914

915
pub fn find_idx<'a>(
17,053✔
916
    name: &str,
17,053✔
917
    from: Evaluated<'a>,
17,053✔
918
    sub: Evaluated<'a>,
17,053✔
919
    start: Option<Evaluated<'a>>,
17,053✔
920
) -> ControlFlow<Evaluated<'a>> {
17,053✔
921
    let from_expr = eval_to_str(name, from)?;
17,053✔
922
    let sub_expr = eval_to_str(name, sub)?;
17,053✔
923

924
    match start {
14,617✔
925
        Some(start) => {
8,526✔
926
            let start = eval_to_int(name, start)?;
8,526✔
927
            Value::find_idx(
7,308✔
928
                &Value::Str(from_expr),
7,308✔
929
                &Value::Str(sub_expr),
7,308✔
930
                &Value::I64(start),
7,308✔
931
            )
932
        }
933
        None => Value::position(&Value::Str(from_expr), &Value::Str(sub_expr)),
6,091✔
934
    }
935
    .map(|v| Evaluated::Value(Cow::Owned(v)))
13,399✔
936
    .into_control_flow()
13,399✔
937
}
17,053✔
938

939
pub fn extract<'a>(field: DateTimeField, expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
20,707✔
940
    Value::try_from(expr)
20,707✔
941
        .and_then(|v| v.extract(&field))
20,707✔
942
        .map(|v| Evaluated::Value(Cow::Owned(v)))
20,707✔
943
        .into_control_flow()
20,707✔
944
}
20,707✔
945

946
pub fn point<'a>(name: &str, x: Evaluated<'_>, y: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
12,180✔
947
    let x = eval_to_float(name, x)?;
12,180✔
948
    let y = eval_to_float(name, y)?;
12,180✔
949

950
    Continue(Evaluated::Value(Cow::Owned(Value::Point(Point::new(x, y)))))
12,180✔
951
}
12,180✔
952

953
pub fn get_x<'a>(name: &str, expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
4,872✔
954
    match expr.try_into().break_if_null()? {
4,872✔
955
        Value::Point(v) => Ok(Evaluated::Value(Cow::Owned(Value::F64(v.x)))),
3,654✔
956
        _ => Err(EvaluateError::FunctionRequiresPointValue(name.to_owned()).into()),
1,218✔
957
    }
958
    .into_control_flow()
4,872✔
959
}
4,872✔
960

961
pub fn get_y<'a>(name: &str, expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
4,872✔
962
    match expr.try_into().break_if_null()? {
4,872✔
963
        Value::Point(v) => Ok(Evaluated::Value(Cow::Owned(Value::F64(v.y)))),
3,654✔
964
        _ => Err(EvaluateError::FunctionRequiresPointValue(name.to_owned()).into()),
1,218✔
965
    }
966
    .into_control_flow()
4,872✔
967
}
4,872✔
968

969
pub fn calc_distance<'a>(
3,654✔
970
    name: &str,
3,654✔
971
    x: Evaluated<'_>,
3,654✔
972
    y: Evaluated<'_>,
3,654✔
973
) -> ControlFlow<Evaluated<'a>> {
3,654✔
974
    let x = eval_to_point(name, x)?;
3,654✔
975
    let y = eval_to_point(name, y)?;
3,654✔
976

977
    Continue(Evaluated::Value(Cow::Owned(Value::F64(
1,218✔
978
        Point::calc_distance(&x, &y),
1,218✔
979
    ))))
1,218✔
980
}
3,654✔
981

982
pub fn length<'a>(name: &str, expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
11,397✔
983
    match expr.try_into().break_if_null()? {
11,397✔
984
        Value::Str(expr) => Ok(Evaluated::Value(Cow::Owned(Value::U64(
8,961✔
985
            expr.chars().count() as u64,
8,961✔
986
        )))),
8,961✔
987
        Value::List(expr) => Ok(Evaluated::Value(Cow::Owned(Value::U64(expr.len() as u64)))),
1,218✔
988
        Value::Map(expr) => Ok(Evaluated::Value(Cow::Owned(Value::U64(expr.len() as u64)))),
1,218✔
UNCOV
989
        _ => Err(EvaluateError::FunctionRequiresStrOrListOrMapValue(name.to_owned()).into()),
×
990
    }
991
    .into_control_flow()
11,397✔
992
}
11,397✔
993

994
pub fn coalesce<'a>(exprs: Vec<Evaluated<'_>>) -> Result<Evaluated<'a>> {
54,810✔
995
    if exprs.is_empty() {
54,810✔
996
        return Err((EvaluateError::FunctionRequiresMoreArguments {
2,436✔
997
            function_name: "COALESCE".to_owned(),
2,436✔
998
            required_minimum: 1,
2,436✔
999
            found: exprs.len(),
2,436✔
1000
        })
2,436✔
1001
        .into());
2,436✔
1002
    }
52,374✔
1003

1004
    let control_flow =
52,374✔
1005
        exprs
52,374✔
1006
            .into_iter()
52,374✔
1007
            .map(TryInto::try_into)
52,374✔
1008
            .try_for_each(|item: Result<Value>| match item {
99,876✔
1009
                Ok(value) if value.is_null() => StdControlFlow::Continue(()),
99,876✔
1010
                Ok(value) => StdControlFlow::Break(Ok(value)),
47,502✔
1011
                Err(err) => StdControlFlow::Break(Err(err)),
×
1012
            });
99,876✔
1013

1014
    match control_flow {
47,502✔
1015
        StdControlFlow::Break(Ok(value)) => Ok(Evaluated::Value(Cow::Owned(value))),
47,502✔
1016
        StdControlFlow::Break(Err(err)) => Err(err),
×
1017
        StdControlFlow::Continue(()) => Ok(Evaluated::Value(Cow::Owned(Value::Null))),
4,872✔
1018
    }
1019
}
54,810✔
1020

1021
pub fn entries<'a>(name: &str, expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
2,436✔
1022
    match expr.try_into().break_if_null()? {
2,436✔
1023
        Value::Map(expr) => {
1,218✔
1024
            let entries = expr
1,218✔
1025
                .into_iter()
1,218✔
1026
                .map(|(k, v)| Value::List(vec![Value::Str(k), v]))
1,218✔
1027
                .collect::<Vec<_>>();
1,218✔
1028
            Ok(Evaluated::Value(Cow::Owned(Value::List(entries))))
1,218✔
1029
        }
1030
        _ => Err(EvaluateError::FunctionRequiresMapValue(name.to_owned()).into()),
1,218✔
1031
    }
1032
    .into_control_flow()
2,436✔
1033
}
2,436✔
1034

1035
pub fn keys<'a>(expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
4,872✔
1036
    match expr.try_into().break_if_null()? {
4,872✔
1037
        Value::Map(m) => Ok(Evaluated::Value(Cow::Owned(Value::List(
3,654✔
1038
            m.into_keys().map(Value::Str).collect(),
3,654✔
1039
        )))),
3,654✔
1040
        _ => Err(EvaluateError::MapTypeRequired.into()),
1,218✔
1041
    }
1042
    .into_control_flow()
4,872✔
1043
}
4,872✔
1044

1045
pub fn values<'a>(expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
6,090✔
1046
    match expr.try_into().break_if_null()? {
6,090✔
1047
        Value::Map(m) => Ok(Evaluated::Value(Cow::Owned(Value::List(
4,872✔
1048
            m.into_values().collect(),
4,872✔
1049
        )))),
4,872✔
1050
        _ => Err(EvaluateError::MapTypeRequired.into()),
1,218✔
1051
    }
1052
    .into_control_flow()
6,090✔
1053
}
6,090✔
1054

1055
pub fn splice<'a>(
7,308✔
1056
    name: &str,
7,308✔
1057
    list_data: Evaluated<'_>,
7,308✔
1058
    begin_index: Evaluated<'_>,
7,308✔
1059
    end_index: Evaluated<'_>,
7,308✔
1060
    values: Option<Evaluated<'_>>,
7,308✔
1061
) -> ControlFlow<Evaluated<'a>> {
7,308✔
1062
    let Value::List(list_data) = list_data.try_into().break_if_null()? else {
7,308✔
1063
        return Err(EvaluateError::ListTypeRequired.into()).into_control_flow();
1,218✔
1064
    };
1065

1066
    let begin_index = eval_to_int(name, begin_index)?.max(0);
6,090✔
1067
    let begin_index = usize::try_from(begin_index)
6,090✔
1068
        .map_err(|_| EvaluateError::FunctionRequiresUSizeValue(name.to_owned()).into())
6,090✔
1069
        .into_control_flow()?;
6,090✔
1070
    let end_index = eval_to_int(name, end_index)?.max(0);
6,090✔
1071
    let end_index = usize::try_from(end_index)
6,090✔
1072
        .map_err(|_| EvaluateError::FunctionRequiresUSizeValue(name.to_owned()).into())
6,090✔
1073
        .into_control_flow()?;
6,090✔
1074

1075
    let (left, right) = {
6,090✔
1076
        let mut list_iter = list_data.into_iter();
6,090✔
1077
        let left: Vec<_> = list_iter.by_ref().take(begin_index).collect();
6,090✔
1078
        let right: Vec<_> = list_iter.skip(end_index - begin_index).collect();
6,090✔
1079
        (left, right)
6,090✔
1080
    };
6,090✔
1081

1082
    let center = match values {
6,090✔
1083
        Some(values) => match values.try_into().break_if_null()? {
4,872✔
1084
            Value::List(list) => list,
3,654✔
1085
            _ => return Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
1086
        },
1087
        None => vec![],
1,218✔
1088
    };
1089

1090
    let result = {
4,872✔
1091
        let mut result = vec![];
4,872✔
1092
        result.extend(left);
4,872✔
1093
        result.extend(center);
4,872✔
1094
        result.extend(right);
4,872✔
1095
        result
4,872✔
1096
    };
1097

1098
    Continue(Evaluated::Value(Cow::Owned(Value::List(result))))
4,872✔
1099
}
7,308✔
1100

1101
pub fn dedup<'a>(list: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
3,654✔
1102
    match list.try_into().break_if_null()? {
3,654✔
1103
        Value::List(mut list) => {
2,436✔
1104
            list.dedup();
2,436✔
1105
            Continue(Evaluated::Value(Cow::Owned(Value::List(list))))
2,436✔
1106
        }
1107
        _ => Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
1108
    }
1109
}
3,654✔
1110

1111
pub fn select_arrow_value(base: &Value, selector: &Value) -> Result<Value> {
49,938✔
1112
    if base.is_null() {
49,938✔
1113
        return Ok(Value::Null);
×
1114
    }
49,938✔
1115

1116
    match base {
49,938✔
1117
        Value::Map(map) => {
23,142✔
1118
            let key = match selector {
23,142✔
1119
                Value::Str(value) => Cow::Borrowed(value.as_str()),
7,308✔
1120
                Value::I8(value) => Cow::Owned(value.to_string()),
1,218✔
1121
                Value::I16(value) => Cow::Owned(value.to_string()),
2,436✔
1122
                Value::I32(value) => Cow::Owned(value.to_string()),
1,218✔
1123
                Value::I64(value) => Cow::Owned(value.to_string()),
2,436✔
1124
                Value::I128(value) => Cow::Owned(value.to_string()),
1,218✔
1125
                Value::U8(value) => Cow::Owned(value.to_string()),
1,218✔
1126
                Value::U16(value) => Cow::Owned(value.to_string()),
1,218✔
1127
                Value::U32(value) => Cow::Owned(value.to_string()),
1,218✔
1128
                Value::U64(value) => Cow::Owned(value.to_string()),
1,218✔
1129
                Value::U128(value) => Cow::Owned(value.to_string()),
1,218✔
1130
                _ => {
1131
                    return Err(EvaluateError::ArrowSelectorRequiresIntegerOrString(format!(
1,218✔
1132
                        "{selector:?}"
1,218✔
1133
                    ))
1,218✔
1134
                    .into());
1,218✔
1135
                }
1136
            };
1137

1138
            Ok(map.get(key.as_ref()).cloned().unwrap_or(Value::Null))
21,924✔
1139
        }
1140
        Value::List(list) => {
23,142✔
1141
            let index = match selector {
23,142✔
1142
                Value::Str(value) => value.parse::<usize>().ok(),
2,436✔
1143
                Value::I8(value) => usize::try_from(*value).ok(),
1,218✔
1144
                Value::I16(value) => usize::try_from(*value).ok(),
2,436✔
1145
                Value::I32(value) => usize::try_from(*value).ok(),
1,218✔
1146
                Value::I64(value) => usize::try_from(*value).ok(),
8,526✔
1147
                Value::I128(value) => usize::try_from(*value).ok(),
1,218✔
1148
                Value::U8(value) => Some(*value as usize),
1,218✔
1149
                Value::U16(value) => Some(*value as usize),
1,218✔
1150
                Value::U32(value) => usize::try_from(*value).ok(),
1,218✔
1151
                Value::U64(value) => usize::try_from(*value).ok(),
1,218✔
1152
                Value::U128(value) => usize::try_from(*value).ok(),
1,218✔
1153
                _ => {
1154
                    return Err(EvaluateError::ArrowSelectorRequiresIntegerOrString(format!(
×
1155
                        "{selector:?}?"
×
1156
                    ))
×
1157
                    .into());
×
1158
                }
1159
            };
1160

1161
            Ok(index
23,142✔
1162
                .and_then(|idx| list.get(idx).cloned())
23,142✔
1163
                .unwrap_or(Value::Null))
23,142✔
1164
        }
1165
        _ => Err(EvaluateError::ArrowBaseRequiresMapOrList.into()),
3,654✔
1166
    }
1167
}
49,938✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc