@@ -153,24 +153,28 @@ impl<'a> UrlBuilder<'a> {
153
153
154
154
/// Build the AST for an allocated url from the path literals and params.
155
155
fn build_owned ( self ) -> syn:: Block {
156
- let lit_len_expr = Self :: literal_length_expr ( & self . path ) ;
156
+
157
157
158
158
// collection of let {name}_str = [self.]{name}.[join(",")|to_string()];
159
159
let let_params_exprs = Self :: let_parameters_exprs ( & self . path , & self . parts ) ;
160
160
161
- let mut params_len_exprs = Self :: parameter_length_exprs ( & self . path , self . parts ) ;
162
-
163
- let mut len_exprs = vec ! [ lit_len_expr] ;
164
- len_exprs. append ( & mut params_len_exprs) ;
165
- let len_expr = Self :: summed_length_expr ( len_exprs) ;
161
+ let mut let_encoded_params_exprs = Self :: let_encoded_exprs ( & self . path , & self . parts ) ;
166
162
167
163
let url_ident = ident ( "p" ) ;
164
+ let len_expr = {
165
+ let lit_len_expr = Self :: literal_length_expr ( & self . path ) ;
166
+ let mut params_len_exprs = Self :: parameter_length_exprs ( & self . path ) ;
167
+ let mut len_exprs = vec ! [ lit_len_expr] ;
168
+ len_exprs. append ( & mut params_len_exprs) ;
169
+ Self :: summed_length_expr ( len_exprs)
170
+ } ;
168
171
let let_stmt = Self :: let_p_stmt ( url_ident. clone ( ) , len_expr) ;
169
172
170
- let mut push_stmts = Self :: push_str_stmts ( url_ident. clone ( ) , & self . path , self . parts ) ;
173
+ let mut push_stmts = Self :: push_str_stmts ( url_ident. clone ( ) , & self . path ) ;
171
174
let return_expr = syn:: Stmt :: Expr ( Box :: new ( parse_expr ( quote ! ( #url_ident. into( ) ) ) ) ) ;
172
175
173
176
let mut stmts = let_params_exprs;
177
+ stmts. append ( & mut let_encoded_params_exprs) ;
174
178
stmts. push ( let_stmt) ;
175
179
stmts. append ( & mut push_stmts) ;
176
180
stmts. push ( return_expr) ;
@@ -206,6 +210,55 @@ impl<'a> UrlBuilder<'a> {
206
210
syn:: ExprKind :: Lit ( syn:: Lit :: Int ( len as u64 , syn:: IntTy :: Usize ) ) . into ( )
207
211
}
208
212
213
+ /// Creates the AST for a let expression to percent encode path parts
214
+ fn let_encoded_exprs (
215
+ url : & [ PathPart < ' a > ] ,
216
+ parts : & BTreeMap < String , Type > ,
217
+ ) -> Vec < syn:: Stmt > {
218
+ url. iter ( )
219
+ . filter_map ( |p| match * p {
220
+ PathPart :: Param ( p) => {
221
+ let name = valid_name ( p) ;
222
+ let path_expr = match & parts[ p] . ty {
223
+ TypeKind :: String => path_none ( name) . into_expr ( ) ,
224
+ _ => path_none ( format ! ( "{}_str" , name) . as_str ( ) ) . into_expr ( )
225
+ } ;
226
+
227
+ let encoded_ident = ident ( format ! ( "encoded_{}" , name) ) ;
228
+ let percent_encode_call: syn:: Expr = syn:: ExprKind :: Call (
229
+ Box :: new ( path_none ( "percent_encode" ) . into_expr ( ) ) ,
230
+ vec ! [
231
+ syn:: ExprKind :: MethodCall (
232
+ ident( "as_bytes" ) ,
233
+ vec![ ] ,
234
+ vec![ path_expr]
235
+ ) . into( ) ,
236
+ path_none( "PARTS_ENCODED" ) . into_expr( )
237
+ ] ,
238
+ ) . into ( ) ;
239
+
240
+ let into_call: syn:: Expr = syn:: ExprKind :: MethodCall (
241
+ ident ( "into" ) ,
242
+ vec ! [ ] ,
243
+ vec ! [ percent_encode_call]
244
+ ) . into ( ) ;
245
+
246
+ Some ( syn:: Stmt :: Local ( Box :: new ( syn:: Local {
247
+ pat : Box :: new ( syn:: Pat :: Ident (
248
+ syn:: BindingMode :: ByValue ( syn:: Mutability :: Immutable ) ,
249
+ encoded_ident,
250
+ None ,
251
+ ) ) ,
252
+ ty : Some ( Box :: new ( ty_path ( "Cow" , vec ! [ ] , vec ! [ ty( "str" ) ] ) ) ) ,
253
+ init : Some ( Box :: new ( into_call) ) ,
254
+ attrs : vec ! [ ] ,
255
+ } ) ) )
256
+ }
257
+ _ => None ,
258
+ } )
259
+ . collect ( )
260
+ }
261
+
209
262
/// Creates the AST for a let expression for path parts
210
263
fn let_parameters_exprs (
211
264
url : & [ PathPart < ' a > ] ,
@@ -216,8 +269,7 @@ impl<'a> UrlBuilder<'a> {
216
269
PathPart :: Param ( p) => {
217
270
let name = valid_name ( p) ;
218
271
let name_ident = ident ( & name) ;
219
- let k = p. to_string ( ) ;
220
- let ty = & parts[ & k] . ty ;
272
+ let ty = & parts[ p] . ty ;
221
273
222
274
// don't generate an assignment expression for strings
223
275
if ty == & TypeKind :: String {
@@ -279,21 +331,16 @@ impl<'a> UrlBuilder<'a> {
279
331
/// Get an expression to find the number of chars in each parameter part for the url.
280
332
fn parameter_length_exprs (
281
333
url : & [ PathPart < ' a > ] ,
282
- parts : & BTreeMap < String , Type > ,
283
334
) -> Vec < syn:: Expr > {
284
335
url. iter ( )
285
336
. filter_map ( |p| match * p {
286
337
PathPart :: Param ( p) => {
287
- let name = match parts[ & p. to_string ( ) ] . ty {
288
- TypeKind :: String => valid_name ( p) . into ( ) ,
289
- // handle lists and enums
290
- _ => format ! ( "{}_str" , valid_name( p) ) ,
291
- } ;
338
+ let name = format ! ( "encoded_{}" , valid_name( p) ) ;
292
339
Some (
293
340
syn:: ExprKind :: MethodCall (
294
341
ident ( "len" ) ,
295
342
vec ! [ ] ,
296
- vec ! [ syn :: ExprKind :: Path ( None , path_none( name. as_ref( ) ) ) . into ( ) ] ,
343
+ vec ! [ path_none( name. as_ref( ) ) . into_expr ( ) ] ,
297
344
)
298
345
. into ( ) ,
299
346
)
@@ -351,8 +398,7 @@ impl<'a> UrlBuilder<'a> {
351
398
/// Get a list of statements that append each part to a `String` in order.
352
399
fn push_str_stmts (
353
400
url_ident : syn:: Ident ,
354
- url : & [ PathPart < ' a > ] ,
355
- parts : & BTreeMap < String , Type > ,
401
+ url : & [ PathPart < ' a > ]
356
402
) -> Vec < syn:: Stmt > {
357
403
url. iter ( )
358
404
. map ( |p| match * p {
@@ -361,11 +407,7 @@ impl<'a> UrlBuilder<'a> {
361
407
syn:: Stmt :: Semi ( Box :: new ( parse_expr ( quote ! ( #url_ident. push_str( #lit) ) ) ) )
362
408
}
363
409
PathPart :: Param ( p) => {
364
- let name = match parts[ & p. to_string ( ) ] . ty {
365
- TypeKind :: String => valid_name ( p) . into ( ) ,
366
- // handle lists and enums
367
- _ => format ! ( "{}_str" , valid_name( p) ) ,
368
- } ;
410
+ let name = format ! ( "encoded_{}" , valid_name( p) ) ;
369
411
let ident = ident ( name) ;
370
412
syn:: Stmt :: Semi ( Box :: new ( parse_expr (
371
413
quote ! ( #url_ident. push_str( #ident. as_ref( ) ) ) ,
0 commit comments