Skip to main content
The bomboni_request crate provides utilities for parsing and validating API requests, particularly focusing on list and search operations following Google AIP standards. It includes filter expression parsing, ordering, query building, and SQL generation.

Core Types

Filter

Filter expression parser following Google AIP-160 standard.
use bomboni_request::filter::Filter;

// Parse a filter expression
let filter = Filter::parse("age >= 18 AND status = \"active\"")?;

// Validate against schema
filter.validate(&schema, None)?;

// Evaluate filter against an item
let matches = filter.evaluate(&user);

Methods

  • parse(source: &str) -> FilterResult<Self> - Parses a filter from a source string
  • evaluate<T: SchemaMapped>(&self, item: &T) -> Option<Value> - Evaluates the filter against an item
  • validate(&self, schema: &Schema, schema_functions: Option<&FunctionSchemaMap>) -> FilterResult<()> - Validates filter against schema
  • len(&self) -> usize - Returns the length of the filter
  • is_empty(&self) -> bool - Checks if the filter is empty
  • add_conjunction(&mut self, other: Self) - Adds a conjunction to the filter
  • add_disjunction(&mut self, other: Self) - Adds a disjunction to the filter

Filter Grammar

Supported operators:
  • Comparison: <, <=, >, >=, =, !=
  • Has operator: :
  • Logical: AND, OR, NOT
  • Parentheses for grouping: (, )
Value types:
  • Strings: "value"
  • Numbers: 42, 3.14
  • Booleans: true, false
  • Timestamps: RFC3339 format
  • Wildcards: *

FilterComparator

Comparison operators for filters.
pub enum FilterComparator {
    Less,           // <
    LessOrEqual,    // <=
    Greater,        // >
    GreaterOrEqual, // >=
    Equal,          // =
    NotEqual,       // !=
    Has,            // :
}

Ordering

Query ordering specification.
use bomboni_request::ordering::Ordering;

// Parse ordering
let ordering = Ordering::parse("age desc, name asc")?;

// Validate ordering
ordering.validate(&schema)?;

// Evaluate ordering between items
let cmp = ordering.evaluate(&user1, &user2);

Methods

  • new(terms: Vec<OrderingTerm>) -> Self - Creates a new ordering
  • parse(source: &str) -> OrderingResult<Self> - Parses an ordering string
  • evaluate<T: SchemaMapped>(&self, lhs: &T, rhs: &T) -> Option<cmp::Ordering> - Evaluates ordering between two items
  • validate(&self, schema: &Schema) -> OrderingResult<()> - Validates the ordering against a schema

OrderingTerm

A single ordering term.
pub struct OrderingTerm {
    pub name: String,
    pub direction: OrderingDirection,
}

OrderingDirection

Sort direction.
pub enum OrderingDirection {
    Ascending,
    Descending,
}

Query Builders

ListQuery

Represents a list query for paginated, filtered, and ordered results following Google AIP-132.
pub struct ListQuery<T = FilterPageToken> {
    pub page_size: i32,
    pub page_token: Option<T>,
    pub filter: Filter,
    pub ordering: Ordering,
}

ListQueryBuilder

Builder for list queries with schema validation.
use bomboni_request::query::list::{ListQueryBuilder, ListQueryConfig};
use bomboni_request::query::page_token::plain::PlainPageTokenBuilder;

let builder = ListQueryBuilder::new(
    schema,
    function_schema_map,
    ListQueryConfig {
        max_page_size: Some(100),
        default_page_size: 20,
        primary_ordering_term: Some(OrderingTerm {
            name: "id".into(),
            direction: OrderingDirection::Descending,
        }),
        max_filter_length: Some(500),
        max_ordering_length: Some(100),
    },
    PlainPageTokenBuilder {},
);

let query = builder.build(
    Some(50),
    None,
    Some("status = \"active\""),
    Some("created_time desc"),
)?;

Methods

  • new(schema, schema_functions, options, page_token_builder) -> Self - Creates a new list query builder
  • build(page_size, page_token, filter, ordering) -> QueryResult<ListQuery> - Builds a list query
  • build_next_page_token<T: SchemaMapped>(query, next_item) -> QueryResult<String> - Builds the next page token

ListQueryConfig

Configuration for list query builder.
pub struct ListQueryConfig {
    pub max_page_size: Option<i32>,
    pub default_page_size: i32,
    pub primary_ordering_term: Option<OrderingTerm>,
    pub max_filter_length: Option<usize>,
    pub max_ordering_length: Option<usize>,
}

SearchQuery

Represents a search query with text search support.
pub struct SearchQuery<T = FilterPageToken> {
    pub query: String,
    pub page_size: i32,
    pub page_token: Option<T>,
    pub filter: Filter,
    pub ordering: Ordering,
}

SearchQueryBuilder

Builder for search queries.
use bomboni_request::query::search::{SearchQueryBuilder, SearchQueryConfig};

let builder = SearchQueryBuilder::new(
    schema,
    function_schema_map,
    SearchQueryConfig {
        max_query_length: Some(200),
        max_page_size: Some(100),
        default_page_size: 20,
        primary_ordering_term: Some(primary_term),
        max_filter_length: Some(500),
        max_ordering_length: Some(100),
    },
    page_token_builder,
);

let query = builder.build(
    "search text",
    Some(50),
    None,
    Some("status = \"active\""),
    Some("relevance desc"),
)?;

Methods

  • new(schema, schema_functions, options, page_token_builder) -> Self - Creates a new search query builder
  • build(query, page_size, page_token, filter, ordering) -> QueryResult<SearchQuery> - Builds a search query
  • build_next_page_token<T: SchemaMapped>(query, next_item) -> QueryResult<String> - Builds the next page token

SearchQueryConfig

Configuration for search query builder.
pub struct SearchQueryConfig {
    pub max_query_length: Option<usize>,
    pub max_page_size: Option<i32>,
    pub default_page_size: i32,
    pub primary_ordering_term: Option<OrderingTerm>,
    pub max_filter_length: Option<usize>,
    pub max_ordering_length: Option<usize>,
}

Page Tokens

FilterPageToken

A page token containing a filter for pagination.
pub struct FilterPageToken {
    pub filter: Filter,
}

PageTokenBuilder

Trait for building and parsing page tokens.
pub trait PageTokenBuilder {
    type PageToken: Clone + ToString;

    fn parse(
        &self,
        filter: &Filter,
        ordering: &Ordering,
        salt: &[u8],
        page_token: &str,
    ) -> QueryResult<Self::PageToken>;

    fn build_next<T: SchemaMapped>(
        &self,
        filter: &Filter,
        ordering: &Ordering,
        salt: &[u8],
        next_item: &T,
    ) -> QueryResult<String>;
}

Page Token Implementations

  • PlainPageTokenBuilder - Plain text page tokens
  • Base64PageTokenBuilder - Base64 encoded page tokens
  • Aes256PageTokenBuilder - AES256 encrypted page tokens
  • RsaPageTokenBuilder - RSA encrypted page tokens

SQL Generation

SqlFilterBuilder

Builder for generating SQL WHERE clauses from filters.
use bomboni_request::sql::{SqlFilterBuilder, SqlDialect};

let mut builder = SqlFilterBuilder::new(SqlDialect::Postgres, &schema);
builder.set_rename_map(&rename_map);
builder.set_argument_style(SqlArgumentStyle::Indexed { prefix: "$".into() });

let (sql, arguments) = builder.build(&filter)?;
// sql: "age >= $1 AND status = $2"
// arguments: [18, "active"]

Methods

  • new(dialect: SqlDialect, schema: &Schema) -> Self - Creates a new SQL filter builder
  • set_schema_functions(&mut self, schema_functions: &FunctionSchemaMap) -> &mut Self - Sets the schema functions
  • set_rename_map(&mut self, rename_map: &SqlRenameMap) -> &mut Self - Sets the rename map
  • set_document_offset(&mut self, offset: usize) -> &mut Self - Sets the document offset
  • case_insensitive_like(&mut self) -> &mut Self - Enables case insensitive like
  • set_argument_style(&mut self, argument_style: SqlArgumentStyle) -> &mut Self - Sets the argument style
  • build(&mut self, filter: &Filter) -> FilterResult<(String, Vec<Value>)> - Builds a SQL filter

SqlDialect

SQL dialect for generation.
pub enum SqlDialect {
    Postgres,
    MySql,
}

SqlArgumentStyle

SQL argument placeholder style.
pub enum SqlArgumentStyle {
    Indexed { prefix: String },  // $1, $2, $3...
    Positional { symbol: String }, // ?, ?, ?...
}

SqlRenameMap

Rename map for SQL generation.
pub struct SqlRenameMap {
    pub members: BTreeMap<String, String>,
    pub functions: BTreeMap<String, String>,
}

Schema

Schema

Schema for query validation.
pub struct Schema {
    pub members: BTreeMap<String, MemberSchema>,
}

Methods

  • get_member(&self, name: &str) -> Option<&MemberSchema> - Gets member schema by name
  • get_field(&self, name: &str) -> Option<&FieldMemberSchema> - Gets field schema by name

MemberSchema

Schema member type.
pub enum MemberSchema {
    Resource(ResourceMemberSchema),
    Field(FieldMemberSchema),
}

FieldMemberSchema

Field member schema.
pub struct FieldMemberSchema {
    pub value_type: ValueType,
    pub repeated: bool,
    pub ordered: bool,
    pub allow_has_operator: bool,
}

Methods

  • new(value_type: ValueType) -> Self - Creates a new field member schema
  • new_ordered(value_type: ValueType) -> Self - Creates a new ordered field member schema
  • new_repeated(value_type: ValueType) -> Self - Creates a new repeated field member schema

ValueType

Value type for schema validation.
pub enum ValueType {
    Integer,
    Float,
    Boolean,
    String,
    Timestamp,
    Any,
}

SchemaMapped

Trait for types that can be mapped to schema values.
pub trait SchemaMapped {
    fn get_field(&self, name: &str) -> Value;
}

Value

Query value representation.
pub enum Value {
    Integer(i64),
    Float(f64),
    Boolean(bool),
    String(String),
    Timestamp(UtcDateTime),
    Repeated(Vec<Self>),
    Any,
}

Methods

  • value_type(&self) -> Option<ValueType> - Gets the value type
  • parse(pair: &Pair<Rule>) -> FilterResult<Self> - Parses a value from a pest pair

Type Aliases

Query Builders

type PlainListQueryBuilder = ListQueryBuilder<PlainPageTokenBuilder>;
type Aes256ListQueryBuilder = ListQueryBuilder<Aes256PageTokenBuilder>;
type Base64ListQueryBuilder = ListQueryBuilder<Base64PageTokenBuilder>;
type RsaListQueryBuilder = ListQueryBuilder<RsaPageTokenBuilder>;

type PlainSearchQueryBuilder = SearchQueryBuilder<PlainPageTokenBuilder>;
type Aes256SearchQueryBuilder = SearchQueryBuilder<Aes256PageTokenBuilder>;
type Base64SearchQueryBuilder = SearchQueryBuilder<Base64PageTokenBuilder>;
type RsaSearchQueryBuilder = SearchQueryBuilder<RsaPageTokenBuilder>;

Examples

Basic Filter Usage

use bomboni_request::filter::Filter;

// Parse and evaluate
let filter = Filter::parse("age >= 18 AND status = \"active\"")?;
let matches = filter.evaluate(&user);

List Query with Pagination

use bomboni_request::query::list::{ListQueryBuilder, ListQueryConfig};

let query = builder.build(
    Some(50),
    None,
    Some("deleted = false"),
    Some("created_time desc"),
)?;

// Process results and generate next page token
let next_token = builder.build_next_page_token(&query, &last_item)?;

SQL Generation

use bomboni_request::sql::SqlFilterBuilder;

let filter = Filter::parse("age >= 18 AND name = \"John\"")?;
let mut builder = SqlFilterBuilder::new(SqlDialect::Postgres, &schema);
let (sql, args) = builder.build(&filter)?;
// Use sql and args with your database query

Build docs developers (and LLMs) love