aip-160

Crates.ioaip-160
lib.rsaip-160
version0.1.5
created_at2025-11-19 03:03:59.603659+00
updated_at2025-11-27 12:46:14.394416+00
descriptionA Rust implementation of Google AIP-160 filtering standard.
homepage
repositoryhttps://github.com/AprilNEA/aip-160
max_upload_size
id1939358
size117,629
AprilNEA (AprilNEA)

documentation

README

AIP-160 Filter Parser with SeaORM Support

A Rust implementation of Google AIP-160 filtering standard with SeaORM integration.

Features

  • Full AIP-160 Support - Parse Google AIP-160 filter expressions
  • Type Safe - Strongly typed AST and error handling
  • Zero Boilerplate - No trait implementation required!
  • Well Tested - Comprehensive test coverage
  • SeaORM Integration - Convert filters directly to SeaORM conditions

Installation

[dependencies]
# Basic parsing only
aip-160 = "0.1"

# With SeaORM support
aip-160 = { version = "0.1", features = ["sea-orm"] }

Quick Start

Basic Parsing

use aip_160::parse_filter;

fn main() {
    let filter = parse_filter("name = \"John\" AND age > 18").unwrap();
    println!("{}", filter);
}

SeaORM Integration with Automatic Type Conversion

use aip_160::{parse_filter, ToSeaOrmCondition};
use sea_orm::entity::prelude::*;

async fn find_users(
    db: &DatabaseConnection,
    filter_str: &str
) -> Result<Vec<Model>, DbErr> {
    // 1. Parse the filter string
    let filter = parse_filter(filter_str)?;

    // 2. Convert to SeaORM condition - pass Entity type!
    let condition = filter.to_condition::<Entity>()?;

    // 3. Use in your query
    Entity::find()
        .filter(condition)
        .all(db)
        .await
}

✨ Zero-Config Automatic Type Conversion

The library automatically detects column types from your Entity and applies appropriate SQL casts!

No manual configuration needed - just pass your Entity type to to_condition():

// PostgreSQL with UUID - automatic casting!
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "users")]
pub struct Model {
    #[sea_orm(primary_key, column_type = "Uuid")]
    pub id: Uuid,
    pub name: String,
    #[sea_orm(column_type = "TimestampWithTimeZone")]
    pub created_at: DateTimeWithTimeZone,
}

// Just use string values - they're automatically cast to the right type!
let filter = parse_filter("id = \"550e8400-e29b-41d4-a716-446655440000\"")?;
let condition = filter.to_condition::<Entity>()?;  // Automatically casts to UUID!

Entity::find().filter(condition).all(db).await?;

Supported automatic conversions:

  • StringUUID (for UUID columns)
  • StringTIMESTAMP / TIMESTAMPTZ (for timestamp columns)
  • StringDATE (for date columns)
  • StringTIME (for time columns)
  • StringENUM (for PostgreSQL enum columns)
  • NumberINTEGER / FLOAT (based on database column type)

The library reads your Entity's column definitions and generates the appropriate SQL CAST expressions automatically!

Supported Filter Syntax

Comparison Operators

Operator Description Example
= Equal name = "John"
!= Not equal status != "inactive"
> Greater than age > 18
>= Greater than or equal age >= 18
< Less than age < 65
<= Less than or equal age <= 65
: Contains/Has email : "@gmail.com"

Logical Operators

Operator Description Example
AND Logical AND active = true AND age > 18
OR Logical OR status = "active" OR status = "pending"
NOT Logical NOT NOT deleted = true
( ) Grouping (a = 1 OR a = 2) AND b = 3

Value Types

Type Example
String "value" or 'value'
Number 42, 3.14, -10, 1e5
Boolean true, false
Null null

💡 Example Filters

# Simple equality
name = "John Doe"

# Numeric comparison
age > 18 AND age < 65

# Multiple conditions
active = true AND age > 18 AND verified = true

# OR conditions
status = "active" OR status = "pending"

# Grouped expressions
(status = "active" OR status = "pending") AND age > 18

# Contains/substring matching
email : "@example.com"

# NOT operator
NOT deleted = true

# Complex query
(active = true OR status = "trial") AND age >= 18 AND email : "@company.com"

How It Works

The library automatically converts snake_case field names to PascalCase Column names:

"created_at" → Column::CreatedAt
"user_id" → Column::UserId
"is_active" → Column::IsActive

Architecture

┌─────────────┐
│ Filter Text │  "age > 18 AND active = true"
└──────┬──────┘
       │ parse_filter()
       ▼
┌─────────────┐
│    AST      │  Filter { expression: And(...) }
└──────┬──────┘
       │ to_condition::<Column>()
       ▼
┌─────────────┐
│  Condition  │  SeaORM Condition
└─────────────┘

Google AIP-160 Compliance

  • ✅ Comparison operators (=, !=, <, <=, >, >=)
  • ✅ Logical operators (AND, OR, NOT)
  • ✅ Grouping with parentheses
  • ✅ String, number, boolean, and null values
  • ✅ Has/contains operator (:)
  • ⚠️ Partial: Function calls (not yet implemented)

License

MIT or Apache-2.0

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

References

Commit count: 0

cargo fmt