use std::collections::HashMap;
use serde_json::{Value, json};
pub fn get_default_rules() -> HashMap<String, Value> {
let mut rules = HashMap::new();
rules.extend(add_contact_rules());
rules.extend(add_location_rules());
rules.extend(add_financial_rules());
rules.extend(add_identifier_rules());
rules.extend(add_transportation_rules());
rules.extend(add_network_rules());
rules.extend(add_content_rules());
rules.extend(add_measurement_rules());
rules
}
fn add_contact_rules() -> HashMap<String, Value> {
let mut rules = HashMap::new();
rules.insert(
"email_domain_eq".to_string(),
json!({
"pattern": "^[a-z0-9]([a-z0-9-]*\\.)*[a-z0-9]([a-z0-9-]*[a-z0-9])?$",
"description": "Valid domain name (RFC 1035)"
}),
);
rules.insert(
"email_domain_in".to_string(),
json!({
"pattern": "^[a-z0-9]([a-z0-9-]*\\.)*[a-z0-9]([a-z0-9-]*[a-z0-9])?$",
"description": "Valid domain name in list"
}),
);
rules.insert(
"email_domain_endswith".to_string(),
json!({
"pattern": "^\\.[a-z0-9]([a-z0-9-]*\\.)*[a-z0-9]([a-z0-9-]*[a-z0-9])?$",
"description": "Domain suffix (starts with dot)"
}),
);
rules.insert(
"email_local_part_startswith".to_string(),
json!({
"min_length": 1,
"max_length": 64,
"description": "Local part prefix (before @)"
}),
);
rules.insert(
"phone_country_code_eq".to_string(),
json!({
"pattern": "^[A-Z]{2}$",
"description": "ISO 3166-1 alpha-2 country code"
}),
);
rules.insert(
"phone_country_code_in".to_string(),
json!({
"pattern": "^[A-Z]{2}$",
"description": "ISO 3166-1 alpha-2 country code"
}),
);
rules.insert(
"phone_type_eq".to_string(),
json!({
"enum": ["mobile", "fixed", "tollfree", "premium", "shared", "voip"],
"description": "Phone number type"
}),
);
rules.insert(
"url_protocol_eq".to_string(),
json!({
"enum": ["http", "https", "ftp", "ftps", "ws", "wss"],
"description": "Protocol scheme"
}),
);
rules.insert(
"domain_name_tld_eq".to_string(),
json!({
"pattern": "^[a-z]{2,}$",
"description": "Top-level domain (lowercase)"
}),
);
rules.insert(
"domain_name_tld_in".to_string(),
json!({
"pattern": "^[a-z]{2,}$",
"description": "Top-level domain"
}),
);
rules.insert(
"hostname_depth_eq".to_string(),
json!({
"min": 1.0,
"max": 127.0,
"description": "Hostname depth (number of labels)"
}),
);
rules
}
fn add_location_rules() -> HashMap<String, Value> {
let mut rules = HashMap::new();
rules.insert(
"postal_code_country_eq".to_string(),
json!({
"pattern": "^[A-Z]{2}$",
"description": "ISO 3166-1 alpha-2 country code"
}),
);
rules.insert(
"latitude_within_range".to_string(),
json!({
"min": -90.0,
"max": 90.0,
"description": "Latitude in degrees"
}),
);
rules.insert(
"latitude_hemisphere_eq".to_string(),
json!({
"enum": ["North", "South"],
"description": "Latitude hemisphere"
}),
);
rules.insert(
"longitude_within_range".to_string(),
json!({
"min": -180.0,
"max": 180.0,
"description": "Longitude in degrees"
}),
);
rules.insert(
"longitude_hemisphere_eq".to_string(),
json!({
"enum": ["East", "West"],
"description": "Longitude hemisphere"
}),
);
rules.insert(
"timezone_eq".to_string(),
json!({
"pattern": "^[A-Za-z_/]+$",
"description": "IANA timezone identifier"
}),
);
rules.insert(
"locale_code_eq".to_string(),
json!({
"pattern": "^[a-z]{2}(?:-[A-Z]{2})?$",
"description": "BCP 47 locale code"
}),
);
rules.insert(
"language_code_eq".to_string(),
json!({
"pattern": "^[a-z]{2}$",
"description": "ISO 639-1 language code"
}),
);
rules.insert(
"country_code_eq".to_string(),
json!({
"pattern": "^[A-Z]{2}$",
"description": "ISO 3166-1 alpha-2 country code"
}),
);
rules
}
fn add_financial_rules() -> HashMap<String, Value> {
let mut rules = HashMap::new();
rules.insert(
"iban_country_eq".to_string(),
json!({
"pattern": "^[A-Z]{2}$",
"description": "ISO 3166-1 country code"
}),
);
rules.insert(
"iban_check_digit_eq".to_string(),
json!({
"pattern": "^[0-9]{2}$",
"length": 2,
"description": "IBAN check digits"
}),
);
rules.insert(
"cusip_issuer_eq".to_string(),
json!({
"length": 6,
"pattern": "^[A-Z0-9]{6}$",
"description": "CUSIP issuer code"
}),
);
rules.insert(
"isin_country_eq".to_string(),
json!({
"pattern": "^[A-Z]{2}$",
"description": "ISO 3166-1 country code"
}),
);
rules.insert(
"sedol_check_digit_eq".to_string(),
json!({
"pattern": "^[0-9]$",
"description": "SEDOL check digit"
}),
);
rules.insert(
"lei_country_eq".to_string(),
json!({
"pattern": "^[A-Z]{2}$",
"description": "ISO 3166-1 country code"
}),
);
rules.insert(
"mic_country_eq".to_string(),
json!({
"pattern": "^[A-Z]{2}$",
"description": "ISO 3166-1 country code"
}),
);
rules.insert(
"currency_code_eq".to_string(),
json!({
"pattern": "^[A-Z]{3}$",
"description": "ISO 4217 currency code"
}),
);
rules.insert(
"money_currency_eq".to_string(),
json!({
"pattern": "^[A-Z]{3}$",
"description": "ISO 4217 currency code"
}),
);
rules.insert(
"money_amount_within_range".to_string(),
json!({
"description": "Numeric money amount range"
}),
);
rules.insert(
"exchange_code_eq".to_string(),
json!({
"pattern": "^[A-Z]{1,4}$",
"description": "ISO 10383 exchange code"
}),
);
rules.insert(
"exchange_rate_within_range".to_string(),
json!({
"min": 0.0,
"description": "Exchange rate range"
}),
);
rules.insert(
"stock_symbol_eq".to_string(),
json!({
"pattern": "^[A-Z0-9]{1,5}$",
"description": "Stock ticker symbol"
}),
);
rules
}
fn add_identifier_rules() -> HashMap<String, Value> {
let mut rules = HashMap::new();
rules.insert(
"slug_eq".to_string(),
json!({
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"description": "URL-safe slug"
}),
);
rules.insert(
"semantic_version_eq".to_string(),
json!({
"pattern": "^[0-9]+(\\.[0-9]+){0,2}(?:-[a-zA-Z0-9]+)?$",
"description": "Semantic versioning (X.Y.Z)"
}),
);
rules.insert(
"hash_sha256_eq".to_string(),
json!({
"pattern": "^[a-f0-9]{64}$",
"length": 64,
"description": "SHA-256 hash (hexadecimal)"
}),
);
rules.insert(
"api_key_eq".to_string(),
json!({
"min_length": 16,
"max_length": 256,
"description": "API key (alphanumeric, dashes, underscores)"
}),
);
rules
}
fn add_transportation_rules() -> HashMap<String, Value> {
let mut rules = HashMap::new();
rules.insert(
"license_plate_country_eq".to_string(),
json!({
"pattern": "^[A-Z]{2}$",
"description": "ISO 3166-1 country code"
}),
);
rules.insert(
"vin_wmi_eq".to_string(),
json!({
"length": 3,
"pattern": "^[A-Z0-9]{3}$",
"description": "VIN World Manufacturer Identifier"
}),
);
rules.insert(
"vin_manufacturer_eq".to_string(),
json!({
"length": 3,
"pattern": "^[A-Z0-9]{3}$",
"description": "VIN manufacturer code"
}),
);
rules.insert(
"tracking_number_carrier_eq".to_string(),
json!({
"enum": ["UPS", "FedEx", "DHL", "USPS", "Other"],
"description": "Shipping carrier"
}),
);
rules.insert(
"container_number_owner_code_eq".to_string(),
json!({
"length": 3,
"pattern": "^[A-Z]{3}$",
"description": "ISO 6346 owner code"
}),
);
rules
}
fn add_network_rules() -> HashMap<String, Value> {
let mut rules = HashMap::new();
rules.insert(
"port_eq".to_string(),
json!({
"min": 1.0,
"max": 65535.0,
"description": "Network port number"
}),
);
rules.insert(
"airport_code_eq".to_string(),
json!({
"pattern": "^[A-Z]{3}$",
"description": "IATA airport code"
}),
);
rules.insert(
"port_code_eq".to_string(),
json!({
"pattern": "^[A-Z]{3}$",
"description": "UN/LOCODE port code"
}),
);
rules.insert(
"flight_number_airline_code_eq".to_string(),
json!({
"pattern": "^[A-Z]{2}$",
"description": "IATA airline code"
}),
);
rules
}
fn add_content_rules() -> HashMap<String, Value> {
let mut rules = HashMap::new();
rules.insert(
"mime_type_eq".to_string(),
json!({
"pattern": "^[a-z]+/[a-z0-9.+\\-]+$",
"description": "MIME type (e.g., image/png)"
}),
);
rules.insert(
"color_format_eq".to_string(),
json!({
"enum": ["hex", "rgb", "hsl", "named"],
"description": "Color format"
}),
);
rules
}
fn add_measurement_rules() -> HashMap<String, Value> {
let mut rules = HashMap::new();
rules.insert(
"duration_within_range".to_string(),
json!({
"min": 0.0,
"description": "Duration in seconds"
}),
);
rules.insert(
"percentage_within_range".to_string(),
json!({
"min": 0.0,
"max": 100.0,
"description": "Percentage value (0-100)"
}),
);
rules
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_rules_exist() {
let rules = get_default_rules();
assert!(!rules.is_empty());
println!("Total default rules: {}", rules.len());
}
#[test]
fn test_email_domain_rule() {
let rules = get_default_rules();
assert!(rules.contains_key("email_domain_eq"));
assert!(rules.contains_key("email_domain_in"));
}
#[test]
fn test_country_code_rule() {
let rules = get_default_rules();
assert!(rules.contains_key("country_code_eq"));
}
}