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 #[arg(short, long, value_name = "TOML_FILE")]
27 pub file: String,
28
29 pub pattern: String,
31 }
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}