greentic-operator 0.4.43

Greentic operator CLI for local dev and demo orchestration.
Documentation
use std::{fs, path::PathBuf};

use anyhow::{Context, Result, anyhow};
use serde_json::Value as JsonValue;
use serde_yaml_bw;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum InputEncoding {
    Json,
    Yaml,
}

impl InputEncoding {
    pub fn label(self) -> &'static str {
        match self {
            InputEncoding::Json => "json",
            InputEncoding::Yaml => "yaml",
        }
    }
}

#[derive(Debug)]
pub enum InputSource {
    Inline(InputEncoding),
    File {
        path: PathBuf,
        encoding: InputEncoding,
    },
}

#[derive(Debug)]
pub struct ParsedInput {
    pub value: JsonValue,
    pub source: InputSource,
}

pub fn parse_input(value: &str) -> Result<ParsedInput> {
    if let Some(rest) = value.strip_prefix('@') {
        let path = PathBuf::from(rest);
        let contents = fs::read_to_string(&path)
            .with_context(|| format!("unable to read input file {}", path.display()))?;
        let (value, encoding) = parse_text(&contents)
            .with_context(|| format!("unable to parse input file {}", path.display()))?;
        Ok(ParsedInput {
            value,
            source: InputSource::File { path, encoding },
        })
    } else {
        let (value, encoding) = parse_text(value)?;
        Ok(ParsedInput {
            value,
            source: InputSource::Inline(encoding),
        })
    }
}

fn parse_text(text: &str) -> Result<(JsonValue, InputEncoding)> {
    match serde_json::from_str(text) {
        Ok(value) => Ok((value, InputEncoding::Json)),
        Err(json_err) => match serde_yaml_bw::from_str(text) {
            Ok(value) => Ok((value, InputEncoding::Yaml)),
            Err(yaml_err) => Err(anyhow!(
                "input parse error: json={json_err}; yaml={yaml_err}"
            )),
        },
    }
}