hypertune 0.6.2

Hypertune SDK for type safe configuration
Documentation
use anyhow::anyhow;
use anyhow::Result;
use serde::Deserialize;
use serde::Serialize;
use serde_json::Value;
use std::collections::HashMap;

use crate::expression::Expression;

pub type Query = HashMap<String, Fragment>;
pub type Selection = HashMap<String, SelectionField>;

#[derive(Deserialize, Serialize, Debug)]
#[serde(try_from = "Value")]
pub struct SelectionField {
    pub field_arguments: Option<HashMap<String, Expression>>,
    pub field_query: Option<Query>,
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Fragment {
    pub object_type_name: String,
    pub selection: Selection,
}

impl TryFrom<Value> for SelectionField {
    type Error = anyhow::Error;

    fn try_from(value: Value) -> Result<Self> {
        match value {
            Value::Object(object) => {
                let field_arguments: Option<HashMap<String, Expression>> = object
                    .get("fieldArguments")
                    .map(|field_arguments| match field_arguments {
                        Value::Object(field_arguments) => field_arguments
                            .clone()
                            .into_iter()
                            .map(|(key, value)| match value.try_into() {
                                Ok(value) => Ok((key, value)),
                                Err(error) => Err(error),
                            })
                            .collect::<Result<_>>(),
                        _ => Err(anyhow!("Field arguments must be a JSON object")),
                    })
                    .transpose()?;

                let field_query: Option<Query> = match object.get("fieldQuery") {
                    Some(field_query) => serde_json::from_value(field_query.clone())?,
                    None => None,
                };

                Ok(Self {
                    field_arguments,
                    field_query,
                })
            }
            _ => Err(anyhow!(
                "Can only construct a selection field from an object query"
            )),
        }
    }
}