fql_serialize 0.2.6

Internal crate for serializing Fauna Query Language (FQL) requests.
Documentation
// Copyright Fauna, Inc.
// SPDX-License-Identifier: MIT-0

use super::values::*;
use super::verbs::*;

extern crate pest;

use pest::error::Error;
use pest::Parser;

#[derive(Parser)]
#[grammar = "fql.pest"]
struct FQLParser;

pub fn parse_expr(expr: &str) -> Result<FQLValue, Error<Rule>> {
  let result = FQLParser::parse(Rule::fql, expr)
    .map_err(|err| err.renamed_rules(|rule| {
      match *rule {
        Rule::object => "Object".to_owned(),
        Rule::array => "Array".to_owned(),
        Rule::string => "String".to_owned(),
        Rule::number => "Number".to_owned(),
        Rule::boolean => "Boolean".to_owned(),
        Rule::null => "null".to_owned(),
        Rule::fqlExpr => "Expression".to_owned(),
        Rule::op => "Opening delimiter '('".to_owned(),
        Rule::cp => "Closing delimiter ')'".to_owned(),
        Rule::osb => "Opening delimiter '['".to_owned(),
        Rule::csb => "Closing delimiter ']'".to_owned(),
        Rule::ocb => "Opening delimiter '{'".to_owned(),
        Rule::ccb => "Closing delimiter '}'".to_owned(),
        Rule::comma => "','".to_owned(),
        Rule::colon => "':'".to_owned(),
        _ => format!("{:?}", rule),
      }
  }));

  let fql = result?.next().unwrap();

  use pest::iterators::Pair;

  fn parse_value(pair: Pair<Rule>) -> FQLValue {
    match pair.as_rule() {
      Rule::object => FQLValue::Object(parse_object(pair).unwrap()),
      Rule::array => FQLValue::Array(parse_array(pair).unwrap()),
      Rule::string => FQLValue::String(pair.into_inner().next().unwrap().as_str()),
      Rule::number => FQLValue::Number(pair.as_str().parse().unwrap()),
      Rule::boolean => FQLValue::Boolean(pair.as_str().parse().unwrap()),
      Rule::niladicExpr => FQLValue::NiladicVerb(parse_niladic_verb(pair).unwrap()),
      Rule::monadicExpr => FQLValue::MonadicVerb(parse_monadic_verb(pair).unwrap()),
      Rule::dyadicExpr => FQLValue::DyadicVerb(parse_dyadic_verb(pair).unwrap()),
      Rule::triadicExpr => FQLValue::TriadicVerb(parse_triadic_verb(pair).unwrap()),
      Rule::quadraticExpr => FQLValue::QuadraticVerb(parse_quadratic_verb(pair).unwrap()),
      Rule::variadicExpr => FQLValue::VariadicVerb(parse_variadic_verb(pair).unwrap()),
      Rule::null => FQLValue::Null,
      Rule::fqlExpr => parse_value(pair.into_inner().nth(0).unwrap()),
      _ => panic!("Parsing Error: unexpected token '{}'", pair.as_str()),
    }
  }

  fn filter_delimiters(pair: &Pair<Rule>) -> bool {
    match pair.as_rule() {
      Rule::op | 
      Rule::cp |
      Rule::osb |
      Rule::csb |
      Rule::ocb |
      Rule::ccb |
      Rule::comma |
      Rule::colon => false,
      _ => true
    }
  }

  fn parse_array(pair: Pair<Rule>) -> Result<Vec<FQLValue>, Error<Rule>> {
    Ok(pair.into_inner().filter(filter_delimiters).map(parse_value).collect())
  }

  fn parse_object(pair: Pair<Rule>) -> Result<Vec<(&str, FQLValue)>, Error<Rule>> {
    Ok(
      pair
        .into_inner()
        .filter(filter_delimiters)
        .map(|pair| {
          let mut inner_rules = pair.into_inner().filter(filter_delimiters);
          let name = inner_rules
            .next()
            .unwrap()
            .into_inner()
            .next()
            .unwrap()
            .as_str();
          let value = parse_value(inner_rules.next().unwrap());
          (name, value)
        })
        .collect(),
    )
  }

  fn parse_niladic_verb(pair: Pair<Rule>) -> Result<NiladicVerb, Error<Rule>> {
    let mut inner_rules = pair.into_inner().filter(filter_delimiters);
    let verb = inner_rules.next().unwrap().as_str();

    Ok(NiladicVerb { verb })
  }

  fn parse_monadic_verb(pair: Pair<Rule>) -> Result<MonadicVerb, Error<Rule>> {
    let mut inner_rules = pair.into_inner().filter(filter_delimiters);
    let verb = inner_rules.next().unwrap().as_str();
    let args: Vec<FQLValue> = inner_rules.map(parse_value).collect();

    Ok(MonadicVerb { verb, args })
  }

  fn parse_dyadic_verb(pair: Pair<Rule>) -> Result<DyadicVerb, Error<Rule>> {
    let mut inner_rules = pair.into_inner().filter(filter_delimiters);
    let verb = inner_rules.next().unwrap().as_str();
    let args: Vec<FQLValue> = inner_rules.map(parse_value).collect();

    Ok(DyadicVerb { verb, args })
  }

  fn parse_triadic_verb(pair: Pair<Rule>) -> Result<TriadicVerb, Error<Rule>> {
    let mut inner_rules = pair.into_inner().filter(filter_delimiters);
    let verb = inner_rules.next().unwrap().as_str();
    let args: Vec<FQLValue> = inner_rules.map(parse_value).collect();

    Ok(TriadicVerb { verb, args })
  }

  fn parse_quadratic_verb(pair: Pair<Rule>) -> Result<QuadraticVerb, Error<Rule>> {
    let mut inner_rules = pair.into_inner().filter(filter_delimiters);
    let verb = inner_rules.next().unwrap().as_str();
    let args: Vec<FQLValue> = inner_rules.map(parse_value).collect();

    Ok(QuadraticVerb { verb, args })
  }

  fn parse_variadic_verb(pair: Pair<Rule>) -> Result<VariadicVerb, Error<Rule>> {
    let mut inner_rules = pair.into_inner().filter(filter_delimiters);
    let verb = inner_rules.next().unwrap().as_str();
    let args: Vec<FQLValue> = inner_rules.map(parse_value).collect();

    Ok(VariadicVerb { verb, args })
  }

  Ok(parse_value(fql))
}