Skip to content

Commit fc1a2f1

Browse files
Rework registry internals.
1 parent e578853 commit fc1a2f1

File tree

1 file changed

+30
-19
lines changed

1 file changed

+30
-19
lines changed

registry/src/lib.rs

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,57 +7,68 @@ use self::args::RegistryArgs;
77
use opts::parser::OptionsPile;
88
use opts::parser::ToOptionsHelp;
99
use std::collections::HashMap;
10+
use std::sync::Arc;
1011
use validates::ValidationError;
1112
use validates::ValidationResult;
1213

14+
struct RegistrantData<R> {
15+
names: Vec<&'static str>,
16+
argct: usize,
17+
init: Box<Fn(&[&str]) -> ValidationResult<R> + Send + Sync>,
18+
}
19+
1320
pub struct Registry<R> {
14-
map: HashMap<&'static str, (usize, Box<Fn(&[&str]) -> ValidationResult<R> + Send + Sync>)>,
15-
aliaseses: Vec<Vec<&'static str>>,
21+
map: HashMap<&'static str, Arc<RegistrantData<R>>>,
22+
list: Vec<Arc<RegistrantData<R>>>,
1623
}
1724

1825
impl<R> Default for Registry<R> {
1926
fn default() -> Self {
2027
return Registry {
2128
map: HashMap::new(),
22-
aliaseses: Vec::new(),
29+
list: Vec::new(),
2330
};
2431
}
2532
}
2633

2734
impl<R: 'static> Registry<R> {
2835
pub fn add<I: Registrant<R> + 'static>(&mut self) {
29-
let names = I::names();
30-
for name in names.iter() {
31-
let prev = self.map.insert(name, (I::argct(), Box::new(I::init)));
36+
let data = Arc::new(RegistrantData {
37+
names: I::names(),
38+
argct: I::argct(),
39+
init: Box::new(I::init),
40+
});
41+
for name in &data.names {
42+
let prev = self.map.insert(name, data.clone());
3243
assert!(prev.is_none(), "registry collision for {}", name);
3344
}
34-
self.aliaseses.push(names);
45+
self.list.push(data);
3546
}
3647

3748
pub fn find(&self, name: &str, args: &[&str]) -> ValidationResult<R> {
3849
match self.map.get(name) {
3950
None => {
4051
return ValidationError::message(format!("No implementation named {}", name));
4152
}
42-
Some((argct, f)) => {
43-
if args.len() != *argct {
53+
Some(data) => {
54+
if args.len() != data.argct {
4455
return ValidationError::message(format!("Wrong number of args for {}", name));
4556
}
46-
return f(args);
57+
return (data.init)(args);
4758
}
4859
}
4960
}
5061

5162
pub fn labelled_multiple_options(&'static self, prefixes: &[&str]) -> OptionsPile<Vec<(String, R)>> {
5263
let mut opt = OptionsPile::<Vec<(String, R)>>::new();
53-
for (alias, (argct, f)) in &self.map {
64+
for (alias, data) in &self.map {
5465
let aliases: Vec<_> = prefixes.iter().map(|prefix| format!("{}-{}", prefix, alias)).collect();
5566
let aliases: Vec<_> = aliases.iter().map(|s| s as &str).collect();
56-
opt.match_n(&aliases, argct + 1, move |rs, a| {
67+
opt.match_n(&aliases, data.argct + 1, move |rs, a| {
5768
let mut iter = a.iter();
5869
let label = iter.next().unwrap().to_string();
5970
let a: Vec<_> = iter.map(|s| s as &str).collect();
60-
rs.push((label, f(&a)?));
71+
rs.push((label, (data.init)(&a)?));
6172
return Result::Ok(());
6273
}, None);
6374
}
@@ -83,12 +94,12 @@ impl<R: 'static> Registry<R> {
8394

8495
pub fn multiple_options(&'static self, prefixes: &[&str]) -> OptionsPile<Vec<R>> {
8596
let mut opt = OptionsPile::<Vec<R>>::new();
86-
for (alias, (argct, f)) in &self.map {
97+
for (alias, data) in &self.map {
8798
let aliases: Vec<_> = prefixes.iter().map(|prefix| format!("{}-{}", prefix, alias)).collect();
8899
let aliases: Vec<_> = aliases.iter().map(|s| s as &str).collect();
89-
opt.match_n(&aliases, *argct, move |rs, a| {
100+
opt.match_n(&aliases, data.argct, move |rs, a| {
90101
let a: Vec<_> = a.iter().map(|s| s as &str).collect();
91-
rs.push(f(&a)?);
102+
rs.push((data.init)(&a)?);
92103
return Result::Ok(());
93104
}, None);
94105
}
@@ -110,10 +121,10 @@ impl<R: 'static> Registry<R> {
110121

111122
pub fn help_options<X: 'static>(&'static self, type_name: &str) -> OptionsPile<X> {
112123
let mut opt = OptionsPile::<X>::new();
113-
let aliaseses = &self.aliaseses;
124+
let list = &self.list;
114125
opt.match_zero(&[&format!("list-{}", type_name)], move |_p| {
115-
return ValidationError::help(aliaseses.iter().map(|aliases| {
116-
let (first, rest) = aliases.split_first().unwrap();
126+
return ValidationError::help(list.iter().map(|data| {
127+
let (first, rest) = data.names.split_first().unwrap();
117128
let mut line = first.to_string();
118129
if !rest.is_empty() {
119130
line.push_str(&format!(" [{}]", rest.join(", ")));

0 commit comments

Comments
 (0)