goat_cli/utils/
variables.rs1use crate::utils::{
2 expression::Variable,
3 utils::{did_you_mean, parse_comma_separated},
4};
5use anyhow::{bail, Result};
6use std::collections::BTreeMap;
7
8pub struct Variables<'a> {
12 variables: &'a str,
14}
15
16impl<'a> Variables<'a> {
17 pub fn new(str: &'a str) -> Self {
19 Self { variables: str }
20 }
21
22 pub fn parse_one(
25 &self,
26 reference_data: &BTreeMap<&'static str, Variable<'static>>,
27 ) -> Result<String> {
28 let variable = self.variables;
29
30 let var_vec_check = reference_data
31 .iter()
32 .map(|(e, _)| e.to_string())
33 .collect::<Vec<String>>();
34
35 if !var_vec_check.contains(&variable.to_string()) {
36 let var_vec_mean = did_you_mean(&var_vec_check, variable);
37 if let Some(value) = var_vec_mean {
38 bail!(
39 "In your variable (`-v`) you typed \"{}\" - did you mean \"{}\"?",
40 variable,
41 value
42 )
43 }
44 }
45 Ok(variable.to_string())
46 }
47
48 pub fn parse(
52 &self,
53 reference_data: &BTreeMap<&'static str, Variable<'static>>,
54 ) -> Result<String> {
55 let base = "&fields=";
56 let delimiter = "%2C";
57
58 let mut parsed_string = String::new();
59
60 let split_vec = parse_comma_separated(self.variables);
61 let var_vec_check = reference_data
63 .iter()
64 .map(|(e, _)| e.to_string())
65 .collect::<Vec<String>>();
66
67 for variable in &split_vec {
68 if !var_vec_check.contains(variable) {
70 let var_vec_mean = did_you_mean(&var_vec_check, variable);
71 if let Some(value) = var_vec_mean {
72 bail!(
73 "In your variable (`-v`) you typed \"{}\" - did you mean \"{}\"?",
74 variable,
75 value
76 )
77 }
78 }
79 }
80
81 parsed_string += base;
82 for el in split_vec {
83 parsed_string += ⪙
84 parsed_string += delimiter;
85 }
86
87 parsed_string.drain(parsed_string.len() - 3..);
89
90 Ok(parsed_string)
91 }
92
93 pub fn parse_exclude(
96 &self,
97 reference_data: &BTreeMap<&'static str, Variable<'static>>,
98 ) -> Result<String> {
99 const ANCESTRAL: &str = "&excludeAncestral";
100 const MISSING: &str = "&excludeMissing";
101 const OPEN_ANGLE_BRACE: &str = "%5B";
102 const CLOSE_ANGLE_BRACE: &str = "%5D";
103
104 let mut exclusion_string = String::new();
105
106 let split_vec = parse_comma_separated(self.variables);
107 let var_vec_check = reference_data
109 .iter()
110 .map(|(e, _)| e.to_string())
111 .collect::<Vec<String>>();
112
113 for variable in &split_vec {
114 if !var_vec_check.contains(variable) {
116 let var_vec_mean = did_you_mean(&var_vec_check, variable);
117 if let Some(value) = var_vec_mean {
118 bail!(
119 "In your variable (`-v`) you typed \"{}\" - did you mean \"{}\"?",
120 variable,
121 value
122 )
123 }
124 }
125 }
126
127 for (exclude_index, field) in split_vec.into_iter().enumerate() {
128 exclusion_string += ANCESTRAL;
129 exclusion_string += OPEN_ANGLE_BRACE;
130 exclusion_string += &exclude_index.to_string();
131 exclusion_string += CLOSE_ANGLE_BRACE;
132 exclusion_string += &format!("={field}");
133
134 exclusion_string += MISSING;
136 exclusion_string += OPEN_ANGLE_BRACE;
137 exclusion_string += &exclude_index.to_string();
138 exclusion_string += CLOSE_ANGLE_BRACE;
139 exclusion_string += &format!("={field}");
140
141 }
142
143 Ok(exclusion_string)
144 }
145}