use std::path::{Path, PathBuf};
use anyhow::Context;
use serde::{Deserialize, Serialize};
use crate::{checker::Checker, input, registry, Any};
#[derive(Debug)]
pub(crate) struct Jobs {
jobs: Vec<Any>,
}
impl Jobs {
pub(crate) fn jobs(&self) -> &[Any] {
&self.jobs
}
pub(crate) fn into_inner(self) -> Vec<Any> {
self.jobs
}
pub(crate) fn load(path: &Path, registry: ®istry::Inputs) -> anyhow::Result<Self> {
Self::parse(&Partial::load(path)?, registry)
}
pub(crate) fn parse(partial: &Partial, registry: ®istry::Inputs) -> anyhow::Result<Self> {
let mut checker = Checker::new(
partial
.search_directories
.iter()
.map(PathBuf::from)
.collect(),
partial.output_directory.as_ref().map(PathBuf::from),
);
let num_jobs = partial.jobs.len();
let jobs: anyhow::Result<Vec<Any>> = partial
.jobs
.iter()
.enumerate()
.map(|(i, unprocessed)| {
let context = || {
format!(
"while processing input {} of {}",
i.wrapping_add(1),
num_jobs
)
};
let input = registry
.get(&unprocessed.tag)
.ok_or_else(|| {
anyhow::anyhow!("Unrecognized input tag: \"{}\"", unprocessed.tag)
})
.with_context(context)?;
checker.set_tag(input.tag());
input
.try_deserialize(&unprocessed.content, &mut checker)
.with_context(context)
})
.collect();
Ok(Self { jobs: jobs? })
}
pub(crate) fn example() -> Result<String, serde_json::Error> {
serde_json::to_string_pretty(&Partial {
search_directories: vec!["directory/a".into(), "directory/b".into()],
output_directory: None,
jobs: Vec::new(),
})
}
}
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct Unprocessed {
#[serde(rename = "type")]
pub(crate) tag: String,
pub(crate) content: serde_json::Value,
}
impl Unprocessed {
pub(crate) fn new(tag: String, content: serde_json::Value) -> Self {
Self { tag, content }
}
pub(crate) fn format_input(example: input::Registered<'_>) -> anyhow::Result<Self> {
let tag = example.tag().to_string();
Ok(Self {
tag,
content: example.example()?,
})
}
}
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct Partial {
search_directories: Vec<String>,
output_directory: Option<String>,
jobs: Vec<Unprocessed>,
}
impl Partial {
pub(crate) fn load(path: &Path) -> anyhow::Result<Self> {
crate::internal::load_from_disk(path)
}
pub(crate) fn jobs(&self) -> &[Unprocessed] {
&self.jobs
}
}