Strings
vld::string() returns a ZString whose output is String. Checks are chained and all of them run, so one parse can report several issues.
use vld::prelude::*;
let username = vld::string()
.trim()
.to_lowercase()
.min(3)
.max(20)
.alphanumeric();
assert_eq!(username.parse(r#"" Ada42 ""#).unwrap(), "ada42");
Length
Lengths count characters (Unicode scalar values), not bytes.
| Method | Check | Issue |
|---|---|---|
min(n) | at least n characters | too_small (origin string) |
max(n) | at most n characters | too_big (origin string) |
len(n) | exactly n characters | invalid_length |
non_empty() | at least one character | too_small |
Content
| Method | Check |
|---|---|
starts_with("pre") | prefix |
ends_with("suf") | suffix |
contains("sub") | substring |
pattern(r"...") | regular expression (feature regex); emitted as JSON Schema pattern. Takes the source (panics on an invalid one, like Regex::new(..).unwrap()) or a prebuilt vld::rules::Pattern |
rule(r) | a reusable custom rule |
// feature = "regex"
let sku = vld::string().pattern(r"^[A-Z]{3}-\d{4}$");
assert!(sku.parse(r#""ABC-1234""#).is_ok());
Most checks need no regex: every format below is a hand-written parser. Reach for pattern only for shapes that are not built in, and prefer a rule when the check is easier to write in Rust.
Transforms and coercion
Transforms run before the checks, in the order they were added.
| Method | Effect |
|---|---|
trim() | strip leading and trailing whitespace |
to_lowercase() | lowercase the input |
to_uppercase() | uppercase the input |
coerce() | accept numbers and booleans and turn them into text (42 → "42") |
Formats
Every format method has a _msg twin that takes a custom message (email_msg("...")). A failed format check reports IssueCode::InvalidString { validation }, key invalid_string. Each format also sets the JSON Schema format keyword.
Network
| Method | Accepts |
|---|---|
email() | email address |
url() | http / https URL |
url_strict() | public http / https URL: real host, not localhost, private, loopback, link-local or unspecified addresses (IPv4-mapped IPv6 included). Feature string-advanced |
uri() | any URI (feature string-advanced) |
ip() | IPv4 or IPv6 address |
ipv4() / ipv6() | one address family (IPv6 accepts IPv4-mapped forms) |
cidr() | IPv4 / IPv6 CIDR block with a decimal prefix |
mac() | MAC address xx:xx:xx:xx:xx:xx |
hostname() | DNS hostname |
Identifiers
| Method | Accepts |
|---|---|
uuid() | any UUID |
uuid_v1() / uuid_v4() / uuid_v7() | a specific UUID version (feature string-advanced) |
cuid2() | CUID2: 2–32 lowercase alphanumerics starting with a letter |
ulid() | 26-character Crockford Base32 ULID |
nanoid() | Nano ID alphabet (alphanumerics, _, -) |
slug() | URL slug [a-z0-9-] |
semver() | MAJOR.MINOR.PATCH with an optional v prefix |
semver_full() | full semantic version parsed by the semver crate (feature string-advanced) |
jwt() | JWT-shaped token header.payload.signature (base64url parts; the signature is not verified) |
credit_card() | 12–19 digits with optional spaces or dashes, Luhn-checked |
phone() | international phone: leading +, 8–15 digits, optional spaces, dashes, parentheses |
phone_e164_strict() | strict E.164, checked with phonenumber (feature string-advanced) |
currency_code() | three uppercase letters (ISO 4217 shape) |
country_code() | ISO 3166 alpha-2 |
locale() | ll or ll-RR (en, en-US) |
cron() | cron expression with 5 or 6 fields |
color() | #RRGGBB, #RRGGBBAA, rgb(...), hsl(...) |
Text
| Method | Accepts |
|---|---|
ascii() | ASCII only |
alpha() | ASCII letters only |
alphanumeric() | ASCII letters and digits |
lowercase() / uppercase() | already lower / upper case (use to_lowercase() to convert instead) |
emoji() | non-empty, emoji only |
json() | a string that contains exactly one JSON document |
Dates and times as strings
These keep the value a String. To get typed dates, use the date schemas.
| Method | Accepts |
|---|---|
iso_date() | YYYY-MM-DD with a real day of month |
iso_datetime() | YYYY-MM-DDTHH:MM:SS[.frac] (seconds required, T or t), optional Z / z / ±HH:MM; the same grammar as vld::chrono::datetime() |
iso_time() | HH:MM[:SS[.frac]] |
Encodings
| Method | Accepts |
|---|---|
base64() | standard Base64 with padding |
base64url() | URL-safe alphabet (-, _), padding optional; rejects + and / |
hex() | hexadecimal characters only |
To decode into bytes instead of keeping text, use vld::bytes().base64().
Messages
let name = vld::string()
.type_error("Name must be text")
.min_msg(2, "Name is too short")
.email_msg("Please enter a valid email");
// Or override many checks by key at once:
let code = vld::string().min(3).max(8).with_messages(|key| match key {
"too_small" => Some("Too short".into()),
"too_big" => Some("Too long".into()),
_ => None,
});
with_messages keys are too_small, too_big, invalid_length, non_empty, invalid_regex (for pattern), a rule's key, invalid_starts_with, invalid_ends_with, invalid_contains and invalid_<format> (invalid_email, invalid_url, invalid_uuid, …). A _msg message wins over with_messages. More in Custom messages.