tq/
lib.rs

1use std::fs::File;
2use std::io::prelude::*;
3
4use clap::Parser;
5use thiserror::Error;
6use toml::Value;
7
8type Result<T> = std::result::Result<T, TqError>;
9
10#[derive(Error, Debug)]
11pub enum TqError {
12    #[error("Failed to open file \"{file_name}\": {cause}")]
13    FileOpenError { file_name: String, cause: String },
14
15    #[error("Failed to parse TOML file \"{file_name}\": {cause}")]
16    TomlParseError { file_name: String, cause: String },
17
18    #[error("Could not find pattern {pattern}")]
19    PatternNotFoundError { pattern: String },
20}
21
22#[derive(Parser, Debug)]
23#[command(author, version, about, long_about = None)]
24pub struct Cli {
25    /// The TOML File to read
26    #[arg(short, long, value_name = "TOML_FILE")]
27    pub file: String,
28
29    /// Field to read from the TOML file
30    pub pattern: String,
31    // /// The TOML File URL to read
32    // #[arg(short, long, value_name = "URL_PATH")]
33    // pub url: String,
34}
35
36pub fn extract_pattern<'a>(toml_file: &'a Value, pattern: &str) -> Result<&'a Value> {
37    pattern
38        .split('.')
39        .fold(Some(toml_file), |acc, key| match acc {
40            Some(a) => a.get(key),
41            None => None,
42        })
43        .ok_or_else(|| TqError::PatternNotFoundError {
44            pattern: pattern.to_string(),
45        })
46}
47
48pub fn load_toml_from_file(file_name: &str) -> Result<toml::Value> {
49    let mut file = File::open(file_name).map_err(|e| TqError::FileOpenError {
50        file_name: file_name.to_string(),
51        cause: e.to_string(),
52    })?;
53    let mut contents = String::new();
54    let _ = file.read_to_string(&mut contents);
55    toml::from_str::<Value>(&contents).map_err(|e| TqError::TomlParseError {
56        file_name: file_name.to_string(),
57        cause: e.to_string(),
58    })
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn test_extract_pattern() {
67        let toml_file = toml::from_str(
68            r#"
69            [package]
70            test = "test"
71            "#,
72        )
73        .unwrap();
74
75        let x = extract_pattern(&toml_file, "package.test").unwrap();
76
77        assert_eq!(x, &Value::String("test".to_string()));
78    }
79
80    #[test]
81    fn test_fail_extract() {
82        let toml_file = toml::from_str(
83            r#"
84            [package]
85            test = "test"
86            "#,
87        )
88        .unwrap();
89
90        let x = extract_pattern(&toml_file, "package.test2");
91
92        assert!(x.is_err());
93        assert_eq!(
94            x.unwrap_err().to_string(),
95            "Could not find pattern package.test2"
96        );
97    }
98
99    #[test]
100    fn test_get_prop_with_many_tables() {
101        let toml_file = toml::from_str(
102            r#"
103            [package]
104            test = "test"
105            [package2]
106            test2 = "test2"
107            "#,
108        )
109        .unwrap();
110
111        let x = extract_pattern(&toml_file, "package.test").unwrap();
112
113        assert_eq!(x, &Value::String("test".to_string()));
114    }
115}