@azure-tools/typespec-rust 0.37.0 → 0.38.1

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 (34) hide show
  1. package/dist/src/codegen/clients.d.ts.map +1 -1
  2. package/dist/src/codegen/clients.js +51 -30
  3. package/dist/src/codegen/clients.js.map +1 -1
  4. package/dist/src/codegen/helpers.d.ts.map +1 -1
  5. package/dist/src/codegen/helpers.js +3 -0
  6. package/dist/src/codegen/helpers.js.map +1 -1
  7. package/dist/src/codegen/models.js +36 -46
  8. package/dist/src/codegen/models.js.map +1 -1
  9. package/dist/src/codegen/unions.js +7 -18
  10. package/dist/src/codegen/unions.js.map +1 -1
  11. package/dist/src/codegen/use.d.ts +2 -1
  12. package/dist/src/codegen/use.d.ts.map +1 -1
  13. package/dist/src/codegen/use.js +14 -8
  14. package/dist/src/codegen/use.js.map +1 -1
  15. package/dist/src/codemodel/client.d.ts +2 -1
  16. package/dist/src/codemodel/client.d.ts.map +1 -1
  17. package/dist/src/codemodel/client.js.map +1 -1
  18. package/dist/src/codemodel/method.d.ts +2 -0
  19. package/dist/src/codemodel/method.d.ts.map +1 -1
  20. package/dist/src/codemodel/method.js +1 -0
  21. package/dist/src/codemodel/method.js.map +1 -1
  22. package/dist/src/codemodel/types.d.ts +13 -6
  23. package/dist/src/codemodel/types.d.ts.map +1 -1
  24. package/dist/src/codemodel/types.js +7 -0
  25. package/dist/src/codemodel/types.js.map +1 -1
  26. package/dist/src/tcgcadapter/adapter.d.ts +1 -0
  27. package/dist/src/tcgcadapter/adapter.d.ts.map +1 -1
  28. package/dist/src/tcgcadapter/adapter.js +171 -46
  29. package/dist/src/tcgcadapter/adapter.js.map +1 -1
  30. package/dist/src/utils/utils.d.ts +16 -0
  31. package/dist/src/utils/utils.d.ts.map +1 -1
  32. package/dist/src/utils/utils.js +29 -0
  33. package/dist/src/utils/utils.js.map +1 -1
  34. package/package.json +3 -3
@@ -222,7 +222,6 @@ export class Adapter {
222
222
  };
223
223
  terminalErrorModelNames = getTerminalErrorModelNames(this.ctx.sdkPackage.clients);
224
224
  }
225
- const processedTypes = new Set();
226
225
  for (const model of this.ctx.sdkPackage.models) {
227
226
  if ((model.usage & (tcgc.UsageFlags.Input | tcgc.UsageFlags.Output | tcgc.UsageFlags.Spread | tcgc.UsageFlags.Exception)) === 0) {
228
227
  // skip types without input and output usage. this will include core
@@ -236,15 +235,7 @@ export class Adapter {
236
235
  continue;
237
236
  }
238
237
  needsCoreAndSerde = true;
239
- // TODO: workaround for https://github.com/Azure/typespec-azure/issues/3614
240
- if (processedTypes.has(model.name)) {
241
- continue;
242
- }
243
- else {
244
- processedTypes.add(model.name);
245
- }
246
- // END workaround
247
- if (model.discriminatedSubtypes) {
238
+ if (isPolymorphicRoot(model)) {
248
239
  const rustUnion = this.getDiscriminatedUnion(model);
249
240
  this.adaptNamespace(model.namespace).unions.push(rustUnion);
250
241
  // we don't want to add the base type to the array
@@ -426,7 +417,7 @@ export class Adapter {
426
417
  // aggregate the properties from the provided type and its parent types
427
418
  const allProps = new Array();
428
419
  for (const prop of model.properties) {
429
- if (prop.discriminator && !model.discriminatedSubtypes) {
420
+ if (prop.discriminator && !isPolymorphicRoot(model)) {
430
421
  rustModel.flags |= rust.ModelFlags.PolymorphicSubtype;
431
422
  }
432
423
  allProps.push(prop);
@@ -492,7 +483,7 @@ export class Adapter {
492
483
  * @returns a Rust union
493
484
  */
494
485
  getDiscriminatedUnion(src) {
495
- var _a, _b, _c, _d, _e, _f, _g;
486
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
496
487
  if (src.name.length === 0) {
497
488
  throw new AdapterError('InternalError', 'unnamed union', (_a = src.__raw) === null || _a === void 0 ? void 0 : _a.node);
498
489
  }
@@ -504,7 +495,7 @@ export class Adapter {
504
495
  }
505
496
  switch (src.kind) {
506
497
  case 'model': {
507
- if (!src.discriminatedSubtypes) {
498
+ if (!isPolymorphicRoot(src)) {
508
499
  // we should have verified this earlier.
509
500
  // having this check means the compiler won't bark
510
501
  // at us when accessing src.discriminatedSubtypes
@@ -528,13 +519,37 @@ export class Adapter {
528
519
  rustUnion.unionKind = new rust.DiscriminatedUnionSealed();
529
520
  }
530
521
  else {
531
- rustUnion.unionKind = new rust.DiscriminatedUnionBase(this.getModel(src));
522
+ const typeName = `Unknown${utils.capitalize(src.name).replace(/\W/g, '')}${utils.capitalize(rustUnion.discriminant)}`;
523
+ const baseModel = this.getModel(src, undefined, typeName);
524
+ const module = this.adaptNamespace(src.namespace);
525
+ if (!module.models.includes(baseModel)) {
526
+ // we only fix up the base model if it's not
527
+ // in the collection of models for this module
528
+ baseModel.flags = rust.ModelFlags.PolymorphicBase;
529
+ // internal serde helper only
530
+ baseModel.visibility = 'pubCrate';
531
+ const lifetime = new rust.Lifetime('a');
532
+ baseModel.lifetime = lifetime;
533
+ for (const field of baseModel.fields) {
534
+ if (field.kind === 'modelField') {
535
+ // strip off the discriminator flag
536
+ field.flags &= ~rust.ModelFieldFlags.Discriminator;
537
+ }
538
+ if (!typeToRefType(field.type)) {
539
+ throw new AdapterError('InternalError', `unsupported field kind ${field.type.kind} in polymorphic base model ${baseModel.name}`, (_d = src.__raw) === null || _d === void 0 ? void 0 : _d.node);
540
+ }
541
+ field.type = this.getRefType(field.type, lifetime);
542
+ }
543
+ module.models.push(baseModel);
544
+ }
545
+ rustUnion.unionKind = new rust.DiscriminatedUnionBase(baseModel);
532
546
  }
533
- for (const subType of Object.values(src.discriminatedSubtypes)) {
547
+ // we need to handle the case where src is a root with no child types
548
+ for (const subType of Object.values((_e = src.discriminatedSubtypes) !== null && _e !== void 0 ? _e : {})) {
534
549
  if (!subType.discriminatorValue) {
535
- throw new AdapterError('InternalError', `model ${subType.name} has no discriminator value`, (_d = subType.__raw) === null || _d === void 0 ? void 0 : _d.node);
550
+ throw new AdapterError('InternalError', `model ${subType.name} has no discriminator value`, (_f = subType.__raw) === null || _f === void 0 ? void 0 : _f.node);
536
551
  }
537
- const unionMemberType = this.getModel(subType);
552
+ const unionMemberType = subType.discriminatedSubtypes ? this.getDiscriminatedUnion(subType) : this.getModel(subType);
538
553
  const rustUnionMember = new rust.DiscriminatedUnionMember(unionMemberType, subType.discriminatorValue);
539
554
  rustUnion.members.push(rustUnionMember);
540
555
  }
@@ -545,7 +560,7 @@ export class Adapter {
545
560
  // we should have verified this earlier.
546
561
  // having this check means the compiler won't bark
547
562
  // at us when accessing src.discriminatedOptions
548
- throw new AdapterError('InternalError', 'getDiscriminatedUnion called for non-discriminated union', (_e = src.__raw) === null || _e === void 0 ? void 0 : _e.node);
563
+ throw new AdapterError('InternalError', 'getDiscriminatedUnion called for non-discriminated union', (_g = src.__raw) === null || _g === void 0 ? void 0 : _g.node);
549
564
  }
550
565
  rustUnion = new rust.DiscriminatedUnion(unionName, adaptAccessFlags(src.access), src.discriminatedOptions.discriminatorPropertyName, this.adaptNamespace(src.namespace));
551
566
  if (src.discriminatedOptions.envelopePropertyName) {
@@ -568,12 +583,12 @@ export class Adapter {
568
583
  // END WORKAROUND
569
584
  for (const unionMember of src.variantTypes) {
570
585
  if (unionMember.kind !== 'model') {
571
- throw new AdapterError('UnsupportedTsp', `non-model union member kind ${unionMember.kind}`, (_f = unionMember.__raw) === null || _f === void 0 ? void 0 : _f.node);
586
+ throw new AdapterError('UnsupportedTsp', `non-model union member kind ${unionMember.kind}`, (_h = unionMember.__raw) === null || _h === void 0 ? void 0 : _h.node);
572
587
  }
573
588
  // TODO: use unionMember.discriminatorValue
574
589
  const discriminatorValue = discriminatorValues.get(unionMember.name);
575
590
  if (!discriminatorValue) {
576
- throw new AdapterError('InternalError', `didn't find discriminant value for type ${unionMember.name}`, (_g = unionMember.__raw) === null || _g === void 0 ? void 0 : _g.node);
591
+ throw new AdapterError('InternalError', `didn't find discriminant value for type ${unionMember.name}`, (_j = unionMember.__raw) === null || _j === void 0 ? void 0 : _j.node);
577
592
  }
578
593
  const unionMemberType = this.getModel(unionMember);
579
594
  const rustUnionMember = new rust.DiscriminatedUnionMember(unionMemberType, discriminatorValue);
@@ -831,6 +846,9 @@ export class Adapter {
831
846
  }
832
847
  modelField.docs.description += `Operational visibility: ${visibilityStr}`;
833
848
  }
849
+ if (property.visibility && property.visibility.length === 1 && property.visibility[0] === http.Visibility.Read) {
850
+ modelField.flags |= rust.ModelFieldFlags.ReadOnly;
851
+ }
834
852
  // if this is a literal, add a doc comment explaining its behavior
835
853
  const unwrappedType = utils.unwrapOption(fieldType);
836
854
  if (unwrappedType.kind === 'enumValue' || unwrappedType.kind === 'literal') {
@@ -985,7 +1003,7 @@ export class Adapter {
985
1003
  if (type.external) {
986
1004
  return this.getExternalType(type.external);
987
1005
  }
988
- else if (type.discriminatedSubtypes) {
1006
+ else if (isPolymorphicRoot(type)) {
989
1007
  return this.getDiscriminatedUnion(type);
990
1008
  }
991
1009
  else if (tcgc.isAzureCoreModel(type)) {
@@ -1305,7 +1323,7 @@ export class Adapter {
1305
1323
  * @returns a Rust client
1306
1324
  */
1307
1325
  recursiveAdaptClient(client, parent) {
1308
- var _a, _b, _c, _d, _e;
1326
+ var _a, _b, _c, _d, _e, _f, _g;
1309
1327
  let clientName = client.name;
1310
1328
  // NOTE: if the client has the @clientName decorator applied then use that verbatim
1311
1329
  if (parent && !hasClientNameDecorator(client.decorators)) {
@@ -1465,10 +1483,16 @@ export class Adapter {
1465
1483
  break;
1466
1484
  }
1467
1485
  case 'method': {
1468
- // https://github.com/Azure/typespec-rust/issues/849
1469
- // Azure doesn't use optional (with no explicit default value) API versions anyway.
1470
1486
  if (param.isApiVersionParam && param.optional && !param.clientDefaultValue) {
1471
- param.optional = false;
1487
+ if (!parent && client.children && client.methods.length === 0) {
1488
+ // this is the top-level client for a multi-client scenario.
1489
+ // each sub-client will have its own api-version parameter.
1490
+ // we omit this "merged" api-version param as it's useless.
1491
+ continue;
1492
+ }
1493
+ else {
1494
+ throw new AdapterError('UnsupportedTsp', 'found optional apiVersion parameter with no default value', (_c = param.__raw) === null || _c === void 0 ? void 0 : _c.node);
1495
+ }
1472
1496
  }
1473
1497
  const clientParam = this.adaptClientParameter(param, rustClient.constructable);
1474
1498
  rustClient.fields.push(new rust.StructField(clientParam.name, 'pubCrate', clientParam.type));
@@ -1506,6 +1530,33 @@ export class Adapter {
1506
1530
  // as these are handled in the parent client.
1507
1531
  continue;
1508
1532
  }
1533
+ else if (prop.isApiVersionParam) {
1534
+ // we didn't find the api-version param in the parent which means
1535
+ // this is a multi-client child with its own api-version param.
1536
+ // we need to find the instantiable parent client.
1537
+ let constructable;
1538
+ let cur = parent;
1539
+ while (cur) {
1540
+ constructable = cur.constructable;
1541
+ if (constructable) {
1542
+ break;
1543
+ }
1544
+ cur = cur.parent;
1545
+ }
1546
+ if (!constructable || !cur) {
1547
+ throw new AdapterError('InternalError', `didn't find constructable client for apiVersion in client ${rustClient.name}`, (_d = prop.__raw) === null || _d === void 0 ? void 0 : _d.node);
1548
+ }
1549
+ rustClient.fields.push(new rust.StructField(utils.snakeCaseName(prop.name), 'pubCrate', this.getStringType()));
1550
+ // we use the client name as a prefix to disambiguate the params in the parent
1551
+ const clientParam = this.adaptClientParameter(prop, constructable, utils.deduplicateClientFieldName(rustClient, name));
1552
+ const field = new rust.StructField(clientParam.name, 'pubCrate', clientParam.type);
1553
+ cur.fields.push(field);
1554
+ // propagate this param to all client constructors
1555
+ for (const constructor of constructable.constructors) {
1556
+ constructor.params.push(clientParam);
1557
+ }
1558
+ continue;
1559
+ }
1509
1560
  // unique field for this client
1510
1561
  rustClient.fields.push(new rust.StructField(name, 'pubCrate', this.getType(prop.type)));
1511
1562
  }
@@ -1513,7 +1564,7 @@ export class Adapter {
1513
1564
  else {
1514
1565
  throw new AdapterError('InternalError', `uninstantiatable client ${client.name} has no parent`);
1515
1566
  }
1516
- for (const child of (_c = client.children) !== null && _c !== void 0 ? _c : []) {
1567
+ for (const child of (_e = client.children) !== null && _e !== void 0 ? _e : []) {
1517
1568
  const subClient = this.recursiveAdaptClient(child, rustClient);
1518
1569
  this.adaptClientAccessor(client, child, rustClient, subClient);
1519
1570
  }
@@ -1525,7 +1576,7 @@ export class Adapter {
1525
1576
  code: 'LroPagingNotSupported',
1526
1577
  severity: 'warning',
1527
1578
  message: `skip emitting Paging LRO ${method.name}`,
1528
- target: (_e = (_d = method.__raw) === null || _d === void 0 ? void 0 : _d.node) !== null && _e !== void 0 ? _e : tsp.NoTarget,
1579
+ target: (_g = (_f = method.__raw) === null || _f === void 0 ? void 0 : _f.node) !== null && _g !== void 0 ? _g : tsp.NoTarget,
1529
1580
  });
1530
1581
  continue;
1531
1582
  }
@@ -1566,11 +1617,12 @@ export class Adapter {
1566
1617
  *
1567
1618
  * @param param the tcgc client parameter to convert
1568
1619
  * @param constructable contains client construction info. if the param is optional, it will go in the options type
1620
+ * @param name optional custom name for the parameter
1569
1621
  * @returns the Rust client parameter
1570
1622
  */
1571
- adaptClientParameter(param, constructable) {
1623
+ adaptClientParameter(param, constructable, name) {
1572
1624
  let paramType = param.isApiVersionParam ? this.getStringType() : this.getType(param.type);
1573
- const paramName = utils.snakeCaseName(param.name);
1625
+ const paramName = name !== null && name !== void 0 ? name : utils.snakeCaseName(param.name);
1574
1626
  let optional = false;
1575
1627
  // client-side default value makes the param optional
1576
1628
  if (param.optional || param.clientDefaultValue) {
@@ -1637,7 +1689,7 @@ export class Adapter {
1637
1689
  * @param rustClient the client to which the method belongs
1638
1690
  */
1639
1691
  adaptMethod(method, rustClient) {
1640
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
1692
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
1641
1693
  let srcMethodName = method.name;
1642
1694
  if (method.kind === 'paging' && !srcMethodName.match(/^list/i)) {
1643
1695
  const chunks = utils.deconstruct(srcMethodName);
@@ -1715,8 +1767,21 @@ export class Adapter {
1715
1767
  // https://github.com/microsoft/typespec/blob/f3d792b252c6f40be0e174496d9f34d453676026/packages/http-client-csharp/emitter/src/type/operation-final-state-via.ts#L23-L27
1716
1768
  lroFinalResultStrategy = new rust.LroFinalResultStrategyHeader('operation-location');
1717
1769
  break;
1770
+ case FinalStateValue.customLink:
1771
+ if (((_d = method.lroMetadata.statusMonitorStep) === null || _d === void 0 ? void 0 : _d.kind) === "nextOperationLink") {
1772
+ const customHeaderName = method.lroMetadata.statusMonitorStep.target.property.name;
1773
+ if (customHeaderName.trim() === '') {
1774
+ throw new AdapterError('UnsupportedTsp', `lroMetadata.finalStateVia === customLink && customHeaderName === "${customHeaderName}"`, (_e = method.__raw) === null || _e === void 0 ? void 0 : _e.node);
1775
+ }
1776
+ lroFinalResultStrategy = new rust.LroFinalResultStrategyHeader(customHeaderName);
1777
+ }
1778
+ else {
1779
+ throw new AdapterError('UnsupportedTsp', `lroMetadata.finalStateVia === customLink && lroMetadata.statusMonitorStep?.kind === "${(_f = method.lroMetadata.statusMonitorStep) === null || _f === void 0 ? void 0 : _f.kind}"`, (_g = method.__raw) === null || _g === void 0 ? void 0 : _g.node);
1780
+ }
1781
+ break;
1718
1782
  default:
1719
- throw new AdapterError('UnsupportedTsp', `lroMetadata.finalStateVia ${method.lroMetadata.finalStateVia} NYI`, (_d = method.__raw) === null || _d === void 0 ? void 0 : _d.node);
1783
+ /* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
1784
+ throw new AdapterError('UnsupportedTsp', `lroMetadata.finalStateVia ${method.lroMetadata.finalStateVia} NYI`, (_h = method.__raw) === null || _h === void 0 ? void 0 : _h.node);
1720
1785
  }
1721
1786
  lroFinalResultStrategy.propertyName = method.lroMetadata.finalResultPath;
1722
1787
  }
@@ -1724,7 +1789,7 @@ export class Adapter {
1724
1789
  }
1725
1790
  break;
1726
1791
  default:
1727
- throw new AdapterError('UnsupportedTsp', `method kind ${method.kind} NYI`, (_e = method.__raw) === null || _e === void 0 ? void 0 : _e.node);
1792
+ throw new AdapterError('UnsupportedTsp', `method kind ${method.kind} NYI`, (_j = method.__raw) === null || _j === void 0 ? void 0 : _j.node);
1728
1793
  }
1729
1794
  rustMethod.docs = this.adaptDocs(method.summary, method.doc);
1730
1795
  rustClient.methods.push(rustMethod);
@@ -1845,7 +1910,7 @@ export class Adapter {
1845
1910
  if (!fieldOptional) {
1846
1911
  if (!paramGroup) {
1847
1912
  if (param.type.kind !== 'model') {
1848
- throw new AdapterError('InternalError', `expected model type for parameter group but got ${param.type.kind}`, (_f = param.__raw) === null || _f === void 0 ? void 0 : _f.node);
1913
+ throw new AdapterError('InternalError', `expected model type for parameter group but got ${param.type.kind}`, (_k = param.__raw) === null || _k === void 0 ? void 0 : _k.node);
1849
1914
  }
1850
1915
  const groupName = utils.capitalize(param.type.name).replace(/\W/g, '');
1851
1916
  const paramName = naming.getEscapedReservedName(utils.snakeCaseName(param.name), 'param', reservedParams);
@@ -1890,7 +1955,7 @@ export class Adapter {
1890
1955
  }
1891
1956
  }
1892
1957
  else {
1893
- throw new AdapterError('InternalError', `didn't find operation parameter for method ${method.name} parameter ${param.name}`, (_g = param.__raw) === null || _g === void 0 ? void 0 : _g.node);
1958
+ throw new AdapterError('InternalError', `didn't find operation parameter for method ${method.name} parameter ${param.name}`, (_l = param.__raw) === null || _l === void 0 ? void 0 : _l.node);
1894
1959
  }
1895
1960
  }
1896
1961
  // client params aren't included in method.parameters so
@@ -1973,16 +2038,16 @@ export class Adapter {
1973
2038
  const responseFormat = getResponseFormat();
1974
2039
  if (method.kind === 'paging') {
1975
2040
  if (responseFormat !== 'JsonFormat' && responseFormat !== 'XmlFormat') {
1976
- throw new AdapterError('InternalError', `paged method ${method.name} unexpected response format ${responseFormat}`, (_h = method.__raw) === null || _h === void 0 ? void 0 : _h.node);
2041
+ throw new AdapterError('InternalError', `paged method ${method.name} unexpected response format ${responseFormat}`, (_m = method.__raw) === null || _m === void 0 ? void 0 : _m.node);
1977
2042
  }
1978
2043
  // for paged methods, tcgc models method.response.type as an Array<T>.
1979
2044
  // however, we want the synthesized paged response envelope type instead.
1980
2045
  const synthesizedType = method.operation.responses[0].type;
1981
2046
  if (!synthesizedType) {
1982
- throw new AdapterError('InternalError', `paged method ${method.name} has no synthesized response type`, (_j = method.__raw) === null || _j === void 0 ? void 0 : _j.node);
2047
+ throw new AdapterError('InternalError', `paged method ${method.name} has no synthesized response type`, (_o = method.__raw) === null || _o === void 0 ? void 0 : _o.node);
1983
2048
  }
1984
2049
  else if (synthesizedType.kind !== 'model') {
1985
- throw new AdapterError('UnsupportedTsp', `paged method ${method.name} synthesized response type has unexpected kind ${synthesizedType.kind}`, (_k = method.__raw) === null || _k === void 0 ? void 0 : _k.node);
2050
+ throw new AdapterError('UnsupportedTsp', `paged method ${method.name} synthesized response type has unexpected kind ${synthesizedType.kind}`, (_p = method.__raw) === null || _p === void 0 ? void 0 : _p.node);
1986
2051
  }
1987
2052
  const synthesizedModel = this.getModel(synthesizedType, new Array());
1988
2053
  const modelNs = this.adaptNamespace(synthesizedType.namespace);
@@ -1991,7 +2056,7 @@ export class Adapter {
1991
2056
  }
1992
2057
  // for the pager response type, remove the Option<T> around the Vec<T> for the page items
1993
2058
  if (!method.pagingMetadata.pageItemsSegments) {
1994
- throw new AdapterError('InternalError', `paged method ${method.name} has no pageItemsSegments`, (_l = method.__raw) === null || _l === void 0 ? void 0 : _l.node);
2059
+ throw new AdapterError('InternalError', `paged method ${method.name} has no pageItemsSegments`, (_q = method.__raw) === null || _q === void 0 ? void 0 : _q.node);
1995
2060
  }
1996
2061
  // unwrap all of the segments for the paged response
1997
2062
  let unwrappedCount = 0;
@@ -2002,13 +2067,13 @@ export class Adapter {
2002
2067
  switch (responseFormat) {
2003
2068
  case 'JsonFormat':
2004
2069
  if (segment.kind !== 'property' || !segment.serializationOptions.json) {
2005
- throw new AdapterError('InternalError', `paged method ${method.name} is missing JSON serialization data`, (_m = method.__raw) === null || _m === void 0 ? void 0 : _m.node);
2070
+ throw new AdapterError('InternalError', `paged method ${method.name} is missing JSON serialization data`, (_r = method.__raw) === null || _r === void 0 ? void 0 : _r.node);
2006
2071
  }
2007
2072
  serde = segment.serializationOptions.json.name;
2008
2073
  break;
2009
2074
  case 'XmlFormat':
2010
2075
  if (segment.kind !== 'property' || !segment.serializationOptions.xml) {
2011
- throw new AdapterError('InternalError', `paged method ${method.name} is missing XML serialization data`, (_o = method.__raw) === null || _o === void 0 ? void 0 : _o.node);
2076
+ throw new AdapterError('InternalError', `paged method ${method.name} is missing XML serialization data`, (_s = method.__raw) === null || _s === void 0 ? void 0 : _s.node);
2012
2077
  }
2013
2078
  serde = segment.serializationOptions.xml.name;
2014
2079
  break;
@@ -2034,7 +2099,7 @@ export class Adapter {
2034
2099
  }
2035
2100
  }
2036
2101
  if (unwrappedCount !== method.pagingMetadata.pageItemsSegments.length) {
2037
- throw new AdapterError('InternalError', `failed to unwrap paged items for method ${method.name}`, (_p = method.__raw) === null || _p === void 0 ? void 0 : _p.node);
2102
+ throw new AdapterError('InternalError', `failed to unwrap paged items for method ${method.name}`, (_t = method.__raw) === null || _t === void 0 ? void 0 : _t.node);
2038
2103
  }
2039
2104
  this.crate.addDependency(new rust.CrateDependency('async-trait'));
2040
2105
  // default to nextLink. will update it as required when we have that info
@@ -2067,7 +2132,7 @@ export class Adapter {
2067
2132
  const statusModel = this.getModel(method.lroMetadata.pollingInfo.responseModel, undefined, `${rustClient.name}${utils.pascalCase(rustMethod.name, false)}OperationStatus`);
2068
2133
  const statusType = this.typeToWireType(statusModel);
2069
2134
  if (statusType.kind !== 'model') {
2070
- throw new AdapterError('InternalError', `status type for an LRO method '${method.name}' is not a model`, (_q = method.__raw) === null || _q === void 0 ? void 0 : _q.node);
2135
+ throw new AdapterError('InternalError', `status type for an LRO method '${method.name}' is not a model`, (_u = method.__raw) === null || _u === void 0 ? void 0 : _u.node);
2071
2136
  }
2072
2137
  // the adapted type likely comes from core which means
2073
2138
  // it will be in the root namespace. since we emit these
@@ -2124,10 +2189,10 @@ export class Adapter {
2124
2189
  // can't do this until the method has been completely adapted
2125
2190
  const pageableMethod = rustMethod;
2126
2191
  pageableMethod.strategy = this.adaptPageableMethodStrategy(method, paramsMap, responseHeadersMap);
2127
- if (((_r = pageableMethod.strategy) === null || _r === void 0 ? void 0 : _r.kind) === 'nextLink') {
2192
+ if (((_v = pageableMethod.strategy) === null || _v === void 0 ? void 0 : _v.kind) === 'nextLink') {
2128
2193
  pageableMethod.strategy.reinjectedParams = this.adaptPageableMethodReinjectionParams(method, paramsMap);
2129
2194
  }
2130
- else if (((_s = pageableMethod.strategy) === null || _s === void 0 ? void 0 : _s.kind) === 'continuationToken') {
2195
+ else if (((_w = pageableMethod.strategy) === null || _w === void 0 ? void 0 : _w.kind) === 'continuationToken') {
2131
2196
  // set the continuation type to token on the Pager and the PagerOptions field in the method options
2132
2197
  pageableMethod.returns.type.continuation = 'token';
2133
2198
  for (const field of pageableMethod.options.type.type.fields) {
@@ -2195,6 +2260,8 @@ export class Adapter {
2195
2260
  return type.name;
2196
2261
  case 'hashmap':
2197
2262
  return `${type.name}${recursiveTypeName(type.type)}`;
2263
+ case 'option':
2264
+ return `Option${recursiveTypeName(type.type)}`;
2198
2265
  case 'ref':
2199
2266
  return `Ref${recursiveTypeName(type.type)}`;
2200
2267
  case 'scalar':
@@ -2369,7 +2436,7 @@ export class Adapter {
2369
2436
  * @returns a Rust method parameter
2370
2437
  */
2371
2438
  adaptMethodParameter(opParam, methodParam, lifetime) {
2372
- var _a, _b, _c, _d, _e, _f, _g, _h;
2439
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
2373
2440
  /**
2374
2441
  * used to create keys for this.clientMethodParams
2375
2442
  * @param param the param for which to create a key
@@ -2498,6 +2565,12 @@ export class Adapter {
2498
2565
  throw new AdapterError('InternalError', `unexpected kind ${paramType.kind} for scalar path ${opParam.serializedName}`, (_g = opParam.__raw) === null || _g === void 0 ? void 0 : _g.node);
2499
2566
  }
2500
2567
  adaptedParam = new rust.PathScalarParameter(paramName, opParam.serializedName, paramLoc, paramOptional, paramType, opParam.allowReserved, style);
2568
+ const allowEmpty = ((_h = opParam.decorators.find(d => d.name === 'Azure.ClientGenerator.Core.@clientOption'
2569
+ && d.arguments['name'] === 'allowEmpty'
2570
+ && d.arguments['scope'] === 'rust')) === null || _h === void 0 ? void 0 : _h.arguments['value']) === true;
2571
+ if (allowEmpty) {
2572
+ adaptedParam.minLength = 0;
2573
+ }
2501
2574
  }
2502
2575
  }
2503
2576
  break;
@@ -2521,7 +2594,7 @@ export class Adapter {
2521
2594
  case 'model':
2522
2595
  case 'slice':
2523
2596
  case 'str':
2524
- throw new AdapterError('InternalError', `unexpected kind ${paramType.kind} for scalar query ${opParam.serializedName}`, (_h = opParam.__raw) === null || _h === void 0 ? void 0 : _h.node);
2597
+ throw new AdapterError('InternalError', `unexpected kind ${paramType.kind} for scalar query ${opParam.serializedName}`, (_j = opParam.__raw) === null || _j === void 0 ? void 0 : _j.node);
2525
2598
  }
2526
2599
  // TODO: hard-coded encoding setting, https://github.com/Azure/typespec-azure/issues/1314
2527
2600
  adaptedParam = new rust.QueryScalarParameter(paramName, opParam.serializedName, paramLoc, paramOptional, paramType, true);
@@ -2730,6 +2803,7 @@ function recursiveKeyName(root, type) {
2730
2803
  switch (type.kind) {
2731
2804
  case 'Vec':
2732
2805
  case 'box':
2806
+ case 'option':
2733
2807
  return recursiveKeyName(`${root}-${type.kind}`, type.type);
2734
2808
  case 'encodedBytes':
2735
2809
  return `${root}-${type.kind}-${type.encoding}${type.slice ? '-slice' : ''}`;
@@ -2904,4 +2978,55 @@ function isLibNamespace(namespace) {
2904
2978
  const ns = namespace.toLowerCase();
2905
2979
  return LIB_NAMESPACE.some((lib) => ns === lib || ns.startsWith(lib + '.'));
2906
2980
  }
2981
+ /**
2982
+ * narrows type to a RefType within the conditional block.
2983
+ * this function throws if the narrowing is not possible.
2984
+ */
2985
+ function typeToRefType(type) {
2986
+ switch (type.kind) {
2987
+ case 'bytes':
2988
+ case 'decimal':
2989
+ case 'discriminatedUnion':
2990
+ case 'encodedBytes':
2991
+ case 'enum':
2992
+ case 'enumValue':
2993
+ case 'Etag':
2994
+ case 'external':
2995
+ case 'hashmap':
2996
+ case 'jsonValue':
2997
+ case 'model':
2998
+ case 'offsetDateTime':
2999
+ case 'option':
3000
+ case 'safeint':
3001
+ case 'scalar':
3002
+ case 'slice':
3003
+ case 'str':
3004
+ case 'String':
3005
+ case 'untaggedUnion':
3006
+ case 'Url':
3007
+ case 'Vec':
3008
+ return true;
3009
+ default:
3010
+ throw new AdapterError('InternalError', `cannot convert ${type.kind} to a ref type`);
3011
+ }
3012
+ }
3013
+ /**
3014
+ * returns true if model is a polymorphic root type.
3015
+ *
3016
+ * @param model the model to inspect
3017
+ * @returns true if the model is a polymorphic root
3018
+ */
3019
+ function isPolymorphicRoot(model) {
3020
+ if (model.discriminatedSubtypes) {
3021
+ // when there are sub-types we know for sure it's a polymorphic root
3022
+ return true;
3023
+ }
3024
+ else if (model.discriminatorProperty && !model.discriminatorValue) {
3025
+ // we can land here if it's a root but has no child types
3026
+ return true;
3027
+ }
3028
+ else {
3029
+ return false;
3030
+ }
3031
+ }
2907
3032
  //# sourceMappingURL=adapter.js.map