use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum OutputFormat {
Json,
Yaml,
Plain,
}
impl OutputFormat {
pub const fn as_str(self) -> &'static str {
match self {
Self::Json => "json",
Self::Yaml => "yaml",
Self::Plain => "plain",
}
}
}
impl fmt::Display for OutputFormat {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(self.as_str())
}
}
impl FromStr for OutputFormat {
type Err = String;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"json" => Ok(Self::Json),
"yaml" => Ok(Self::Yaml),
"plain" => Ok(Self::Plain),
_ => Err("invalid output format: expected json, yaml, or plain".to_string()),
}
}
}
#[cfg(feature = "cli")]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum OutputTo {
Split,
Stdout,
Stderr,
}
#[cfg(feature = "cli")]
impl OutputTo {
pub const fn as_str(self) -> &'static str {
match self {
Self::Split => "split",
Self::Stdout => "stdout",
Self::Stderr => "stderr",
}
}
pub fn parse(value: &str) -> Result<Self, String> {
value.parse()
}
}
#[cfg(feature = "cli")]
impl fmt::Display for OutputTo {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(self.as_str())
}
}
#[cfg(feature = "cli")]
impl FromStr for OutputTo {
type Err = String;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"split" => Ok(Self::Split),
"stdout" => Ok(Self::Stdout),
"stderr" => Ok(Self::Stderr),
_ => Err("unsupported --output-to: expected split, stdout, or stderr".to_string()),
}
}
}
#[cfg(test)]
mod tests {
use super::OutputFormat;
#[cfg(feature = "cli")]
use super::OutputTo;
#[test]
fn output_types_round_trip_text_and_serde() {
for format in [OutputFormat::Json, OutputFormat::Yaml, OutputFormat::Plain] {
assert_eq!(format.to_string().parse(), Ok(format));
assert_eq!(
serde_json::from_str::<OutputFormat>(
&serde_json::to_string(&format).unwrap_or_default()
)
.ok(),
Some(format)
);
}
#[cfg(feature = "cli")]
{
for destination in [OutputTo::Split, OutputTo::Stdout, OutputTo::Stderr] {
assert_eq!(destination.to_string().parse(), Ok(destination));
assert_eq!(
serde_json::from_str::<OutputTo>(
&serde_json::to_string(&destination).unwrap_or_default()
)
.ok(),
Some(destination)
);
}
}
let format_canary = "canary-output-format-secret";
let format_error = format_canary.parse::<OutputFormat>().unwrap_err();
assert!(!format_error.contains(format_canary));
assert!(format_error.contains("json"));
#[cfg(feature = "cli")]
{
let destination_canary = "canary-output-to-secret";
let destination_error = destination_canary.parse::<OutputTo>().unwrap_err();
assert!(!destination_error.contains(destination_canary));
assert!(destination_error.contains("split"));
}
}
}