use crate::datatypes::RandomData;
use failure::Fail;
use std::iter::Iterator;
use std::string::ToString;
use serde_derive::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Reference {
path: String,
property: String,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "type", content = "value")]
pub enum DataType {
RandomData(RandomData),
List(Box<DataType>),
Model(String),
Reference { path: String, property: String },
}
use std::collections::{hash_map::Iter, HashMap};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Model {
#[serde(flatten)]
properties: HashMap<String, DataType>,
}
impl Model {
pub fn type_iter(&self) -> Iter<String, DataType> {
self.properties.iter()
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Specification {
serialize: HashMap<String, Vec<String>>,
models: HashMap<String, Model>,
}
impl Specification {
pub fn has_model<S: ToString>(&self, name: S) -> bool {
self.models.contains_key(&name.to_string())
}
pub fn get_definition<S: ToString>(&self, name: S) -> &Model {
&self.models.get(&name.to_string()).unwrap()
}
pub fn get_serialize_ref<S: ToString>(&self, name: S) -> Option<&Vec<String>> {
self.serialize.get(&name.to_string())
}
}
pub mod io {
use super::Specification;
use crate::generator::from_spec;
use failure::Fail;
use std::convert::AsRef;
use std::fs::read_to_string;
use std::io::Result;
use std::path::{Path, PathBuf};
use serde_derive::{Deserialize, Serialize};
use serde_json::{error::Category, from_str};
pub type SpecResult<Success> = std::result::Result<Success, SpecError>;
#[derive(Debug, Fail)]
pub enum SpecError {
#[fail(display = "Could not find the spec file: {}", 0)]
MissingFile(String),
#[fail(display = "Failed for unhandled reason: {}", inner)]
IOError { inner: std::io::Error },
#[fail(display = "The provided spec path could not be correctly converted")]
BadPath,
#[fail(display = "The specification is not valid JSON")]
BadFormat,
#[fail(display = "The specification contained one or more invalid definitions")]
BadData,
}
fn pathable_to_string<P: AsRef<Path>>(path: &P) -> SpecResult<String> {
return match path.as_ref().to_str() {
Some(string) => Ok(String::from(string)),
None => Err(SpecError::BadPath),
};
}
pub fn read_spec<P: AsRef<Path>>(path: P) -> SpecResult<Specification> {
let content = match read_to_string(&path) {
Ok(content) => content,
Err(e) => match e.kind() {
std::io::ErrorKind::NotFound => {
return Err(SpecError::MissingFile(pathable_to_string(&path)?))
}
_ => return Err(SpecError::IOError { inner: e }),
},
};
match from_str(&content) {
Ok(spec) => Ok(spec),
Err(e) => match e.classify() {
Category::Eof | Category::Syntax => Err(SpecError::BadFormat),
Category::Data => Err(SpecError::BadData),
Category::Io => Err(SpecError::IOError { inner: e.into() }),
},
}
}
}