@@ -2,6 +2,7 @@ use std::{
2
2
borrow:: Cow ,
3
3
collections:: { hash_map:: Entry , HashMap } ,
4
4
fmt:: Debug ,
5
+ hash:: Hash ,
5
6
} ;
6
7
7
8
use super :: { error:: TemplateError , BuiltInFormatter , Error , PatternKind , Result } ;
@@ -89,3 +90,176 @@ impl<F> PatternRegistry<F> {
89
90
}
90
91
}
91
92
}
93
+
94
+ pub fn check_custom_pattern_names < N , I > ( names : I ) -> Result < ( ) >
95
+ where
96
+ N : AsRef < str > + Eq + PartialEq + Hash ,
97
+ I : IntoIterator < Item = N > ,
98
+ {
99
+ let mut seen_names: HashMap < N , usize > = HashMap :: new ( ) ;
100
+ let mut result = Ok ( ( ) ) ;
101
+
102
+ for name in names {
103
+ if let Some ( existing) = BuiltInFormatter :: iter ( ) . find ( |f| f. placeholder ( ) == name. as_ref ( ) )
104
+ {
105
+ result = Error :: push_err (
106
+ result,
107
+ Error :: ConflictName {
108
+ existing : PatternKind :: BuiltIn ( existing) ,
109
+ incoming : PatternKind :: Custom {
110
+ placeholder : Cow :: Owned ( name. as_ref ( ) . into ( ) ) ,
111
+ factory : ( ) ,
112
+ } ,
113
+ } ,
114
+ ) ;
115
+ }
116
+
117
+ if let Some ( seen_count) = seen_names. get_mut ( & name) {
118
+ * seen_count += 1 ;
119
+ if * seen_count == 2 {
120
+ let conflict_pattern = PatternKind :: Custom {
121
+ placeholder : Cow :: Owned ( name. as_ref ( ) . into ( ) ) ,
122
+ factory : ( ) ,
123
+ } ;
124
+ result = Error :: push_err (
125
+ result,
126
+ Error :: ConflictName {
127
+ existing : conflict_pattern. clone ( ) ,
128
+ incoming : conflict_pattern,
129
+ } ,
130
+ ) ;
131
+ }
132
+ } else {
133
+ seen_names. insert ( name, 1 ) ;
134
+ }
135
+ }
136
+
137
+ debug_assert ! ( seen_names. iter( ) . all( |( _, seen_count) | * seen_count == 1 ) || result. is_err( ) ) ;
138
+
139
+ result
140
+ }
141
+
142
+ #[ cfg( test) ]
143
+ mod tests {
144
+ use super :: * ;
145
+ use crate :: pattern_parser:: BuiltInFormatterInner ;
146
+
147
+ #[ test]
148
+ fn custom_pattern_names_checker ( ) {
149
+ use check_custom_pattern_names as check;
150
+
151
+ assert ! ( check( [ "a" , "b" ] ) . is_ok( ) ) ;
152
+ assert_eq ! (
153
+ check( [ "a" , "a" ] ) ,
154
+ Err ( Error :: ConflictName {
155
+ existing: PatternKind :: Custom {
156
+ placeholder: "a" . into( ) ,
157
+ factory: ( )
158
+ } ,
159
+ incoming: PatternKind :: Custom {
160
+ placeholder: "a" . into( ) ,
161
+ factory: ( )
162
+ }
163
+ } )
164
+ ) ;
165
+ assert_eq ! (
166
+ check( [ "a" , "b" , "a" ] ) ,
167
+ Err ( Error :: ConflictName {
168
+ existing: PatternKind :: Custom {
169
+ placeholder: "a" . into( ) ,
170
+ factory: ( )
171
+ } ,
172
+ incoming: PatternKind :: Custom {
173
+ placeholder: "a" . into( ) ,
174
+ factory: ( )
175
+ }
176
+ } )
177
+ ) ;
178
+ assert_eq ! (
179
+ check( [ "date" ] ) ,
180
+ Err ( Error :: ConflictName {
181
+ existing: PatternKind :: BuiltIn ( BuiltInFormatter ( BuiltInFormatterInner :: Date ) ) ,
182
+ incoming: PatternKind :: Custom {
183
+ placeholder: "date" . into( ) ,
184
+ factory: ( )
185
+ }
186
+ } )
187
+ ) ;
188
+ assert_eq ! (
189
+ check( [ "date" , "a" , "a" ] ) ,
190
+ Err ( Error :: Multiple ( vec![
191
+ Error :: ConflictName {
192
+ existing: PatternKind :: BuiltIn ( BuiltInFormatter ( BuiltInFormatterInner :: Date ) ) ,
193
+ incoming: PatternKind :: Custom {
194
+ placeholder: "date" . into( ) ,
195
+ factory: ( )
196
+ }
197
+ } ,
198
+ Error :: ConflictName {
199
+ existing: PatternKind :: Custom {
200
+ placeholder: "a" . into( ) ,
201
+ factory: ( )
202
+ } ,
203
+ incoming: PatternKind :: Custom {
204
+ placeholder: "a" . into( ) ,
205
+ factory: ( )
206
+ }
207
+ }
208
+ ] ) )
209
+ ) ;
210
+ assert_eq ! (
211
+ check( [ "date" , "a" , "a" , "a" ] ) ,
212
+ Err ( Error :: Multiple ( vec![
213
+ Error :: ConflictName {
214
+ existing: PatternKind :: BuiltIn ( BuiltInFormatter ( BuiltInFormatterInner :: Date ) ) ,
215
+ incoming: PatternKind :: Custom {
216
+ placeholder: "date" . into( ) ,
217
+ factory: ( )
218
+ }
219
+ } ,
220
+ Error :: ConflictName {
221
+ existing: PatternKind :: Custom {
222
+ placeholder: "a" . into( ) ,
223
+ factory: ( )
224
+ } ,
225
+ incoming: PatternKind :: Custom {
226
+ placeholder: "a" . into( ) ,
227
+ factory: ( )
228
+ }
229
+ }
230
+ ] ) )
231
+ ) ;
232
+ assert_eq ! (
233
+ check( [ "b" , "date" , "a" , "b" , "a" , "a" ] ) ,
234
+ Err ( Error :: Multiple ( vec![
235
+ Error :: ConflictName {
236
+ existing: PatternKind :: BuiltIn ( BuiltInFormatter ( BuiltInFormatterInner :: Date ) ) ,
237
+ incoming: PatternKind :: Custom {
238
+ placeholder: "date" . into( ) ,
239
+ factory: ( )
240
+ }
241
+ } ,
242
+ Error :: ConflictName {
243
+ existing: PatternKind :: Custom {
244
+ placeholder: "b" . into( ) ,
245
+ factory: ( )
246
+ } ,
247
+ incoming: PatternKind :: Custom {
248
+ placeholder: "b" . into( ) ,
249
+ factory: ( )
250
+ }
251
+ } ,
252
+ Error :: ConflictName {
253
+ existing: PatternKind :: Custom {
254
+ placeholder: "a" . into( ) ,
255
+ factory: ( )
256
+ } ,
257
+ incoming: PatternKind :: Custom {
258
+ placeholder: "a" . into( ) ,
259
+ factory: ( )
260
+ }
261
+ }
262
+ ] ) )
263
+ ) ;
264
+ }
265
+ }
0 commit comments