use super::{JsonDeserializationError, JsonDeserializationErrorContext, SchemaType, ValueParser};
use crate::ast::{Context, ContextCreationError};
use crate::extensions::Extensions;
use miette::Diagnostic;
use std::collections::HashMap;
use thiserror::Error;
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(),
open_attrs: false,
}
}
}
#[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, ContextJsonDeserializationError> {
let val = serde_json::from_str(json).map_err(JsonDeserializationError::Serde)?;
self.from_json_value(val)
}
pub fn from_json_value(
&self,
json: serde_json::Value,
) -> Result<Context, ContextJsonDeserializationError> {
let vparser = ValueParser::new(self.extensions);
let expected_ty = self.schema.map(|s| s.context_type());
let rexpr = vparser.val_into_restricted_expr(json, expected_ty.as_ref(), || {
JsonDeserializationErrorContext::Context
})?;
Context::from_expr(rexpr.as_borrowed(), self.extensions)
.map_err(ContextJsonDeserializationError::ContextCreation)
}
pub fn from_json_file(
&self,
json: impl std::io::Read,
) -> Result<Context, ContextJsonDeserializationError> {
let val = serde_json::from_reader(json).map_err(JsonDeserializationError::from)?;
self.from_json_value(val)
}
}
#[derive(Debug, Diagnostic, Error)]
pub enum ContextJsonDeserializationError {
#[error("while parsing context, {0}")]
#[diagnostic(transparent)]
JsonDeserialization(#[from] JsonDeserializationError),
#[error(transparent)]
#[diagnostic(transparent)]
ContextCreation(#[from] ContextCreationError),
}