start_command/
args_parser_queries.rs1use crate::args_parser::{WrapperOptions, VALID_OUTPUT_FORMATS};
10
11type IdentifierSetter = fn(&mut WrapperOptions, String);
13
14type FlagSetter = fn(&mut WrapperOptions);
16
17const IDENTIFIER_OPTIONS: [(&str, IdentifierSetter); 6] = [
19 ("--status", |o, v| o.status = Some(v)),
20 ("--upload-log", |o, v| o.upload_log = Some(v)),
21 ("--stop", |o, v| o.stop = Some(v)),
22 ("--terminate", |o, v| o.terminate = Some(v)),
23 ("--attach", |o, v| o.attach = Some(v)),
24 ("--resume", |o, v| o.resume = Some(v)),
25];
26
27const FLAG_OPTIONS: [(&str, FlagSetter); 6] = [
29 ("--list", |o| o.list = true),
30 ("--running", |o| o.running = true),
31 ("--read-only", |o| o.read_only = true),
32 ("--resume-all", |o| o.resume_all = true),
33 ("--cleanup", |o| o.cleanup = true),
34 ("--cleanup-dry-run", |o| {
35 o.cleanup = true;
36 o.cleanup_dry_run = true;
37 }),
38];
39
40const OUTPUT_FORMAT_MODES: [&str; 4] = ["--status", "--list", "--resume", "--resume-all"];
42
43pub fn parse_query_option(
48 args: &[String],
49 index: usize,
50 options: &mut WrapperOptions,
51) -> Result<usize, String> {
52 let arg = &args[index];
53
54 for (name, apply) in FLAG_OPTIONS {
55 if arg == name {
56 apply(options);
57 return Ok(1);
58 }
59 }
60
61 for (name, apply) in IDENTIFIER_OPTIONS {
62 if arg == name {
63 if index + 1 < args.len() && !args[index + 1].starts_with('-') {
64 apply(options, args[index + 1].clone());
65 return Ok(2);
66 }
67 return Err(format!(
68 "Option {} requires a UUID or session name argument",
69 arg
70 ));
71 }
72
73 let prefix = format!("{}=", name);
74 if let Some(value) = arg.strip_prefix(&prefix) {
75 if value.is_empty() {
76 return Err(format!(
77 "Option {} requires a UUID or session name argument",
78 name
79 ));
80 }
81 apply(options, value.to_string());
82 return Ok(1);
83 }
84 }
85
86 if arg == "--output-format" {
87 if index + 1 < args.len() && !args[index + 1].starts_with('-') {
88 options.output_format = Some(args[index + 1].to_lowercase());
89 return Ok(2);
90 }
91 return Err(format!("Option {} requires a format argument", arg));
92 }
93
94 if arg.starts_with("--output-format=") {
95 options.output_format = Some(arg.split('=').nth(1).unwrap_or("").to_lowercase());
96 return Ok(1);
97 }
98
99 Ok(0)
100}
101
102pub fn active_query_modes(options: &WrapperOptions) -> Vec<&'static str> {
104 let mut modes = Vec::new();
105 if options.status.is_some() {
106 modes.push("--status");
107 }
108 if options.list {
109 modes.push("--list");
110 }
111 if options.upload_log.is_some() {
112 modes.push("--upload-log");
113 }
114 if options.stop.is_some() {
115 modes.push("--stop");
116 }
117 if options.terminate.is_some() {
118 modes.push("--terminate");
119 }
120 if options.attach.is_some() {
121 modes.push("--attach");
122 }
123 if options.resume.is_some() {
124 modes.push("--resume");
125 }
126 if options.resume_all {
127 modes.push("--resume-all");
128 }
129 if options.cleanup {
130 modes.push("--cleanup");
131 }
132 modes
133}
134
135pub fn has_query_mode(options: &WrapperOptions) -> bool {
137 !active_query_modes(options).is_empty()
138}
139
140pub fn validate_query_options(options: &WrapperOptions) -> Result<(), String> {
142 if let Some(ref format) = options.output_format {
143 if !VALID_OUTPUT_FORMATS.contains(&format.as_str()) {
144 return Err(format!(
145 "Invalid output format: \"{}\". Valid options are: {}",
146 format,
147 VALID_OUTPUT_FORMATS.join(", ")
148 ));
149 }
150 }
151
152 let modes = active_query_modes(options);
153
154 if modes.len() > 1 {
155 return Err(
156 "Cannot combine --status, --list, --upload-log, --stop, --terminate, --attach, --resume, --resume-all, or --cleanup in the same invocation"
157 .to_string(),
158 );
159 }
160
161 if options.output_format.is_some()
162 && !modes.iter().any(|mode| OUTPUT_FORMAT_MODES.contains(mode))
163 {
164 return Err(
165 "--output-format option is only valid with --status, --list, --resume, or --resume-all"
166 .to_string(),
167 );
168 }
169
170 if options.running && !options.list {
171 return Err("--running option is only valid with --list".to_string());
172 }
173
174 if options.read_only && options.attach.is_none() {
175 return Err("--read-only option is only valid with --attach".to_string());
176 }
177
178 Ok(())
179}