diff options
| author | PgBiel <9021226+PgBiel@users.noreply.github.com> | 2023-12-05 15:15:03 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-12-05 19:15:03 +0100 |
| commit | 0ebce56b36ea2a875609949f4da81c9ca6a4a081 (patch) | |
| tree | 98fb0485843c2a34e22a3994b985add38fd1fdec /crates | |
| parent | 3960f8f7d935fc5b47404abeb5a64f458d0616c2 (diff) | |
Implement lexicographic array comparison (#2827)
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/typst/src/eval/ops.rs | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/crates/typst/src/eval/ops.rs b/crates/typst/src/eval/ops.rs index cb830614..8e8b6d29 100644 --- a/crates/typst/src/eval/ops.rs +++ b/crates/typst/src/eval/ops.rs @@ -551,6 +551,7 @@ pub fn compare(lhs: &Value, rhs: &Value) -> StrResult<Ordering> { (Duration(a), Duration(b)) => a.cmp(b), (Datetime(a), Datetime(b)) => try_cmp_datetimes(a, b)?, + (Array(a), Array(b)) => try_cmp_arrays(a.as_slice(), b.as_slice())?, _ => mismatch!("cannot compare {} and {}", lhs, rhs), }) @@ -568,6 +569,26 @@ fn try_cmp_datetimes(a: &Datetime, b: &Datetime) -> StrResult<Ordering> { .ok_or_else(|| eco_format!("cannot compare {} and {}", a.kind(), b.kind())) } +/// Try to compare arrays of values lexicographically. +fn try_cmp_arrays(a: &[Value], b: &[Value]) -> StrResult<Ordering> { + a.iter() + .zip(b.iter()) + .find_map(|(first, second)| { + match compare(first, second) { + // Keep searching for a pair of elements that isn't equal. + Ok(Ordering::Equal) => None, + // Found a pair which either is not equal or not comparable, so + // we stop searching. + result => Some(result), + } + }) + .unwrap_or_else(|| { + // The two arrays are equal up to the shortest array's extent, + // so compare their lengths instead. + Ok(a.len().cmp(&b.len())) + }) +} + /// Test whether one value is "in" another one. pub fn in_(lhs: Value, rhs: Value) -> StrResult<Value> { if let Some(b) = contains(&lhs, &rhs) { |
