query only.Expand description
Predicates and cardinality helpers for native iterators.
Start with a replayable collection, borrow it with .iter(), and keep
inline closures on native Iterator::filter. Use
QueryIteratorExt::matching for a named Matcher or typed
FilterExpr, then apply exact cardinality without collecting or
exhausting more than two items:
use libtmux::query::{Matcher, QueryIteratorExt};
struct IsPending;
impl Matcher<(&'static str, bool)> for IsPending {
fn matches(&self, candidate: &(&'static str, bool)) -> bool {
!candidate.1
}
}
let tasks = vec![("build", false), ("test", true)];
let visible = tasks.iter().filter(|task| task.0.starts_with('b'));
assert_eq!(visible.collect::<Vec<_>>(), vec![&tasks[0]]);
assert_eq!(tasks.iter().matching(IsPending).exactly_one(), Ok(&tasks[0]));QueryIteratorExt::exactly_one distinguishes zero from multiple items;
QueryIteratorExt::one_or_none permits zero but rejects multiple items.
Both preserve the iterator’s item type and pull at most two items.
To take ownership, use .into_iter() with
QueryIteratorExt::matching_owned; selected values need not be Clone.
Portable expressions are owned, inert local values. With derive, typed
handles can be generated for downstream data without exposing the hidden
expansion constructors:
use libtmux::query::{Filterable as _, QueryIteratorExt as _};
#[derive(libtmux::Filterable)]
#[filterable(target = "task")]
struct Task {
name: String,
done: bool,
}
let tasks = vec![Task { name: "build".into(), done: false }];
let fields = Task::filter_fields();
let expression = fields.name.eq("build").and(fields.done.eq(false));
assert_eq!(tasks.iter().matching(&expression).count(), 1);Local matching is synchronous, ordered, and never performs tmux I/O or
native pushdown. Text predicates require strict candidate UTF-8, so every
text predicate returns false for invalid bytes, including not_in([]);
an outer FilterExpr::not may invert that result. Relations inspect only
already-hydrated candidate data: empty to-many data makes any false and
all and none true, while absent to-one data makes is false.
The optional derive and serde features are independent. Serde uses the
closed version 1 grammar, whose membership values are arrays even though
Rust authoring accepts any IntoIterator. Decoding accepts at most 64
expression levels, 4,096 expression nodes, and 4,096 membership values.
Regex operators use Rust syntax and reject Python-only look-around and
backreferences with source-less, value-free errors. Dynamic
field__operator parsing and remote pushdown belong to later ingress and
execution layers.
Scalar field handles expose only operators valid for their field type. A boolean field rejects string equality and membership:
use libtmux::query::__private;
struct Row;
let field = __private::bool_field::<Row>("row", "done");
let _ = field.eq("true");use libtmux::query::__private;
struct Row;
let field = __private::bool_field::<Row>("row", "done");
let _ = field.is_in(["true"]);use libtmux::query::__private;
struct Row;
let field = __private::bool_field::<Row>("row", "done");
let _ = field.not_in(["true"]);Boolean fields also have none of the text-only operators:
use libtmux::query::__private;
struct Row;
let field = __private::bool_field::<Row>("row", "done");
let _ = field.eq_ignore_case("true");use libtmux::query::__private;
struct Row;
let field = __private::bool_field::<Row>("row", "done");
let _ = field.contains("true");use libtmux::query::__private;
struct Row;
let field = __private::bool_field::<Row>("row", "done");
let _ = field.contains_ignore_case("true");use libtmux::query::__private;
struct Row;
let field = __private::bool_field::<Row>("row", "done");
let _ = field.starts_with("true");use libtmux::query::__private;
struct Row;
let field = __private::bool_field::<Row>("row", "done");
let _ = field.starts_with_ignore_case("true");use libtmux::query::__private;
struct Row;
let field = __private::bool_field::<Row>("row", "done");
let _ = field.ends_with("true");use libtmux::query::__private;
struct Row;
let field = __private::bool_field::<Row>("row", "done");
let _ = field.ends_with_ignore_case("true");use libtmux::query::__private;
struct Row;
let field = __private::bool_field::<Row>("row", "done");
let _ = field.regex("true");use libtmux::query::__private;
struct Row;
let field = __private::bool_field::<Row>("row", "done");
let _ = field.regex_ignore_case("true");Platform-width integers are intentionally outside the portable grammar:
use libtmux::query::__private;
struct Row;
let field = __private::integer_field::<Row, isize>("row", "count");
let _ = field.eq(0_isize);use libtmux::query::__private;
struct Row;
let field = __private::integer_field::<Row, isize>("row", "count");
let _ = field.is_in([0_isize]);use libtmux::query::__private;
struct Row;
let field = __private::integer_field::<Row, isize>("row", "count");
let _ = field.not_in([0_isize]);use libtmux::query::__private;
struct Row;
let field = __private::integer_field::<Row, usize>("row", "count");
let _ = field.eq(0_usize);use libtmux::query::__private;
struct Row;
let field = __private::integer_field::<Row, usize>("row", "count");
let _ = field.is_in([0_usize]);use libtmux::query::__private;
struct Row;
let field = __private::integer_field::<Row, usize>("row", "count");
let _ = field.not_in([0_usize]);Relation handles accept only portable expressions for their related type, never closures or arbitrary matchers:
use libtmux::query::__private;
struct Parent;
struct Child;
let relation = __private::many_relation::<Parent, Child>("parent", "children");
let _ = relation.any(|_: &Child| true);use libtmux::query::{Matcher, OneRelation};
use libtmux::query::__private;
struct Parent;
struct Child;
struct ChildMatcher;
impl Matcher<Child> for ChildMatcher {
fn matches(&self, _: &Child) -> bool { true }
}
let relation: OneRelation<Parent, Child> =
__private::one_relation("parent", "child");
let _ = relation.is(ChildMatcher);A relation expression cannot cross related schemas:
use libtmux::query::{FilterExpressionError, Filterable};
use libtmux::query::__private::{self, Predicate};
struct Parent;
struct Child;
struct Other;
macro_rules! filterable {
($type:ty, $target:literal) => {
impl Filterable for $type {
type Fields = ();
const FILTER_TARGET: &'static str = $target;
fn filter_fields() {}
fn __filter_matches(&self, _: &Predicate) -> bool { false }
fn __filter_validate(_: &Predicate) -> Result<(), FilterExpressionError> {
Ok(())
}
}
};
}
filterable!(Child, "child");
filterable!(Other, "other");
let relation = __private::many_relation::<Parent, Child>("parent", "children");
let other = __private::bool_field::<Other>("other", "enabled").eq(true);
let _ = relation.any(other);use libtmux::query::{FilterExpressionError, Filterable};
use libtmux::query::__private::{self, Predicate};
struct Parent;
struct Child;
struct Other;
macro_rules! filterable {
($type:ty, $target:literal) => {
impl Filterable for $type {
type Fields = ();
const FILTER_TARGET: &'static str = $target;
fn filter_fields() {}
fn __filter_matches(&self, _: &Predicate) -> bool { false }
fn __filter_validate(_: &Predicate) -> Result<(), FilterExpressionError> {
Ok(())
}
}
};
}
filterable!(Child, "child");
filterable!(Other, "other");
let relation = __private::one_relation::<Parent, Child>("parent", "child");
let other = __private::bool_field::<Other>("other", "enabled").eq(true);
let _ = relation.is(other);To-many and to-one relations expose disjoint quantifier families:
use libtmux::query::__private;
struct Parent;
struct Child;
let relation = __private::many_relation::<Parent, Child>("parent", "children");
let child = __private::bool_field::<Child>("child", "enabled").eq(true);
let _ = relation.is(child);use libtmux::query::__private;
struct Parent;
struct Child;
let relation = __private::one_relation::<Parent, Child>("parent", "child");
let child = __private::bool_field::<Child>("child", "enabled").eq(true);
let _ = relation.any(child);use libtmux::query::__private;
struct Parent;
struct Child;
let relation = __private::one_relation::<Parent, Child>("parent", "child");
let child = __private::bool_field::<Child>("child", "enabled").eq(true);
let _ = relation.all(child);use libtmux::query::__private;
struct Parent;
struct Child;
let relation = __private::one_relation::<Parent, Child>("parent", "child");
let child = __private::bool_field::<Child>("child", "enabled").eq(true);
let _ = relation.none(child);Expression error kinds are non-exhaustive for downstream callers:
use libtmux::query::FilterExpressionErrorKind;
fn label(kind: FilterExpressionErrorKind) -> &'static str {
match kind {
FilterExpressionErrorKind::InvalidRegex => "invalid regex",
FilterExpressionErrorKind::UnsupportedVersion => "unsupported version",
FilterExpressionErrorKind::InvalidTarget => "invalid target",
FilterExpressionErrorKind::UnknownField => "unknown field",
FilterExpressionErrorKind::UnknownOperator => "unknown operator",
FilterExpressionErrorKind::UnknownQuantifier => "unknown quantifier",
FilterExpressionErrorKind::InvalidLiteral => "invalid literal",
FilterExpressionErrorKind::InvalidStructure => "invalid structure",
}
}Structs§
- Bool
Field - A typed handle for a portable boolean field on
T. - Enum
Field - A typed handle for a custom enum field
EonT. - Filter
Expr - An opaque, portable predicate over candidates of type
T. - Filter
Expression Error - A source-less, value-free portable expression validation error.
- Integer
Field - A typed handle for a fixed-width integer field
NonT. - Many
Relation - A value-only handle for a to-many relation from
FromtoTo. - Multiple
Items Error - An error indicating that an iterator contained more than one item.
- OneRelation
- A value-only handle for a to-one relation from
FromtoTo. - Text
Field - A typed handle for a portable text field on
T.
Enums§
- Exactly
OneError - The ways an iterator can fail to contain exactly one item.
- Filter
Expression Error Kind - The category of an invalid portable filter expression.
Traits§
- Filter
Enum - Stable string semantics for a custom enum filter field.
- Filter
Schema - A filter target whose portable expression grammar can be described.
- Filterable
- A type with a stable schema that can evaluate portable filter predicates.
- Matcher
- A predicate that evaluates a borrowed candidate.
- Query
Iterator Ext - Cardinality and named-predicate operations for native iterators.
- Read
Field - A field handle whose value a
Targetsnapshot holds.