Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Operators Overview

datalogic-rs provides 59 built-in operators organized into logical categories. In the Rust crate, 33 baseline operators are always available in the default build (default = []); a further 24 canonical operators are enabled by opt-in Cargo features, and two flagd-compatible operators (fractional, sem_ver) sit behind the flagd feature. Every language binding (WASM, Node, Python, Go, JVM, .NET, PHP) ships with all operator features enabled, so the full set is available out of the box outside Rust. Counts are by canonical operator: var and ?: are accepted as input aliases of val and if, and match is an alias of switch, so the aliases are not counted separately. This section documents each operator with syntax, examples, and notes on behavior.

Operator Categories

CategoryOperatorsDescription
Variable Accessval (alias var), existsAccess and check data
Comparison==, ===, !=, !==, >, >=, <, <=Compare values
Logical!, !!, and, orBoolean logic
Arithmetic+, -, *, /, %, max, min, abs, ceil, floorMath operations
Control Flowif (alias ?:), ??, switch (alias match), typeConditional branching
Stringcat, substr, in, length, starts_with, ends_with, upper, lower, trim, splitString manipulation
Arraymerge, filter, map, reduce, all, some, none, sort, sliceArray operations
DateTimedatetime, timestamp, parse_date, format_date, date_diff, nowDate and time
Missing Valuesmissing, missing_someCheck for missing data
Error Handlingtry, throwException handling
flagd-Compatfractional, sem_verFeature-flag targeting (OpenFeature flagd spec); requires features = ["flagd"]

Which operators need which Cargo feature

This split only affects the Rust crate: only the baseline set compiles in the default build (default = []), and using any other operator against an engine compiled without its feature errors at compile time as InvalidOperator. Every language binding enables all operator features, so the full set is always available there.

Cargo featureOperators
baseline (always on)val/var, comparison (==<=), and, or, !, !!, if/?:, + - * / %, min, max, cat, substr, in, map, filter, reduce, merge, all, some, none, missing, missing_some
ext-stringlength, starts_with, ends_with, upper, lower, trim, split
ext-arraysort, slice
ext-mathabs, ceil, floor
ext-controlexists, ??, switch/match, type
error-handlingtry, throw
datetimedatetime, timestamp, parse_date, format_date, date_diff, now
flagdfractional, sem_ver

Operator Syntax

All operators follow the JSONLogic format:

{ "operator": [arg1, arg2, ...] }

Some operators accept a single argument without an array:

{ "var": "name" }
// Equivalent to:
{ "var": ["name"] }

Lazy Evaluation

Several operators use lazy (short-circuit) evaluation:

  • and: Stops at first falsy value
  • or: Stops at first truthy value
  • if: Only evaluates the matching branch
  • ?:: Only evaluates the matching branch
  • ??: Only evaluates fallback if first value is null

This is important when operations have side effects or when you want to avoid errors:

{
  "and": [
    { "var": "user" },
    { "var": "user.profile.name" }
  ]
}

If user is null, the second condition is never evaluated, avoiding an error.

Type Coercion

Operators handle types differently:

Loose vs Strict

  • == and != perform type coercion
  • === and !== require exact type match
{ "==": [1, "1"] }   // true (loose)
{ "===": [1, "1"] }  // false (strict)

Numeric Coercion

Arithmetic operators attempt to convert values to numbers:

{ "+": ["5", 3] }  // 8 (string "5" becomes number 5)

Truthiness

Boolean operators use configurable truthiness rules. By default (JavaScript-style):

  • Falsy: false, 0, "", null, [], {}
  • Truthy: Everything else

Custom Operators

You can add your own operators. See Custom Operators for details.

In v5 operator registration is builder-only:

let engine = Engine::builder()
    .add_operator("myop", MyOperator)
    .build();

Custom operators follow the same syntax in rules:

{ "myop": [arg1, arg2] }

Note: v5 removed the preserve operator. Wrap literals in templating mode (Engine::builder().with_templating(true).build(), requires feature = "templating") if you need to emit a JSON object verbatim from a rule. Literal scalars and arrays already work inline.