@@ -7,57 +7,68 @@ use self::args::RegistryArgs;
77use opts:: parser:: OptionsPile ;
88use opts:: parser:: ToOptionsHelp ;
99use std:: collections:: HashMap ;
10+ use std:: sync:: Arc ;
1011use validates:: ValidationError ;
1112use 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+
1320pub 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
1825impl < 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
2734impl < 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