#rules #context #arguments #box #logic #overhead #hierarchies #rusty-rules #fetchers

rusty-rules

A blazingly fast, flexible, and extensible rules engine written in Rust

2 releases

new 0.1.1 May 19, 2025
0.1.0 May 19, 2025

#2 in #overhead

MIT license

89KB
1.5K SLoC

rusty-rules

Latest Version API Documentation Coverage Status

A blazingly fast, flexible, and extensible rules engine written in Rust. Evaluate complex logical rules against custom data structures using a simple JSON-based DSL. Supports both synchronous and asynchronous fetchers, custom operators, and a variety of matchers.

Features

  • Composable rules: Combine conditions with all, any, and not logical blocks for complex rule hierarchies
  • Custom fetchers: Extract values from data structures with named fetchers that accept arguments
  • Matcher support: String, regex, IP address, numeric, and boolean matchers out of the box
  • Custom operators: Define operators for advanced matching and domain-specific logic
  • Async support: Register async fetchers and operators for use with async/await contexts
  • JSON-schema validation: Validate rules with automatically generated JSON schema (requires validation feature)
  • Thread-safety option: Optional Send/Sync trait bounds with the send feature flag
  • Performance-focused: Designed for high-throughput rule evaluation with minimal overhead

Installation

Add to Cargo.toml:

[dependencies]
rusty-rules = "0.1"

Basic Usage

Define context

use std::collections::HashMap;
use std::net::IpAddr;

struct MyContext {
    method: String,
    path: String,
    headers: HashMap<String, String>,
    addr: IpAddr,
}

Register fetchers

use rusty_rules::{Engine, Value};

let mut engine = Engine::new();

engine.register_fetcher("method", |ctx: &MyContext, _args| {
    Ok(Value::from(&ctx.method))
});

engine.register_fetcher("header", |ctx: &MyContext, args| {
    Ok(args.first().and_then(|name| ctx.headers.get(name)).into())
});

engine.register_fetcher("addr", |ctx: &MyContext, _args| {
    Ok(ctx.addr.into())
});

// ...register other fetchers...

Compile and evaluate a rule

use serde_json::json;

let rule = engine.compile_rule(&json!({
    "method": "GET",
    "header(host)": "www.example.com",
    "addr": {
        "ip": ["10.0.0.0/8"]
    }
})).unwrap();

let ctx = /* MyContext instance */;
assert!(rule.evaluate(&ctx).unwrap());

Dependencies

~3–12MB
~118K SLoC