Skip to main content

greentic_operator/demo/
input.rs

1use std::{fs, path::PathBuf};
2
3use anyhow::{Context, Result, anyhow};
4use serde_json::Value as JsonValue;
5use serde_yaml_bw;
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub enum InputEncoding {
9    Json,
10    Yaml,
11}
12
13impl InputEncoding {
14    pub fn label(self) -> &'static str {
15        match self {
16            InputEncoding::Json => "json",
17            InputEncoding::Yaml => "yaml",
18        }
19    }
20}
21
22#[derive(Debug)]
23pub enum InputSource {
24    Inline(InputEncoding),
25    File {
26        path: PathBuf,
27        encoding: InputEncoding,
28    },
29}
30
31#[derive(Debug)]
32pub struct ParsedInput {
33    pub value: JsonValue,
34    pub source: InputSource,
35}
36
37pub fn parse_input(value: &str) -> Result<ParsedInput> {
38    if let Some(rest) = value.strip_prefix('@') {
39        let path = PathBuf::from(rest);
40        let contents = fs::read_to_string(&path)
41            .with_context(|| format!("unable to read input file {}", path.display()))?;
42        let (value, encoding) = parse_text(&contents)
43            .with_context(|| format!("unable to parse input file {}", path.display()))?;
44        Ok(ParsedInput {
45            value,
46            source: InputSource::File { path, encoding },
47        })
48    } else {
49        let (value, encoding) = parse_text(value)?;
50        Ok(ParsedInput {
51            value,
52            source: InputSource::Inline(encoding),
53        })
54    }
55}
56
57fn parse_text(text: &str) -> Result<(JsonValue, InputEncoding)> {
58    match serde_json::from_str(text) {
59        Ok(value) => Ok((value, InputEncoding::Json)),
60        Err(json_err) => match serde_yaml_bw::from_str(text) {
61            Ok(value) => Ok((value, InputEncoding::Yaml)),
62            Err(yaml_err) => Err(anyhow!(
63                "input parse error: json={json_err}; yaml={yaml_err}"
64            )),
65        },
66    }
67}