#![recursion_limit = "128"]
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde;
#[macro_use]
extern crate maplit;
mod ast;
mod avro;
mod bigquery;
pub mod casing;
mod jsonschema;
mod traits;
use regex::Regex;
use serde_json::{json, Value};
use traits::TranslateFrom;
#[derive(Copy, Clone, Default, Deserialize)]
pub enum ResolveMethod {
#[default]
Cast,
Drop,
Panic,
}
#[derive(Clone, Default, Deserialize)]
#[serde(default)]
pub struct Context {
pub resolve_method: ResolveMethod,
pub normalize_case: bool,
pub force_nullable: bool,
pub tuple_struct: bool,
pub allow_maps_without_value: bool,
pub json_object_path_regex: Option<String>,
}
impl Context {
fn is_json_object_path(&self, fqn: &str) -> bool {
self.json_object_path_regex
.as_ref()
.map(|object_regex| {
let re = format!(r"\A{}", object_regex);
let json_object_path_re = Regex::new(&re).unwrap();
json_object_path_re.is_match(fqn)
})
.unwrap_or(false)
}
}
fn into_ast(input: &Value, context: &mut Context) -> ast::Tag {
let jsonschema: jsonschema::Tag = match serde_json::from_value(json!(input)) {
Ok(tag) => tag,
Err(e) => panic!("{:#?}", e),
};
let metadata = jsonschema
.extra
.get("mozPipelineMetadata")
.and_then(|obj| obj["json_object_path_regex"].as_str());
if let Some(json_object_path_regex) = metadata {
context.json_object_path_regex = Some(json_object_path_regex.to_string());
}
ast::Tag::translate_from(jsonschema, context).unwrap()
}
pub fn convert_avro(input: &Value, mut context: Context) -> Value {
let ast = into_ast(input, &mut context);
let avro = avro::Type::translate_from(ast, &context).unwrap();
json!(avro)
}
pub fn convert_bigquery(input: &Value, mut context: Context) -> Value {
let ast = into_ast(input, &mut context);
let bq = bigquery::Schema::translate_from(ast, &context).unwrap();
json!(bq)
}