pub(crate) mod source;
use std::str::FromStr;
pub(crate) use source::InputSource;
#[derive(Debug, thiserror::Error, miette::Diagnostic)]
#[error(transparent)]
#[remain::sorted]
pub(crate) enum Error {
Json(#[from] serde_json::Error),
Source(#[from] source::Error),
Yaml(#[from] serde_yml::Error),
}
pub(crate) const HELP: &str = "data to use as input";
pub(crate) const LONG_HELP: &str = constcat::concat!(
HELP,
".\n",
super::INPUT_SOURCE_LONG_HELP,
"
The data may be any valid YAML value (all valid JSON is also valid YAML).
Supports anchors/aliases and merge tags."
);
#[derive(Debug, Clone, clap::Args)]
#[group(id = "input.data")]
#[remain::sorted]
#[rustfmt::skip]
pub(crate) struct InputData {
#[arg(
env = "INPUT_DATA",
long = "input-data",
id = "input.data.source",
value_name = "SOURCE",
help_heading = "Input Options",
help = HELP,
long_help = LONG_HELP,
)]
pub(crate) source: InputSource,
}
impl InputData {
pub(crate) fn consume<T: serde::de::DeserializeOwned>(self) -> Result<T, Error> {
Ok(serde_json::from_value(serde_json::Value::try_from(self)?)?)
}
}
impl FromStr for InputData {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let source = InputSource::from_str(s)?;
Ok(Self { source })
}
}
impl TryFrom<InputData> for String {
type Error = Error;
fn try_from(data: InputData) -> Result<Self, Self::Error> {
Ok(Self::try_from(data.source.cache()?)?)
}
}
impl TryFrom<InputData> for serde_yml::Value {
type Error = Error;
fn try_from(data: InputData) -> Result<Self, Self::Error> {
let yaml = String::try_from(data)?;
let mut value: Self = serde_yml::from_str(&yaml)?;
value.apply_merge();
Ok(value)
}
}
impl TryFrom<InputData> for serde_json::Value {
type Error = Error;
fn try_from(data: InputData) -> Result<Self, Self::Error> {
Ok(serde_yml::from_value(serde_yml::Value::try_from(data)?)?)
}
}