1use crate::RpcError;
2#[cfg(feature = "validation")]
3use jsonschema;
4use schemars::{schema_for, JsonSchema};
5use serde_json::Value;
6
7#[cfg(feature = "validation")]
8pub struct Validator {
9 schema: jsonschema::Validator,
10}
11
12#[cfg(feature = "validation")]
13impl Validator {
14 pub fn new(schema: Value) -> Result<Self, RpcError> {
15 let compiled = jsonschema::validator_for(&schema)
16 .map_err(|e| RpcError::bad_request(format!("Invalid schema: {}", e)))?;
17 Ok(Validator { schema: compiled })
18 }
19
20 pub fn from_type<T: JsonSchema>() -> Result<Self, RpcError> {
21 let schema = schema_for!(T);
22 let schema_value = serde_json::to_value(schema)
23 .map_err(|e| RpcError::internal(format!("Schema serialization error: {}", e)))?;
24 Self::new(schema_value)
25 }
26
27 pub fn validate(&self, value: &Value) -> Result<(), Vec<String>> {
28 if self.schema.is_valid(value) {
29 Ok(())
30 } else {
31 Err(vec!["Validation failed".to_string()])
32 }
33 }
34
35 pub fn is_valid(&self, value: &Value) -> bool {
36 self.schema.is_valid(value)
37 }
38}
39
40#[cfg(not(feature = "validation"))]
41pub struct Validator;
42
43#[cfg(not(feature = "validation"))]
44impl Validator {
45 pub fn new(_schema: Value) -> Result<Self, RpcError> {
46 Err(RpcError::internal("Validation feature not enabled"))
47 }
48
49 pub fn validate(&self, _value: &Value) -> Result<(), Vec<String>> {
50 Err(vec!["Validation feature not enabled".to_string()])
51 }
52
53 pub fn is_valid(&self, _value: &Value) -> bool {
54 true
55 }
56}
57
58#[cfg(all(test, feature = "validation"))]
59mod tests {
60 use super::*;
61 use serde_json::json;
62
63 #[test]
64 fn test_validator_creation() {
65 let schema = json!({
66 "type": "object",
67 "properties": {
68 "name": { "type": "string" },
69 "age": { "type": "number" }
70 },
71 "required": ["name"]
72 });
73
74 let validator = Validator::new(schema).unwrap();
75 assert!(validator.is_valid(&json!({"name": "Alice", "age": 30})));
76 assert!(validator.is_valid(&json!({"name": "Bob"})));
77 assert!(!validator.is_valid(&json!({"age": 30})));
78 }
79
80 #[test]
81 fn test_validation_errors() {
82 let schema = json!({
83 "type": "object",
84 "properties": {
85 "count": {
86 "type": "integer",
87 "minimum": 0,
88 "maximum": 100
89 }
90 }
91 });
92
93 let validator = Validator::new(schema).unwrap();
94
95 let valid = json!({"count": 50});
96 assert!(validator.validate(&valid).is_ok());
97
98 let invalid = json!({"count": 150});
99 let result = validator.validate(&invalid);
100 assert!(result.is_err());
101 }
102
103 #[derive(JsonSchema)]
104 #[allow(dead_code)]
105 struct TestStruct {
106 name: String,
107 age: Option<u32>,
108 }
109
110 #[test]
111 fn test_from_type() {
112 let validator = Validator::from_type::<TestStruct>().unwrap();
113
114 assert!(validator.is_valid(&json!({
115 "name": "Alice",
116 "age": 30
117 })));
118
119 assert!(validator.is_valid(&json!({
120 "name": "Bob"
121 })));
122
123 assert!(!validator.is_valid(&json!({
124 "age": 30
125 })));
126 }
127}