Skip to content

Commit f1a7735

Browse files
Refactoring: command dispatch, internal type error, reduce duplication in CLI parser definitions
1 parent 196d68f commit f1a7735

17 files changed

+2186
-1920
lines changed

Cargo.lock

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/arg_helpers.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright (C) 2023-2025 RabbitMQ Core Team ([email protected])
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
use crate::errors::CommandRunError;
16+
use clap::ArgMatches;
17+
use std::fmt::Display;
18+
use std::str::FromStr;
19+
20+
type CommandResult<T> = Result<T, CommandRunError>;
21+
22+
pub trait ArgMatchesExt {
23+
fn str_arg(&self, name: &str) -> &String;
24+
fn string_arg(&self, name: &str) -> String;
25+
26+
fn required_string(&self, name: &str) -> CommandResult<String>;
27+
fn optional_string(&self, name: &str) -> Option<String>;
28+
fn optional_typed<T: Clone + Send + Sync + 'static>(&self, name: &str) -> Option<T>;
29+
fn optional_typed_or<T: Clone + Send + Sync + 'static>(&self, name: &str, default: T) -> T;
30+
fn parse_required<T: FromStr>(&self, name: &str) -> CommandResult<T>
31+
where
32+
T::Err: Display;
33+
}
34+
35+
impl ArgMatchesExt for ArgMatches {
36+
fn str_arg(&self, name: &str) -> &String {
37+
self.get_one::<String>(name).unwrap()
38+
}
39+
40+
fn string_arg(&self, name: &str) -> String {
41+
self.get_one::<String>(name).cloned().unwrap()
42+
}
43+
44+
fn required_string(&self, name: &str) -> CommandResult<String> {
45+
self.get_one::<String>(name).cloned().ok_or_else(|| {
46+
CommandRunError::MissingRequiredArgument {
47+
name: name.to_string(),
48+
}
49+
})
50+
}
51+
52+
fn optional_string(&self, name: &str) -> Option<String> {
53+
self.get_one::<String>(name).cloned()
54+
}
55+
56+
fn optional_typed<T: Clone + Send + Sync + 'static>(&self, name: &str) -> Option<T> {
57+
self.get_one::<T>(name).cloned()
58+
}
59+
60+
fn optional_typed_or<T: Clone + Send + Sync + 'static>(&self, name: &str, default: T) -> T {
61+
self.get_one::<T>(name).cloned().unwrap_or(default)
62+
}
63+
64+
fn parse_required<T: FromStr>(&self, name: &str) -> CommandResult<T>
65+
where
66+
T::Err: Display,
67+
{
68+
let value = self.required_string(name)?;
69+
value
70+
.parse::<T>()
71+
.map_err(|e| CommandRunError::InvalidArgumentValue {
72+
name: name.to_string(),
73+
message: e.to_string(),
74+
})
75+
}
76+
}

0 commit comments

Comments
 (0)