use super::{JsonDeserializationError, JsonDeserializationErrorContext, SchemaType, ValueParser};
use crate::ast::{Context, ExprKind};
use crate::extensions::Extensions;
use std::collections::HashMap;
pub trait ContextSchema {
fn context_type(&self) -> SchemaType;
}
#[derive(Debug, Clone)]
pub struct NullContextSchema;
impl ContextSchema for NullContextSchema {
fn context_type(&self) -> SchemaType {
SchemaType::Record {
attrs: HashMap::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct ContextJsonParser<'e, 's, S: ContextSchema = NullContextSchema> {
schema: Option<&'s S>,
extensions: Extensions<'e>,
}
impl<'e, 's, S: ContextSchema> ContextJsonParser<'e, 's, S> {
pub fn new(schema: Option<&'s S>, extensions: Extensions<'e>) -> Self {
Self { schema, extensions }
}
pub fn from_json_str(&self, json: &str) -> Result<Context, JsonDeserializationError> {
let val = serde_json::from_str(json)?;
self.from_json_value(val)
}
pub fn from_json_value(
&self,
json: serde_json::Value,
) -> Result<Context, JsonDeserializationError> {
let vparser = ValueParser::new(self.extensions.clone());
let expected_ty = self.schema.map(|s| s.context_type());
let rexpr = vparser.val_into_rexpr(json, expected_ty.as_ref(), || {
JsonDeserializationErrorContext::Context
})?;
match rexpr.expr_kind() {
ExprKind::Record { .. } => Ok(Context::from_expr(rexpr)),
_ => Err(JsonDeserializationError::ExpectedContextToBeRecord {
got: Box::new(rexpr),
}),
}
}
pub fn from_json_file(
&self,
json: impl std::io::Read,
) -> Result<Context, JsonDeserializationError> {
let val = serde_json::from_reader(json).map_err(JsonDeserializationError::from)?;
self.from_json_value(val)
}
}