Qubit Argument
Ownership-preserving argument validation for Rust.
Overview
Qubit Argument provides extension traits and focused checking functions for
numeric values, durations, strings, collections, optional values, indexes, and
bounds.
Every validation failure is an ArgumentError with an owned argument path and
an inspectable ArgumentErrorKind. Validation APIs return Result; callers
choose whether to recover, convert the error, or explicitly treat a failure as
an internal invariant violation.
Successful validation returns the original owned value or borrow without cloning it, so checks can be chained while preserving ownership.
Validation extension traits are sealed and implemented only for their
documented standard-library types. ArgumentErrorKind, ArgumentValue, and
LengthMetric are non-exhaustive; downstream matches must include a wildcard
arm so new structured cases can be added compatibly.
Installation
The default feature set is empty (default = []), so core validation has no
runtime dependency on the regex engine.
[]
= "0.4"
# Enable only when regex validation is needed.
= { = "0.4", = ["regex"] }
Quick Start
The traits and error types are exported directly from the crate root:
use ;
Both age and name are returned in their original forms. In particular, the
owned String is not cloned during validation.
Downstream Error Conversion
A downstream crate can preserve the structured error in its own domain error.
After implementing From<ArgumentError>, the ? operator performs the
conversion directly:
use ;
Optional values can use the same ownership-preserving validators without a
manual if let. None is left unchanged, while Some is validated and
rewrapped:
use ;
Use ArgumentError::path() and ArgumentError::kind() for programmatic
decisions. The Display text is intended for diagnostics, not parsing;
caller-provided paths, patterns, custom codes, and messages are escaped so the
diagnostic remains on one line without changing the structured values.
Nested validators can keep local field names and add parent context only when
they fail. ArgumentResultExt::with_path_prefix leaves Ok values unchanged
and turns a local path such as connect into timeouts.connect on Err.
use ;
use Duration;
Domain-specific rules can retain a stable machine code and human-readable message while still participating in the same structured error flow:
use ;
Validation remains recoverable by default. When a value is an internal
invariant rather than external input, the caller may explicitly use expect
with a meaningful explanation:
use NumericArgument;
Validation APIs
Numeric values
NumericArgument supports all primitive integer types plus f32 and f64:
- zero, non-zero, positive, non-negative, negative, and non-positive checks;
require_less_than,require_at_most,require_greater_than, andrequire_at_leastcomparisons;require_in_rangewith standard inclusive, exclusive, and unboundedRangeBounds.
Floating-point values and range endpoints that are NaN are rejected. A
reversed or structurally empty range is reported separately from a value that
falls outside a valid range.
Durations and finite floats
DurationArgument is implemented for std::time::Duration. It provides a
strictly positive check plus strict and inclusive comparisons. Structured
comparison errors retain the exact Duration, including its unit, rather than
converting it to an ambiguous integer.
FloatArgument::require_finite is implemented only for f32 and f64. It
returns NotANumber for NaN and NotFinite { actual } for positive or negative
infinity. Finite values can continue into the comparison and range methods from
NumericArgument.
Strings
StringArgument is implemented for String and &str:
require_non_blankchecks Unicode whitespace;require_byte_len*methods count UTF-8 bytes;require_char_count*methods count Unicode scalar values;- with the
regexfeature,require_matchandrequire_not_matchaccept a compiledregex::Regex.
Byte length and Unicode scalar count are deliberately distinct. For example,
"汉😀" contains seven UTF-8 bytes and two Unicode scalar values. Scalar
counts are not grapheme-cluster counts.
Regex validation uses Regex::is_match semantics and is not implicitly
anchored. Add ^ and $ to the pattern when the entire string must match.
Collections and optional values
CollectionArgument validates Vec<T>, &[T], and [T; N] without cloning
elements. It provides non-empty, exact-length, minimum-length, maximum-length,
and inclusive length-range checks.
OptionArgument::require_some moves a present value out of its option.
OptionArgument::validate_if_some borrows a present value for validation,
skips the validator for None, and returns the original option without
cloning. OptionArgument::validate_some moves a present value through an
ownership-preserving validator, allowing validation or transformation without
requiring Clone or Copy; None is returned unchanged.
Custom rules and bounds
require_thatapplies a caller-provided predicate and reports a structuredCustomerror on failure.check_boundsvalidates an offset and length without unchecked addition.check_element_indexandcheck_position_indexdistinguish element indexes from boundary positions.check_position_rangevalidates a half-open position range.
Error Privacy
String validation errors record the path, failure kind, observed length or
count, and any required constraint. They do not store the original validated
string, so Debug and Display do not reveal it. Pattern errors retain the
pattern, not the input. Callers of require_that remain responsible for
keeping their own custom code and message free of sensitive data.
Length and InvalidLengthConstraint errors also carry a LengthMetric:
Bytes for UTF-8 byte methods, UnicodeScalars for character-count methods,
and Elements for collection methods. Equal numeric lengths therefore remain
structurally distinguishable by measurement unit.
Testing
# Core API with the default empty feature set
# Core API plus regex validation
# Project CI checks
See COVERAGE.md for coverage details.
License
Copyright (c) 2025 - 2026. Haixing Hu, Qubit Co. Ltd. All rights reserved.
Licensed under the Apache License, Version 2.0. See LICENSE for the full license text.
Contributing
Contributions are welcome. Please follow the Rust API guidelines, keep public
API documentation and tests current, and run ./ci-check.sh before submitting
a pull request.
Author
Haixing Hu - Qubit Co. Ltd.
Repository: https://github.com/qubit-ltd/rs-argument