use castep_cell_fmt::{Cell, CellValue, ToCell, ToCellValue};
use castep_cell_fmt::parse::{FromCellValue, FromKeyValue};
use castep_cell_fmt::{CResult, Error};
use castep_cell_fmt::query::value_as_str;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename = "TASK")]
#[derive(Default)]
pub enum Task {
#[serde(alias = "SINGLEPOINT", alias = "singlepoint")]
#[default]
SinglePoint,
#[serde(alias = "BANDSTRUCTURE", alias = "bandstructure")]
BandStructure,
#[serde(alias = "GEOMETRYOPTIMIZATION", alias = "geometryoptimization")]
GeometryOptimization,
#[serde(alias = "MOLECULARDYNAMICS", alias = "moleculardynamics")]
MolecularDynamics,
#[serde(alias = "OPTICS", alias = "optics")]
Optics,
#[serde(alias = "PHONON", alias = "phonon")]
Phonon,
#[serde(alias = "EFIELD", alias = "efield")]
Efield,
#[serde(alias = "PHONON+EFIELD", alias = "phonon+efield")]
PhononPlusEfield,
#[serde(alias = "TRANSITIONSTATESEARCH", alias = "transitionstatesearch")]
TransitionStateSearch,
#[serde(alias = "MAGRES", alias = "magres")]
MagRes,
#[serde(alias = "ELNES", alias = "elnes")]
Elnes,
#[serde(alias = "ELECTRONICSPECTROSCOPY", alias = "electronicspectroscopy")]
ElectronicSpectroscopy,
#[serde(alias = "AUTOSOLVATION", alias = "autosolvation")]
Autosolvation,
}
impl FromCellValue for Task {
fn from_cell_value(value: &CellValue<'_>) -> CResult<Self> {
match value_as_str(value)?.to_ascii_lowercase().as_str() {
"singlepoint" => Ok(Self::SinglePoint),
"bandstructure" => Ok(Self::BandStructure),
"geometryoptimization" => Ok(Self::GeometryOptimization),
"moleculardynamics" => Ok(Self::MolecularDynamics),
"optics" => Ok(Self::Optics),
"phonon" => Ok(Self::Phonon),
"efield" => Ok(Self::Efield),
"phonon+efield" => Ok(Self::PhononPlusEfield),
"transitionstatesearch" => Ok(Self::TransitionStateSearch),
"magres" => Ok(Self::MagRes),
"elnes" => Ok(Self::Elnes),
"electronicspectroscopy" => Ok(Self::ElectronicSpectroscopy),
"autosolvation" => Ok(Self::Autosolvation),
other => Err(Error::Message(format!("unknown Task: {other}"))),
}
}
}
impl FromKeyValue for Task {
const KEY_NAME: &'static str = "TASK";
fn from_cell_value_kv(value: &CellValue<'_>) -> CResult<Self> {
Self::from_cell_value(value)
}
}
impl ToCell for Task {
fn to_cell(&self) -> Cell<'_> {
Cell::KeyValue("TASK", self.to_cell_value())
}
}
impl ToCellValue for Task {
fn to_cell_value(&self) -> CellValue<'_> {
CellValue::String(
match self {
Task::SinglePoint => "SinglePoint",
Task::BandStructure => "BandStructure",
Task::GeometryOptimization => "GeometryOptimization",
Task::MolecularDynamics => "MolecularDynamics",
Task::Optics => "Optics",
Task::Phonon => "Phonon",
Task::Efield => "Efield",
Task::PhononPlusEfield => "Phonon+Efield",
Task::TransitionStateSearch => "TransitionStateSearch",
Task::MagRes => "MagRes",
Task::Elnes => "Elnes",
Task::ElectronicSpectroscopy => "ElectronicSpectroscopy",
Task::Autosolvation => "Autosolvation",
}
.to_string(),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use castep_cell_fmt::CellValue;
#[test]
fn test_case_insensitive_parsing() {
let val = CellValue::Str("singlepoint");
assert_eq!(Task::from_cell_value(&val).unwrap(), Task::SinglePoint);
let val = CellValue::Str("SINGLEPOINT");
assert_eq!(Task::from_cell_value(&val).unwrap(), Task::SinglePoint);
let val = CellValue::Str("SinglePoint");
assert_eq!(Task::from_cell_value(&val).unwrap(), Task::SinglePoint);
}
#[test]
fn test_all_variants() {
assert_eq!(Task::from_cell_value(&CellValue::Str("bandstructure")).unwrap(), Task::BandStructure);
assert_eq!(Task::from_cell_value(&CellValue::Str("geometryoptimization")).unwrap(), Task::GeometryOptimization);
assert_eq!(Task::from_cell_value(&CellValue::Str("moleculardynamics")).unwrap(), Task::MolecularDynamics);
assert_eq!(Task::from_cell_value(&CellValue::Str("optics")).unwrap(), Task::Optics);
assert_eq!(Task::from_cell_value(&CellValue::Str("phonon")).unwrap(), Task::Phonon);
assert_eq!(Task::from_cell_value(&CellValue::Str("efield")).unwrap(), Task::Efield);
assert_eq!(Task::from_cell_value(&CellValue::Str("phonon+efield")).unwrap(), Task::PhononPlusEfield);
assert_eq!(Task::from_cell_value(&CellValue::Str("transitionstatesearch")).unwrap(), Task::TransitionStateSearch);
assert_eq!(Task::from_cell_value(&CellValue::Str("magres")).unwrap(), Task::MagRes);
assert_eq!(Task::from_cell_value(&CellValue::Str("elnes")).unwrap(), Task::Elnes);
assert_eq!(Task::from_cell_value(&CellValue::Str("electronicspectroscopy")).unwrap(), Task::ElectronicSpectroscopy);
assert_eq!(Task::from_cell_value(&CellValue::Str("autosolvation")).unwrap(), Task::Autosolvation);
}
#[test]
fn test_invalid_variant() {
let val = CellValue::Str("invalid");
assert!(Task::from_cell_value(&val).is_err());
}
#[test]
fn test_key_name() {
assert_eq!(Task::KEY_NAME, "TASK");
}
}