API Reference
Core types and methods in datalogic-rs.
DataLogic
The main engine for compiling and evaluating JSONLogic rules.
Creating an Engine
#![allow(unused)]
fn main() {
use datalogic_rs::DataLogic;
// Default engine
let engine = DataLogic::new();
// With configuration
let engine = DataLogic::with_config(config);
// With structure preservation (templating mode)
let engine = DataLogic::with_preserve_structure();
// With both
let engine = DataLogic::with_config_and_structure(config, true);
}
Methods
compile
Compile a JSONLogic rule into an optimized representation.
#![allow(unused)]
fn main() {
pub fn compile(&self, logic: &Value) -> Result<Arc<CompiledLogic>>
}
Parameters:
logic- The JSONLogic rule as aserde_json::Value
Returns:
Ok(Arc<CompiledLogic>)- Compiled rule, thread-safe and shareableErr(Error)- Compilation error
Example:
#![allow(unused)]
fn main() {
let rule = json!({ ">": [{ "var": "x" }, 10] });
let compiled = engine.compile(&rule)?;
}
evaluate
Evaluate compiled logic against borrowed data.
#![allow(unused)]
fn main() {
pub fn evaluate(&self, compiled: &CompiledLogic, data: &Value) -> Result<Value>
}
Parameters:
compiled- Reference to compiled logicdata- Reference to input data
Returns:
Ok(Value)- Evaluation resultErr(Error)- Evaluation error
Example:
#![allow(unused)]
fn main() {
let data = json!({ "x": 15 });
let result = engine.evaluate(&compiled, &data)?;
}
evaluate_owned
Evaluate compiled logic, taking ownership of data.
#![allow(unused)]
fn main() {
pub fn evaluate_owned(&self, compiled: &CompiledLogic, data: Value) -> Result<Value>
}
Parameters:
compiled- Reference to compiled logicdata- Input data (owned)
Returns:
Ok(Value)- Evaluation resultErr(Error)- Evaluation error
Example:
#![allow(unused)]
fn main() {
let result = engine.evaluate_owned(&compiled, json!({ "x": 15 }))?;
}
evaluate_json
Convenience method to evaluate JSON strings directly.
#![allow(unused)]
fn main() {
pub fn evaluate_json(&self, logic: &str, data: &str) -> Result<Value>
}
Parameters:
logic- JSONLogic rule as a JSON stringdata- Input data as a JSON string
Returns:
Ok(Value)- Evaluation resultErr(Error)- Parse or evaluation error
Example:
#![allow(unused)]
fn main() {
let result = engine.evaluate_json(
r#"{ "+": [1, 2] }"#,
r#"{}"#
)?;
}
add_operator
Register a custom operator.
#![allow(unused)]
fn main() {
pub fn add_operator(&mut self, name: String, operator: Box<dyn Operator>)
}
Parameters:
name- Operator name (used in rules)operator- Boxed operator implementation
Example:
#![allow(unused)]
fn main() {
engine.add_operator("double".to_string(), Box::new(DoubleOperator));
}
CompiledLogic
Pre-compiled rule representation. Created by DataLogic::compile().
Characteristics
- Thread-safe: Wrapped in
Arc, implementsSend + Sync - Immutable: Cannot be modified after compilation
- Shareable: Cheap to clone (reference counting)
Usage
#![allow(unused)]
fn main() {
// Compile once
let compiled = engine.compile(&rule)?;
// Share across threads
let compiled_clone = Arc::clone(&compiled);
std::thread::spawn(move || {
engine.evaluate(&compiled_clone, &data);
});
// Evaluate multiple times
for data in datasets {
engine.evaluate(&compiled, &data)?;
}
}
EvaluationConfig
Configuration for evaluation behavior.
Creating Configuration
#![allow(unused)]
fn main() {
use datalogic_rs::EvaluationConfig;
let config = EvaluationConfig::default();
}
Builder Methods
#![allow(unused)]
fn main() {
// NaN handling
config.with_nan_handling(NanHandling::IgnoreValue)
// Division by zero
config.with_division_by_zero(DivisionByZero::ReturnNull)
// Truthiness evaluation
config.with_truthy_evaluator(TruthyEvaluator::Python)
// Loose equality errors
config.with_loose_equality_throws_errors(false)
}
Presets
#![allow(unused)]
fn main() {
// Lenient arithmetic
let config = EvaluationConfig::safe_arithmetic();
// Strict type checking
let config = EvaluationConfig::strict();
}
NanHandling
How to handle non-numeric values in arithmetic.
#![allow(unused)]
fn main() {
pub enum NanHandling {
ThrowError, // Default: throw an error
IgnoreValue, // Skip non-numeric values
CoerceToZero, // Treat as 0
}
}
DivisionByZero
How to handle division by zero.
#![allow(unused)]
fn main() {
pub enum DivisionByZero {
ReturnBounds, // Default: return Infinity/-Infinity
ThrowError, // Throw an error
ReturnNull, // Return null
}
}
TruthyEvaluator
How to evaluate truthiness.
#![allow(unused)]
fn main() {
pub enum TruthyEvaluator {
JavaScript, // Default: JS-style truthiness
Python, // Python-style truthiness
StrictBoolean, // Only true/false are valid
Custom(Arc<dyn Fn(&Value) -> bool + Send + Sync>),
}
}
Operator Trait
Interface for custom operators.
#![allow(unused)]
fn main() {
pub trait Operator: Send + Sync {
fn evaluate(
&self,
args: &[Value],
context: &mut ContextStack,
evaluator: &dyn Evaluator,
) -> Result<Value>;
}
}
Parameters:
args- Unevaluated arguments from the rulecontext- Current evaluation contextevaluator- Interface to evaluate nested expressions
Important: Arguments are unevaluated. Call evaluator.evaluate() to resolve them.
Evaluator Trait
Interface for evaluating expressions (used in custom operators).
#![allow(unused)]
fn main() {
pub trait Evaluator {
fn evaluate(&self, value: &Value, context: &mut ContextStack) -> Result<Value>;
}
}
ContextStack
Manages variable scope during evaluation.
Accessing Current Element
In array operations (map, filter, reduce):
#![allow(unused)]
fn main() {
// Access current element
let current = context.current();
// Access current index
let index = context.index();
// Access accumulator (in reduce)
let acc = context.accumulator();
}
Error
Error types returned by datalogic-rs.
#![allow(unused)]
fn main() {
pub enum Error {
InvalidArguments(String),
UnknownOperator(String),
TypeError(String),
DivisionByZero,
Custom(String),
// ... other variants
}
}
Common Error Handling
#![allow(unused)]
fn main() {
use datalogic_rs::Error;
match engine.evaluate(&compiled, &data) {
Ok(result) => println!("Result: {}", result),
Err(Error::InvalidArguments(msg)) => eprintln!("Bad arguments: {}", msg),
Err(Error::UnknownOperator(op)) => eprintln!("Unknown operator: {}", op),
Err(e) => eprintln!("Error: {}", e),
}
}
Result Type
#![allow(unused)]
fn main() {
pub type Result<T> = std::result::Result<T, Error>;
}
Full Example
use datalogic_rs::{DataLogic, EvaluationConfig, NanHandling, Error};
use serde_json::json;
use std::sync::Arc;
fn main() -> Result<(), Error> {
// Create configured engine
let config = EvaluationConfig::default()
.with_nan_handling(NanHandling::IgnoreValue);
let engine = Arc::new(DataLogic::with_config(config));
// Compile rule
let rule = json!({
"if": [
{ ">=": [{ "var": "score" }, 60] },
"pass",
"fail"
]
});
let compiled = engine.compile(&rule)?;
// Evaluate with different data
let results: Vec<_> = vec![
json!({ "score": 85 }),
json!({ "score": 45 }),
json!({ "score": 60 }),
].into_iter()
.map(|data| engine.evaluate_owned(&compiled, data))
.collect();
for result in results {
println!("{}", result?);
}
Ok(())
}