@@ -16,56 +16,87 @@ impl SliceArgFinder {
16
16
pub fn feed ( & mut self , idx : usize , arg : & Field ) {
17
17
self . state = match self . state . take ( ) {
18
18
None => match arg. slice_arg_eligibility ( ) {
19
- SliceArgEligibility :: NotEligible => {
20
- if arg. can_be_slice_arg_len ( ) {
21
- Some ( SliceArgFinderState :: LenArgFound ( idx) )
22
- } else {
23
- None
24
- }
25
- }
26
- SliceArgEligibility :: Eligible => Some ( SliceArgFinderState :: SliceArgFound ( idx) ) ,
27
- SliceArgEligibility :: EligibleWithMultiple => Some ( SliceArgFinderState :: SliceArgWithPotentialMultipleFound ( vec ! [ idx] ) ) ,
19
+ SliceArgEligibility :: None => None ,
20
+ SliceArgEligibility :: SliceArgLength => Some ( SliceArgFinderState :: LenArgFound ( idx) ) ,
21
+ SliceArgEligibility :: SliceArgSingle => Some ( SliceArgFinderState :: SliceArgFound ( idx) ) ,
22
+ SliceArgEligibility :: SliceArgMultiple => Some ( SliceArgFinderState :: SliceArgWithPotentialMultipleFound ( vec ! [ idx] ) ) ,
28
23
} ,
29
- Some ( SliceArgFinderState :: SliceArgFound ( slice_arg_idx) ) => {
30
- if arg. can_be_slice_arg_len ( ) {
24
+ Some ( SliceArgFinderState :: SliceArgFound ( slice_arg_idx) ) => match arg. slice_arg_eligibility ( ) {
25
+ SliceArgEligibility :: None => Some ( SliceArgFinderState :: SliceArgFound ( slice_arg_idx) ) ,
26
+ SliceArgEligibility :: SliceArgLength => {
31
27
self . slice_args . push ( ( vec ! [ slice_arg_idx] , idx) ) ;
32
28
None
33
- } else {
34
- Some ( SliceArgFinderState :: SliceArgFound ( slice_arg_idx) )
35
29
}
36
- }
30
+ SliceArgEligibility :: SliceArgSingle => Some ( SliceArgFinderState :: SliceArgFound ( idx) ) ,
31
+ SliceArgEligibility :: SliceArgMultiple => Some ( SliceArgFinderState :: SliceArgWithPotentialMultipleFound ( vec ! [
32
+ slice_arg_idx,
33
+ idx,
34
+ ] ) ) ,
35
+ } ,
37
36
Some ( SliceArgFinderState :: SliceArgWithPotentialMultipleFound ( mut slice_arg_indices) ) => {
38
37
match arg. slice_arg_eligibility ( ) {
39
- SliceArgEligibility :: NotEligible if arg . can_be_slice_arg_len ( ) => {
38
+ SliceArgEligibility :: SliceArgLength => {
40
39
self . slice_args . push ( ( slice_arg_indices, idx) ) ;
41
40
None
42
41
}
43
42
// multiple slice arguments are consecutive
44
- SliceArgEligibility :: NotEligible | SliceArgEligibility :: Eligible => {
43
+ SliceArgEligibility :: None | SliceArgEligibility :: SliceArgSingle => {
45
44
slice_arg_indices. into_iter ( ) . next ( ) . map ( SliceArgFinderState :: SliceArgFound )
46
45
} // todo: try `idx`
47
- SliceArgEligibility :: EligibleWithMultiple => {
46
+ SliceArgEligibility :: SliceArgMultiple => {
48
47
slice_arg_indices. push ( idx) ;
49
48
Some ( SliceArgFinderState :: SliceArgWithPotentialMultipleFound ( slice_arg_indices) )
50
49
}
51
50
}
52
51
}
53
- Some ( SliceArgFinderState :: LenArgFound ( slice_len_arg_idx) ) => match arg. slice_arg_eligibility ( ) {
54
- SliceArgEligibility :: NotEligible => Some ( SliceArgFinderState :: LenArgFound ( slice_len_arg_idx) ) ,
55
- SliceArgEligibility :: Eligible => {
56
- self . slice_args . push ( ( vec ! [ idx] , slice_len_arg_idx) ) ;
57
- None
52
+ Some ( SliceArgFinderState :: SliceArgWithPotentialMultipleAndLenFound ( mut slice_arg_indices, slice_len_arg_idx) ) => {
53
+ match arg. slice_arg_eligibility ( ) {
54
+ SliceArgEligibility :: None => {
55
+ self . slice_args . push ( ( slice_arg_indices, slice_len_arg_idx) ) ;
56
+ None
57
+ }
58
+ SliceArgEligibility :: SliceArgLength => {
59
+ self . slice_args . push ( ( slice_arg_indices, slice_len_arg_idx) ) ;
60
+ Some ( SliceArgFinderState :: LenArgFound ( idx) )
61
+ }
62
+ SliceArgEligibility :: SliceArgSingle => {
63
+ self . slice_args . push ( ( slice_arg_indices, slice_len_arg_idx) ) ;
64
+ Some ( SliceArgFinderState :: SliceArgFound ( idx) )
65
+ }
66
+ SliceArgEligibility :: SliceArgMultiple => {
67
+ slice_arg_indices. push ( idx) ;
68
+ Some ( SliceArgFinderState :: SliceArgWithPotentialMultipleAndLenFound (
69
+ slice_arg_indices,
70
+ slice_len_arg_idx,
71
+ ) )
72
+ }
58
73
}
59
- SliceArgEligibility :: EligibleWithMultiple => {
60
- // fixme: case where slice len argument comes before 2 slice arguments is not handled
74
+ }
75
+ Some ( SliceArgFinderState :: LenArgFound ( slice_len_arg_idx) ) => match arg. slice_arg_eligibility ( ) {
76
+ SliceArgEligibility :: None => Some ( SliceArgFinderState :: LenArgFound ( slice_len_arg_idx) ) ,
77
+ SliceArgEligibility :: SliceArgLength => Some ( SliceArgFinderState :: LenArgFound ( idx) ) ,
78
+ SliceArgEligibility :: SliceArgSingle => {
61
79
self . slice_args . push ( ( vec ! [ idx] , slice_len_arg_idx) ) ;
62
80
None
63
81
}
82
+ SliceArgEligibility :: SliceArgMultiple => Some ( SliceArgFinderState :: SliceArgWithPotentialMultipleAndLenFound (
83
+ vec ! [ idx] ,
84
+ slice_len_arg_idx,
85
+ ) ) ,
64
86
} ,
65
87
} ;
66
88
}
67
89
68
- pub fn finish ( self ) -> Vec < ( Vec < usize > , usize ) > {
90
+ pub fn finish ( mut self ) -> Vec < ( Vec < usize > , usize ) > {
91
+ match self . state {
92
+ None
93
+ | Some ( SliceArgFinderState :: LenArgFound ( _) )
94
+ | Some ( SliceArgFinderState :: SliceArgFound ( _) )
95
+ | Some ( SliceArgFinderState :: SliceArgWithPotentialMultipleFound ( _) ) => { }
96
+ Some ( SliceArgFinderState :: SliceArgWithPotentialMultipleAndLenFound ( slice_arg_indices, slice_len_arg_idx) ) => {
97
+ self . slice_args . push ( ( slice_arg_indices, slice_len_arg_idx) ) ;
98
+ }
99
+ }
69
100
self . slice_args
70
101
}
71
102
}
@@ -76,5 +107,103 @@ enum SliceArgFinderState {
76
107
SliceArgFound ( usize ) ,
77
108
/// Found a slice argument which might have an additional connected slice arg (e.g. `src`/`dst` which share the same slice length argument)
78
109
SliceArgWithPotentialMultipleFound ( Vec < usize > ) ,
110
+ /// Same as [SliceArgFinderState::SliceArgWithPotentialMultipleFound], but also a length for those arg has also been found
111
+ SliceArgWithPotentialMultipleAndLenFound ( Vec < usize > , usize ) ,
79
112
LenArgFound ( usize ) ,
80
113
}
114
+
115
+ #[ cfg( test) ]
116
+ mod test {
117
+ use super :: SliceArgFinder ;
118
+ use crate :: field:: { Field , FieldDesc } ;
119
+ use crate :: type_ref:: { TypeRef , TypeRefDesc } ;
120
+
121
+ #[ test]
122
+ fn test_slice_arg_finder ( ) {
123
+ // one arg, not slice
124
+ {
125
+ let mut finder = SliceArgFinder :: with_capacity ( 0 ) ;
126
+ finder. feed ( 0 , & Field :: new_desc ( FieldDesc :: new ( "src" , TypeRefDesc :: int ( ) ) ) ) ;
127
+ assert_eq ! ( finder. finish( ) , vec![ ] ) ;
128
+ }
129
+
130
+ // slice len after
131
+ {
132
+ let mut finder = SliceArgFinder :: with_capacity ( 0 ) ;
133
+ finder. feed (
134
+ 0 ,
135
+ & Field :: new_desc ( FieldDesc :: new ( "dims" , TypeRef :: new_pointer ( TypeRefDesc :: float ( ) ) ) ) ,
136
+ ) ;
137
+ finder. feed ( 1 , & Field :: new_desc ( FieldDesc :: new ( "ndims" , TypeRefDesc :: size_t ( ) ) ) ) ;
138
+ assert_eq ! ( finder. finish( ) , vec![ ( vec![ 0 ] , 1 ) ] ) ;
139
+ }
140
+
141
+ // slice len first
142
+ {
143
+ let mut finder = SliceArgFinder :: with_capacity ( 0 ) ;
144
+ finder. feed ( 0 , & Field :: new_desc ( FieldDesc :: new ( "argc" , TypeRefDesc :: int ( ) ) ) ) ;
145
+ finder. feed (
146
+ 1 ,
147
+ & Field :: new_desc ( FieldDesc :: new ( "argv" , TypeRef :: new_array ( TypeRefDesc :: char_ptr ( ) , None ) ) ) ,
148
+ ) ;
149
+ assert_eq ! ( finder. finish( ) , vec![ ( vec![ 1 ] , 0 ) ] ) ;
150
+ }
151
+
152
+ // slice name prevents eligibility
153
+ {
154
+ let mut finder = SliceArgFinder :: with_capacity ( 0 ) ;
155
+ finder. feed (
156
+ 0 ,
157
+ & Field :: new_desc ( FieldDesc :: new ( "rmsd" , TypeRef :: new_pointer ( TypeRefDesc :: float ( ) ) ) ) ,
158
+ ) ;
159
+ finder. feed ( 1 , & Field :: new_desc ( FieldDesc :: new ( "ndims" , TypeRefDesc :: size_t ( ) ) ) ) ;
160
+ assert_eq ! ( finder. finish( ) , vec![ ] ) ;
161
+ }
162
+
163
+ // 2 slices with 1 length, size first
164
+ {
165
+ let mut finder = SliceArgFinder :: with_capacity ( 0 ) ;
166
+ finder. feed ( 0 , & Field :: new_desc ( FieldDesc :: new ( "abSize" , TypeRefDesc :: int ( ) ) ) ) ;
167
+ finder. feed (
168
+ 1 ,
169
+ & Field :: new_desc ( FieldDesc :: new ( "a" , TypeRef :: new_pointer ( TypeRefDesc :: float ( ) ) ) ) ,
170
+ ) ;
171
+ finder. feed (
172
+ 2 ,
173
+ & Field :: new_desc ( FieldDesc :: new ( "b" , TypeRef :: new_pointer ( TypeRefDesc :: int ( ) ) ) ) ,
174
+ ) ;
175
+ assert_eq ! ( finder. finish( ) , vec![ ( vec![ 1 , 2 ] , 0 ) ] ) ;
176
+ }
177
+
178
+ // 2 slices with 1 length, size last
179
+ {
180
+ let mut finder = SliceArgFinder :: with_capacity ( 0 ) ;
181
+ finder. feed (
182
+ 0 ,
183
+ & Field :: new_desc ( FieldDesc :: new ( "a" , TypeRef :: new_pointer ( TypeRefDesc :: float ( ) ) ) ) ,
184
+ ) ;
185
+ finder. feed (
186
+ 1 ,
187
+ & Field :: new_desc ( FieldDesc :: new ( "b" , TypeRef :: new_pointer ( TypeRefDesc :: int ( ) ) ) ) ,
188
+ ) ;
189
+ finder. feed ( 2 , & Field :: new_desc ( FieldDesc :: new ( "abSize" , TypeRefDesc :: int ( ) ) ) ) ;
190
+ assert_eq ! ( finder. finish( ) , vec![ ( vec![ 0 , 1 ] , 2 ) ] ) ;
191
+ }
192
+
193
+ // 2 sets of slices with lengths
194
+ {
195
+ let mut finder = SliceArgFinder :: with_capacity ( 0 ) ;
196
+ finder. feed (
197
+ 0 ,
198
+ & Field :: new_desc ( FieldDesc :: new ( "a" , TypeRef :: new_pointer ( TypeRefDesc :: float ( ) ) ) ) ,
199
+ ) ;
200
+ finder. feed ( 1 , & Field :: new_desc ( FieldDesc :: new ( "aSize" , TypeRefDesc :: int ( ) ) ) ) ;
201
+ finder. feed (
202
+ 2 ,
203
+ & Field :: new_desc ( FieldDesc :: new ( "b" , TypeRef :: new_pointer ( TypeRefDesc :: uint64_t ( ) ) ) ) ,
204
+ ) ;
205
+ finder. feed ( 3 , & Field :: new_desc ( FieldDesc :: new ( "len" , TypeRefDesc :: int ( ) ) ) ) ;
206
+ assert_eq ! ( finder. finish( ) , vec![ ( vec![ 0 ] , 1 ) , ( vec![ 2 ] , 3 ) ] ) ;
207
+ }
208
+ }
209
+ }
0 commit comments