use super::*;
use crate::{JssKind, JssSchema, JssValue};
use json_value::{JsonMaybeObject, JsonValueCheck, JsonValueWrap};
impl From<JsonValue> for JssValue {
fn from(v: JsonValue) -> Self {
match v {
JsonValue::Null => Self::Null,
JsonValue::Bool(v) => Self::Boolean(v),
JsonValue::Number(v) => Self::Number(v),
JsonValue::String(v) => Self::String(v),
JsonValue::Array(v) => Self::Array(v.into_iter().map(|v| v.into()).collect()),
JsonValue::Object(v) => Self::Object(v.into_iter().map(|(k, v)| (k, v.into())).collect()),
}
}
}
impl JssSchema {
pub fn parse_json_schema(top: JsonValue) -> Result<Self, Vec<JssError>> {
let mut errors = vec![];
match Self::try_parse_json_schema(top, &mut errors) {
Ok(o) => Ok(o),
Err(e) => {
errors.push(e);
Err(errors)
}
}
}
pub(crate) fn try_parse_json_schema(top: JsonValue, errors: Errors) -> Result<Self> {
let mut top = top;
if top.is_true() || top.is_empty() {
return Ok(JssSchema::anything());
}
if top.is_false() {
return Ok(JssSchema::nothing());
}
if top.is_null() || top.is_array() {
return Err(JssError::undefined_variable("TODO"));
}
let mut jss = JssSchema::top();
jss.parse_steps(true, &mut top, errors);
jss.consume_rest(top, errors);
Ok(jss)
}
}
impl JssSchema {
fn parse_value(name: String, value: JsonValue, errors: Errors) -> Result<Self> {
let mut value = value;
let mut jss = Self::default();
jss.set_name(name);
jss.parse_steps(false, &mut value, errors);
jss.consume_rest(value, errors);
Ok(jss)
}
fn parse_steps(&mut self, is_top: bool, value: &mut JsonValue, errors: Errors) {
self.parse_type(value, errors);
self.parse_name(value, errors);
self.parse_description(value, errors);
self.extend_properties("properties", is_top, value, errors);
self.extend_definition("$defs", value, errors);
self.extend_definition("definitions", value, errors);
}
fn consume_rest(&mut self, value: JsonValue, _: Errors) {
let object = match value.into_object() {
None => return,
Some(s) => s,
};
for (k, v) in object {
self.insert_attribute(k, v);
}
}
}
impl JssSchema {
fn extend_properties(&mut self, key: &str, is_top: bool, value: &mut JsonValue, errors: Errors) {
if let Some(object) = value.extract_key_as_object(key) {
for (key, value) in object {
match JssSchema::parse_value(key.to_owned(), value, errors) {
Ok(mut o) => {
if is_top {
o.kind = JssKind::PropertyTop
}
self.insert_property(key, o);
}
Err(e) => errors.push(e),
}
}
}
}
fn extend_definition(&mut self, key: &str, value: &mut JsonValue, errors: Errors) {
if let Some(object) = value.extract_key_as_object(key) {
for (key, value) in object {
match JssSchema::parse_value(key.to_owned(), value, errors) {
Ok(mut o) => {
o.kind = JssKind::Definition;
self.insert_definition(key, o);
}
Err(e) => errors.push(e),
}
}
}
}
}