vld
Type-safe runtime validation for Rust, inspired by Zod.
vld combines schema definition with type-safe parsing. Define your validation
rules once and get both runtime checks and strongly-typed Rust structs.
Features
- Zero-cost schema definitions — the
schema!macro generates plain Rust structs with built-inparse()methods. Or useschema_validated!to get lenient parsing too. - Error accumulation — all validation errors are collected, not just the first one.
- Rich primitives — string, number, integer, boolean, literal, enum, any, custom.
- Extra primitives —
decimal(featuredecimal),duration,path,bytes,file(featurefile). - Extended file validation —
file-advancedenables hash checks, image metadata, EXIF, and advanced media-type checks. - String formats — email, URL, UUID, IPv4, IPv6, Base64, ISO date/time/datetime, hostname, CUID2, ULID, Nano ID, emoji.
All validated without regex by default. Every check has a
_msgvariant for custom messages. - Composable — optional, nullable, nullish, default, catch, refine, super_refine, transform, pipe, preprocess, describe,
.or(),.and(). - Collections — arrays, tuples (up to 6), records, Map (
HashMap), Set (HashSet). - Unions —
union(a, b),union3(a, b, c),.or(),discriminated_union("field"),intersection(a, b),.and(). - Recursive schemas —
lazy()for self-referencing data structures (trees, graphs). - Dynamic objects —
strict(),strip(),passthrough(),pick(),omit(),extend(),merge(),partial(),required(),catchall(),keyof(). - Custom schemas —
vld::custom(|v| ...)for arbitrary validation logic. - Multiple input sources — parse from
&str,String,&[u8],Path,PathBuf, orserde_json::Value. - Validate existing values —
.validate(&value)and.is_valid(&value)work with anySerializetype.schema!structs getStruct::validate(&instance). - Lenient parsing —
parse_lenient()returnsParseResult<T>with the struct, per-field diagnostics, and.save_to_file(). - Error formatting —
prettify_error,flatten_error,treeify_errorutilities. - Custom error messages —
_msgvariants,type_error(), andwith_messages()for per-check and bulk message overrides, including translations. - JSON Schema / OpenAPI —
JsonSchematrait on all schema types;json_schema()andto_openapi_document()onschema!structs;field_schema()for rich object property schemas;to_openapi_document_multi()helper. - Derive macro —
#[derive(Validate)]with#[vld(...)]attributes (optionalderivefeature). - Benchmarks — criterion-based benchmarks included.
- CI — GitHub Actions workflow for testing, clippy, and formatting.
- Minimal dependencies by default — heavy integrations are behind opt-in features.
Quick Start
Add to your Cargo.toml:
[]
= "0.4"
Optional Features
Default build enables only std. Optional features:
| Feature | Description |
|---|---|
serialize |
Adds #[derive(Serialize)] on error/result types, enables VldSchema::validate()/is_valid(), ParseResult::save_to_file()/to_json_string()/to_json_value() |
deserialize |
Adds #[derive(Deserialize)] on error/result types |
openapi |
Enables JsonSchema trait, to_json_schema(), json_schema(), to_openapi_document(), field_schema() |
diff |
Schema diffing — compare two JSON Schemas to detect breaking vs non-breaking changes |
regex |
Custom regex patterns via .regex() (uses regex-lite) |
derive |
#[derive(Validate)] procedural macro |
chrono |
ZDate / ZDateTime with chrono parsing (NaiveDate, DateTime<Utc>) |
jiff |
Same ZDate / ZDateTime API with jiff parsing (civil::Date, Timestamp). Alternative to chrono. |
time |
Same API with time parsing (time::Date, time::OffsetDateTime UTC). Alternative to chrono / jiff. |
decimal |
Enables decimal schema (vld::decimal()) backed by rust_decimal |
net |
Enables network schema (vld::ip_network()) backed by ipnet |
file |
Enables file schema (vld::file()) and basic file checks (size/extensions/media type) |
file-advanced |
Advanced file checks: hash (sha2, md-5), image dimensions (image), EXIF (kamadak-exif) |
string-advanced |
Advanced string checks: strict URL/URI, UUID versions, strict E.164, full semver (url, uuid, phonenumber, semver) |
Enable features as needed:
[]
= { = "0.4", = ["serialize", "openapi"] }
Basic Usage
use *;
// Define a validated struct
schema!
// Parse from a JSON string
let user = parse.unwrap;
assert_eq!;
assert_eq!;
// Errors are accumulated
let err = parse.unwrap_err;
assert!;
Nested Structs
use *;
schema!
schema!
let user = parse.unwrap;
Primitives
String
string
.min // minimum length
.max // maximum length
.len // exact length
.email // email format
.url // URL format (http/https)
.uuid // UUID format
.ipv4 // IPv4 address
.ipv6 // IPv6 address
.base64 // Base64 string
.iso_date // ISO 8601 date (YYYY-MM-DD)
.iso_time // ISO 8601 time (HH:MM:SS)
.iso_datetime // ISO 8601 datetime
.hostname // valid hostname
.cuid2 // CUID2 format
.ulid // ULID format (26 chars, Crockford Base32)
.nanoid // Nano ID format (alphanumeric + _-)
.emoji // must contain emoji
.url_strict // strict http/https URL with host
.uri // URI via parser
.uuid_v1 // UUID version 1
.uuid_v4 // UUID version 4
.uuid_v7 // UUID version 7
.phone_e164_strict // strict E.164 phone
.semver_full // strict semver parser
.slug // [a-z0-9-], no edge dashes
.color // #RRGGBB/#RRGGBBAA/rgb(...)/hsl(...)
.currency_code // ISO-4217-like (e.g. USD)
.country_code // ISO-3166 alpha-2 (e.g. US)
.locale // ll or ll-RR (e.g. en-US)
.cron // cron expression (5/6 fields, basic cron syntax)
.starts_with // must start with
.ends_with // must end with
.contains // must contain
.non_empty // must not be empty
.trim // trim whitespace before validation
.to_lowercase // convert to lowercase
.to_uppercase // convert to uppercase
.coerce // coerce numbers/booleans to string
Number
number
.min // minimum (inclusive)
.max // maximum (inclusive)
.gt // greater than (exclusive)
.lt // less than (exclusive)
.positive // > 0
.negative // < 0
.non_negative // >= 0
.finite // not NaN or infinity
.multiple_of
.safe // JS safe integer range (-(2^53-1) to 2^53-1)
.int // switch to integer mode (i64)
.coerce // coerce strings/booleans to number
Decimal
let price = decimal
.min
.max
.non_negative;
Duration (std feature)
let timeout = duration
.min_secs
.max_secs;
// accepts: 10, "10s", "250ms", "PT10S"
Path (std feature)
let cfg = path.exists.file.absolute;
let dir = path.exists.dir;
Integer
number.int
.min
.max
.gte
.positive
.non_positive
Bytes
bytes
.min_len
.max_len
.len
.non_empty
.base64 // parse Base64 string
.base64url // parse Base64URL string
.hex // parse hex string
Decimal
let price = decimal.min.max.non_negative;
Duration (std feature)
let timeout = duration.min_secs.max_secs;
// accepts: 10, "10s", "250ms", "PT10S"
Path (std feature)
let cfg = path.exists.file.absolute;
let safe_rel = path.relative.within;
Boolean
boolean
.coerce // "true"/"false"/"1"/"0" -> bool
Literal
literal // exact string match
literal // exact integer match
literal // exact boolean match
Enum
enumeration
Any
any // accepts any JSON value
Date / Datetime (chrono, jiff, or time feature)
Enable one backend in production: chrono, jiff, or time. The builder API is the same (vld::date(), vld::datetime()). If multiple flags are on (e.g. --all-features), priority is chrono > jiff > time.
| Feature | vld::date() output |
vld::datetime() output |
|---|---|---|
chrono |
chrono::NaiveDate |
chrono::DateTime<chrono::Utc> |
jiff |
jiff::civil::Date |
jiff::Timestamp |
time |
time::Date |
time::OffsetDateTime (UTC) |
datetime
.past
.future
.naive_allowed // disallow naive datetime without timezone
.with_timezone_only; // alias for naive_allowed(false)
// Require explicit +03:00 timezone in RFC3339 input
datetime.timezone_offset_only;
// For naive input, interpret wall-clock time in +03:00 before normalizing to UTC
datetime.naive_timezone_offset;
chrono (features = ["chrono", ...]):
schema!
jiff (features = ["jiff", ...]):
schema!
time (features = ["time", ...]):
schema!
File (std feature)
// In-memory mode (default): path + metadata + bytes
let f = file
.non_empty
.max_size
.extension
.media_type
.parse_value?;
println!;
let bytes = f.bytes.unwrap;
// Path-only mode: store only path/metadata, open/read lazily later
let f = file
.store_path_only
.parse_value?;
let data = f.read_bytes?; // lazy read from disk
let handle = f.open?; // std::fs::File
// Advanced checks: checksums / image constraints / magic-type rules
let f = file
.sha256
.md5
.allow_magic_type
.deny_magic_type
.min_width
.min_height
.require_exif
.parse_value?;
IP Network / Socket Addr / JSON Value
let net = ip_network.ipv4_only; // "10.0.0.0/24"
let addr = socket_addr.min_port; // "127.0.0.1:8080"
let any = json_value.object.require_key.max_depth;
Modifiers
// Optional: null/missing -> None
string.optional
// Nullable: null -> None
string.nullable
// Nullish: both optional + nullable
string.nullish
// Default: null/missing -> default value
string.with_default
// Catch: ANY error -> fallback value
string.min.catch
Collections
Array
array
.min_len
.max_len
.len // exact length
.non_empty // alias for min_len(1)
Tuple
// Tuples of 1-6 elements
let schema = ;
let = schema.parse.unwrap;
Record
record
.min_keys
.max_keys
Map
// Input: [["a", 1], ["b", 2]] -> HashMap
map
Set
// Input: ["a", "b", "a"] -> HashSet {"a", "b"}
set
.min_size
.max_size
Combinators
Union
// Union of 2 types
let schema = union;
// Returns Either<String, i64>
// Union of 3 types
let schema = union3;
// Returns Either3<String, f64, bool>
union! macro
For convenience, use the union! macro to combine 2–6 schemas without
nesting calls manually. The macro dispatches to union() / union3() or
nests them automatically for higher arities:
use *;
// 2 schemas — same as vld::union(a, b)
let s2 = union!;
// 3 schemas — same as vld::union3(a, b, c)
let s3 = union!;
// 4 schemas — nested automatically
let s4 = union!;
// 5 and 6 schemas work the same way
let s5 = union!;
You can also use the method chaining equivalent .or() for two schemas:
let schema = string.or;
Discriminated Union
// Efficient union by discriminator field
let schema = discriminated_union
.variant_str
.variant_str;
Intersection
// Input must satisfy both schemas
let schema = intersection;
Refine
number.int.refine
Super Refine
// Produce multiple errors in one check
string.super_refine
Transform
string.transform // String -> usize
Pipe
// Chain schemas: output of first -> input of second
string
.transform
.pipe
Preprocess
preprocess
Lazy (Recursive)
// Self-referencing schemas for trees, graphs, etc.
Describe
// Attach metadata (does not affect validation)
string.min.describe
Dynamic Object
For runtime-defined schemas (without compile-time type safety):
let obj = object
.field
.field
.strict; // reject unknown fields
// .strip() // remove unknown fields (default)
// .passthrough() // keep unknown fields as-is
// Object manipulation
let base = object.field.field;
base.pick // keep only "a"
base.omit // remove "b"
base.partial // all fields become optional
base.required // all fields must not be null (opposite of partial)
base.deep_partial // partial (nested objects: apply separately)
base.extend // merge fields from another schema
base.merge // alias for extend
base.catchall // validate unknown fields with a schema
base.keyof // Vec<String> of field names
Per-Field Validation & Lenient Parsing
Use schema_validated! for zero-duplication, or schema! + impl_validate_fields! separately:
use *;
// Option A: single macro (requires Serialize + Default on field types)
schema_validated!
// Option B: separate macros (more control)
// vld::schema! { ... }
// vld::impl_validate_fields!(User { name: String => ..., });
validate_fields — per-field diagnostics
let results = validate_fields.unwrap;
for f in &results
// Output:
// ✖ name: String must be at least 2 characters (received: "X")
// ✖ email: Invalid email address (received: "bad")
// ✔ age: null
parse_lenient — returns a ParseResult<T>
parse_lenient returns a [ParseResult<T>] — a wrapper around the struct and
per-field diagnostics. You can inspect it, convert to JSON, or save to a file
whenever you want.
let result = parse_lenient.unwrap;
// Inspect
println!; // false
println!; // 2
println!; // User { name: "", email: "", age: None }
// Per-field diagnostics
for f in result.fields
// Only errors
for f in result.error_fields
// Display trait prints a summary
println!;
// Convert to JSON string
let json = result.to_json_string.unwrap;
// Save to file at any time
result.save_to_file.unwrap;
// Or extract the struct
let user = result.into_value;
ParseResult<T> methods:
| Method | Description |
|---|---|
.value |
The constructed struct (invalid fields use Default) |
.fields() |
All per-field results (&[FieldResult]) |
.valid_fields() |
Only passed fields |
.error_fields() |
Only failed fields |
.is_valid() |
true if all fields passed |
.has_errors() |
true if any field failed |
.valid_count() |
Number of valid fields |
.error_count() |
Number of invalid fields |
.save_to_file(path) |
Serialize to JSON file (requires Serialize) |
.to_json_string() |
Serialize to JSON string |
.to_json_value() |
Serialize to serde_json::Value |
.into_value() |
Consume and return the inner struct |
.into_parts() |
Consume and return (T, Vec<FieldResult>) |
Single-Field Extraction
Parse the entire schema first, then extract individual fields from the result.
Use parse_lenient + .field("name") to inspect a specific field's validation
status — even when other fields are invalid:
use *;
// Define and register per-field validation
schema!
impl_validate_fields!;
// Strict parse — access fields directly
let user = parse.unwrap;
println!; // "Alex"
// Lenient parse — some fields may be invalid
let result = parse_lenient.unwrap;
// The struct is always available (invalid fields use Default)
println!; // 25 — valid, kept as-is
// Check a specific field
let name_field = result.field.unwrap;
println!; // ✖ name: String must be at least 2 characters
println!; // false
let age_field = result.field.unwrap;
println!; // ✔ age: 25
println!; // true
Error Formatting
use ;
match parse
Input Sources
Schemas accept any type implementing VldInput:
// JSON string
parse?;
// serde_json::Value
let val = json!;
parse?;
// File path
parse?;
// Byte slice
parse?;
Validate Existing Rust Values
Requires the
serializefeature.
Instead of only parsing JSON, you can validate any existing Rust value using
.validate() and .is_valid(). The value is serialized to JSON internally,
then validated against the schema.
On any schema
use *;
// Validate a Vec
let schema = array.min_len.max_len;
assert!;
assert!;
// Validate a String
let email = string.email;
assert!;
assert!;
// Validate a number
let age = number.int.min.max;
assert!;
assert!;
// Validate a HashMap
let schema = record;
let mut map = new;
map.insert;
assert!;
On schema! structs
Structs with #[derive(serde::Serialize)] get validate() and is_valid()
that check an already-constructed instance against the schema:
use *;
schema!
// Construct a struct normally (bypassing parse)
let user = User ;
// Validate it
assert!;
let err = validate.unwrap_err;
// err contains: .name: too short, .email: invalid
// Also works with serde_json::Value or any Serialize type
let json = json!;
assert!;
impl_rules! — Attach Validation to Existing Structs
Use impl_rules! to add .validate() and .is_valid() to a struct you
already have. No need to redefine it — just list the field rules:
use *;
// No #[derive(Serialize)] or #[derive(Debug)] required
impl_rules!;
let p = Product ;
assert!;
let bad = Product ;
assert!;
let err = bad.validate.unwrap_err;
for issue in &err.issues
// .name: String must be at least 2 characters
// .price: Number must be positive
// .quantity: Number must be non-negative
// .tags[0]: String must be at least 1 characters
The struct itself does not need Serialize or Debug — each field is
serialized individually (standard types like String, f64, Vec<T> already
implement Serialize). You can use all schema features inside impl_rules!:
with_messages(), type_error(), refine(), etc.
Chain Syntax: .or() / .and()
// Union via method chaining
let schema = string.or;
// Equivalent to vld::union(vld::string(), vld::number().int())
// Intersection via method chaining
let bounded = string.min.and;
// Input must satisfy both constraints
Custom Schema
Create a schema from any closure:
let even = custom;
assert_eq!;
assert!;
JSON Schema / OpenAPI Generation
Requires the
openapifeature.
Generate JSON Schema (compatible with OpenAPI 3.1)
from any vld schema via the JsonSchema trait:
use *; // imports JsonSchema trait
// Any individual schema
let js = string.min.max.email.json_schema;
// {"type": "string", "minLength": 2, "maxLength": 50, "format": "email"}
// Collections
let js = array.min_len.json_schema;
// {"type": "array", "items": {"type": "integer", ...}, "minItems": 1}
// Modifiers (optional wraps with oneOf)
let js = string.email.optional.json_schema;
// {"oneOf": [{"type": "string", "format": "email"}, {"type": "null"}]}
// Unions → oneOf, Intersections → allOf
let js = union.json_schema;
// {"oneOf": [{"type": "string"}, {"type": "number"}]}
Object field schemas
Use field_schema() (instead of field()) to include full JSON Schema for
each property:
let js = object
.field_schema
.field_schema
.strict
.json_schema;
// {"type": "object", "properties": {"email": {...}, "score": {...}}, ...}
schema! macro — struct-level JSON Schema
Structs defined via schema! automatically get json_schema() and
to_openapi_document() class methods:
use *;
schema!
// Full JSON Schema for the struct
let schema = json_schema;
// {
// "type": "object",
// "required": ["name", "email", "age"],
// "properties": {
// "name": {"type": "string", "minLength": 2, "maxLength": 100},
// "email": {"type": "string", "format": "email"},
// "age": {"type": "integer", "minimum": 0}
// }
// }
// Wrap in a minimal OpenAPI 3.1 document
let doc = to_openapi_document;
// {"openapi": "3.1.0", "components": {"schemas": {"User": {...}}}, ...}
Multi-schema OpenAPI document
use to_openapi_document_multi;
let doc = to_openapi_document_multi;
JsonSchema trait
The trait is implemented for all core types: ZString, ZNumber, ZInt,
ZBoolean, ZBytes, ZEnum, ZAny, ZArray, ZRecord, ZSet, ZObject,
ZOptional, ZNullable, ZNullish, ZDefault, ZCatch, ZRefine,
ZTransform, ZDescribe, ZUnion2, ZUnion3, ZIntersection,
NestedSchema.
Custom Error Messages
Error messages are configured at the schema level, not after validation. There are three mechanisms:
1. _msg variants — per-check custom messages
Every validation method has a _msg variant that accepts a custom error message:
use *;
let schema = string
.min_msg
.max_msg
.email_msg;
let err = schema.parse.unwrap_err;
// -> "Name must be at least 3 characters"
// -> "Please enter a valid email"
Available on all string checks (email_msg, url_msg, uuid_msg, ipv4_msg, etc.)
and number checks are set via with_messages (see below).
2. type_error() — custom type mismatch message
Override the "Expected X, received Y" message when the input has the wrong JSON type:
use *;
let schema = string.type_error;
let err = schema.parse.unwrap_err;
assert!;
let schema = number.type_error;
let schema = number.int.int_error;
3. with_messages() — bulk override by check key
Override multiple messages at once using check category keys. The closure receives
the key and returns Some(new_message) to replace, or None to keep the original:
use *;
let schema = string.min.max.email
.with_messages;
Works on numbers too — great for translations:
use *;
let schema = number.min.max
.with_messages;
For integers, the key "not_int" overrides the "not an integer" message:
use *;
let schema = number.int.min.max
.with_messages;
4. In objects — per-field custom messages
Combine type_error() and with_messages() on individual fields:
use *;
let schema = object
.field
.field;
String check keys
| Key | Check |
|---|---|
too_small |
min |
too_big |
max |
invalid_length |
len |
invalid_email |
email |
invalid_url |
url |
invalid_uuid |
uuid |
invalid_regex |
regex |
invalid_starts_with |
starts_with |
invalid_ends_with |
ends_with |
invalid_contains |
contains |
non_empty |
non_empty |
invalid_ipv4 |
ipv4 |
invalid_ipv6 |
ipv6 |
invalid_base64 |
base64 |
invalid_iso_date |
iso_date |
invalid_iso_datetime |
iso_datetime |
invalid_iso_time |
iso_time |
invalid_hostname |
hostname |
invalid_cuid2 |
cuid2 |
invalid_ulid |
ulid |
invalid_nanoid |
nanoid |
invalid_emoji |
emoji |
Number check keys
| Key | Check |
|---|---|
too_small |
min, gt, gte |
too_big |
max, lt, lte |
not_positive |
positive |
not_negative |
negative |
not_non_negative |
non_negative |
not_non_positive |
non_positive |
not_finite |
finite |
not_multiple_of |
multiple_of |
not_safe |
safe |
not_int |
int (ZInt only) |
Derive Macro
Enable the derive feature for #[derive(Validate)]:
[]
= { = "0.4", = ["derive"] }
use Validate;
// Generates: vld_parse(), parse_value(), validate_fields(), parse_lenient()
let user = vld_parse.unwrap;
Derive + utoipa (OpenAPI)
#[derive(Validate)] works with impl_to_schema! from vld-utoipa, including
full support for #[serde(rename_all = "...")]. Enable both derive and openapi features:
[]
= { = "0.4", = ["derive", "openapi"] }
= "0.4"
= "5"
use Validate;
use impl_to_schema;
impl_to_schema!;
// OpenAPI schema uses camelCase keys: "streetAddress", "streetNumber", etc.
// Validation also expects camelCase JSON input.
Query and path parameters use the same impl_to_schema! bridge. Mark the struct with
utoipa's #[into_params(parameter_in = Query)] or Path (requires utoipa in dependencies):
use Validate;
use impl_to_schema;
impl_to_schema!;
// Use in #[utoipa::path(get, path = "/search", params(SearchQuery))]
With vld::schema!, the #[into_params] attribute is stripped from the emitted struct
(so utoipa is not required at compile time). With #[derive(Validate)], the attribute
stays on the struct like a normal utoipa derive helper.
See vld-utoipa README for migration from older macros
(impl_to_schema_query!, impl_into_params!(T, Query), etc.).
Optional Regex Support
Requires the
regexfeature.
By default, vld validates all string formats (email, UUID, etc.) without regex.
If you need custom regex patterns via .regex(), enable the regex feature:
[]
= { = "0.4", = ["regex"] }
let schema = string.regex;
Running the Playground
Benchmarks
Full CI Locally
Run the same high-level checks as CI with one command:
Workspace Crates
Use full links below (GitHub, crates.io, docs.rs). This avoids relative-link issues after publication.
| Crate | Version | GitHub | crates.io | docs.rs | Description |
|---|---|---|---|---|---|
vld |
GitHub | crates.io | docs.rs | Core validation library: schemas, parsers, macros, errors, i18n | |
vld-derive |
GitHub | crates.io | docs.rs | Proc-macro #[derive(Validate)] for struct validation |
|
vld-axum |
GitHub | crates.io | docs.rs | Axum extractors (VldJson, VldQuery, VldPath, VldForm, etc.) |
|
vld-actix |
GitHub | crates.io | docs.rs | Actix-web extractors (VldJson, VldQuery, VldPath, VldForm, etc.) |
|
vld-rocket |
GitHub | crates.io | docs.rs | Rocket extractors plus JSON error catchers | |
vld-poem |
GitHub | crates.io | docs.rs | Poem extractors (VldJson, VldQuery, VldPath, VldForm, etc.) |
|
vld-warp |
GitHub | crates.io | docs.rs | Warp filters (vld_json, vld_query, vld_param, vld_path) |
|
vld-salvo |
GitHub | crates.io | docs.rs | Salvo extractors (VldJson, VldQuery, VldPath, VldForm, etc.) |
|
vld-tower |
GitHub | crates.io | docs.rs | Universal Tower middleware for JSON validation | |
vld-diesel |
GitHub | crates.io | docs.rs | Diesel ORM wrappers and validated column types | |
vld-sea |
GitHub | crates.io | docs.rs | SeaORM ActiveModel validation hooks | |
vld-utoipa |
GitHub | crates.io | docs.rs | utoipa integration (ToSchema from vld) |
|
vld-aide |
GitHub | crates.io | docs.rs | aide/schemars integration (JsonSchema from vld) |
|
vld-config |
GitHub | crates.io | docs.rs | Config validation for TOML/YAML/JSON/ENV | |
vld-clap |
GitHub | crates.io | docs.rs | Clap argument validation via #[derive(Validate)] |
|
vld-tauri |
GitHub | crates.io | docs.rs | Tauri IPC/event/state/channel/plugin-config validation | |
vld-ts |
GitHub | crates.io | docs.rs | TypeScript codegen (Zod/Valibot/OpenAPI fragments) | |
vld-fake |
GitHub | crates.io | docs.rs | Fake data generation helpers for validated types | |
vld-sqlx |
GitHub | crates.io | docs.rs | SQLx wrappers and pre-insert/update validation | |
vld-tonic |
GitHub | crates.io | docs.rs | tonic gRPC message and metadata validation | |
vld-leptos |
GitHub | crates.io | docs.rs | Shared validation for Leptos server/WASM clients | |
vld-dioxus |
GitHub | crates.io | docs.rs | Shared validation for Dioxus server/WASM clients | |
vld-ntex |
GitHub | crates.io | docs.rs | ntex extractors (VldJson, VldQuery, VldPath, VldForm, etc.) |
|
vld-surrealdb |
GitHub | crates.io | docs.rs | SurrealDB document validation before/after DB operations | |
vld-redis |
GitHub | crates.io | docs.rs | Redis integration with validation and typed payload conversion | |
vld-lapin |
GitHub | crates.io | docs.rs | lapin/RabbitMQ integration for validated AMQP payloads | |
vld-schemars |
GitHub | crates.io | docs.rs | Bidirectional bridge between vld and schemars schemas |
|
vld-http-common |
GitHub | crates.io | docs.rs | Shared HTTP parsing/coercion/error helpers for web crates |
License
MIT