vehicle_parser 0.1.0

Parse data about vehicles to json
Documentation
use pest::Parser;
use pest_derive::Parser;
use serde_json::{json, to_string_pretty, Value};
use thiserror::Error;

#[derive(Parser)]
#[grammar = "grammar.pest"]
pub struct VehicleParser;

#[derive(Error, Debug)]
pub enum VehicleParseError {
    #[error("Pest parsing error: {0}")]
    PestError(#[from] Box<pest::error::Error<Rule>>),

    #[error("JSON formatting error: {0}")]
    JsonError(#[from] serde_json::Error),
}

pub fn parse_vehicle(input: &str) -> Result<Value, VehicleParseError> {
    let mut parsed = VehicleParser::parse(Rule::vehicle, input)
        .map_err(|e| VehicleParseError::PestError(Box::new(e)))?;

    let mut brand = "";
    let mut model = "";
    let mut year = "";
    let mut class = "";
    let mut volume = "";
    let mut power = "";
    let mut engine_type = "";
    let mut dimensions = ("", "", "");
    let mut max_speed = "";
    let mut acceleration = "";

    for record in parsed.next().unwrap().into_inner() {
        match record.as_rule() {
            Rule::brand => brand = record.into_inner().as_str(),
            Rule::model => model = record.into_inner().as_str(),
            Rule::year => year = record.into_inner().as_str(),
            Rule::class => class = record.into_inner().as_str(),
            Rule::volume => volume = record.as_str(),
            Rule::power => power = record.as_str(),
            Rule::engine_type => engine_type = record.into_inner().as_str(),
            Rule::dimensions => {
                let mut dim_parts = record.into_inner();
                dimensions = (
                    dim_parts.next().unwrap().as_str(),
                    dim_parts.next().unwrap().as_str(),
                    dim_parts.next().unwrap().as_str(),
                );
            }
            Rule::max_speed => max_speed = record.into_inner().as_str(),
            Rule::acceleration => acceleration = record.into_inner().as_str(),
            Rule::engine => {
                let engine_parts = record.into_inner();
                for engine_record in engine_parts {
                    match engine_record.as_rule() {
                        Rule::volume => volume = engine_record.into_inner().as_str(),
                        Rule::power => power = engine_record.into_inner().as_str(),
                        Rule::engine_type => engine_type = engine_record.into_inner().as_str(),
                        _ => {}
                    }
                }
            }
            _ => {}
        }
    }

    let vehicle_json = json!({
        "brand": brand,
        "model": model,
        "year": year,
        "class": class,
        "engine": {
            "volume": volume,
            "power": power,
            "type": engine_type,
        },
        "dimensions": {
            "length": dimensions.0,
            "width": dimensions.1,
            "height": dimensions.2,
        },
        "max_speed": max_speed,
        "acceleration": acceleration,
    });

    let pretty_json = to_string_pretty(&vehicle_json)?;

    println!("Parsed Vehicle JSON:\n{}", pretty_json);
    Ok(vehicle_json)
}