Skip to main content

Crate dnf

Crate dnf 

Source
Expand description

§DNF Query Library

Build and evaluate DNF (Disjunctive Normal Form) queries against Rust structs. DNF queries are OR-ed ANDs: (a AND b) OR (c AND d) OR ...

§Quick Start

use dnf::{DnfEvaluable, DnfQuery, Op};

#[derive(DnfEvaluable)]
struct User { age: u32, premium: bool }

let query = DnfQuery::builder()
    .or(|c| c.and("age", Op::GTE, 18))
    .or(|c| c.and("premium", Op::EQ, true))
    .build();

let user = User { age: 25, premium: false };
assert!(query.evaluate(&user));

§Validation

The builder API doesn’t check field names at compile time — typos silently return false. Use validate() to catch mistakes early:

let query = DnfQuery::builder()
    .or(|c| c.and("age", Op::GT, 18))
    .validate::<User>()   // catches typos before build
    .unwrap()
    .build();

Or use the parser — it validates automatically:

let query = DnfQuery::parse::<User>("age > 18")?;

§Features

FeatureWhat it does
derive#[derive(DnfEvaluable)] macro (default)
serdeSerialization support
parserParse queries from strings

§Operators

CategoryOperators
ComparisonEQ NE GT GTE LT LTE
StringCONTAINS STARTS_WITH ENDS_WITH (+ NOT variants)
CollectionANY_OF ALL_OF (+ NOT variants)
RangeBETWEEN NOT_BETWEEN
CustomOp::custom("NAME")

§Collections & Range

use dnf::{DnfEvaluable, DnfQuery, Op, Value};

#[derive(DnfEvaluable)]
struct User { tags: Vec<String>, score: f64 }

let q = DnfQuery::builder()
    .or(|c| c.and("tags", Op::CONTAINS, "rust"))
    .or(|c| c.and("score", Op::BETWEEN, vec![60.0, 100.0]))
    .build();

§Custom Operators

use dnf::{DnfQuery, Op, Value};

let q = DnfQuery::builder()
    .with_custom_op("IS_ADULT", true, |f, _| matches!(f, Value::Uint(n) if *n >= 18))
    .or(|c| c.and("age", Op::custom("IS_ADULT"), Value::None))
    .build();

§Nested Structs

Field typeAttributeQuery syntax
Single struct#[dnf(nested)] required"address.city"
Vec<T>Auto-detected"offices.city" (any match)
HashMapN/AValue::at_key("k", "v")
use dnf::{DnfEvaluable, DnfQuery, Op};

#[derive(DnfEvaluable)]
struct Address { city: String }

#[derive(DnfEvaluable)]
struct User {
    #[dnf(nested)]         // required
    address: Address,
    offices: Vec<Address>, // auto-detected
}

§Derive Attributes

AttributeWhat it does
#[dnf(rename = "x")]Use different name in queries
#[dnf(skip)]Exclude field from queries
#[dnf(nested)]Enable dot notation for nested struct

§Map Queries

use dnf::{DnfEvaluable, DnfQuery, Op, Value};
use std::collections::HashMap;

#[derive(DnfEvaluable)]
struct Doc { meta: HashMap<String, String> }

let q = DnfQuery::builder()
    .or(|c| c.and("meta", Op::EQ, Value::at_key("author", "Alice")))
    .build();
OperationCode
Key’s valueValue::at_key("key", value)
Key existsValue::keys("key")
Value existsValue::values(value)

§Supported Types

CategoryTypes
Integersi8i64, isize, u8u64, usize
Floatsf32, f64
StringsString, &str, Box<str>, Cow<str>
Otherbool
CollectionsVec<T>, HashSet<T>
MapsHashMap<String, V>, BTreeMap<String, V>
WrappersOption<T>

§Manual Implementation

For computed fields or custom logic:

use dnf::{DnfEvaluable, DnfField, FieldInfo, Op, Value};

struct Doc { title: String, tags: Vec<String> }

impl DnfEvaluable for Doc {
    fn evaluate_field(&self, field: &str, op: &Op, value: &Value) -> bool {
        match field {
            "title" => self.title.evaluate(op, value),
            "tag_count" => self.tags.len().evaluate(op, value), // computed
            _ => false,
        }
    }
    fn fields() -> impl Iterator<Item = FieldInfo> {
        [FieldInfo::new("title", "String"), FieldInfo::new("tag_count", "usize")].into_iter()
    }
}

Structs§

Condition
Public query types: a Condition groups into a Conjunction, conjunctions into a DnfQuery. Represents a single field operator value test in a DNF query.
Conjunction
Public query types: a Condition groups into a Conjunction, conjunctions into a DnfQuery. An AND of Conditions — one clause inside a DnfQuery.
DnfQuery
Public query types: a Condition groups into a Conjunction, conjunctions into a DnfQuery. A query in disjunctive normal form: an OR of Conjunctions.
FieldInfo
Static metadata about one queryable field on a DnfEvaluable type.
Op
Operator constructed for a Condition (e.g. Op::EQ, Op::custom). A query operator with an optional negation flag.
OpRegistry
Registry of custom operator implementations. A thread-safe registry of custom operators.
QueryBuilder
Fluent builder for DnfQuery. Constructs a DnfQuery with a fluent API.

Enums§

DnfError
Unified error type returned by builder, parser, and evaluation APIs. The error type returned by all fallible DNF operations.
FieldKind
Classifies a field by how it must be evaluated against a query.
Value
Typed value used inside a Condition. A value used in a DNF query condition.

Traits§

DnfEvaluable
Types that can be evaluated against a DnfQuery.
DnfField
Trait implemented by every type that can appear as a field value. Evaluates a struct field against a DNF operator and value.

Derive Macros§

DnfEvaluable
Derive macro that generates a DnfEvaluable implementation for a struct. Derives DnfEvaluable for a struct with named fields.