Skip to content

A fast, type-safe Rust implementation of JSONLogic for evaluating logical rules as JSON. Perfect for business rules engines and dynamic filtering in Rust applications.

License

Notifications You must be signed in to change notification settings

GoPlasmatic/datalogic-rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Plasmatic Logo

datalogic-rs

A high-performance, production-ready Rust implementation of JSONLogic.

Evaluate complex rules and dynamic expressions with a powerful, memory-efficient, and developer-friendly engine.

License: Apache 2.0 Rust Crates.io Documentation Downloads

🏒 Organization β€’ πŸ“– Docs β€’ πŸ› Report a Bug


datalogic-rs is a Rust implementation of JSONLogic designed for performance, safety, and ease of use. Whether you're building a feature flagging system, a dynamic pricing engine, or a complex validation pipeline, datalogic-rs provides the power and flexibility you need.

Our secret sauce? An arena-based memory model that delivers zero-copy parsing and evaluation, making it up to 30% faster than other implementations.

πŸš€ What Makes datalogic-rs Awesome?

  • Blazing Fast: Our arena-based allocator minimizes memory overhead and maximizes speed.
  • 100% JSONLogic Compliant: Full compatibility with the official JSONLogic test suite.
  • Extensible: Easily add your own custom operators with our simple or advanced APIs.
  • Powerful Templating: Preserve object structures for dynamic, structured output.
  • Ready for Production: Thread-safe, statically dispatched, and optimized for real-world workloads.
  • Batteries Included: Over 50 built-in operators, including datetime and regex support.
  • WASM Support: Compile to WebAssembly for use in browser environments.

πŸ—οΈ How It Works: The Arena Advantage

datalogic-rs uses an arena allocator for memory-efficient evaluation. This means we can parse a rule once and evaluate it many times with minimal overhead.

use datalogic_rs::DataLogic;

// Create an evaluator with a custom arena chunk size.
let dl = DataLogic::with_chunk_size(8192);

// Parse your rule and data once.
let rule = dl.parse_logic(r#"{ ">": [{ "var": "temp" }, 100] }"#).unwrap();
let data = dl.parse_data(r#"{ "temp": 110 }"#).unwrap();

// Evaluate efficiently.
let result = dl.evaluate(&rule, &data).unwrap();
assert!(result.to_json().as_bool().unwrap());

// Reset the arena to reuse memory for the next batch of evaluations.
dl.reset_arena();

Structured Object Preservation

Generate powerful, structured outputs by preserving non-operator keys in your JSON.

use datalogic_rs::DataLogic;

// Enable structure preservation for templating.
let dl = DataLogic::with_preserve_structure();

let result = dl.evaluate_str(
    r#"{
        "status": { "if": [{ ">=": [{ "var": "score" }, 90] }, "pass", "fail"] },
        "grade": { "+": [{ "var": "score" }, { "var": "bonus" }] },
        "timestamp": { "now": [] }
    }"#,
    r#"{ "score": 85, "bonus": 10 }"#,
).unwrap();

// The result is a structured object with evaluated fields.
// { "status": "pass", "grade": 95, "timestamp": "2024-01-15T10:30:00Z" }

🎯 Getting Started: Core API

1. evaluate - For Reusable Rules & Data

Ideal for scenarios where you need to run the same rule against different data.

use datalogic_rs::DataLogic;

let dl = DataLogic::new();

// Parse the rule and data once.
let rule = dl.parse_logic(r#"{ ">": [{ "var": "temp" }, 100] }"#).unwrap();
let data = dl.parse_data(r#"{ "temp": 110 }"#).unwrap();

// Evaluate as many times as you need.
let result = dl.evaluate(&rule, &data).unwrap();
assert!(result.to_json().as_bool().unwrap());

2. evaluate_str - For Quick, One-Shot Evaluations

Perfect for when your rules are dynamic or you only need a single evaluation.

use datalogic_rs::DataLogic;

let dl = DataLogic::new();

let result = dl.evaluate_str(
    r#"{ "abs": -42 }"#,
    r#"{}"#, // No data needed for this rule.
).unwrap();

assert_eq!(result.as_i64().unwrap(), 42);

3. evaluate_json - For Seamless JSON Integration

Works directly with serde_json::Value for easy integration into your existing JSON workflows.

use datalogic_rs::DataLogic;
use serde_json::json;

let dl = DataLogic::new();

let logic = json!({
    "if": [
        { ">": [{ "var": "cart.total" }, 100] },
        "Premium",
        "Standard"
    ]
});

let data = json!({ "cart": { "total": 120 } });

let result = dl.evaluate_json(&logic, &data).unwrap();
assert_eq!(result.as_str().unwrap(), "Premium");

πŸ”§ Installation

Add datalogic-rs to your Cargo.toml:

[dependencies]
datalogic-rs = "3.0"

πŸ“– Real-World Examples

Complex Business Rules

Check for multi-condition eligibility with nested logic.

use datalogic_rs::DataLogic;

let dl = DataLogic::new();

let result = dl.evaluate_str(
    r#"{
        "and": [
            { ">=": [{ "var": "age" }, 18] },
            { "<": [{ "var": "age" }, 65] },
            { "or": [
                { "==": [{ "var": "subscription" }, "premium"] },
                { ">=": [{ "var": "purchases" }, 5] }
            ] }
        ]
    }"#,
    r#"{ "age": 25, "subscription": "basic", "purchases": 7 }"#,
).unwrap();

assert!(result.as_bool().unwrap());

Array Processing & Filtering

Filter and map user data with ease.

use datalogic_rs::DataLogic;

let dl = DataLogic::new();

let result = dl.evaluate_str(
    r#"{
        "map": [
            {
                "filter": [
                    { "var": "users" },
                    { ">=": [{ "var": "age" }, 18] }
                ]
            },
            { "var": "name" }
        ]
    }"#,
    r#"{
        "users": [
            { "name": "Alice", "age": 20 },
            { "name": "Bob", "age": 15 },
            { "name": "Charlie", "age": 25 }
        ]
    }"#,
).unwrap();

// Returns ["Alice", "Charlie"]
assert_eq!(result.as_array().unwrap().len(), 2);

DateTime Operations

Perform date arithmetic with timezone support.

use datalogic_rs::DataLogic;

let dl = DataLogic::new();

let result = dl.evaluate_str(
    r#"{
        ">": [
            { "+": [
                { "datetime": "2023-07-15T08:30:00Z" },
                { "duration": "2d" }
            ] },
            { "datetime": "2023-07-16T08:30:00Z" }
        ]
    }"#,
    r#"{}"#,
).unwrap();

assert!(result.as_bool().unwrap());

Regex Data Extraction

Extract structured data from strings using named capture groups.

use datalogic_rs::DataLogic;

let dl = DataLogic::new();

let result = dl.evaluate_str(
    r#"{
        "split": [
            "SBININBB101",
            "^(?P<bank>[A-Z]{4})(?P<country>[A-Z]{2})(?P<location>[A-Z0-9]{2})(?P<branch>[A-Z0-9]{3})?$"
        ]
    }"#,
    r#"{}"#,
).unwrap();

// Returns: { "bank": "SBIN", "country": "IN", "location": "BB", "branch": "101" }
let obj = result.as_object().unwrap();
assert_eq!(obj.get("bank").unwrap().as_str().unwrap(), "SBIN");

πŸ”Œ Custom Operators

Extend datalogic-rs with your own domain-specific logic.

use datalogic_rs::{DataLogic, DataValue};
use datalogic_rs::value::NumberValue;

// Define a custom operator that doubles a number.
fn double(args: Vec<DataValue>, _data: DataValue) -> Result<DataValue, String> {
    if let Some(n) = args.first().and_then(|v| v.as_f64()) {
        return Ok(DataValue::Number(NumberValue::from_f64(n * 2.0)));
    }
    Err("Argument must be a number".to_string())
}

let mut dl = DataLogic::new();
dl.register_simple_operator("double", double);

// Use your custom operator in a rule.
let result = dl.evaluate_str(r#"{ "double": 21 }"#, r#"{}"#).unwrap();

assert_eq!(result.as_f64().unwrap(), 42.0);

πŸ“Š Performance

datalogic-rs is fast. Here's how it stacks up against other implementations on an Apple M2 Pro:

Implementation Execution Time Relative Performance
datalogic-rs 380ms 1.0x (baseline)
json-logic-engine (pre-compiled) 417ms 1.1x slower
json-logic-engine (interpreted) 986ms 2.6x slower
json-logic-js 5,755ms 15.1x slower

Benchmarks run on the standard JSONLogic test suite.

🎯 Use Cases

Feature Flagging

{
    "and": [
        { "==": [{ "var": "user.country" }, "US"] },
        { "or": [
            { "==": [{ "var": "user.role" }, "beta_tester"] },
            { ">=": [{ "var": "user.account_age_days" }, 30] }
        ] }
    ]
}

Dynamic Pricing

{
    "if": [
        { ">=": [{ "var": "cart.total" }, 100] },
        { "-": [{ "var": "cart.total" }, { "*": [{ "var": "cart.total" }, 0.1] }] },
        { "var": "cart.total" }
    ]
}

Fraud Detection

{
    "or": [
        { "and": [
            { "!=": [{ "var": "transaction.billing_country" }, { "var": "user.country" }] },
            { ">=": [{ "var": "transaction.amount" }, 1000] }
        ] },
        { ">=": [{ "var": "transaction.attempts_last_hour" }, 5] }
    ]
}

πŸ“‹ Supported Operations

Category Operators
Comparison ==, ===, !=, !==, >, >=, <, <=
Logic and, or, !, !!
Arithmetic +, -, *, /, %, min, max, abs, ceil, floor
Control Flow if, ?:, ??
Arrays map, filter, reduce, all, some, none, merge, in, length, slice, sort
Strings cat, substr, starts_with, ends_with, upper, lower, trim, replace, split
Data Access var, val, exists, missing, missing_some
DateTime datetime, timestamp, now, parse_date, format_date, date_diff
Error Handling throw, try
Custom User-defined operators

🀝 Contributing

We welcome contributions! Please see CONTRIBUTING.md for details on how to get started.

🏒 About Plasmatic

datalogic-rs is developed by Plasmatic, an organization dedicated to building open-source tools for financial infrastructure and data processing.

Check out our other projects:

  • SwiftMTMessage: A library for parsing SWIFT MT messages with CBPR+ compliance.
  • Reframe: A transformation engine for converting SWIFT MT messages to ISO 20022.
  • MXMessage: A library for parsing ISO 20022 (MX) messages.

πŸ“„ License

datalogic-rs is licensed under the Apache License, Version 2.0. See LICENSE for details.


Built with ❀️ by the Plasmatic team

About

A fast, type-safe Rust implementation of JSONLogic for evaluating logical rules as JSON. Perfect for business rules engines and dynamic filtering in Rust applications.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages