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

gluesql / gluesql / 20000719104

07 Dec 2025 07:12AM UTC coverage: 98.107% (+0.1%) from 98.003%
20000719104

push

github

web-flow
Eliminate Literal type by absorbing into Evaluated (#1845)

This PR eliminates the data::Literal type entirely by absorbing its functionality into the existing Evaluated enum in the evaluator layer.

**Background**
The codebase had three overlapping types for representing values during query execution:

* AstLiteral – parsed literal from SQL input
* Literal – intermediate representation for literal operations
* Value – final evaluated result
The Literal type was supposed to handle literal-specific operations (arithmetic, comparison, concatenation, etc.) before converting to Value. However, the Evaluated enum already existed in the evaluator and could handle these cases directly, making Literal an unnecessary intermediate layer.

**What Changed**
- Removed:
data::Literal enum (Boolean, Number, Text, Bytea, Null variants)
data::LiteralError
data::value::ConvertError

- Replaced with:
// Before: Evaluated wrapped Literal
pub enum Evaluated<'a> {
    Literal(Literal<'a>),
    StrSlice { ... },
    Value(Value),
}

// After: Evaluated handles literals directly
pub enum Evaluated<'a> {
    Number(Cow<'a, BigDecimal>),  // numeric literals
    Text(Cow<'a, str>),           // string literals
    StrSlice { ... },
    Value(Value),                  // bool, bytea, null → directly to Value
}

- Error consolidation:

LiteralError → merged into EvaluateError
ConvertError → merged into ValueError::ConvertFailed
New modules under executor/evaluate/evaluated/:

binary_op.rs, unary_op.rs – arithmetic operations
cmp.rs, eq.rs – comparisons
concat.rs, like.rs – string operations
convert/number.rs, convert/text.rs – type conversions

1628 of 1628 new or added lines in 17 files covered. (100.0%)

6 existing lines in 2 files now uncovered.

39692 of 40458 relevant lines covered (98.11%)

64601.45 hits per line

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

97.73
/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>> {
UNCOV
44
    fn break_if_null(self) -> ControlFlow<Evaluated<'a>> {
×
UNCOV
45
        match self {
×
46
            Err(err) => Break(BreakCase::Err(err)),
×
UNCOV
47
            Ok(value) if value.is_null() => Break(BreakCase::Null),
×
UNCOV
48
            Ok(value) => Continue(value),
×
49
        }
UNCOV
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(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(Evaluated::Value)
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(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(Evaluated::Value)
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(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(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(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(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(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(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(Value::Str((expr as char).to_string())))
19,488✔
327
        }
328
        _ => Err(EvaluateError::ChrFunctionRequiresIntegerValueInRange0To255.into())
3,654✔
329
            .into_control_flow(),
3,654✔
330
    }
331
}
24,360✔
332

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

340
    Continue(Evaluated::Value(Value::Str(result)))
2,436✔
341
}
3,654✔
342

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

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

363
// --- float ---
364

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

380
    Continue(Evaluated::Value(value))
24,360✔
381
}
29,232✔
382

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

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

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

401
    Continue(Evaluated::Value(Value::I8(x.signum() as i8)))
7,308✔
402
}
19,488✔
403

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

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

419
    Continue(Evaluated::Value(Value::F64(expr.powf(power))))
6,090✔
420
}
13,398✔
421

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

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

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

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

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

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

451
pub fn degrees<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
19,488✔
452
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Value::F64(n.to_degrees())))
19,488✔
453
}
19,488✔
454

455
pub fn exp<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
6,090✔
456
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Value::F64(n.exp())))
6,090✔
457
}
6,090✔
458

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

467
    Continue(Evaluated::Value(Value::F64(antilog.log(base))))
3,654✔
468
}
8,526✔
469

470
pub fn ln<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
6,090✔
471
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Value::F64(n.ln())))
6,090✔
472
}
6,090✔
473

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

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

482
pub fn sin<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
7,308✔
483
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Value::F64(n.sin())))
7,308✔
484
}
7,308✔
485

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

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

494
pub fn asin<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
4,872✔
495
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Value::F64(n.asin())))
4,872✔
496
}
4,872✔
497

498
pub fn acos<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
6,090✔
499
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Value::F64(n.acos())))
6,090✔
500
}
6,090✔
501

502
pub fn atan<'a>(name: &str, n: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
7,308✔
503
    eval_to_float(name, n).map_continue(|n| Evaluated::Value(Value::F64(n.atan())))
7,308✔
504
}
7,308✔
505

506
// --- integer ---
507

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

518
    if divisor == 0.0 {
25,578✔
519
        return Err(EvaluateError::DivisorShouldNotBeZero.into()).into_control_flow();
2,436✔
520
    }
23,142✔
521

522
    Continue(Evaluated::Value(Value::I64((dividend / divisor) as i64)))
23,142✔
523
}
30,450✔
524

525
pub fn gcd<'a>(
28,014✔
526
    name: &str,
28,014✔
527
    left: Evaluated<'_>,
28,014✔
528
    right: Evaluated<'_>,
28,014✔
529
) -> ControlFlow<Evaluated<'a>> {
28,014✔
530
    let left = eval_to_int(name, left)?;
28,014✔
531
    let right = eval_to_int(name, right)?;
24,360✔
532

533
    gcd_i64(left, right).map_continue(|gcd| Evaluated::Value(Value::I64(gcd)))
21,924✔
534
}
28,014✔
535

536
pub fn lcm<'a>(
28,014✔
537
    name: &str,
28,014✔
538
    left: Evaluated<'_>,
28,014✔
539
    right: Evaluated<'_>,
28,014✔
540
) -> ControlFlow<Evaluated<'a>> {
28,014✔
541
    fn lcm(a: i64, b: i64) -> ControlFlow<i64> {
23,142✔
542
        let gcd_val: i128 = gcd_i64(a, b)?.into();
23,142✔
543

544
        let a: i128 = a.into();
21,924✔
545
        let b: i128 = b.into();
21,924✔
546

547
        // lcm(a, b) = abs(a * b) / gcd(a, b)   if gcd(a, b) != 0
548
        // lcm(a, b) = 0                        if gcd(a, b) == 0
549
        let result = (a * b).abs().checked_div(gcd_val).unwrap_or(0);
21,924✔
550

551
        i64::try_from(result)
21,924✔
552
            .map_err(|_| EvaluateError::LcmResultOutOfRange.into())
21,924✔
553
            .into_control_flow()
21,924✔
554
    }
23,142✔
555

556
    let left = eval_to_int(name, left)?;
28,014✔
557
    let right = eval_to_int(name, right)?;
25,578✔
558

559
    lcm(left, right).map_continue(|lcm| Evaluated::Value(Value::I64(lcm)))
23,142✔
560
}
28,014✔
561

562
fn gcd_i64(a: i64, b: i64) -> ControlFlow<i64> {
45,066✔
563
    let mut a = a
45,066✔
564
        .checked_abs()
45,066✔
565
        .continue_or_break(EvaluateError::GcdLcmOverflow(a).into())?;
45,066✔
566
    let mut b = b
42,630✔
567
        .checked_abs()
42,630✔
568
        .continue_or_break(EvaluateError::GcdLcmOverflow(b).into())?;
42,630✔
569

570
    while b > 0 {
127,890✔
571
        (a, b) = (b, a % b);
85,260✔
572
    }
85,260✔
573

574
    Continue(a)
42,630✔
575
}
45,066✔
576

577
// --- list ---
578
pub fn append<'a>(expr: Evaluated<'_>, value: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
4,872✔
579
    let expr = expr.try_into().break_if_null()?;
4,872✔
580
    let value = value.try_into().break_if_null()?;
4,872✔
581

582
    match (expr, value) {
4,872✔
583
        (Value::List(mut l), v) => {
3,654✔
584
            l.push(v);
3,654✔
585
            Continue(Evaluated::Value(Value::List(l)))
3,654✔
586
        }
587
        _ => Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
588
    }
589
}
4,872✔
590

591
pub fn prepend<'a>(expr: Evaluated<'_>, value: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
4,872✔
592
    let expr = expr.try_into().break_if_null()?;
4,872✔
593
    let value = value.try_into().break_if_null()?;
4,872✔
594

595
    match (expr, value) {
4,872✔
596
        (Value::List(mut l), v) => {
3,654✔
597
            l.insert(0, v);
3,654✔
598
            Continue(Evaluated::Value(Value::List(l)))
3,654✔
599
        }
600
        _ => Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
601
    }
602
}
4,872✔
603

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

617
    match expr {
3,654✔
618
        Value::List(l) => {
2,436✔
619
            let l = l.into_iter().skip(size).collect();
2,436✔
620
            Continue(Evaluated::Value(Value::List(l)))
2,436✔
621
        }
622
        _ => Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
623
    }
624
}
8,526✔
625

626
pub fn sort<'a>(expr: Evaluated<'_>, order: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
12,180✔
627
    let expr = expr.try_into().break_if_null()?;
12,180✔
628
    let order = order.try_into().break_if_null()?;
12,180✔
629

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

641
            let asc = match order {
9,744✔
642
                Value::Str(s) => match s.to_uppercase().as_str() {
8,526✔
643
                    "ASC" => true,
8,526✔
644
                    "DESC" => false,
3,654✔
645
                    _ => return Err(EvaluateError::InvalidSortOrder.into()).into_control_flow(),
1,218✔
646
                },
647
                _ => return Err(EvaluateError::InvalidSortOrder.into()).into_control_flow(),
1,218✔
648
            };
649

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

652
            Continue(Evaluated::Value(Value::List(
653
                l.into_iter().map(|(_, v)| v).collect(),
7,308✔
654
            )))
655
        }
656
        _ => Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
657
    }
658
}
12,180✔
659

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

673
    match expr {
12,180✔
674
        Value::List(l) => {
10,962✔
675
            if start < 0 {
10,962✔
676
                start += l.len() as i64;
3,654✔
677
            }
7,308✔
678
            if start < 0 {
10,962✔
679
                start = 0;
1,218✔
680
            }
9,744✔
681

682
            let start_usize = start as usize;
10,962✔
683

684
            let l = l.into_iter().skip(start_usize).take(length).collect();
10,962✔
685
            Continue(Evaluated::Value(Value::List(l)))
10,962✔
686
        }
687
        _ => Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
688
    }
689
}
14,616✔
690

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

702
    match expr {
7,308✔
703
        Value::List(l) => {
6,090✔
704
            let l = l.into_iter().take(size).collect();
6,090✔
705
            Continue(Evaluated::Value(Value::List(l)))
6,090✔
706
        }
707
        _ => Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
708
    }
709
}
12,180✔
710

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

721
    Continue(Evaluated::Value(Value::Bool(length == 0)))
12,180✔
722
}
13,398✔
723

724
// --- etc ---
725

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

741
    value
37,758✔
742
        .selector(&selector)
37,758✔
743
        .into_control_flow()
37,758✔
744
        .map_continue(Evaluated::Value)
37,758✔
745
}
42,630✔
746

747
pub fn generate_uuid<'a>() -> Evaluated<'a> {
10,963✔
748
    Evaluated::Value(Value::Uuid(Uuid::new_v4().as_u128()))
10,963✔
749
}
10,963✔
750

751
pub fn greatest<'a>(name: &str, exprs: Vec<Evaluated<'a>>) -> Result<Evaluated<'a>> {
9,744✔
752
    exprs
9,744✔
753
        .into_iter()
9,744✔
754
        .try_fold(None, |greatest, expr| -> Result<_> {
35,322✔
755
            let Some(greatest) = greatest else {
35,322✔
756
                return Ok(Some(expr));
9,744✔
757
            };
758

759
            match greatest.evaluate_cmp(&expr) {
25,578✔
760
                Some(std::cmp::Ordering::Less) => Ok(Some(expr)),
12,180✔
761
                Some(_) => Ok(Some(greatest)),
9,744✔
762
                None => Err(EvaluateError::NonComparableArgumentError(name.to_owned()).into()),
3,654✔
763
            }
764
        })?
35,322✔
765
        .ok_or(EvaluateError::FunctionRequiresAtLeastOneArgument(name.to_owned()).into())
6,090✔
766
}
9,744✔
767

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

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

797
    Continue(Evaluated::Value(Value::Date(
4,872✔
798
        date + Months::new(1) - Duration::days(i64::from(date.day())),
4,872✔
799
    )))
4,872✔
800
}
6,090✔
801

802
pub fn to_date<'a>(
15,834✔
803
    name: &str,
15,834✔
804
    expr: Evaluated<'_>,
15,834✔
805
    format: Evaluated<'_>,
15,834✔
806
) -> ControlFlow<Evaluated<'a>> {
15,834✔
807
    match expr.try_into().break_if_null()? {
15,834✔
808
        Value::Str(expr) => {
14,616✔
809
            let format = eval_to_str(name, format)?;
14,616✔
810

811
            chrono::NaiveDate::parse_from_str(&expr, &format)
14,616✔
812
                .map(Value::Date)
14,616✔
813
                .map(Evaluated::Value)
14,616✔
814
                .map_err(|err| {
14,616✔
815
                    let err: EvaluateError = err.into();
1,218✔
816
                    err.into()
1,218✔
817
                })
1,218✔
818
        }
819
        _ => Err(EvaluateError::FunctionRequiresStringValue(name.to_owned()).into()),
1,218✔
820
    }
821
    .into_control_flow()
15,834✔
822
}
15,834✔
823

824
pub fn to_timestamp<'a>(
15,834✔
825
    name: &str,
15,834✔
826
    expr: Evaluated<'_>,
15,834✔
827
    format: Evaluated<'_>,
15,834✔
828
) -> ControlFlow<Evaluated<'a>> {
15,834✔
829
    match expr.try_into().break_if_null()? {
15,834✔
830
        Value::Str(expr) => {
14,616✔
831
            let format = eval_to_str(name, format)?;
14,616✔
832

833
            chrono::NaiveDateTime::parse_from_str(&expr, &format)
14,616✔
834
                .map(Value::Timestamp)
14,616✔
835
                .map(Evaluated::Value)
14,616✔
836
                .map_err(|err| {
14,616✔
837
                    let err: EvaluateError = err.into();
7,308✔
838
                    err.into()
7,308✔
839
                })
7,308✔
840
        }
841
        _ => Err(EvaluateError::FunctionRequiresStringValue(name.to_owned()).into()),
1,218✔
842
    }
843
    .into_control_flow()
15,834✔
844
}
15,834✔
845

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

865
        if size <= 0 {
7,308✔
866
            expr.checked_sub_months(new_months)
2,436✔
867
        } else {
868
            expr.checked_add_months(new_months)
4,872✔
869
        }
870
        .continue_or_break(EvaluateError::ChrFunctionRequiresIntegerValueInRange0To255.into())?
7,308✔
871
    };
872
    Continue(Evaluated::Value(Value::Date(date)))
6,090✔
873
}
13,398✔
874

875
pub fn to_time<'a>(
9,744✔
876
    name: &str,
9,744✔
877
    expr: Evaluated<'_>,
9,744✔
878
    format: Evaluated<'_>,
9,744✔
879
) -> ControlFlow<Evaluated<'a>> {
9,744✔
880
    match expr.try_into().break_if_null()? {
9,744✔
881
        Value::Str(expr) => {
8,526✔
882
            let format = eval_to_str(name, format)?;
8,526✔
883

884
            chrono::NaiveTime::parse_from_str(&expr, &format)
8,526✔
885
                .map(Value::Time)
8,526✔
886
                .map(Evaluated::Value)
8,526✔
887
                .map_err(|err| {
8,526✔
888
                    let err: EvaluateError = err.into();
1,218✔
889
                    err.into()
1,218✔
890
                })
1,218✔
891
        }
892
        _ => Err(EvaluateError::FunctionRequiresStringValue(name.to_owned()).into()),
1,218✔
893
    }
894
    .into_control_flow()
9,744✔
895
}
9,744✔
896

897
pub fn position<'a>(
7,309✔
898
    from_expr: Evaluated<'_>,
7,309✔
899
    sub_expr: Evaluated<'_>,
7,309✔
900
) -> ControlFlow<Evaluated<'a>> {
7,309✔
901
    let from: Value = from_expr.try_into().break_if_null()?;
7,309✔
902
    let sub = sub_expr.try_into().break_if_null()?;
7,309✔
903

904
    from.position(&sub)
6,091✔
905
        .map(Evaluated::Value)
6,091✔
906
        .into_control_flow()
6,091✔
907
}
7,309✔
908

909
pub fn find_idx<'a>(
17,053✔
910
    name: &str,
17,053✔
911
    from: Evaluated<'a>,
17,053✔
912
    sub: Evaluated<'a>,
17,053✔
913
    start: Option<Evaluated<'a>>,
17,053✔
914
) -> ControlFlow<Evaluated<'a>> {
17,053✔
915
    let from_expr = eval_to_str(name, from)?;
17,053✔
916
    let sub_expr = eval_to_str(name, sub)?;
17,053✔
917

918
    match start {
14,617✔
919
        Some(start) => {
8,526✔
920
            let start = eval_to_int(name, start)?;
8,526✔
921
            Value::find_idx(
7,308✔
922
                &Value::Str(from_expr),
7,308✔
923
                &Value::Str(sub_expr),
7,308✔
924
                &Value::I64(start),
7,308✔
925
            )
926
        }
927
        None => Value::position(&Value::Str(from_expr), &Value::Str(sub_expr)),
6,091✔
928
    }
929
    .map(Evaluated::Value)
13,399✔
930
    .into_control_flow()
13,399✔
931
}
17,053✔
932

933
pub fn extract<'a>(field: DateTimeField, expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
20,707✔
934
    Value::try_from(expr)
20,707✔
935
        .and_then(|v| v.extract(&field))
20,707✔
936
        .map(Evaluated::Value)
20,707✔
937
        .into_control_flow()
20,707✔
938
}
20,707✔
939

940
pub fn point<'a>(name: &str, x: Evaluated<'_>, y: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
12,180✔
941
    let x = eval_to_float(name, x)?;
12,180✔
942
    let y = eval_to_float(name, y)?;
12,180✔
943

944
    Continue(Evaluated::Value(Value::Point(Point::new(x, y))))
12,180✔
945
}
12,180✔
946

947
pub fn get_x<'a>(name: &str, expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
4,872✔
948
    match expr.try_into().break_if_null()? {
4,872✔
949
        Value::Point(v) => Ok(Evaluated::Value(Value::F64(v.x))),
3,654✔
950
        _ => Err(EvaluateError::FunctionRequiresPointValue(name.to_owned()).into()),
1,218✔
951
    }
952
    .into_control_flow()
4,872✔
953
}
4,872✔
954

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

963
pub fn calc_distance<'a>(
3,654✔
964
    name: &str,
3,654✔
965
    x: Evaluated<'_>,
3,654✔
966
    y: Evaluated<'_>,
3,654✔
967
) -> ControlFlow<Evaluated<'a>> {
3,654✔
968
    let x = eval_to_point(name, x)?;
3,654✔
969
    let y = eval_to_point(name, y)?;
3,654✔
970

971
    Continue(Evaluated::Value(Value::F64(Point::calc_distance(&x, &y))))
1,218✔
972
}
3,654✔
973

974
pub fn length<'a>(name: &str, expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
11,397✔
975
    match expr.try_into().break_if_null()? {
11,397✔
976
        Value::Str(expr) => Ok(Evaluated::Value(Value::U64(expr.chars().count() as u64))),
8,961✔
977
        Value::List(expr) => Ok(Evaluated::Value(Value::U64(expr.len() as u64))),
1,218✔
978
        Value::Map(expr) => Ok(Evaluated::Value(Value::U64(expr.len() as u64))),
1,218✔
979
        _ => Err(EvaluateError::FunctionRequiresStrOrListOrMapValue(name.to_owned()).into()),
×
980
    }
981
    .into_control_flow()
11,397✔
982
}
11,397✔
983

984
pub fn coalesce<'a>(exprs: Vec<Evaluated<'_>>) -> Result<Evaluated<'a>> {
54,810✔
985
    if exprs.is_empty() {
54,810✔
986
        return Err((EvaluateError::FunctionRequiresMoreArguments {
2,436✔
987
            function_name: "COALESCE".to_owned(),
2,436✔
988
            required_minimum: 1,
2,436✔
989
            found: exprs.len(),
2,436✔
990
        })
2,436✔
991
        .into());
2,436✔
992
    }
52,374✔
993

994
    let control_flow =
52,374✔
995
        exprs
52,374✔
996
            .into_iter()
52,374✔
997
            .map(TryInto::try_into)
52,374✔
998
            .try_for_each(|item: Result<Value>| match item {
99,876✔
999
                Ok(value) if value.is_null() => StdControlFlow::Continue(()),
99,876✔
1000
                Ok(value) => StdControlFlow::Break(Ok(value)),
47,502✔
1001
                Err(err) => StdControlFlow::Break(Err(err)),
×
1002
            });
99,876✔
1003

1004
    match control_flow {
47,502✔
1005
        StdControlFlow::Break(Ok(value)) => Ok(Evaluated::Value(value)),
47,502✔
1006
        StdControlFlow::Break(Err(err)) => Err(err),
×
1007
        StdControlFlow::Continue(()) => Ok(Evaluated::Value(Value::Null)),
4,872✔
1008
    }
1009
}
54,810✔
1010

1011
pub fn entries<'a>(name: &str, expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
2,436✔
1012
    match expr.try_into().break_if_null()? {
2,436✔
1013
        Value::Map(expr) => {
1,218✔
1014
            let entries = expr
1,218✔
1015
                .into_iter()
1,218✔
1016
                .map(|(k, v)| Value::List(vec![Value::Str(k), v]))
1,218✔
1017
                .collect::<Vec<_>>();
1,218✔
1018
            Ok(Evaluated::Value(Value::List(entries)))
1,218✔
1019
        }
1020
        _ => Err(EvaluateError::FunctionRequiresMapValue(name.to_owned()).into()),
1,218✔
1021
    }
1022
    .into_control_flow()
2,436✔
1023
}
2,436✔
1024

1025
pub fn keys<'a>(expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
4,872✔
1026
    match expr.try_into().break_if_null()? {
4,872✔
1027
        Value::Map(m) => Ok(Evaluated::Value(Value::List(
3,654✔
1028
            m.into_keys().map(Value::Str).collect(),
3,654✔
1029
        ))),
3,654✔
1030
        _ => Err(EvaluateError::MapTypeRequired.into()),
1,218✔
1031
    }
1032
    .into_control_flow()
4,872✔
1033
}
4,872✔
1034

1035
pub fn values<'a>(expr: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
6,090✔
1036
    match expr.try_into().break_if_null()? {
6,090✔
1037
        Value::Map(m) => Ok(Evaluated::Value(Value::List(m.into_values().collect()))),
4,872✔
1038
        _ => Err(EvaluateError::MapTypeRequired.into()),
1,218✔
1039
    }
1040
    .into_control_flow()
6,090✔
1041
}
6,090✔
1042

1043
pub fn splice<'a>(
7,308✔
1044
    name: &str,
7,308✔
1045
    list_data: Evaluated<'_>,
7,308✔
1046
    begin_index: Evaluated<'_>,
7,308✔
1047
    end_index: Evaluated<'_>,
7,308✔
1048
    values: Option<Evaluated<'_>>,
7,308✔
1049
) -> ControlFlow<Evaluated<'a>> {
7,308✔
1050
    let Value::List(list_data) = list_data.try_into().break_if_null()? else {
7,308✔
1051
        return Err(EvaluateError::ListTypeRequired.into()).into_control_flow();
1,218✔
1052
    };
1053

1054
    let begin_index = eval_to_int(name, begin_index)?.max(0);
6,090✔
1055
    let begin_index = usize::try_from(begin_index)
6,090✔
1056
        .map_err(|_| EvaluateError::FunctionRequiresUSizeValue(name.to_owned()).into())
6,090✔
1057
        .into_control_flow()?;
6,090✔
1058
    let end_index = eval_to_int(name, end_index)?.max(0);
6,090✔
1059
    let end_index = usize::try_from(end_index)
6,090✔
1060
        .map_err(|_| EvaluateError::FunctionRequiresUSizeValue(name.to_owned()).into())
6,090✔
1061
        .into_control_flow()?;
6,090✔
1062

1063
    let (left, right) = {
6,090✔
1064
        let mut list_iter = list_data.into_iter();
6,090✔
1065
        let left: Vec<_> = list_iter.by_ref().take(begin_index).collect();
6,090✔
1066
        let right: Vec<_> = list_iter.skip(end_index - begin_index).collect();
6,090✔
1067
        (left, right)
6,090✔
1068
    };
6,090✔
1069

1070
    let center = match values {
6,090✔
1071
        Some(values) => match values.try_into().break_if_null()? {
4,872✔
1072
            Value::List(list) => list,
3,654✔
1073
            _ => return Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
1074
        },
1075
        None => vec![],
1,218✔
1076
    };
1077

1078
    let result = {
4,872✔
1079
        let mut result = vec![];
4,872✔
1080
        result.extend(left);
4,872✔
1081
        result.extend(center);
4,872✔
1082
        result.extend(right);
4,872✔
1083
        result
4,872✔
1084
    };
1085

1086
    Continue(Evaluated::Value(Value::List(result)))
4,872✔
1087
}
7,308✔
1088

1089
pub fn dedup<'a>(list: Evaluated<'_>) -> ControlFlow<Evaluated<'a>> {
3,654✔
1090
    match list.try_into().break_if_null()? {
3,654✔
1091
        Value::List(mut list) => {
2,436✔
1092
            list.dedup();
2,436✔
1093
            Continue(Evaluated::Value(Value::List(list)))
2,436✔
1094
        }
1095
        _ => Err(EvaluateError::ListTypeRequired.into()).into_control_flow(),
1,218✔
1096
    }
1097
}
3,654✔
1098

1099
pub fn select_arrow_value(base: &Value, selector: &Value) -> Result<Value> {
49,938✔
1100
    if base.is_null() {
49,938✔
1101
        return Ok(Value::Null);
×
1102
    }
49,938✔
1103

1104
    match base {
49,938✔
1105
        Value::Map(map) => {
23,142✔
1106
            let key = match selector {
23,142✔
1107
                Value::Str(value) => Cow::Borrowed(value.as_str()),
7,308✔
1108
                Value::I8(value) => Cow::Owned(value.to_string()),
1,218✔
1109
                Value::I16(value) => Cow::Owned(value.to_string()),
2,436✔
1110
                Value::I32(value) => Cow::Owned(value.to_string()),
1,218✔
1111
                Value::I64(value) => Cow::Owned(value.to_string()),
2,436✔
1112
                Value::I128(value) => Cow::Owned(value.to_string()),
1,218✔
1113
                Value::U8(value) => Cow::Owned(value.to_string()),
1,218✔
1114
                Value::U16(value) => Cow::Owned(value.to_string()),
1,218✔
1115
                Value::U32(value) => Cow::Owned(value.to_string()),
1,218✔
1116
                Value::U64(value) => Cow::Owned(value.to_string()),
1,218✔
1117
                Value::U128(value) => Cow::Owned(value.to_string()),
1,218✔
1118
                _ => {
1119
                    return Err(EvaluateError::ArrowSelectorRequiresIntegerOrString(format!(
1,218✔
1120
                        "{selector:?}"
1,218✔
1121
                    ))
1,218✔
1122
                    .into());
1,218✔
1123
                }
1124
            };
1125

1126
            Ok(map.get(key.as_ref()).cloned().unwrap_or(Value::Null))
21,924✔
1127
        }
1128
        Value::List(list) => {
23,142✔
1129
            let index = match selector {
23,142✔
1130
                Value::Str(value) => value.parse::<usize>().ok(),
2,436✔
1131
                Value::I8(value) => usize::try_from(*value).ok(),
1,218✔
1132
                Value::I16(value) => usize::try_from(*value).ok(),
2,436✔
1133
                Value::I32(value) => usize::try_from(*value).ok(),
1,218✔
1134
                Value::I64(value) => usize::try_from(*value).ok(),
8,526✔
1135
                Value::I128(value) => usize::try_from(*value).ok(),
1,218✔
1136
                Value::U8(value) => Some(*value as usize),
1,218✔
1137
                Value::U16(value) => Some(*value as usize),
1,218✔
1138
                Value::U32(value) => usize::try_from(*value).ok(),
1,218✔
1139
                Value::U64(value) => usize::try_from(*value).ok(),
1,218✔
1140
                Value::U128(value) => usize::try_from(*value).ok(),
1,218✔
1141
                _ => {
1142
                    return Err(EvaluateError::ArrowSelectorRequiresIntegerOrString(format!(
×
1143
                        "{selector:?}?"
×
1144
                    ))
×
1145
                    .into());
×
1146
                }
1147
            };
1148

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

© 2026 Coveralls, Inc