1use rskit_errors::{AppError, AppResult, ErrorCode};
4
5pub struct DatasetSchema {
7 compiled: rskit_schema::CompiledSchema,
8}
9
10impl DatasetSchema {
11 pub fn compile(schema: &serde_json::Value) -> AppResult<Self> {
13 rskit_schema::compile(schema).map(|compiled| Self { compiled })
14 }
15
16 pub fn validate(&self, record: &serde_json::Value) -> AppResult<()> {
18 let result = self.compiled.validate(record);
19 if result.valid {
20 return Ok(());
21 }
22 let detail = result
23 .errors
24 .iter()
25 .map(ToString::to_string)
26 .collect::<Vec<_>>()
27 .join("; ");
28 Err(AppError::new(
29 ErrorCode::InvalidInput,
30 format!("dataset record failed schema validation: {detail}"),
31 ))
32 }
33}
34
35pub fn validate_record(schema: &DatasetSchema, record: &serde_json::Value) -> AppResult<()> {
37 schema.validate(record)
38}
39
40#[cfg(test)]
41mod tests {
42 use serde_json::json;
43
44 use super::*;
45
46 #[test]
47 fn dataset_schema_validates_records_and_reports_failures() {
48 let schema = DatasetSchema::compile(&json!({
49 "type": "object",
50 "required": ["id"],
51 "properties": {
52 "id": {"type": "string"},
53 "score": {"type": "number"}
54 }
55 }))
56 .unwrap();
57
58 validate_record(&schema, &json!({"id": "a", "score": 1.0})).unwrap();
59
60 let err = validate_record(&schema, &json!({"score": "bad"})).unwrap_err();
61 assert_eq!(err.code(), ErrorCode::InvalidInput);
62 assert!(
63 err.to_string()
64 .contains("dataset record failed schema validation")
65 );
66 }
67}