clap_adapters/yaml.rs
1use serde::de::DeserializeOwned;
2
3use crate::prelude::FromReader;
4
5/// An adapter for deserializing a Yaml document from a buffered reader
6#[derive(Debug, Clone)]
7pub struct YamlOf<T>(pub T);
8impl<T: DeserializeOwned> FromReader for YamlOf<T> {
9 type Error = serde_yaml::Error;
10 fn from_reader(reader: &mut impl std::io::BufRead) -> Result<Self, Self::Error> {
11 let yaml = serde_yaml::from_reader(reader)?;
12 Ok(YamlOf(yaml))
13 }
14}
15
16impl<T> crate::fs::PathTo<YamlOf<T>> {
17 /// Returns reference to the inner Yaml datatype
18 ///
19 /// # Example
20 ///
21 /// ```
22 /// # fn main() -> anyhow::Result<()> {
23 /// use clap::Parser;
24 /// use clap_adapters::prelude::*;
25 ///
26 /// #[derive(Debug, Parser)]
27 /// struct Cli {
28 /// #[clap(long)]
29 /// config: PathTo<YamlOf<serde_json::Value>>,
30 /// }
31 ///
32 /// // Create a config file in a temporary directory
33 /// let config_dir = tempfile::tempdir()?;
34 /// let config_path = config_dir.path().join("config.json");
35 /// let config_path_string = config_path.display().to_string();
36 ///
37 /// // Write a test config to the config file
38 /// let config_string = r#"hello: "world""#;
39 /// std::fs::write(&config_path, &config_string)?;
40 ///
41 /// // Parse our CLI, passing our config file path to --config
42 /// let cli = Cli::parse_from(["app", "--config", &config_path_string]);
43 /// let data = cli.config.data();
44 ///
45 /// // We should expect the value we get to match what we wrote to the config
46 /// assert_eq!(data, &serde_json::json!({"hello":"world"}));
47 /// # Ok(())
48 /// # }
49 /// ```
50 pub fn data(&self) -> &T {
51 &self.data.0
52 }
53
54 /// Returns the owned inner datatype parsed from Yaml
55 ///
56 /// # Example
57 ///
58 /// ```
59 /// # fn main() -> anyhow::Result<()> {
60 /// use clap::Parser;
61 /// use clap_adapters::prelude::*;
62 ///
63 /// #[derive(Debug, Parser)]
64 /// struct Cli {
65 /// #[clap(long)]
66 /// config: PathTo<YamlOf<serde_json::Value>>,
67 /// }
68 ///
69 /// // Create a config file in a temporary directory
70 /// let config_dir = tempfile::tempdir()?;
71 /// let config_path = config_dir.path().join("config.json");
72 /// let config_path_string = config_path.display().to_string();
73 ///
74 /// // Write a test config to the config file
75 /// let config_string = r#"hello: "world""#;
76 /// std::fs::write(&config_path, &config_string)?;
77 ///
78 /// // Parse our CLI, passing our config file path to --config
79 /// let cli = Cli::parse_from(["app", "--config", &config_path_string]);
80 /// let data = cli.config.into_data();
81 ///
82 /// // We should expect the value we get to match what we wrote to the config
83 /// assert_eq!(data, serde_json::json!({"hello":"world"}));
84 /// # Ok(())
85 /// # }
86 /// ```
87 pub fn into_data(self) -> T {
88 self.data.0
89 }
90}