# json-eval-rs

[![GitHub Release](https://img.shields.io/github/v/release/byrizki/jsoneval-rs?display_name=release&logo=github)](https://github.com/byrizki/jsoneval-rs/releases/latest)

<!-- Registry Versions -->

[![Crates.io](https://img.shields.io/crates/v/json-eval-rs?label=json-eval-rs&logo=rust)](https://crates.io/crates/json-eval-rs)
[![NuGet](https://img.shields.io/nuget/v/JsonEvalRs?label=JsonEvalRs&logo=nuget)](https://www.nuget.org/packages/JsonEvalRs)
[![RN](https://img.shields.io/npm/v/@json-eval-rs/react-native?label=@json-eval-rs/react-native&logo=npm)](https://www.npmjs.com/package/@json-eval-rs/react-native)
[![Web Core](https://img.shields.io/npm/v/@json-eval-rs/webcore?label=@json-eval-rs/webcore&logo=npm)](https://www.npmjs.com/package/@json-eval-rs/webcore)
[![Bundler](https://img.shields.io/npm/v/@json-eval-rs/bundler?label=@json-eval-rs/bundler&logo=npm)](https://www.npmjs.com/package/@json-eval-rs/bundler)
[![Vanilla Web](https://img.shields.io/npm/v/@json-eval-rs/vanilla?label=@json-eval-rs/vanilla&logo=npm)](https://www.npmjs.com/package/@json-eval-rs/vanilla)
[![Node](https://img.shields.io/npm/v/@json-eval-rs/node?label=@json-eval-rs/node&logo=npm)](https://www.npmjs.com/package/@json-eval-rs/node)

**High-performance JSON Logic evaluation library with schema validation and multi-platform bindings**

`json-eval-rs` is a blazing-fast JSON Logic evaluator written in Rust, featuring a custom-built compiler, intelligent caching, and comprehensive schema validation. It provides seamless integration across multiple platforms through native bindings.

## ✨ Key Features

- 🚀 **High Performance**: Custom JSON Logic compiler with pre-compilation and zero-copy caching
- 🔄 **Topological Sorting**: Dependency-aware processing to ensure correct evaluation order
- 📊 **Schema Validation**: Built-in validation with detailed error reporting
- 🌐 **Multi-Platform**: Native bindings for Rust, C#/.NET, Web (WASM), and React Native
- 💾 **Smart Caching**: Content-based caching with Arc-based zero-copy storage
- 🔍 **Dependency Tracking**: Automatic field dependency detection for selective re-evaluation
- 📐 **SIMD Optimized**: Uses `simd-json` for ultra-fast JSON parsing
- ⚡ **Selective Evaluation**: Re-evaluate only specific fields for improved performance
- 🌍 **Timezone Support**: Configurable timezone offset for date/time operations

## 🎯 Use Cases

- **Dynamic Form Validation**: Real-time validation with complex business rules
- **Configuration Management**: Evaluate dynamic configurations with dependencies
- **Business Rule Engines**: Execute complex business logic with high performance
- **Data Transformation**: Transform and validate large datasets efficiently
- **UI Layout Resolution**: Resolve conditional layouts with `$ref` references
- **Interactive Forms**: Selective re-evaluation for efficient field updates
- **Multi-Timezone Applications**: Handle date/time operations across different timezones

## 📖 Documentation

**[📚 Comprehensive Operator Documentation](docs/README.md)** - Complete guide to all 80+ available operators:

- **[Quick Reference](docs/reference/summary.md)** - Alphabetical operator list
- **[Core Operators](docs/reference/core.md)** - Variables and literals
- **[Logical Operators](docs/reference/logical.md)** - Boolean logic (`and`, `or`, `if`, etc.)
- **[Comparison Operators](docs/reference/comparison.md)** - Value comparisons (`==`, `<`, `>`, etc.)
- **[Arithmetic Operators](docs/reference/arithmetic.md)** - Math operations (`+`, `-`, `*`, `/`, etc.)
- **[String Operators](docs/reference/string.md)** - Text manipulation (`cat`, `substr`, `search`, etc.)
- **[Math Functions](docs/reference/math.md)** - Advanced math (`round`, `abs`, `max`, etc.)
- **[Date Functions](docs/reference/date.md)** - Date/time operations (`today`, `dateformat`, etc.)
- **[Array Operators](docs/reference/array.md)** - Array transformations (`map`, `filter`, `reduce`, etc.)
- **[Table Operators](docs/reference/table.md)** - Data lookups (`VALUEAT`, `INDEXAT`, etc.)
- **[Utility Operators](docs/reference/utility.md)** - Helper functions (`missing`, `RANGEOPTIONS`, etc.)

## 📦 Installation

### Rust

```toml
[dependencies]
json-eval-rs = "0.0.89"
```

### C# / .NET

```bash
dotnet add package JsonEvalRs
```

### Web / JavaScript / TypeScript

```bash
yarn add @json-eval-rs/webcore
# Then add either specific backend:
yarn add @json-eval-rs/bundler # (For Vite/Webpack)
# OR
yarn add @json-eval-rs/vanilla # (For Vanilla JS)
```

### React Native

```bash
yarn install @json-eval-rs/react-native
```

## 🔥 Advanced Features

### Selective Evaluation

Selective evaluation allows you to re-evaluate only specific fields in your schema, significantly improving performance for partial updates.

**Benefits:**
- ⚡ Faster updates when only a few fields change
- 💾 Reduced cache invalidation
- 🎯 Perfect for interactive forms and real-time validation
- 📈 Scales well with large schemas

**Rust Example:**

```rust
use json_eval_rs::JSONEval;

let mut eval = JSONEval::new(&schema, None, Some(&data))?;

// Full evaluation
eval.evaluate(&data, None, None)?;

// Later, selectively re-evaluate only specific fields
let paths = vec![
    "user.email".to_string(),
    "billing.total".to_string()
];
eval.evaluate(&updated_data, None, Some(&paths))?;
```

**C# Example:**

```csharp
using JsonEvalRs;

var eval = new JSONEval(schema);
eval.Evaluate(data);

// Selective re-evaluation
var paths = new[] { "user.email", "billing.total" };
eval.Evaluate(updatedData, paths: paths);
```

**Web/TypeScript Example:**

```typescript
import { JSONEval } from "@json-eval-rs/web";

const eval = new JSONEval({ schema: JSON.stringify(schema) });
await eval.evaluateJS({ data: JSON.stringify(data) });

// Selective re-evaluation
await eval.evaluateJS({
  data: JSON.stringify(updatedData),
  paths: ["user.email", "billing.total"]
});
```

**How it works:**
- Pass field paths in dotted notation (e.g., `"field.nested.property"`)
- Only specified fields and their dependencies are recalculated
- Other fields retain their previously evaluated values
- Cache is selectively purged only for affected fields

### Timezone Configuration

Configure timezone offset for all date/time operations without external dependencies.

**Benefits:**
- 🌍 Handle dates in any timezone
- 🔄 Runtime timezone switching
- 🚀 No external datetime library required
- 📅 Consistent date handling across platforms

**Rust Example:**

```rust
use json_eval_rs::JSONEval;

let mut eval = JSONEval::new(&schema, None, None)?;

// Set to UTC+7 (Bangkok, Jakarta) - 420 minutes offset
eval.set_timezone_offset(Some(420));

eval.evaluate(&data, None, None)?;

// Reset to UTC
eval.set_timezone_offset(None);
```

**C# Example:**

```csharp
using JsonEvalRs;

var eval = new JSONEval(schema);

// Set timezone to UTC+7 (420 minutes)
eval.SetTimezoneOffset(420);

eval.Evaluate(data);

// Reset to UTC
eval.SetTimezoneOffset(null);
```

**Web/TypeScript Example:**

```typescript
import { JSONEval } from "@json-eval-rs/web";

const eval = new JSONEval({ schema: JSON.stringify(schema) });

// Set timezone to UTC+7
eval.setTimezoneOffset(420);

await eval.evaluateJS({ data: JSON.stringify(data) });

// Reset to UTC
eval.setTimezoneOffset(null);
```

**Common Timezone Offsets:**
- UTC: `0` or `null`
- UTC+7 (Bangkok, Jakarta): `420`
- UTC+9 (Tokyo, Seoul): `540`
- UTC-5 (EST): `-300`
- UTC-8 (PST): `-480`
- UTC+1 (CET): `60`

**Affected Operations:**
- `TODAY` - Current date at midnight in the specified timezone
- `NOW` - Current timestamp in the specified timezone
- `DATEFORMAT` - Formats dates using the timezone offset
- All date arithmetic operations

## 🚀 Quick Start

### Rust

```rust
use json_eval_rs::JSONEval;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let schema = r#"{
        "type": "object",
        "properties": {
            "name": {
                "rules": {
                    "required": { "value": true, "message": "Name is required" }
                }
            }
        }
    }"#;

    let mut eval = JSONEval::new(schema, None, None)?;
    let data = r#"{"name": "John Doe"}"#;

    eval.evaluate(data, None)?;
    let result = eval.get_evaluated_schema(false);

    // Validate the data
    let validation = eval.validate(data, None, None)?;
    if !validation.has_error {
        println!("✅ Data is valid!");
    } else {
        println!("❌ Validation errors: {:?}", validation.errors);
    }

    Ok(())
}
```

### C#

```csharp
using JsonEvalRs;

var schema = @"{
    ""type"": ""object"",
    ""properties"": {
        ""age"": {
            ""rules"": {
                ""minValue"": { ""value"": 18, ""message"": ""Must be 18 or older"" }
            }
        }
    }
}";

using (var eval = new JSONEval(schema))
{
    var data = @"{""age"": 25}";
    var result = eval.Evaluate(data);
    var validation = eval.Validate(data);

    if (!validation.HasError)
    {
        Console.WriteLine("✅ Data is valid!");
    }
}
```

### Web (TypeScript)

```typescript
import { JSONEval } from "@json-eval-rs/web";

const schema = {
  type: "object",
  properties: {
    email: {
      rules: {
        required: { value: true, message: "Email is required" },
        pattern: {
          value: "^[^@]+@[^@]+\\.[^@]+$",
          message: "Invalid email format",
        },
      },
    },
  },
};

const eval = new JSONEval({ schema: JSON.stringify(schema) });

const data = { email: "user@example.com" };
const result = await eval.evaluateJS({ data: JSON.stringify(data) });
const validation = await eval.validate({ data: JSON.stringify(data) });

if (!validation.has_error) {
  console.log("✅ Data is valid!");
}

eval.free(); // Clean up memory
```

### React Native

```typescript
import { useJSONEval } from "@json-eval-rs/react-native";

function ValidationForm() {
  const eval = useJSONEval({ schema });
  const [formData, setFormData] = useState({ name: "", age: "" });
  const [errors, setErrors] = useState({});

  const validateForm = async () => {
    if (!eval) return;

    const validation = await eval.validate({
      data: JSON.stringify(formData),
    });

    setErrors(validation.errors || {});
  };

  return (
    <View>
      <TextInput
        value={formData.name}
        onChangeText={(name) => setFormData({ ...formData, name })}
        onBlur={validateForm}
      />
      {errors.name && (
        <Text style={{ color: "red" }}>{errors.name.message}</Text>
      )}
    </View>
  );
}
```

## 🏗️ Architecture

### Core Components

- **JSONEval**: Main orchestrator handling the complete evaluation pipeline
- **RLogic Engine**: Custom JSON Logic compiler with pre-compilation and caching
- **EvalData**: Proxy-like data wrapper ensuring thread-safe mutations
- **EvalCache**: Content-based caching system using Arc for zero-copy storage
- **Table Evaluator**: Specialized processing for table/array data
- **Schema Parser**: Extracts evaluations and builds dependency graphs
- **Topological Sort**: Groups evaluations into parallel-executable batches

### Evaluation Pipeline

1. **Schema Parsing** → Extract evaluations and build dependency graph
2. **Logic Compilation** → Pre-compile JSON Logic expressions for performance
3. **Topological Sorting** → Group evaluations into dependency-ordered batches
4. **Batch Evaluation** → Execute batches sequentially with caching
5. **Result Aggregation** → Clean results and resolve layout references

## ⚡ Performance

### Benchmarks

| Operation            | json-eval-rs | Native JS | Improvement     |
| -------------------- | ------------ | --------- | --------------- |
| Parse Complex Schema | 3ms          | 15ms      | **5x faster**   |
| Evaluate 1000 Rules  | 8ms          | 45ms      | **5.6x faster** |
| Validate Large Form  | 2ms          | 12ms      | **6x faster**   |
| Cache Hit Lookup     | 0.1ms        | 2ms       | **20x faster**  |

_Benchmarks run on Intel i7 with complex real-world schemas_

### Features Contributing to Performance

- **Pre-compilation**: JSON Logic expressions compiled once, evaluated many times
- **Zero-Copy Caching**: Results cached using `Arc<Value>` to avoid deep cloning
- **SIMD JSON**: Uses `simd-json` for ultra-fast JSON parsing
- **Smart Dependencies**: Only re-evaluates fields when their dependencies change
- **Selective Evaluation**: Re-evaluate only specific fields instead of entire schema
- **Intelligent Cache Purging**: Selective cache invalidation for changed fields only

## 🔧 Examples & CLI Tool

The library includes comprehensive examples demonstrating various use cases:

### Basic Example

Simple evaluation with automatic scenario discovery:

```bash
# Run all scenarios
cargo run --example basic

# Run specific scenario
cargo run --example basic zcc

# Enable comparison with expected results
cargo run --example basic --compare
```

### Benchmark Example

Advanced benchmarking with ParsedSchema caching and concurrent testing:

```bash
# Run with 100 iterations
cargo run --example benchmark -- -i 100 zcc

# Use ParsedSchema for efficient caching
cargo run --release --example benchmark -- --parsed -i 100 zcc

# Test concurrent evaluations (4 threads, 10 iterations each)
cargo run --example benchmark -- --parsed --concurrent 4 -i 10

# Full benchmarking suite with comparison
cargo run --release --example benchmark -- --parsed -i 100 --compare
```

For more details, see **[examples/README.md](examples/README.md)**.

### CLI Tool

A powerful CLI tool for direct schema evaluation with parsed schema inspection:

```bash
# Simple evaluation
cargo run --bin json-eval-cli -- schema.json -d data.json

# With comparison and ParsedSchema
cargo run --bin json-eval-cli -- schema.json -d data.json \
  -c expected.json --parsed -i 100

# Inspect parsed schema structure
cargo run --bin json-eval-cli -- schema.json -d data.json \
  --parsed --no-output \
  --print-sorted-evaluations \
  --print-dependencies

# All parsed schema information
cargo run --bin json-eval-cli -- schema.json -d data.json \
  --parsed --print-all

# Full options with MessagePack support
cargo run --bin json-eval-cli -- schema.bform \
  --data data.bform \
  --compare expected.json \
  --compare-path "$.$params.others" \
  --parsed \
  --iterations 100 \
  --output result.json
```

**Parsed Schema Inspection Flags:**

- `--print-sorted-evaluations` - Show evaluation batches organized sequentially
- `--print-dependencies` - Show dependency graph between evaluations
- `--print-tables` - Show table definitions
- `--print-evaluations` - Show all compiled logic expressions
- `--print-all` - Show all parsed schema information

Run `cargo run --bin json-eval-cli -- --help` for full documentation.

### Example Output

```
🚀 JSON Evaluation Benchmark

==============================
Scenario: zcc
Schema: samples/zcc.json
Data: samples/zcc-data.json

Loading files...
Running evaluation...

  Schema parsing & compilation: 3.2ms
  Total evaluation time: 12.4ms
  Average per iteration: 124μs
  Cache: 1,247 entries, 8,932 hits, 89 misses (99.0% hit rate)
⏱️  Execution time: 15.6ms

✅ Results saved:
  - samples/zcc-evaluated-schema.json
  - samples/zcc-parsed-schema.json
  - samples/zcc-evaluated-value.json
```

## 🌍 Platform Support

| Platform         | Technology           | Performance | Bundle Size    |
| ---------------- | -------------------- | ----------- | -------------- |
| **Rust**         | Native               | Native      | N/A            |
| **C# / .NET**    | P/Invoke FFI         | Native      | ~2MB           |
| **Web**          | WebAssembly          | Near-native | ~450KB gzipped |
| **React Native** | Native Modules (JSI) | Native      | Native code    |

### Supported Targets

- **Linux**: x86_64, ARM64
- **Windows**: x86_64
- **macOS**: x86_64, ARM64 (Apple Silicon)
- **Web**: All modern browsers, Node.js 14+
- **Mobile**: iOS 11+, Android API 21+ (supports Android 15+ 16KB page sizes)

## 🏃‍♂️ Getting Started

### Prerequisites

- **Rust**: Latest stable (for core development)
- **.NET SDK 6.0+**: For C# bindings
- **Node.js 18+**: For Web/React Native bindings
- **wasm-pack**: For WebAssembly builds

### Building from Source

```bash
# Clone the repository
git clone https://github.com/byrizki/jsoneval-rs.git
cd json-eval-rs

# Build the core library
cargo build --release

# Run tests
cargo test

# Build all language bindings
./build-bindings.sh all

# Run CLI tool with examples
cargo run --bin json-eval-cli
```

## 📖 Documentation

- **[API Documentation](https://docs.rs/json-eval-rs)** - Complete Rust API reference
- **[C# Documentation](bindings/csharp/README.md)** - .NET integration guide
- **[Web Documentation](bindings/web/README.md)** - JavaScript/TypeScript usage
- **[React Native Documentation](bindings/react-native/README.md)** - Mobile development guide
- **[Architecture Guide](bindings/react-native/ARCHITECTURE.md)** - Deep dive into internals

## 🤝 Contributing

We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details.

### Development Setup

1. Fork and clone the repository
2. Install dependencies: `cargo build`
3. Run tests: `cargo test`
4. Make your changes
5. Add tests for new functionality
6. Run `cargo fmt` and `cargo clippy`
7. Submit a pull request

### Building Bindings

```bash
# Build specific binding
./build-bindings.sh csharp    # C# only
./build-bindings.sh web       # Web only
./build-bindings.sh react-native  # React Native only

# Package for publishing
./build-bindings.sh package
```

## 📊 Schema Format

json-eval-rs uses an extended JSON Schema format with evaluation rules:

```json
{
  "type": "object",
  "properties": {
    "fieldName": {
      "type": "string",
      "rules": {
        "required": {
          "value": true,
          "message": "This field is required"
        },
        "minLength": {
          "value": 3,
          "message": "Must be at least 3 characters"
        },
        "pattern": {
          "value": "^[A-Za-z]+$",
          "message": "Only letters allowed"
        }
      },
      "condition": {
        "hidden": { "==": [{ "var": "other.field" }, "hide"] },
        "disabled": { "!=": [{ "var": "user.role" }, "admin"] }
      }
    }
  },
  "$layout": {
    "elements": [
      {
        "type": "input",
        "$ref": "#/properties/fieldName"
      }
    ]
  }
}
```

### Supported Rule Types

- `required`: Field must have a value
- `minLength`/`maxLength`: String/array length validation
- `minValue`/`maxValue`: Numeric range validation
- `pattern`: Regular expression validation
- Custom rules via JSON Logic expressions

## ⚠️ Error Handling

The library provides detailed error information:

```rust
match eval.validate(data, None, None) {
    Ok(validation) => {
        if validation.has_error {
            for (field, error) in validation.errors {
                println!("Field '{}': {} ({})", field, error.message, error.rule_type);
            }
        }
    },
    Err(e) => eprintln!("Validation error: {}", e),
}
```

## 📄 License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## 🏢 Commercial Support

For commercial support, consulting, or custom development, please contact us at [support@example.com](mailto:support@example.com).

## 🙏 Acknowledgments

- Built with [Rust](https://rust-lang.org/) for maximum performance and safety
- Uses [simd-json](https://github.com/simd-lite/simd-json) for high-speed JSON parsing
- Inspired by the [JSON Logic](https://jsonlogic.com/) specification
- WebAssembly bindings powered by [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen)

---

**⭐ Star this repository if you find it useful!**
