use serde::{Deserialize, Serialize};
use std::{collections::HashMap, path::PathBuf};
use crate::Error;
#[derive(Debug)]
pub enum ParseError {
IO,
Cycle,
Sanity(String),
}
impl Into<Error> for ParseError {
fn into(self) -> Error {
Error::InternalError(format!("Parsing Error: {:?}", self))
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Message {
def: String,
default: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Queue {
pub ns: String,
pub fork: Vec<String>,
pub push_back: bool,
pub message: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Contract {
pub message: HashMap<String, HashMap<String, String>>,
pub queue: HashMap<String, Queue>,
}
pub struct ContractParser {
file_path: PathBuf,
}
impl ContractParser {
pub fn new(file_path: PathBuf) -> Self {
Self { file_path }
}
pub fn parse(&self) -> Result<Contract, ParseError> {
let toml_buf = std::fs::read(&self.file_path).map_err(|e| {
eprintln!("Error while reading the toml : {}", e);
return ParseError::IO;
})?;
let contract: Contract =
toml::from_str(std::str::from_utf8(&toml_buf).unwrap()).map_err(|e| {
eprintln!("Error while parsing \"contract.toml\" : {}", e);
ParseError::Cycle
})?;
for k in contract.queue.keys() {
let q = contract.queue.get(k).unwrap();
let has_message = contract.message.get(&q.message).is_some();
if !has_message {
return Err(ParseError::Sanity(format!(
"Message: {} not found",
q.message
)));
}
}
Ok(contract)
}
}