1- use jsonschema:: JSONSchema ;
1+ use jsonschema:: { JSONSchema , SchemaResolver , SchemaResolverError } ;
22use serde:: { Deserialize , Serialize } ;
33use thiserror:: Error ;
4-
4+ use serde_json:: Value ;
5+ use std:: { sync:: Arc } ;
6+ use url:: Url ;
57// This file is supposed to be auto-generated via rust/build.rs
68pub mod schema_types {
79 include ! ( concat!( env!( "OUT_DIR" ) , "/schema_types.rs" ) ) ;
@@ -148,6 +150,32 @@ fn get_topic_schema(topic: &str, version: Option<u16>) -> Result<TopicSchema, Sc
148150 Ok ( schema_metadata)
149151}
150152
153+ struct FileSchemaResolver { }
154+
155+ impl FileSchemaResolver {
156+ fn new ( ) -> Self {
157+ Self { }
158+ }
159+ }
160+
161+ impl SchemaResolver for FileSchemaResolver {
162+ fn resolve ( & self , _root_schema : & Value , url : & Url , _original_reference : & str ) -> Result < Arc < Value > , SchemaResolverError > {
163+ if url. scheme ( ) == "file" {
164+ let url_str = url. as_str ( ) ;
165+ let relative_path = & url_str[ 7 ..url_str. len ( ) - 1 ] ;
166+ let schema = find_entry ( SCHEMAS , relative_path) . ok_or ( SchemaError :: InvalidSchema ) ?;
167+ let schema_json = serde_json:: from_str ( schema) . map_err ( |_| SchemaError :: InvalidSchema ) ?;
168+ return Ok ( Arc :: new ( schema_json) ) ;
169+
170+ }
171+
172+ Err ( SchemaResolverError :: new ( Box :: new ( std:: io:: Error :: new (
173+ std:: io:: ErrorKind :: NotFound ,
174+ format ! ( "Unsupported URL scheme: {}" , url. scheme( ) ) ,
175+ ) ) ) )
176+ }
177+ }
178+
151179/// Returns the schema for a topic. If `version` is passed, return the schema for
152180/// the specified version, otherwise the latest version is returned.
153181///
@@ -163,7 +191,8 @@ pub fn get_schema(topic: &str, version: Option<u16>) -> Result<Schema, SchemaErr
163191 find_entry ( SCHEMAS , & schema_metadata. resource ) . ok_or ( SchemaError :: InvalidSchema ) ?;
164192
165193 let s = serde_json:: from_str ( schema) . map_err ( |_| SchemaError :: InvalidSchema ) ?;
166- let compiled_json_schema = JSONSchema :: compile ( & s) . map_err ( |_| SchemaError :: InvalidSchema ) ?;
194+ let resolver = FileSchemaResolver :: new ( ) ;
195+ let compiled_json_schema = JSONSchema :: options ( ) . with_resolver ( resolver) . compile ( & s) . map_err ( |_| SchemaError :: InvalidSchema ) ?;
167196
168197 // FIXME(swatinem): This assumes that there is only a single `examples` entry in the definition.
169198 // If we would want to support multiple, we would have to either merge those in code generation,
@@ -209,11 +238,11 @@ mod tests {
209238 // Did not error
210239 get_schema ( "snuba-queries" , Some ( 1 ) ) . unwrap ( ) ;
211240 get_schema ( "transactions" , Some ( 1 ) ) . unwrap ( ) ;
241+ get_schema ( "snuba-uptime-results" , Some ( 1 ) ) . unwrap ( ) ;
212242 }
213243
214- #[ test]
215- fn test_validate ( ) {
216- let schema = get_schema ( "snuba-queries" , None ) . unwrap ( ) ;
244+ fn validate_schema ( schema_name : & str ) {
245+ let schema = get_schema ( schema_name, None ) . unwrap ( ) ;
217246
218247 let examples = schema. examples ( ) ;
219248 assert ! ( !examples. is_empty( ) ) ;
@@ -226,4 +255,11 @@ mod tests {
226255 Err ( SchemaError :: InvalidMessage )
227256 ) ) ;
228257 }
258+
259+ #[ test]
260+ fn test_validate ( ) {
261+ validate_schema ( "snuba-queries" ) ;
262+ validate_schema ( "uptime-results" ) ;
263+ validate_schema ( "snuba-uptime-results" ) ;
264+ }
229265}
0 commit comments