runtimo_core/schema.rs
1//! JSON Schema validation for capability arguments.
2//!
3//! Provides basic type-checking validation against a JSON Schema object.
4//! Currently supports simple `"type"` field matching. For full JSON Schema
5//! validation, integrate the `jsonschema` crate.
6//!
7//! # Example
8//!
9//! ```rust
10//! use runtimo_core::SchemaValidator;
11//! use serde_json::json;
12//!
13//! let validator = SchemaValidator::new();
14//! let schema = json!({"type": "object"});
15//! let args = json!({"path": "/tmp/test.txt"});
16//!
17//! assert!(validator.validate(&args, &schema).is_ok());
18//! ```
19
20use crate::Result;
21use serde_json::Value;
22
23/// Validates JSON values against a simplified JSON Schema.
24///
25/// Currently performs basic type checking. Future versions may use the
26/// `jsonschema` crate for full draft-07 validation.
27pub struct SchemaValidator {
28 // Could use jsonschema crate for full JSON Schema validation
29}
30
31impl SchemaValidator {
32 /// Creates a new (stateless) schema validator.
33 pub fn new() -> Self {
34 Self {}
35 }
36
37 /// Validates arguments against a JSON Schema.
38 ///
39 /// # Arguments
40 ///
41 /// * `args` — The JSON value to validate
42 /// * `schema` — A JSON Schema object (currently only `"type"` is checked)
43 ///
44 /// # Returns
45 ///
46 /// `Ok(())` if the value matches the schema.
47 ///
48 /// # Errors
49 ///
50 /// Returns [`Error::SchemaValidationFailed`](crate::Error::SchemaValidationFailed)
51 /// if the value's type does not match the schema's `"type"` field.
52 pub fn validate(&self, args: &Value, schema: &Value) -> Result<()> {
53 if let Some(expected_type) = schema.get("type").and_then(|t| t.as_str()) {
54 let actual_type = if args.is_string() {
55 "string"
56 } else if args.is_number() {
57 "number"
58 } else if args.is_boolean() {
59 "boolean"
60 } else if args.is_array() {
61 "array"
62 } else if args.is_object() {
63 "object"
64 } else {
65 "null"
66 };
67
68 if expected_type != actual_type {
69 return Err(crate::Error::SchemaValidationFailed(format!(
70 "Expected type '{}', got '{}'",
71 expected_type, actual_type
72 )));
73 }
74 }
75
76 if let Some(required) = schema.get("required").and_then(|r| r.as_array()) {
77 if let Some(obj) = args.as_object() {
78 for key in required {
79 if let Some(key_str) = key.as_str() {
80 if !obj.contains_key(key_str) {
81 return Err(crate::Error::SchemaValidationFailed(format!(
82 "Missing required field: '{}'",
83 key_str
84 )));
85 }
86 }
87 }
88 }
89 }
90
91 Ok(())
92 }
93}
94
95impl Default for SchemaValidator {
96 fn default() -> Self {
97 Self::new()
98 }
99}