Skip to main content

rskit_dataset/record/
validator.rs

1//! Schema-backed validation for structured records.
2
3use rskit_errors::AppResult;
4
5use crate::schema::DatasetSchema;
6use crate::validate::Validator;
7
8use super::model::DatasetRecord;
9
10/// Rejects records that fail a compiled [`DatasetSchema`].
11pub struct SchemaValidator {
12    schema: DatasetSchema,
13}
14
15impl SchemaValidator {
16    /// Create a validator from a compiled schema.
17    #[must_use]
18    pub fn new(schema: DatasetSchema) -> Self {
19        Self { schema }
20    }
21
22    /// Compile a JSON Schema and wrap it as a record validator.
23    pub fn compile(schema: &serde_json::Value) -> AppResult<Self> {
24        Ok(Self::new(DatasetSchema::compile(schema)?))
25    }
26}
27
28impl Validator<DatasetRecord> for SchemaValidator {
29    fn validate(&self, item: &DatasetRecord) -> AppResult<()> {
30        self.schema.validate(&item.to_json())
31    }
32}
33
34#[cfg(test)]
35mod tests {
36    use rskit_errors::ErrorCode;
37    use serde_json::json;
38
39    use super::*;
40
41    #[test]
42    fn schema_validator_accepts_valid_and_rejects_invalid_records() {
43        let validator = SchemaValidator::compile(&json!({
44            "type": "object",
45            "required": ["id"],
46            "properties": { "id": {"type": "string"} }
47        }))
48        .unwrap();
49
50        validator
51            .validate(&DatasetRecord::from_fields([("id", json!("a"))]))
52            .unwrap();
53
54        let error = validator
55            .validate(&DatasetRecord::from_fields([("id", json!(1))]))
56            .unwrap_err();
57        assert_eq!(error.code(), ErrorCode::InvalidInput);
58    }
59}