use std::{collections::HashMap, path::PathBuf};
use serde::{Deserialize, de::Visitor};
use crate::{
environment::EVAL_ID,
workflow::{NowStep, NowStepDownload, NowStepEnvVar, NowStepSecret},
};
impl<'de> Deserialize<'de> for NowStep {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct NowStepVisitor;
impl<'de> Visitor<'de> for NowStepVisitor {
type Value = NowStep;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a now step")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let mut name: Option<String> = None;
let mut run_drv: Option<PathBuf> = None;
let mut teardown_drv: Option<PathBuf> = None;
let mut env: Option<HashMap<String, NowStepEnvVar>> = None;
let mut upload_key: Option<String> = None;
while let Some(key) = map.next_key::<String>()? {
match key.as_ref() {
"name" => name = Some(map.next_value()?),
"runDrv" => run_drv = Some(map.next_value()?),
"teardownDrv" => teardown_drv = map.next_value()?,
"env" => env = Some(map.next_value()?),
_ if matches!(key.split_once(&*EVAL_ID), Some(("__nowUpload_", ""))) => {
upload_key = map.next_value()?
}
_ => {
return Err(serde::de::Error::unknown_field(
&key,
&[
"name",
"runDrv",
"teardownDrv",
"env",
"__nowUpload_<EVAL_ID>",
],
));
}
}
}
let name = name.ok_or_else(|| serde::de::Error::missing_field("name"))?;
let run_drv = run_drv.ok_or_else(|| serde::de::Error::missing_field("runDrv"))?;
let env = env.ok_or_else(|| serde::de::Error::missing_field("env"))?;
Ok(NowStep {
name,
run_drv,
teardown_drv,
env,
upload_key,
})
}
}
deserializer.deserialize_struct(
"NowStep",
&["name", "run_drv", "teardown_drv", "env", "upload_key"],
NowStepVisitor,
)
}
}
impl<'de> Deserialize<'de> for NowStepSecret {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct NowStepSecretVisitor;
impl<'de> Visitor<'de> for NowStepSecretVisitor {
type Value = NowStepSecret;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("an env secret")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let key = map
.next_key::<String>()?
.ok_or_else(|| serde::de::Error::custom("missing key for map"))?;
match key.split_once(&EVAL_ID.to_string()) {
Some(("__nowSecret_", "")) => Ok(NowStepSecret {
secret_name: map.next_value()?,
}),
Some(_) | None => Err(serde::de::Error::custom("invalid map key")),
}
}
}
deserializer.deserialize_struct("NowStepSecret", &["secret_name"], NowStepSecretVisitor)
}
}
impl<'de> Deserialize<'de> for NowStepDownload {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct NowStepDownloadVisitor;
impl<'de> Visitor<'de> for NowStepDownloadVisitor {
type Value = NowStepDownload;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("an env download")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let key = map
.next_key::<String>()?
.ok_or_else(|| serde::de::Error::custom("missing key for map"))?;
match key.split_once(&EVAL_ID.to_string()) {
Some(("__nowDownload_", "")) => Ok(NowStepDownload {
download_name: map.next_value()?,
}),
Some(_) | None => Err(serde::de::Error::custom("invalid map key")),
}
}
}
deserializer.deserialize_struct(
"NowStepDownload",
&["download_name"],
NowStepDownloadVisitor,
)
}
}