rson-schema

Crates.iorson-schema
lib.rsrson-schema
version1.0.0
created_at2025-05-31 21:15:03.780185+00
updated_at2025-05-31 21:25:05.000423+00
descriptionSchema validation for RSON
homepagehttps://rson.dev
repositoryhttps://github.com/RSON-Rust-Serialized-Object-Notation/RSON-core
max_upload_size
id1696652
size16,518
Okware (okwareddevnest)

documentation

README

๐Ÿ›ก๏ธ rson-schema

Schema validation and type safety for RSON (Rust Serialized Object Notation)

Crates.io Documentation License


๐ŸŽฏ What is rson-schema?

rson-schema provides powerful schema validation for RSON data, ensuring your configuration files and data structures conform to expected formats and constraints.

Key Features:

  • Type validation - Ensure structs, enums, and fields match expected types
  • Constraint checking - Validate ranges, lengths, patterns, and custom rules
  • Schema generation - Auto-generate schemas from Rust types
  • JSON Schema compatible - Leverage existing JSON Schema tooling
  • Developer-friendly errors - Clear validation error messages

๐Ÿš€ Quick Start

Installation

[dependencies]
rson-schema = "0.1.0"
serde = { version = "1.0", features = ["derive"] }

Basic Usage

use rson_schema::{Schema, validate, SchemaBuilder};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
struct Config {
    #[schema(min_length = 1, max_length = 50)]
    name: String,
    
    #[schema(minimum = 1, maximum = 65535)]
    port: u16,
    
    #[schema(pattern = "^[a-z0-9]+$")]
    database_name: String,
    
    features: Vec<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Generate schema from Rust type
    let schema = Schema::from_type::<Config>()?;
    
    // Validate RSON data against schema
    let rson_text = r#"
        Config(
            name: "my-app",
            port: 8080,
            database_name: "mydb123",
            features: ["auth", "logging"],
        )
    "#;
    
    // Validate returns detailed errors if validation fails
    match validate(&schema, rson_text) {
        Ok(_) => println!("โœ… Valid RSON data"),
        Err(errors) => {
            for error in errors {
                println!("โŒ {}", error);
            }
        }
    }
    
    Ok(())
}

๐Ÿ“š Schema Definition

Using Attributes

Add validation constraints directly to your Rust types:

use serde::{Deserialize, Serialize};
use rson_schema::schema;

#[derive(Serialize, Deserialize)]
struct User {
    #[schema(min_length = 2, max_length = 50)]
    name: String,
    
    #[schema(minimum = 13, maximum = 120)]
    age: u8,
    
    #[schema(pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$")]
    email: String,
    
    #[schema(items = "String", min_items = 1, max_items = 10)]
    roles: Vec<String>,
    
    #[schema(optional)]
    phone: Option<String>,
}

Programmatic Schema Building

use rson_schema::{SchemaBuilder, SchemaType, Constraint};

let schema = SchemaBuilder::new()
    .struct_type("Config")
    .field("name", SchemaType::String)
        .constraint(Constraint::MinLength(1))
        .constraint(Constraint::MaxLength(100))
    .field("port", SchemaType::Integer)
        .constraint(Constraint::Minimum(1))
        .constraint(Constraint::Maximum(65535))
    .field("enabled", SchemaType::Boolean)
    .field("tags", SchemaType::Array(Box::new(SchemaType::String)))
        .constraint(Constraint::MinItems(0))
        .constraint(Constraint::MaxItems(20))
    .build()?;

๐Ÿ”ง Validation Constraints

String Constraints

#[derive(Serialize, Deserialize)]
struct StringValidation {
    #[schema(min_length = 5, max_length = 50)]
    name: String,
    
    #[schema(pattern = r"^[A-Z][a-z]+$")]
    title: String,
    
    #[schema(format = "email")]
    email: String,
    
    #[schema(format = "uri")]
    website: String,
    
    #[schema(enum_values = ["dev", "staging", "prod"])]
    environment: String,
}

Numeric Constraints

#[derive(Serialize, Deserialize)]
struct NumericValidation {
    #[schema(minimum = 0, maximum = 100)]
    percentage: u8,
    
    #[schema(exclusive_minimum = 0.0)]
    price: f64,
    
    #[schema(multiple_of = 5)]
    step: u32,
}

Array Constraints

#[derive(Serialize, Deserialize)]
struct ArrayValidation {
    #[schema(min_items = 1, max_items = 10)]
    tags: Vec<String>,
    
    #[schema(unique_items = true)]
    ids: Vec<u32>,
    
    #[schema(items = "Integer", min_value = 1, max_value = 100)]
    scores: Vec<u8>,
}

Object Constraints

#[derive(Serialize, Deserialize)]
struct ObjectValidation {
    #[schema(min_properties = 1, max_properties = 50)]
    metadata: std::collections::HashMap<String, String>,
    
    #[schema(required = ["host", "port"])]
    config: DatabaseConfig,
}

๐ŸŽจ Schema Formats

RSON Schema Format

// config.rschema
Schema(
    type: "struct",
    name: "Config",
    fields: {
        "name": FieldSchema(
            type: "string",
            constraints: [
                MinLength(1),
                MaxLength(50),
            ],
        ),
        "port": FieldSchema(
            type: "integer",
            constraints: [
                Minimum(1),
                Maximum(65535),
            ],
        ),
        "features": FieldSchema(
            type: "array",
            items: "string",
            constraints: [
                MinItems(0),
                MaxItems(20),
            ],
        ),
    },
)

JSON Schema Compatible

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 50
    },
    "port": {
      "type": "integer",
      "minimum": 1,
      "maximum": 65535
    },
    "features": {
      "type": "array",
      "items": { "type": "string" },
      "minItems": 0,
      "maxItems": 20
    }
  },
  "required": ["name", "port", "features"]
}

๐Ÿ” Advanced Validation

Custom Validators

use rson_schema::{Validator, ValidationResult, ValidationError};

struct EmailValidator;

impl Validator for EmailValidator {
    fn validate(&self, value: &str) -> ValidationResult {
        if value.contains('@') && value.contains('.') {
            Ok(())
        } else {
            Err(ValidationError::new("Invalid email format"))
        }
    }
}

// Use custom validator
#[derive(Serialize, Deserialize)]
struct User {
    #[schema(custom = EmailValidator)]
    email: String,
}

Conditional Validation

#[derive(Serialize, Deserialize)]
struct ConditionalConfig {
    #[schema(required_if = "ssl_enabled == true")]
    ssl_cert: Option<String>,
    
    ssl_enabled: bool,
    
    #[schema(min_value_if = "environment == 'prod'", min_value = 8080)]
    port: u16,
    
    environment: String,
}

Cross-Field Validation

use rson_schema::cross_field_validator;

#[derive(Serialize, Deserialize)]
#[schema(cross_field = "validate_password_confirmation")]
struct RegisterUser {
    password: String,
    password_confirmation: String,
}

#[cross_field_validator]
fn validate_password_confirmation(data: &RegisterUser) -> ValidationResult {
    if data.password == data.password_confirmation {
        Ok(())
    } else {
        Err(ValidationError::new("Passwords do not match"))
    }
}

๐Ÿ› ๏ธ CLI Integration

Schema Generation

# Generate schema from Rust code
rsonc schema generate --type Config --output config.rschema src/config.rs

# Generate JSON Schema
rsonc schema generate --type Config --format json-schema --output config.schema.json src/config.rs

Validation

# Validate RSON file against schema
rsonc validate --schema config.rschema config.rson

# Validate multiple files
rsonc validate --schema config.rschema configs/*.rson

๐Ÿ“Š Performance

Schema validation is designed to be fast:

Operation Speed Memory Usage
Schema compile ~1ms Low
Validate small file ~100ฮผs Minimal
Validate large file ~10MB/s Low

Benchmarks on typical configuration files


๐ŸŽฏ Use Cases

Configuration Validation

// Validate server configuration
#[derive(Serialize, Deserialize)]
struct ServerConfig {
    #[schema(format = "ipv4")]
    host: String,
    
    #[schema(minimum = 1024, maximum = 65535)]
    port: u16,
    
    #[schema(minimum = 1, maximum = 100)]
    worker_threads: u8,
    
    #[schema(enum_values = ["debug", "info", "warn", "error"])]
    log_level: String,
}

API Request Validation

// Validate incoming API requests
#[derive(Serialize, Deserialize)]
struct CreateUserRequest {
    #[schema(min_length = 2, max_length = 50, pattern = r"^[a-zA-Z\s]+$")]
    name: String,
    
    #[schema(format = "email")]
    email: String,
    
    #[schema(minimum = 13, maximum = 120)]
    age: u8,
    
    #[schema(items = "String", enum_values = ["user", "admin", "moderator"])]
    roles: Vec<String>,
}

Data Pipeline Validation

// Validate data transformation outputs
#[derive(Serialize, Deserialize)]
struct ProcessedData {
    #[schema(format = "iso8601")]
    timestamp: String,
    
    #[schema(minimum = 0.0)]
    value: f64,
    
    #[schema(pattern = r"^[A-Z]{2,4}$")]
    currency_code: String,
    
    #[schema(min_properties = 1)]
    metadata: std::collections::HashMap<String, serde_json::Value>,
}

๐Ÿงช Testing

#[cfg(test)]
mod tests {
    use super::*;
    use rson_schema::{validate, Schema};

    #[test]
    fn test_valid_config() {
        let schema = Schema::from_type::<Config>().unwrap();
        let rson = r#"Config(name: "test", port: 8080, features: ["auth"])"#;
        
        assert!(validate(&schema, rson).is_ok());
    }

    #[test]
    fn test_invalid_port() {
        let schema = Schema::from_type::<Config>().unwrap();
        let rson = r#"Config(name: "test", port: 70000, features: ["auth"])"#;
        
        let result = validate(&schema, rson);
        assert!(result.is_err());
        
        let errors = result.unwrap_err();
        assert!(errors.iter().any(|e| e.field == "port"));
    }
}

๐Ÿ“– Documentation


๐Ÿค Contributing

We welcome contributions! Please see our Contributing Guide.

Areas we need help with:

  • Additional constraint types
  • Performance optimizations
  • Better error messages
  • Schema migration tools

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.


๐Ÿ”— Related Projects


Made with ๐Ÿ›ก๏ธ by the RSON community

Commit count: 7

cargo fmt