@azure-tools/typespec-rust 0.33.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/src/codegen/clients.d.ts.map +1 -1
  2. package/dist/src/codegen/clients.js +120 -93
  3. package/dist/src/codegen/clients.js.map +1 -1
  4. package/dist/src/codegen/codeGenerator.js +16 -16
  5. package/dist/src/codegen/codeGenerator.js.map +1 -1
  6. package/dist/src/codegen/context.js +1 -1
  7. package/dist/src/codegen/context.js.map +1 -1
  8. package/dist/src/codegen/enums.d.ts +5 -5
  9. package/dist/src/codegen/enums.d.ts.map +1 -1
  10. package/dist/src/codegen/enums.js +10 -6
  11. package/dist/src/codegen/enums.js.map +1 -1
  12. package/dist/src/codegen/headerTraits.d.ts.map +1 -1
  13. package/dist/src/codegen/headerTraits.js +5 -3
  14. package/dist/src/codegen/headerTraits.js.map +1 -1
  15. package/dist/src/codegen/helpers.d.ts +23 -0
  16. package/dist/src/codegen/helpers.d.ts.map +1 -1
  17. package/dist/src/codegen/helpers.js +38 -18
  18. package/dist/src/codegen/helpers.js.map +1 -1
  19. package/dist/src/codegen/mod.d.ts.map +1 -1
  20. package/dist/src/codegen/mod.js +4 -2
  21. package/dist/src/codegen/mod.js.map +1 -1
  22. package/dist/src/codegen/models.d.ts +4 -6
  23. package/dist/src/codegen/models.d.ts.map +1 -1
  24. package/dist/src/codegen/models.js +170 -70
  25. package/dist/src/codegen/models.js.map +1 -1
  26. package/dist/src/codegen/unions.d.ts +8 -6
  27. package/dist/src/codegen/unions.d.ts.map +1 -1
  28. package/dist/src/codegen/unions.js +142 -9
  29. package/dist/src/codegen/unions.js.map +1 -1
  30. package/dist/src/codegen/use.d.ts +1 -19
  31. package/dist/src/codegen/use.d.ts.map +1 -1
  32. package/dist/src/codegen/use.js +7 -41
  33. package/dist/src/codegen/use.js.map +1 -1
  34. package/dist/src/codemodel/client.d.ts +5 -3
  35. package/dist/src/codemodel/client.d.ts.map +1 -1
  36. package/dist/src/codemodel/client.js +1 -1
  37. package/dist/src/codemodel/client.js.map +1 -1
  38. package/dist/src/codemodel/crate.d.ts +1 -1
  39. package/dist/src/codemodel/crate.d.ts.map +1 -1
  40. package/dist/src/codemodel/customizations.d.ts +12 -0
  41. package/dist/src/codemodel/customizations.d.ts.map +1 -0
  42. package/dist/src/codemodel/customizations.js +13 -0
  43. package/dist/src/codemodel/customizations.js.map +1 -0
  44. package/dist/src/codemodel/index.d.ts +1 -0
  45. package/dist/src/codemodel/index.d.ts.map +1 -1
  46. package/dist/src/codemodel/index.js +1 -0
  47. package/dist/src/codemodel/index.js.map +1 -1
  48. package/dist/src/codemodel/types.d.ts +38 -4
  49. package/dist/src/codemodel/types.d.ts.map +1 -1
  50. package/dist/src/codemodel/types.js +24 -0
  51. package/dist/src/codemodel/types.js.map +1 -1
  52. package/dist/src/tcgcadapter/adapter.d.ts +7 -2
  53. package/dist/src/tcgcadapter/adapter.d.ts.map +1 -1
  54. package/dist/src/tcgcadapter/adapter.js +266 -173
  55. package/dist/src/tcgcadapter/adapter.js.map +1 -1
  56. package/dist/src/tcgcadapter/naming.d.ts.map +1 -1
  57. package/dist/src/tcgcadapter/naming.js +2 -2
  58. package/dist/src/tcgcadapter/naming.js.map +1 -1
  59. package/dist/src/utils/utils.d.ts +99 -0
  60. package/dist/src/utils/utils.d.ts.map +1 -0
  61. package/dist/src/utils/utils.js +288 -0
  62. package/dist/src/utils/utils.js.map +1 -0
  63. package/package.json +16 -19
  64. package/dist/src/shared/shared.d.ts +0 -29
  65. package/dist/src/shared/shared.d.ts.map +0 -1
  66. package/dist/src/shared/shared.js +0 -109
  67. package/dist/src/shared/shared.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../../src/codegen/clients.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAGxC,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAG9C,yBAAyB;AACzB,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAE/B,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,aAAa,GAAG,SAAS,CAuRxE"}
1
+ {"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../../src/codegen/clients.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAGxC,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAG9C,yBAAyB;AACzB,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAE/B,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,aAAa,GAAG,SAAS,CA+RxE"}
@@ -3,15 +3,13 @@
3
3
  * Licensed under the MIT License. See License.txt in the project root for license information.
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  // cspell: ignore conv
6
- import * as codegen from '@azure-tools/codegen';
7
- import { values } from '@azure-tools/linq';
8
6
  import { emitHeaderTraitDocExample } from './docTests.js';
9
7
  import { CodegenError } from './errors.js';
10
8
  import * as helpers from './helpers.js';
11
9
  import queryString from 'query-string';
12
10
  import { Use } from './use.js';
13
11
  import * as rust from '../codemodel/index.js';
14
- import * as shared from '../shared/shared.js';
12
+ import * as utils from '../utils/utils.js';
15
13
  /**
16
14
  * emits the content for all client files
17
15
  *
@@ -26,9 +24,13 @@ export function emitClients(crate) {
26
24
  const clientOptionsImplDefault = function (constructable) {
27
25
  // only implement Default when there's more than one field (i.e. more than just client_options)
28
26
  // and the field(s) contain a client default value.
29
- return !constructable.suppressed && constructable.options.type.fields.length > 1 && values(constructable.options.type.fields)
30
- .where((field) => field.name !== 'client_options')
31
- .where((field) => field.defaultValue !== undefined).any();
27
+ if (constructable.suppressed === 'yes') {
28
+ return false;
29
+ }
30
+ const optionsType = constructable.options.type;
31
+ return optionsType.fields.length > 1 && optionsType.fields.some((field) => {
32
+ return field.name !== 'client_options' && field.defaultValue !== undefined;
33
+ });
32
34
  };
33
35
  const clientModules = new Array();
34
36
  // emit the clients, one file per client
@@ -44,7 +46,7 @@ export function emitClients(crate) {
44
46
  body += `${indent.get()}${helpers.emitVisibility(field.visibility)}${field.name}: ${helpers.getTypeDeclaration(field.type)},\n`;
45
47
  }
46
48
  body += '}\n\n'; // end client
47
- if (client.constructable && !client.constructable.suppressed) {
49
+ if (client.constructable && client.constructable.suppressed !== 'yes') {
48
50
  // if client options doesn't require an impl for Default then just derive it
49
51
  let deriveDefault = 'Default, ';
50
52
  if (clientOptionsImplDefault(client.constructable)) {
@@ -68,7 +70,7 @@ export function emitClients(crate) {
68
70
  }
69
71
  }
70
72
  body += `impl ${client.name} {\n`;
71
- if (client.constructable && !client.constructable.suppressed) {
73
+ if (client.constructable && client.constructable.suppressed === 'no') {
72
74
  // this is an instantiable client, so we need to emit client options and constructors
73
75
  use.add('azure_core', 'Result');
74
76
  for (let i = 0; i < client.constructable.constructors.length; ++i) {
@@ -113,9 +115,9 @@ export function emitClients(crate) {
113
115
  // propagate the required client params to the initializer
114
116
  // NOTE: we do this on a sorted copy of the client params as we must preserve their order.
115
117
  // exclude endpoint params as they aren't propagated to clients (they're consumed when creating the complete endpoint)
116
- const sortedParams = values([...constructor.params]
117
- .sort((a, b) => { return helpers.sortAscending(a.name, b.name); }))
118
- .where((each) => each.kind !== 'clientSupplementalEndpoint' && each.kind !== 'clientCredential').toArray();
118
+ const sortedParams = [...constructor.params]
119
+ .filter((each) => each.kind !== 'clientSupplementalEndpoint' && each.kind !== 'clientCredential')
120
+ .sort((a, b) => { return helpers.sortAscending(a.name, b.name); });
119
121
  for (const param of sortedParams) {
120
122
  if (param.optional) {
121
123
  continue;
@@ -260,8 +262,12 @@ export function emitClients(crate) {
260
262
  let content = helpers.contentPreamble();
261
263
  content += use.text();
262
264
  content += body;
263
- const clientMod = codegen.deconstruct(client.name).join('_');
264
- clientModules.push({ name: clientMod, content: content });
265
+ const clientMod = utils.deconstruct(client.name).join('_');
266
+ clientModules.push({
267
+ name: clientMod,
268
+ content: content,
269
+ visibility: 'pubUse',
270
+ });
265
271
  }
266
272
  return {
267
273
  modules: clientModules,
@@ -271,6 +277,7 @@ export function emitClients(crate) {
271
277
  function getMethodOptions(crate) {
272
278
  const use = new Use('modelsOther');
273
279
  const indent = new helpers.indentation();
280
+ const visTracker = new helpers.VisibilityTracker();
274
281
  let body = '';
275
282
  for (const client of crate.clients) {
276
283
  for (let i = 0; i < client.methods.length; ++i) {
@@ -281,7 +288,8 @@ function getMethodOptions(crate) {
281
288
  body += helpers.formatDocComment(method.options.type.docs);
282
289
  use.add('azure_core::fmt', 'SafeDebug');
283
290
  body += '#[derive(Clone, Default, SafeDebug)]\n';
284
- body += `${helpers.emitVisibility(method.visibility)}struct ${helpers.getTypeDeclaration(method.options.type)} {\n`;
291
+ body += `${helpers.emitVisibility(method.options.type.visibility)}struct ${helpers.getTypeDeclaration(method.options.type)} {\n`;
292
+ visTracker.update(method.options.type.visibility);
285
293
  for (let i = 0; i < method.options.type.fields.length; ++i) {
286
294
  const field = method.options.type.fields[i];
287
295
  use.addForType(field.type);
@@ -327,6 +335,7 @@ function getMethodOptions(crate) {
327
335
  return {
328
336
  name: 'method_options',
329
337
  content: content,
338
+ visibility: visTracker.get(),
330
339
  };
331
340
  }
332
341
  /**
@@ -491,7 +500,7 @@ function getHeaderTraitDocComment(indent, crate, method) {
491
500
  */
492
501
  function getAuthPolicy(ctor, use) {
493
502
  for (const param of ctor.params) {
494
- const arcTokenCred = shared.asTypeOf(param.type, 'tokenCredential', 'arc');
503
+ const arcTokenCred = utils.asTypeOf(param.type, 'tokenCredential', 'arc');
495
504
  if (arcTokenCred) {
496
505
  use.add('azure_core::http::policies', 'auth::BearerTokenAuthorizationPolicy', 'Policy');
497
506
  const scopes = new Array();
@@ -816,7 +825,7 @@ function constructUrl(indent, use, method, paramGroups, urlVarName) {
816
825
  const valueVar = queryParam.name[0];
817
826
  let text = `${indent.get()}for ${valueVar} in ${queryParam.name}.iter() {\n`;
818
827
  // if queryParam is a &[&str] then we'll need to deref the iterator
819
- const deref = shared.asTypeOf(queryParam.type, 'str', 'ref', 'slice', 'ref') ? '*' : '';
828
+ const deref = utils.asTypeOf(queryParam.type, 'str', 'ref', 'slice', 'ref') ? '*' : '';
820
829
  text += `${indent.push().get()}query_builder.append_pair("${queryParam.key}", ${deref}${getHeaderPathQueryParamValue(use, queryParam, !queryParam.optional, false, valueVar)});\n`;
821
830
  text += `${indent.pop().get()}}\n`;
822
831
  return text;
@@ -873,7 +882,7 @@ function applyHeaderParams(indent, use, method, paramGroups, inClosure, requestV
873
882
  body += `${indent.get()}let ${headerParam.name} = ` + helpers.buildMatch(indent, headerParam.name, [
874
883
  {
875
884
  pattern: `PagerState::More(${headerParam.name})`,
876
- body: (indent) => `${indent.get()}&Some(${headerParam.name})\n`,
885
+ body: (indent) => `${indent.get()}&Some(${headerParam.name}.into())\n`,
877
886
  },
878
887
  {
879
888
  pattern: 'PagerState::Initial',
@@ -927,7 +936,7 @@ function constructRequest(indent, use, method, paramGroups, inClosure, urlVarNam
927
936
  // when constructing the request var name we need to ensure
928
937
  // that it doesn't collide with any parameter name.
929
938
  const requestVarName = helpers.getUniqueVarName(method.params, ['request', 'core_req']);
930
- let body = `${indent.get()}let ${(forceMut || paramGroups.header.length > 0) ? 'mut ' : ''}${requestVarName} = Request::new(${urlVarName}${cloneUrl ? '.clone()' : ''}, Method::${codegen.capitalize(method.httpMethod)});\n`;
939
+ let body = `${indent.get()}let ${(forceMut || paramGroups.header.length > 0) ? 'mut ' : ''}${requestVarName} = Request::new(${urlVarName}${cloneUrl ? '.clone()' : ''}, Method::${utils.capitalize(method.httpMethod)});\n`;
931
940
  body += applyHeaderParams(indent, use, method, paramGroups, inClosure, requestVarName);
932
941
  let optionalContentTypeParam;
933
942
  for (const headerParam of paramGroups.header) {
@@ -1127,7 +1136,7 @@ function getPageableMethodBody(indent, use, client, method) {
1127
1136
  switch (method.strategy.kind) {
1128
1137
  case 'continuationToken': {
1129
1138
  const reqTokenParam = method.strategy.requestToken.name;
1130
- body += `${indent.get()}Ok(${method.returns.type.name}::new(move |${reqTokenParam}: PagerState<String>, pager_options| {\n`;
1139
+ body += `${indent.get()}Ok(${method.returns.type.name}::new(move |${reqTokenParam}: PagerState, pager_options| {\n`;
1131
1140
  body += `${indent.push().get()}let ${method.strategy.requestToken.kind === 'queryScalar' ? 'mut ' : ''}url = first_url.clone();\n`;
1132
1141
  if (method.strategy.requestToken.kind === 'queryScalar') {
1133
1142
  // if the url already contains the token query param,
@@ -1139,7 +1148,7 @@ function getPageableMethodBody(indent, use, client, method) {
1139
1148
  condition: `let PagerState::More(${reqTokenParam}) = ${reqTokenParam}`,
1140
1149
  body: (indent) => {
1141
1150
  return `${indent.get()}let mut query_builder = url.query_builder();\n`
1142
- + `${indent.get()}query_builder.set_pair("${reqTokenValue}", &${reqTokenParam});\n`
1151
+ + `${indent.get()}query_builder.set_pair("${reqTokenValue}", ${reqTokenParam}.as_ref());\n`
1143
1152
  + `${indent.get()}query_builder.build();\n`;
1144
1153
  }
1145
1154
  })}\n`;
@@ -1150,22 +1159,25 @@ function getPageableMethodBody(indent, use, client, method) {
1150
1159
  case 'nextLink': {
1151
1160
  const nextLinkName = method.strategy.nextLinkPath[method.strategy.nextLinkPath.length - 1].name;
1152
1161
  const reinjectedParams = method.strategy.reinjectedParams;
1153
- body += `${indent.get()}Ok(${method.returns.type.name}::new(move |${nextLinkName}: PagerState<Url>, pager_options| {\n`;
1162
+ body += `${indent.get()}Ok(${method.returns.type.name}::new(move |${nextLinkName}: PagerState, pager_options| {\n`;
1154
1163
  body += `${indent.push().get()}let url = ` + helpers.buildMatch(indent, nextLinkName, [{
1155
1164
  pattern: `PagerState::More(${nextLinkName})`,
1156
1165
  body: (indent) => {
1157
- const cloneNextLink = `${indent.get()}let mut ${nextLinkName} = ${nextLinkName}.clone();\n`;
1166
+ const cloneNextLink = `${indent.get()}let mut ${nextLinkName}: Url = ${nextLinkName}.try_into().expect("expected Url");\n`;
1158
1167
  let content = '';
1159
1168
  let hasQueryBuilder = false;
1169
+ let needsTryInto = true;
1160
1170
  if (paramGroups.apiVersion && paramGroups.apiVersion.kind === 'queryScalar') {
1161
1171
  content += cloneNextLink;
1162
1172
  hasQueryBuilder = true;
1173
+ needsTryInto = false;
1163
1174
  use.add('azure_core::http', 'UrlExt');
1164
1175
  content += `${indent.get()}let mut query_builder = ${nextLinkName}.query_builder();\n`;
1165
1176
  content += `${indent.get()}query_builder.set_pair("${paramGroups.apiVersion.key}", &${paramGroups.apiVersion.name});\n`;
1166
1177
  }
1167
1178
  else if (reinjectedParams.length > 0) {
1168
- // if we didn't clone it above, we'll need to clone it for this case
1179
+ // if we didn't try_into above, we'll need to do it for this case
1180
+ needsTryInto = false;
1169
1181
  content += cloneNextLink;
1170
1182
  }
1171
1183
  // add query params for reinjection
@@ -1182,7 +1194,7 @@ function getPageableMethodBody(indent, use, client, method) {
1182
1194
  if (hasQueryBuilder) {
1183
1195
  content += `${indent.get()}query_builder.build();\n`;
1184
1196
  }
1185
- content += `${indent.get()}${nextLinkName}\n`;
1197
+ content += `${indent.get()}${nextLinkName}${needsTryInto ? '.try_into().expect("expected Url")' : ''}\n`;
1186
1198
  return content;
1187
1199
  }
1188
1200
  }, {
@@ -1197,7 +1209,7 @@ function getPageableMethodBody(indent, use, client, method) {
1197
1209
  }
1198
1210
  else {
1199
1211
  // no next link when there's no strategy
1200
- body += `${indent.get()}Ok(${method.returns.type.name}::new(move |_: PagerState<Url>, pager_options| {\n`;
1212
+ body += `${indent.get()}Ok(${method.returns.type.name}::new(move |_: PagerState, pager_options| {\n`;
1201
1213
  indent.push();
1202
1214
  cloneUrl = true;
1203
1215
  srcUrlVar = urlVar;
@@ -1240,6 +1252,7 @@ function getPageableMethodBody(indent, use, client, method) {
1240
1252
  }
1241
1253
  return fullPath;
1242
1254
  };
1255
+ use.add('azure_core::http::pager', 'PagerContinuation');
1243
1256
  let srcNextPage;
1244
1257
  let nextPageValue;
1245
1258
  let continuation;
@@ -1259,13 +1272,13 @@ function getPageableMethodBody(indent, use, client, method) {
1259
1272
  srcNextPage = `rsp.${method.strategy.responseToken.name}()?`;
1260
1273
  break;
1261
1274
  }
1262
- continuation = nextPageValue;
1275
+ continuation = `PagerContinuation::Token(${nextPageValue})`;
1263
1276
  break;
1264
1277
  case 'nextLink': {
1265
1278
  const lastFieldName = method.strategy.nextLinkPath[method.strategy.nextLinkPath.length - 1].name;
1266
1279
  nextPageValue = lastFieldName;
1267
1280
  srcNextPage = `res.${buildNextLinkPath(method.strategy.nextLinkPath)}`;
1268
- continuation = `${lastFieldName}.parse()?`;
1281
+ continuation = `PagerContinuation::Link(${lastFieldName}.parse()?)`;
1269
1282
  break;
1270
1283
  }
1271
1284
  }
@@ -1318,7 +1331,7 @@ function getLroMethodBody(crate, indent, use, client, method) {
1318
1331
  const bodyFormat = helpers.convertResponseFormat(method.returns.type.type.format);
1319
1332
  use.add('azure_core::http', 'Method', 'RawResponse', 'Request', 'Url');
1320
1333
  use.add('azure_core::http::headers', 'RETRY_AFTER', 'X_MS_RETRY_AFTER_MS', 'RETRY_AFTER_MS');
1321
- use.add('azure_core::http::poller', 'get_retry_after', 'PollerResult', 'PollerState', 'PollerStatus', 'StatusMonitor as _');
1334
+ use.add('azure_core::http::poller', 'get_retry_after', 'PollerContinuation', 'PollerResult', 'PollerState', 'PollerStatus', 'StatusMonitor');
1322
1335
  if (pollingStepHeaderName !== undefined || method.finalResultStrategy.kind !== 'originalUri') {
1323
1336
  use.add('azure_core::http::headers', 'HeaderName');
1324
1337
  }
@@ -1335,17 +1348,6 @@ function getLroMethodBody(crate, indent, use, client, method) {
1335
1348
  }
1336
1349
  // we call this eagerly so that we have access to the request var name
1337
1350
  const initialRequestResult = constructRequest(indent, use, method, paramGroups, true, urlVar, true, false);
1338
- const applyApiVersionParam = function (indent, paramGroups, newLinkVarName, existingLinkVarAccessor) {
1339
- var _a;
1340
- if (((_a = paramGroups.apiVersion) === null || _a === void 0 ? void 0 : _a.kind) === 'queryScalar') {
1341
- use.add('azure_core::http', 'UrlExt');
1342
- return `${indent.get()}let mut ${newLinkVarName} = ${existingLinkVarAccessor}.clone();\n`
1343
- + `${indent.get()}let mut query_builder = ${newLinkVarName}.query_builder();\n`
1344
- + `${indent.get()}query_builder.set_pair("${paramGroups.apiVersion.key}", &${paramGroups.apiVersion.name});\n`
1345
- + `${indent.get()}query_builder.build();\n`;
1346
- }
1347
- return '';
1348
- };
1349
1351
  const declareRequest = function (indent, use, method, paramGroups, requestVarName, linkExpr, forceMut, optionsPrefix) {
1350
1352
  let mutRequest = '';
1351
1353
  // if the only header is optional Content-Type it will not be used
@@ -1356,46 +1358,46 @@ function getLroMethodBody(crate, indent, use, client, method) {
1356
1358
  return `${indent.get()}let ${mutRequest}${requestVarName} = Request::new(${linkExpr}, Method::Get);\n`
1357
1359
  + applyHeaderParams(indent, use, method, paramGroups, true, requestVarName, optionsPrefix);
1358
1360
  };
1359
- let stateVarType = 'Url';
1360
- let progressVarName = 'next_link';
1361
- let stateNextLinkAccessor = 'next_link';
1362
- let pollerStateMoreReturn = 'next_link';
1363
- let pollerStateInitialReturn = `${urlVar}.clone()`;
1364
- let pollerStatusInProgressReturn = 'next_link';
1365
- if (method.finalResultStrategy.kind === 'header' && method.finalResultStrategy.headerName !== pollingStepHeaderName) {
1366
- // A case when the initial response contains two headers - one (usually, 'azure-asyncoperation') to poll operation status
1367
- // and another (usually, 'location') to collect the final result. Both values are URLs.
1368
- // But only the initial response will have these headers, i.e. responses from 'azure-asyncoperation' URL won't have the 'location'.
1369
- // Therefore, we need to preserve both URLs and pass them between poller states, up to the moment when the operation status
1370
- // is Succeeded, so that when operation is Succeeded, the poller can send a request to 'location' to collect the result.
1371
- body += `${indent.get()}struct Progress{ next_link: Url, final_link: Url, }`;
1372
- body += `${indent.get()}impl AsRef<str> for Progress{ fn as_ref(&self) -> &str{ self.next_link.as_ref() }}\n`;
1373
- stateVarType = 'Progress';
1374
- progressVarName = 'progress';
1375
- stateNextLinkAccessor = 'progress.next_link';
1376
- pollerStateMoreReturn = 'Progress{next_link, final_link: progress.final_link}';
1377
- pollerStateInitialReturn = `Progress{next_link: ${urlVar}.clone(), final_link: ${urlVar}.clone()}`;
1378
- pollerStatusInProgressReturn = 'Progress{next_link, final_link}';
1379
- }
1380
1361
  body += `${indent.get()}Ok(${method.returns.type.name}::new(\n`;
1381
- body += `${indent.push().get()}move |poller_state: PollerState<${stateVarType}>, poller_options| {\n`;
1382
- body += `${indent.push().get()}let (mut ${initialRequestResult.requestVarName}, ${progressVarName}) = ${helpers.buildMatch(indent, 'poller_state', [{
1383
- pattern: `PollerState::More(${progressVarName})`,
1362
+ body += `${indent.push().get()}move |poller_state: PollerState, poller_options| {\n`;
1363
+ body += `${indent.push().get()}let (mut ${initialRequestResult.requestVarName}, continuation) = ${helpers.buildMatch(indent, 'poller_state', [{
1364
+ pattern: `PollerState::More(continuation)`,
1384
1365
  body: (indent) => {
1385
- return applyApiVersionParam(indent, paramGroups, 'next_link', stateNextLinkAccessor)
1386
- + declareRequest(indent, use, method, paramGroups, initialRequestResult.requestVarName, 'next_link.clone()')
1387
- + `${indent.get()}(${initialRequestResult.requestVarName}, ${pollerStateMoreReturn})\n`;
1366
+ var _a, _b;
1367
+ const mutNextLink = ((_a = paramGroups.apiVersion) === null || _a === void 0 ? void 0 : _a.kind) === 'queryScalar' ? 'mut ' : '';
1368
+ const continuationMatchExpr = (!paramGroups.body && paramGroups.partialBody.length === 0) ? 'continuation.clone()' : 'continuation';
1369
+ let body = `${indent.get()}let (${mutNextLink}next_link, final_link) = ${helpers.buildMatch(indent, continuationMatchExpr, [{
1370
+ pattern: 'PollerContinuation::Links { next_link, final_link }',
1371
+ body: (indent) => `${indent.get()}(next_link, final_link)\n`,
1372
+ }, {
1373
+ pattern: '_',
1374
+ body: (indent) => `${indent.get()}unreachable!()\n`,
1375
+ }])};\n`;
1376
+ if (((_b = paramGroups.apiVersion) === null || _b === void 0 ? void 0 : _b.kind) === 'queryScalar') {
1377
+ use.add('azure_core::http', 'UrlExt');
1378
+ body += `${indent.get()}let mut query_builder = next_link.query_builder();\n`;
1379
+ body += `${indent.get()}query_builder.set_pair("${paramGroups.apiVersion.key}", &${paramGroups.apiVersion.name});\n`;
1380
+ body += `${indent.get()}query_builder.build();\n`;
1381
+ }
1382
+ body += declareRequest(indent, use, method, paramGroups, initialRequestResult.requestVarName, 'next_link.clone()');
1383
+ body += `${indent.get()}(${initialRequestResult.requestVarName}, PollerContinuation::Links { next_link, final_link })\n`;
1384
+ return body;
1388
1385
  },
1389
1386
  }, {
1390
1387
  pattern: 'PollerState::Initial',
1391
1388
  body: (indent) => {
1392
1389
  let body = initialRequestResult.content;
1393
- body += `${indent.get()}(${initialRequestResult.requestVarName}, ${pollerStateInitialReturn})\n`;
1390
+ body += `${indent.get()}(${initialRequestResult.requestVarName}, PollerContinuation::Links { next_link: url.clone(), final_link: None, })\n`;
1394
1391
  return body;
1395
1392
  },
1396
1393
  }])};\n`;
1397
1394
  body += `${indent.get()}let ctx = poller_options.context.clone();\n`;
1398
1395
  body += `${indent.get()}let pipeline = pipeline.clone();\n`;
1396
+ if (method.finalResultStrategy.kind === 'header' && method.finalResultStrategy.headerName !== pollingStepHeaderName) {
1397
+ // Avoid moving the poller closure's captured `url` into the async block.
1398
+ // We shadow it with a per-iteration clone so the outer closure can remain `Fn`.
1399
+ body += `${indent.get()}let url = url.clone();\n`;
1400
+ }
1399
1401
  if (method.finalResultStrategy.kind === 'originalUri') {
1400
1402
  body += `${indent.get()}let final_link = url.clone();\n`;
1401
1403
  for (const headerParam of paramGroups.header.filter(h => h.type.kind !== 'literal' && !isOptionalContentTypeHeader(h))) {
@@ -1460,20 +1462,32 @@ function getLroMethodBody(crate, indent, use, client, method) {
1460
1462
  body += `${indent.pop().get()}}\n`;
1461
1463
  }
1462
1464
  if (pollingStepHeaderName !== undefined) {
1463
- body += `${indent.get()}let next_link = ${helpers.buildMatch(indent, `headers.get_optional_string(&HeaderName::from_static("${pollingStepHeaderName}"))`, [{
1464
- pattern: 'Some(operation_location)',
1465
- body: (indent) => {
1466
- return `${indent.get()}Url::parse(&operation_location)?\n`;
1467
- }
1468
- }, {
1469
- pattern: 'None',
1470
- body: (indent) => {
1471
- return `${indent.get()}${stateNextLinkAccessor}`;
1472
- }
1473
- }])};\n`;
1465
+ body += `${indent.get()}let continuation = ${helpers.buildIfBlock(indent, {
1466
+ condition: `let Some(operation_location) = headers.get_optional_string(&HeaderName::from_static("${pollingStepHeaderName}"))`,
1467
+ body: (indent) => {
1468
+ let body = `${indent.get()}let next_link = Url::parse(&operation_location)?;\n`;
1469
+ body += `${indent.get()}${helpers.buildMatch(indent, 'continuation', [{
1470
+ pattern: 'PollerContinuation::Links { final_link, .. }',
1471
+ body: (indent) => `${indent.get()}PollerContinuation::Links { next_link, final_link }\n`,
1472
+ }, {
1473
+ pattern: '_',
1474
+ body: (indent) => `${indent.get()}unreachable!()\n`,
1475
+ }])}\n`;
1476
+ return body;
1477
+ }
1478
+ }, {
1479
+ body: (indent) => `${indent.get()}continuation\n`
1480
+ })};\n`;
1474
1481
  }
1475
1482
  if (isArmPutLro || isArmPatchLro) {
1476
1483
  use.add('azure_core::http', 'StatusCode');
1484
+ body += `${indent.get()}let next_link = ${helpers.buildMatch(indent, '&continuation', [{
1485
+ pattern: 'PollerContinuation::Links { next_link, .. }',
1486
+ body: (indent) => `${indent.get()}next_link\n`,
1487
+ }, {
1488
+ pattern: '_',
1489
+ body: (indent) => `${indent.get()}unreachable!()\n`,
1490
+ }])};\n`;
1477
1491
  body += `${indent.get()}let mut final_body = None;\n`;
1478
1492
  body += `${indent.get()}if status == StatusCode::Ok && next_link.as_str() == original_url.as_str() {\n`;
1479
1493
  body += `${indent.push().get()}final_body = Some(body);\n`;
@@ -1481,16 +1495,28 @@ function getLroMethodBody(crate, indent, use, client, method) {
1481
1495
  body += `${indent.pop().get()}}\n`;
1482
1496
  }
1483
1497
  if (method.finalResultStrategy.kind === 'header' && method.finalResultStrategy.headerName !== pollingStepHeaderName) { // separate link for picking up the result
1484
- body += `${indent.get()}let final_link = ${helpers.buildMatch(indent, `headers.get_optional_string(&HeaderName::from_static("${method.finalResultStrategy.headerName}"))`, [{
1485
- pattern: 'Some(final_link)',
1486
- body: (indent) => {
1487
- return `${indent.get()}Url::parse(&final_link)?\n`;
1488
- }
1498
+ body += `${indent.get()}let continuation = ${helpers.buildIfBlock(indent, {
1499
+ condition: `let Some(final_link) = headers.get_optional_string(&HeaderName::from_static("${method.finalResultStrategy.headerName}"))`,
1500
+ body: (indent) => {
1501
+ let body = `${indent.get()}let final_link = Url::parse(&final_link)?;\n`;
1502
+ body += `${indent.get()}${helpers.buildMatch(indent, 'continuation', [{
1503
+ pattern: 'PollerContinuation::Links { next_link, .. }',
1504
+ body: (indent) => `${indent.get()}PollerContinuation::Links { next_link, final_link: Some(final_link) }\n`,
1505
+ }, {
1506
+ pattern: '_',
1507
+ body: (indent) => `${indent.get()}unreachable!()\n`,
1508
+ }])}\n`;
1509
+ return body;
1510
+ }
1511
+ }, {
1512
+ body: (indent) => `${indent.get()}continuation\n`
1513
+ })};\n`;
1514
+ body += `${indent.get()}let final_link = ${helpers.buildMatch(indent, '&continuation', [{
1515
+ pattern: 'PollerContinuation::Links { final_link, .. }',
1516
+ body: (indent) => `${indent.get()}final_link.clone().unwrap_or_else(|| url.clone())\n`,
1489
1517
  }, {
1490
- pattern: 'None',
1491
- body: (indent) => {
1492
- return `${indent.get()}progress.final_link`;
1493
- }
1518
+ pattern: '_',
1519
+ body: (indent) => `${indent.get()}unreachable!()\n`,
1494
1520
  }])};\n`;
1495
1521
  }
1496
1522
  body += `${indent.get()}let retry_after = get_retry_after(&headers, &[X_MS_RETRY_AFTER_MS, RETRY_AFTER_MS, RETRY_AFTER], &poller_options);\n`;
@@ -1519,7 +1545,7 @@ function getLroMethodBody(crate, indent, use, client, method) {
1519
1545
  const arms = [{
1520
1546
  pattern: `PollerStatus::InProgress`,
1521
1547
  body: (indent) => {
1522
- return `${indent.get()}response: rsp, retry_after, continuation_token: ${pollerStatusInProgressReturn}\n`;
1548
+ return `${indent.get()}response: rsp, retry_after, continuation\n`;
1523
1549
  },
1524
1550
  returns: 'PollerResult::InProgress'
1525
1551
  }];
@@ -1660,7 +1686,7 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow, overrid
1660
1686
  default:
1661
1687
  strConv = '|i| i.to_string()';
1662
1688
  }
1663
- paramValue = `${param.name}.iter().map(${strConv}).collect::<Vec<String>>().join("${getCollectionDelimiter(param.format)}")`;
1689
+ paramValue = `${paramName}.iter().map(${strConv}).collect::<Vec<String>>().join("${getCollectionDelimiter(param.format)}")`;
1664
1690
  }
1665
1691
  }
1666
1692
  else {
@@ -1676,7 +1702,8 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow, overrid
1676
1702
  mustBorrow = false;
1677
1703
  break;
1678
1704
  case 'decimal':
1679
- paramValue = `${param.name}.to_string()`;
1705
+ case 'Etag':
1706
+ paramValue = `${paramName}.to_string()`;
1680
1707
  break;
1681
1708
  case 'encodedBytes':
1682
1709
  paramValue = encodeBytes(paramType, paramName);
@@ -1685,7 +1712,7 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow, overrid
1685
1712
  case 'scalar':
1686
1713
  if (isEnumString(paramType) && (helpers.isPathParameter(param) || helpers.isQueryParameter(param))) {
1687
1714
  // append_pair and path.replace() want a reference to the string
1688
- paramValue = `${paramName}.as_ref()`;
1715
+ paramValue = (param.location === 'client' && fromSelf) ? `${paramName}.as_str()` : `${paramName}.as_ref()`;
1689
1716
  // as_ref() elides the need to borrow
1690
1717
  mustBorrow = false;
1691
1718
  }
@@ -1700,7 +1727,7 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow, overrid
1700
1727
  paramValue = `"${paramType.value}"`;
1701
1728
  break;
1702
1729
  case 'offsetDateTime':
1703
- paramValue = encodeDateTime(paramType, param.name);
1730
+ paramValue = encodeDateTime(paramType, paramName);
1704
1731
  break;
1705
1732
  default:
1706
1733
  throw new CodegenError('InternalError', `unhandled ${param.kind} param type kind ${paramType.kind}`);
@@ -1737,7 +1764,7 @@ function getCollectionDelimiter(format) {
1737
1764
  }
1738
1765
  /** returns true if the type isn't copyable thus needs to be cloned or borrowed */
1739
1766
  function nonCopyableType(type) {
1740
- const unwrappedType = shared.unwrapOption(type);
1767
+ const unwrappedType = utils.unwrapOption(type);
1741
1768
  switch (unwrappedType.kind) {
1742
1769
  case 'String':
1743
1770
  case 'Url':