Skip to main content

rain_metadata/cli/schema/
show.rs

1use clap::Parser;
2use std::path::PathBuf;
3use crate::meta::KnownMeta;
4use crate::cli::output::SupportedOutputEncoding;
5use super::json_schema;
6
7#[derive(Parser)]
8pub struct Show {
9    /// One of a set of known JSON schemas that can be produced to match a subset
10    /// of the validation performed on known metas. Additional validation beyond
11    /// what can be expressed by JSON schema is performed when parsing and
12    /// validating metadata.
13    #[arg(value_parser = clap::value_parser!(KnownMeta))]
14    schema: KnownMeta,
15    /// If provided the schema will be written to the given path instead of
16    /// stdout.
17    #[arg(short, long)]
18    output_path: Option<PathBuf>,
19    /// If true the schema will be pretty printed. Defaults to false.
20    #[arg(short, long)]
21    pretty_print: bool,
22}
23
24pub fn show(s: Show) -> anyhow::Result<()> {
25    let schema_json = json_schema(s.schema)
26        .ok_or_else(|| anyhow::anyhow!("Unsupported for {} meta", s.schema))?;
27    let schema_string = if s.pretty_print {
28        serde_json::to_string_pretty(&schema_json)?
29    } else {
30        serde_json::to_string(&schema_json)?
31    };
32
33    crate::cli::output::output(
34        &s.output_path,
35        SupportedOutputEncoding::Binary,
36        schema_string.as_bytes(),
37    )
38}
39
40#[cfg(all(test, not(target_family = "wasm")))]
41mod tests {
42    use super::*;
43
44    fn show_to_string(schema: KnownMeta, pretty_print: bool) -> anyhow::Result<String> {
45        let file = tempfile::NamedTempFile::new().unwrap();
46        let path = file.path().to_path_buf();
47        show(Show {
48            schema,
49            output_path: Some(path.clone()),
50            pretty_print,
51        })?;
52        Ok(std::fs::read_to_string(&path).unwrap())
53    }
54
55    /// Each supported meta produces its own schema; compact output by
56    /// default (no newlines).
57    #[test]
58    fn test_show_authoring_v1_schema_compact() {
59        let s = show_to_string(KnownMeta::AuthoringMetaV1, false).unwrap();
60        let v: serde_json::Value = serde_json::from_str(&s).unwrap();
61        assert!(s.contains("AuthoringMeta"), "{}", v["title"]);
62        assert!(!s.contains('\n'));
63    }
64
65    /// OpV1 (#304), SolidityAbiV2 and InterpreterCallerMetaV1 (#317) are
66    /// known metas with no schema here, so show refuses them rather than
67    /// producing one.
68    #[test]
69    fn test_show_refuses_unmodelled_metas() {
70        for meta in [
71            KnownMeta::OpV1,
72            KnownMeta::SolidityAbiV2,
73            KnownMeta::InterpreterCallerMetaV1,
74        ] {
75            assert!(show_to_string(meta, false).is_err(), "{:?}", meta);
76        }
77    }
78
79    /// The pretty flag pretty-prints the same schema.
80    #[test]
81    fn test_show_pretty_print() {
82        let s = show_to_string(KnownMeta::AuthoringMetaV1, true).unwrap();
83        assert!(s.starts_with("{\n"));
84        let v: serde_json::Value = serde_json::from_str(&s).unwrap();
85        assert!(v["title"].is_string());
86    }
87
88    /// Metas without a JSON schema error with the exact unsupported
89    /// message.
90    #[test]
91    fn test_show_unsupported_meta_error() {
92        let file = tempfile::NamedTempFile::new().unwrap();
93        let err = show(Show {
94            schema: KnownMeta::DotrainV1,
95            output_path: Some(file.path().to_path_buf()),
96            pretty_print: false,
97        })
98        .unwrap_err();
99        assert_eq!(err.to_string(), "Unsupported for dotrain-v1 meta");
100    }
101}