@azure-tools/typespec-rust 0.13.3 → 0.14.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.
- package/dist/src/codegen/clients.d.ts.map +1 -1
- package/dist/src/codegen/clients.js +165 -92
- package/dist/src/codegen/clients.js.map +1 -1
- package/dist/src/codegen/context.d.ts.map +1 -1
- package/dist/src/codegen/context.js +3 -2
- package/dist/src/codegen/context.js.map +1 -1
- package/dist/src/codegen/errors.d.ts +13 -0
- package/dist/src/codegen/errors.d.ts.map +1 -0
- package/dist/src/codegen/errors.js +15 -0
- package/dist/src/codegen/errors.js.map +1 -0
- package/dist/src/codegen/headerTraits.d.ts.map +1 -1
- package/dist/src/codegen/headerTraits.js +4 -2
- package/dist/src/codegen/headerTraits.js.map +1 -1
- package/dist/src/codegen/helpers.d.ts +7 -1
- package/dist/src/codegen/helpers.d.ts.map +1 -1
- package/dist/src/codegen/helpers.js +20 -4
- package/dist/src/codegen/helpers.js.map +1 -1
- package/dist/src/codegen/models.d.ts.map +1 -1
- package/dist/src/codegen/models.js +133 -71
- package/dist/src/codegen/models.js.map +1 -1
- package/dist/src/codegen/use.d.ts.map +1 -1
- package/dist/src/codegen/use.js +4 -2
- package/dist/src/codegen/use.js.map +1 -1
- package/dist/src/codemodel/client.d.ts +17 -31
- package/dist/src/codemodel/client.d.ts.map +1 -1
- package/dist/src/codemodel/client.js +1 -35
- package/dist/src/codemodel/client.js.map +1 -1
- package/dist/src/codemodel/method.d.ts +0 -2
- package/dist/src/codemodel/method.d.ts.map +1 -1
- package/dist/src/codemodel/method.js +0 -1
- package/dist/src/codemodel/method.js.map +1 -1
- package/dist/src/codemodel/types.d.ts +52 -5
- package/dist/src/codemodel/types.d.ts.map +1 -1
- package/dist/src/codemodel/types.js +26 -7
- package/dist/src/codemodel/types.js.map +1 -1
- package/dist/src/emitter.d.ts.map +1 -1
- package/dist/src/emitter.js +84 -34
- package/dist/src/emitter.js.map +1 -1
- package/dist/src/lib.d.ts +37 -4
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +27 -2
- package/dist/src/lib.js.map +1 -1
- package/dist/src/tcgcadapter/adapter.d.ts +58 -10
- package/dist/src/tcgcadapter/adapter.d.ts.map +1 -1
- package/dist/src/tcgcadapter/adapter.js +401 -179
- package/dist/src/tcgcadapter/adapter.js.map +1 -1
- package/dist/src/tcgcadapter/helpers.d.ts +8 -0
- package/dist/src/tcgcadapter/helpers.d.ts.map +1 -1
- package/dist/src/tcgcadapter/helpers.js +16 -1
- package/dist/src/tcgcadapter/helpers.js.map +1 -1
- package/package.json +25 -27
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../../src/codegen/clients.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../../src/codegen/clients.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAGxC,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAE9C,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,CAoPxE"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import * as codegen from '@azure-tools/codegen';
|
|
6
6
|
import { values } from '@azure-tools/linq';
|
|
7
|
+
import { CodegenError } from './errors.js';
|
|
7
8
|
import * as helpers from './helpers.js';
|
|
8
9
|
import queryString from 'query-string';
|
|
9
10
|
import { Use } from './use.js';
|
|
@@ -112,7 +113,7 @@ export function emitClients(crate) {
|
|
|
112
113
|
continue;
|
|
113
114
|
}
|
|
114
115
|
if (!client.fields.find((v) => { return v.name === param.name; })) {
|
|
115
|
-
throw new
|
|
116
|
+
throw new CodegenError('InternalError', `didn't find field in client ${client.name} for param ${param.name}`);
|
|
116
117
|
}
|
|
117
118
|
// by convention, the param field and param name are the
|
|
118
119
|
// same so we can use shorthand initialization syntax
|
|
@@ -124,10 +125,10 @@ export function emitClients(crate) {
|
|
|
124
125
|
continue;
|
|
125
126
|
}
|
|
126
127
|
if (!client.fields.find((v) => { return v.name === param.name; })) {
|
|
127
|
-
throw new
|
|
128
|
+
throw new CodegenError('InternalError', `didn't find field in client ${client.name} for param ${param.name}`);
|
|
128
129
|
}
|
|
129
130
|
if (!client.constructable.options.type.fields.find((v) => { return v.name === param.name; })) {
|
|
130
|
-
throw new
|
|
131
|
+
throw new CodegenError('InternalError', `didn't find field in client options ${client.constructable.options.type.name} for optional param ${param.name}`);
|
|
131
132
|
}
|
|
132
133
|
body += `${indent.get()}${param.name}: options.${param.name},\n`;
|
|
133
134
|
}
|
|
@@ -349,11 +350,7 @@ function getConstructorParamsSig(params, options, use) {
|
|
|
349
350
|
continue;
|
|
350
351
|
}
|
|
351
352
|
use.addForType(param.type);
|
|
352
|
-
|
|
353
|
-
if (param.kind === 'clientMethod' && param.ref) {
|
|
354
|
-
ref = '&';
|
|
355
|
-
}
|
|
356
|
-
paramsSig.push(`${param.name}: ${ref}${helpers.getTypeDeclaration(param.type)}`);
|
|
353
|
+
paramsSig.push(`${param.name}: ${helpers.getTypeDeclaration(param.type)}`);
|
|
357
354
|
}
|
|
358
355
|
paramsSig.push(`options: ${helpers.getTypeDeclaration(options)}`);
|
|
359
356
|
return paramsSig.join(', ');
|
|
@@ -379,13 +376,14 @@ function getMethodParamsSig(method, use) {
|
|
|
379
376
|
}
|
|
380
377
|
else {
|
|
381
378
|
for (const param of method.params) {
|
|
382
|
-
|
|
379
|
+
const paramType = helpers.unwrapType(param.type);
|
|
380
|
+
if (paramType.kind === 'literal') {
|
|
383
381
|
// literal params are embedded directly in the code (e.g. accept header param)
|
|
384
382
|
continue;
|
|
385
383
|
}
|
|
386
|
-
else if (
|
|
384
|
+
else if (paramType.kind === 'enumValue') {
|
|
387
385
|
// enum values are treated like literals, we just need to use their type
|
|
388
|
-
use.addForType(
|
|
386
|
+
use.addForType(paramType.type);
|
|
389
387
|
continue;
|
|
390
388
|
}
|
|
391
389
|
// don't add client or optional params to the method param sig
|
|
@@ -428,7 +426,7 @@ function getAuthPolicy(ctor, use) {
|
|
|
428
426
|
*/
|
|
429
427
|
function formatParamTypeName(param) {
|
|
430
428
|
let format = '';
|
|
431
|
-
if (param.ref) {
|
|
429
|
+
if (param.ref === true) {
|
|
432
430
|
format = '&';
|
|
433
431
|
}
|
|
434
432
|
if (param.mut) {
|
|
@@ -462,13 +460,13 @@ function getEndpointFieldName(client) {
|
|
|
462
460
|
for (const field of client.fields) {
|
|
463
461
|
if (field.type.kind === 'Url') {
|
|
464
462
|
if (endpointFieldName) {
|
|
465
|
-
throw new
|
|
463
|
+
throw new CodegenError('InternalError', `found multiple URL fields in client ${client.name} which is unexpected`);
|
|
466
464
|
}
|
|
467
465
|
endpointFieldName = field.name;
|
|
468
466
|
}
|
|
469
467
|
}
|
|
470
468
|
if (!endpointFieldName) {
|
|
471
|
-
throw new
|
|
469
|
+
throw new CodegenError('InternalError', `didn't find URI field for client ${client.name}`);
|
|
472
470
|
}
|
|
473
471
|
return endpointFieldName;
|
|
474
472
|
}
|
|
@@ -533,7 +531,7 @@ function getMethodParamGroup(method) {
|
|
|
533
531
|
queryParams.push(param);
|
|
534
532
|
break;
|
|
535
533
|
}
|
|
536
|
-
if (param.kind === 'query' && param.isApiVersion) {
|
|
534
|
+
if ((param.kind === 'header' || param.kind === 'query') && param.isApiVersion) {
|
|
537
535
|
apiVersionParam = param;
|
|
538
536
|
}
|
|
539
537
|
}
|
|
@@ -544,7 +542,7 @@ function getMethodParamGroup(method) {
|
|
|
544
542
|
for (const param of method.params) {
|
|
545
543
|
if (param.kind === 'body') {
|
|
546
544
|
if (bodyParam) {
|
|
547
|
-
throw new
|
|
545
|
+
throw new CodegenError('InternalError', `method ${method.name} has multiple body parameters`);
|
|
548
546
|
}
|
|
549
547
|
bodyParam = param;
|
|
550
548
|
}
|
|
@@ -568,13 +566,14 @@ function getMethodParamGroup(method) {
|
|
|
568
566
|
* @param indent the indentation helper currently in scope
|
|
569
567
|
* @param param the parameter to which the contents of setter apply
|
|
570
568
|
* @param setter the callback that emits the code to read from a param var
|
|
569
|
+
* @param inClosure indicates if the value is being read from within a closure (e.g. pageable methods)
|
|
571
570
|
* @returns
|
|
572
571
|
*/
|
|
573
|
-
function getParamValueHelper(indent, param, setter) {
|
|
572
|
+
function getParamValueHelper(indent, param, inClosure, setter) {
|
|
574
573
|
if (param.optional) {
|
|
575
574
|
// optional params are in the unwrapped options local var
|
|
576
575
|
const op = indent.get() + helpers.buildIfBlock(indent, {
|
|
577
|
-
condition: `let Some(${param.name}) = options.${param.name}`,
|
|
576
|
+
condition: `let Some(${param.name}) = ${inClosure ? '&' : ''}options.${param.name}`,
|
|
578
577
|
body: setter,
|
|
579
578
|
});
|
|
580
579
|
return op + '\n';
|
|
@@ -596,11 +595,14 @@ function constructUrl(indent, use, method, paramGroups, urlVarName = 'url') {
|
|
|
596
595
|
// including them in the call to set_path() causes the chars to be path-escaped.
|
|
597
596
|
const pathChunks = method.httpPath.split('?');
|
|
598
597
|
if (pathChunks.length > 2) {
|
|
599
|
-
throw new
|
|
598
|
+
throw new CodegenError('InternalError', 'too many HTTP path chunks');
|
|
600
599
|
}
|
|
601
600
|
/** returns & if the param needs to be borrowed (which is the majority of cases), else the empty string */
|
|
602
601
|
const borrowOrNot = function (param) {
|
|
603
|
-
|
|
602
|
+
if (param.type.kind !== 'ref' || param.type.type.kind === 'encodedBytes' || param.type.type.kind === 'slice') {
|
|
603
|
+
return '&';
|
|
604
|
+
}
|
|
605
|
+
return '';
|
|
604
606
|
};
|
|
605
607
|
let body = '';
|
|
606
608
|
// if path is just "/" no need to set it again, we're already there
|
|
@@ -649,7 +651,7 @@ function constructUrl(indent, use, method, paramGroups, urlVarName = 'url') {
|
|
|
649
651
|
}
|
|
650
652
|
for (const queryParam of paramGroups.query) {
|
|
651
653
|
if (queryParam.kind === 'queryCollection' && queryParam.format === 'multi') {
|
|
652
|
-
body += getParamValueHelper(indent, queryParam, () => {
|
|
654
|
+
body += getParamValueHelper(indent, queryParam, false, () => {
|
|
653
655
|
const valueVar = queryParam.name[0];
|
|
654
656
|
let text = `${indent.get()}for ${valueVar} in ${queryParam.name}.iter() {\n`;
|
|
655
657
|
text += `${indent.push().get()}${urlVarName}.query_pairs_mut().append_pair("${queryParam.key}", ${valueVar});\n`;
|
|
@@ -658,7 +660,7 @@ function constructUrl(indent, use, method, paramGroups, urlVarName = 'url') {
|
|
|
658
660
|
});
|
|
659
661
|
}
|
|
660
662
|
else {
|
|
661
|
-
body += getParamValueHelper(indent, queryParam, () => {
|
|
663
|
+
body += getParamValueHelper(indent, queryParam, false, () => {
|
|
662
664
|
// for enums we call .as_ref() which elides the need to borrow
|
|
663
665
|
const borrow = queryParam.type.kind === 'enum' ? '' : borrowOrNot(queryParam);
|
|
664
666
|
return `${indent.get()}${urlVarName}.query_pairs_mut().append_pair("${queryParam.key}", ${borrow}${getHeaderPathQueryParamValue(use, queryParam, !queryParam.optional)});\n`;
|
|
@@ -676,28 +678,40 @@ function constructUrl(indent, use, method, paramGroups, urlVarName = 'url') {
|
|
|
676
678
|
* @param use the use statement builder currently in scope
|
|
677
679
|
* @param method the method for which we're building the body
|
|
678
680
|
* @param paramGroups the param groups for the provided method
|
|
679
|
-
* @param
|
|
681
|
+
* @param inClosure indicates if the request is being constructed within a closure (e.g. pageable methods)
|
|
680
682
|
* @returns the request construction code
|
|
681
683
|
*/
|
|
682
|
-
function constructRequest(indent, use, method, paramGroups,
|
|
684
|
+
function constructRequest(indent, use, method, paramGroups, inClosure) {
|
|
685
|
+
var _a, _b, _c;
|
|
683
686
|
let body = `${indent.get()}let mut request = Request::new(url, Method::${codegen.capitalize(method.httpMethod)});\n`;
|
|
684
687
|
for (const headerParam of paramGroups.header) {
|
|
685
|
-
|
|
688
|
+
if (method.kind === 'pageable' && ((_a = method.strategy) === null || _a === void 0 ? void 0 : _a.kind) === 'continuationToken' && ((_b = method.strategy) === null || _b === void 0 ? void 0 : _b.requestToken.kind) === 'header' && ((_c = method.strategy) === null || _c === void 0 ? void 0 : _c.requestToken) === headerParam) {
|
|
689
|
+
// we have some special handling for the header continuation token.
|
|
690
|
+
// if we have a token value, i.e. from the next page, then use that value.
|
|
691
|
+
// if not, then check if an optional token value was provided.
|
|
692
|
+
body += indent.get() + helpers.buildIfBlock(indent, {
|
|
693
|
+
condition: `let Some(${headerParam.name}) = ${headerParam.name}.or_else(|| options.${headerParam.name}.clone())`,
|
|
694
|
+
body: (indent) => `${indent.get()}request.insert_header("${headerParam.header}", ${headerParam.name});\n`,
|
|
695
|
+
});
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
body += getParamValueHelper(indent, headerParam, inClosure, () => {
|
|
686
699
|
if (headerParam.kind === 'headerHashMap') {
|
|
687
700
|
let setter = `for (k, v) in &${headerParam.name} {\n`;
|
|
688
701
|
setter += `${indent.push().get()}request.insert_header(format!("${headerParam.header}-{}", k), v);\n`;
|
|
689
702
|
setter += `${indent.pop().get()}}\n`;
|
|
690
703
|
return setter;
|
|
691
704
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
705
|
+
// for non-copyable params (e.g. String), we need to borrow them if they're on the
|
|
706
|
+
// client or we're in a closure and the param is required (header params are always owned)
|
|
707
|
+
const borrow = nonCopyableType(headerParam.type) && (headerParam.location === 'client' || (inClosure && !headerParam.optional)) ? '&' : '';
|
|
708
|
+
return `${indent.get()}request.insert_header("${headerParam.header.toLowerCase()}", ${borrow}${getHeaderPathQueryParamValue(use, headerParam, !inClosure)});\n`;
|
|
695
709
|
});
|
|
696
710
|
}
|
|
697
711
|
const bodyParam = paramGroups.body;
|
|
698
712
|
if (bodyParam) {
|
|
699
|
-
body += getParamValueHelper(indent, bodyParam, () => {
|
|
700
|
-
return `${indent.get()}request.set_body(${bodyParam.name});\n`;
|
|
713
|
+
body += getParamValueHelper(indent, bodyParam, inClosure, () => {
|
|
714
|
+
return `${indent.get()}request.set_body(${bodyParam.name}${inClosure ? '.clone()' : ''});\n`;
|
|
701
715
|
});
|
|
702
716
|
}
|
|
703
717
|
else if (paramGroups.partialBody.length > 0) {
|
|
@@ -708,16 +722,13 @@ function constructRequest(indent, use, method, paramGroups, fromSelf = true) {
|
|
|
708
722
|
indent.push();
|
|
709
723
|
for (const partialBodyParam of paramGroups.partialBody) {
|
|
710
724
|
if (partialBodyParam.type.content.type !== requestContentType.content.type) {
|
|
711
|
-
throw new
|
|
725
|
+
throw new CodegenError('InternalError', `spread param ${partialBodyParam.name} has conflicting model type ${partialBodyParam.type.content.type.name}, expected model type ${requestContentType.content.type.name}`);
|
|
712
726
|
}
|
|
713
727
|
if (partialBodyParam.optional) {
|
|
714
728
|
body += `${indent.get()}${partialBodyParam.name}: options.${partialBodyParam.name},\n`;
|
|
715
729
|
continue;
|
|
716
730
|
}
|
|
717
731
|
let initializer = partialBodyParam.name;
|
|
718
|
-
if (partialBodyParam.ref) {
|
|
719
|
-
initializer = `${initializer}.to_owned()`;
|
|
720
|
-
}
|
|
721
732
|
if (requestContentType.content.type.visibility === 'pub') {
|
|
722
733
|
// spread param maps to a non-internal model, so it must be wrapped in Some()
|
|
723
734
|
initializer = `Some(${initializer})`;
|
|
@@ -761,7 +772,7 @@ function getAsyncMethodBody(indent, use, client, method) {
|
|
|
761
772
|
body += `${indent.get()}let ctx = Context::with_context(&options.method_options.context);\n`;
|
|
762
773
|
body += `${indent.get()}let ${urlVarNeedsMut(paramGroups, method)}url = self.${getEndpointFieldName(client)}.clone();\n`;
|
|
763
774
|
body += constructUrl(indent, use, method, paramGroups);
|
|
764
|
-
body += constructRequest(indent, use, method, paramGroups);
|
|
775
|
+
body += constructRequest(indent, use, method, paramGroups, false);
|
|
765
776
|
body += `${indent.get()}self.pipeline.send(&ctx, &mut request).await\n`;
|
|
766
777
|
return body;
|
|
767
778
|
}
|
|
@@ -776,14 +787,10 @@ function getAsyncMethodBody(indent, use, client, method) {
|
|
|
776
787
|
*/
|
|
777
788
|
function getPageableMethodBody(indent, use, client, method) {
|
|
778
789
|
if (!method.strategy) {
|
|
779
|
-
throw new
|
|
780
|
-
}
|
|
781
|
-
else if (method.strategy.kind !== 'nextLink') {
|
|
782
|
-
throw new Error('paged methods other than nextLink NYI');
|
|
790
|
+
throw new CodegenError('InternalError', 'paged method with no strategy NYI');
|
|
783
791
|
}
|
|
784
|
-
const nextLinkName = method.strategy.nextLink.name;
|
|
785
792
|
use.add('azure_core::http', 'Method', 'Pager', 'PagerResult', 'Request', 'Response', 'Url');
|
|
786
|
-
use.add('azure_core',
|
|
793
|
+
use.add('azure_core', method.returns.type.type.format, 'Result');
|
|
787
794
|
use.addForType(method.returns.type.type.type);
|
|
788
795
|
const paramGroups = getMethodParamGroup(method);
|
|
789
796
|
const urlVar = 'first_url';
|
|
@@ -794,49 +801,114 @@ function getPageableMethodBody(indent, use, client, method) {
|
|
|
794
801
|
if (paramGroups.apiVersion) {
|
|
795
802
|
body += `${indent.get()}let ${paramGroups.apiVersion.name} = ${getHeaderPathQueryParamValue(use, paramGroups.apiVersion, true)}.clone();\n`;
|
|
796
803
|
}
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
body
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
804
|
+
switch (method.strategy.kind) {
|
|
805
|
+
case 'continuationToken': {
|
|
806
|
+
const reqTokenParam = method.strategy.requestToken.name;
|
|
807
|
+
body += `${indent.get()}Ok(Pager::from_callback(move |${reqTokenParam}: Option<String>| {\n`;
|
|
808
|
+
body += `${indent.push().get()}let ${method.strategy.requestToken.kind === 'query' ? 'mut ' : ''}url = first_url.clone();\n`;
|
|
809
|
+
if (method.strategy.requestToken.kind === 'query') {
|
|
810
|
+
// if the url already contains the token query param,
|
|
811
|
+
// e.g. we started on some page, then we need to remove
|
|
812
|
+
// it before appending the token for the next page.
|
|
813
|
+
const reqTokenValue = method.strategy.requestToken.key;
|
|
814
|
+
body += `${indent.get()}${helpers.buildIfBlock(indent, {
|
|
815
|
+
condition: `let Some(${reqTokenParam}) = ${reqTokenParam}`,
|
|
816
|
+
body: (indent) => {
|
|
817
|
+
let body = indent.get() + helpers.buildIfBlock(indent, {
|
|
818
|
+
condition: `url.query_pairs().any(|(name, _)| name.eq("${reqTokenValue}"))`,
|
|
819
|
+
body: (indent) => {
|
|
820
|
+
let body = `${indent.get()}let mut new_url = url.clone();\n`;
|
|
821
|
+
body += `${indent.get()}new_url.query_pairs_mut().clear().extend_pairs(url.query_pairs().filter(|(name, _)| name.ne("${reqTokenValue}")));\n`;
|
|
822
|
+
body += `${indent.get()}url = new_url;\n`;
|
|
823
|
+
return body;
|
|
824
|
+
},
|
|
825
|
+
});
|
|
826
|
+
body += `${indent.get()}url.query_pairs_mut().append_pair("${reqTokenValue}", &${reqTokenParam});\n`;
|
|
827
|
+
return body;
|
|
828
|
+
}
|
|
829
|
+
})}`;
|
|
814
830
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
831
|
+
break;
|
|
832
|
+
}
|
|
833
|
+
case 'nextLink': {
|
|
834
|
+
const nextLinkName = method.strategy.nextLink.name;
|
|
835
|
+
body += `${indent.get()}Ok(Pager::from_callback(move |${nextLinkName}: Option<Url>| {\n`;
|
|
836
|
+
body += `${indent.push().get()}let url = ` + helpers.buildMatch(indent, nextLinkName, [{
|
|
837
|
+
pattern: `Some(${nextLinkName})`,
|
|
838
|
+
body: (indent) => {
|
|
839
|
+
if (paramGroups.apiVersion && paramGroups.apiVersion.kind === 'query') {
|
|
840
|
+
const apiVersionKey = `"${paramGroups.apiVersion.key}"`;
|
|
841
|
+
// there are no APIs to set/update an existing query parameter.
|
|
842
|
+
// so, we filter the existing query params to remove the api-version
|
|
843
|
+
// query param. we then add back the filtered set and then add the
|
|
844
|
+
// api-version as specified on the client.
|
|
845
|
+
let setApiVerBody = `${indent.get()}let qp = ${nextLinkName}.query_pairs().filter(|(name, _)| name.ne(${apiVersionKey}));\n`;
|
|
846
|
+
setApiVerBody += `${indent.get()}let mut ${nextLinkName} = ${nextLinkName}.clone();\n`;
|
|
847
|
+
setApiVerBody += `${indent.get()}${nextLinkName}.query_pairs_mut().clear().extend_pairs(qp).append_pair(${apiVersionKey}, &${paramGroups.apiVersion.name});\n`;
|
|
848
|
+
setApiVerBody += `${indent.get()}${nextLinkName}\n`;
|
|
849
|
+
return setApiVerBody;
|
|
850
|
+
}
|
|
851
|
+
return `${indent.get()} ${nextLinkName}\n`;
|
|
852
|
+
}
|
|
853
|
+
}, {
|
|
854
|
+
pattern: 'None',
|
|
855
|
+
body: (indent) => `${indent.get()}${urlVar}.clone()\n`
|
|
856
|
+
}]);
|
|
857
|
+
body += ';\n';
|
|
858
|
+
break;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
820
861
|
// here we want the T in Pager<T>
|
|
821
862
|
const returnType = helpers.getTypeDeclaration(method.returns.type.type.type);
|
|
822
|
-
body += constructRequest(indent, use, method, paramGroups,
|
|
863
|
+
body += constructRequest(indent, use, method, paramGroups, true);
|
|
823
864
|
body += `${indent.get()}let ctx = options.method_options.context.clone();\n`;
|
|
824
865
|
body += `${indent.get()}let pipeline = pipeline.clone();\n`;
|
|
825
866
|
body += `${indent.get()}async move {\n`;
|
|
826
867
|
body += `${indent.push().get()}let rsp: Response<${returnType}> = pipeline.send(&ctx, &mut request).await?;\n`;
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
868
|
+
// check if we need to extract the next link field from the response model
|
|
869
|
+
if (method.strategy.kind === 'nextLink' || method.strategy.responseToken.kind === 'modelField') {
|
|
870
|
+
body += `${indent.get()}let (status, headers, body) = rsp.deconstruct();\n`;
|
|
871
|
+
body += `${indent.get()}let bytes = body.collect().await?;\n`;
|
|
872
|
+
const deserialize = method.returns.type.type.format === 'json' ? 'json::from_json' : 'xml::read_xml';
|
|
873
|
+
body += `${indent.get()}let res: ${returnType} = ${deserialize}(&bytes)?;\n`;
|
|
874
|
+
body += `${indent.get()}let rsp = Response::from_bytes(status, headers, bytes);\n`;
|
|
875
|
+
}
|
|
876
|
+
let srcNextPage;
|
|
877
|
+
let nextPageValue;
|
|
878
|
+
let continuation;
|
|
879
|
+
switch (method.strategy.kind) {
|
|
880
|
+
case 'continuationToken':
|
|
881
|
+
nextPageValue = method.strategy.responseToken.name;
|
|
882
|
+
continuation = nextPageValue;
|
|
883
|
+
switch (method.strategy.responseToken.kind) {
|
|
884
|
+
case 'modelField':
|
|
885
|
+
srcNextPage = `res.${nextPageValue}`;
|
|
886
|
+
break;
|
|
887
|
+
case 'responseHeaderScalar':
|
|
888
|
+
if (!method.responseHeaders) {
|
|
889
|
+
throw new CodegenError('InternalError', `missing response headers trait for method ${method.name}`);
|
|
890
|
+
}
|
|
891
|
+
use.addForType(method.responseHeaders);
|
|
892
|
+
srcNextPage = `rsp.${method.strategy.responseToken.name}()?`;
|
|
893
|
+
break;
|
|
894
|
+
}
|
|
895
|
+
break;
|
|
896
|
+
case 'nextLink':
|
|
897
|
+
nextPageValue = method.strategy.nextLink.name;
|
|
898
|
+
srcNextPage = `res.${nextPageValue}`;
|
|
899
|
+
continuation = `${nextPageValue}.parse()?`;
|
|
900
|
+
break;
|
|
901
|
+
}
|
|
902
|
+
// we need to handle the case where the next page value is the empty string,
|
|
903
|
+
// so checking strickly for None(theNextLink) is insufficient.
|
|
904
|
+
// the most common case for this is XML, e.g. an empty tag like <NextLink />
|
|
905
|
+
body += `${indent.get()}let ${nextPageValue} = ${srcNextPage}.unwrap_or_default();\n`;
|
|
906
|
+
body += `${indent.get()}Ok(${helpers.buildIfBlock(indent, {
|
|
907
|
+
condition: `${nextPageValue}.is_empty()`,
|
|
908
|
+
body: (indent) => `${indent.get()}PagerResult::Complete { response: rsp }\n`,
|
|
909
|
+
}, {
|
|
910
|
+
body: (indent) => `${indent.get()} PagerResult::Continue { response: rsp, continuation: ${continuation} }\n`,
|
|
911
|
+
})}`;
|
|
840
912
|
body += ')\n'; // end Ok
|
|
841
913
|
body += `${indent.pop().get()}}\n`; // end async move
|
|
842
914
|
body += `${indent.pop().get()}}))`; // end Ok/Pager::from_callback
|
|
@@ -862,7 +934,7 @@ function getClientEndpointParamValue(param) {
|
|
|
862
934
|
case 'scalar':
|
|
863
935
|
return `&${paramName}.to_string()`;
|
|
864
936
|
default:
|
|
865
|
-
throw new
|
|
937
|
+
throw new CodegenError('InternalError', `unhandled ${param.kind} param type kind ${param.type.kind}`);
|
|
866
938
|
}
|
|
867
939
|
}
|
|
868
940
|
/**
|
|
@@ -913,51 +985,52 @@ function getHeaderPathQueryParamValue(use, param, fromSelf) {
|
|
|
913
985
|
return `${param}.unix_timestamp().to_string()`;
|
|
914
986
|
}
|
|
915
987
|
};
|
|
988
|
+
const paramType = helpers.unwrapType(param.type);
|
|
916
989
|
if (param.kind === 'headerCollection' || param.kind === 'queryCollection') {
|
|
917
990
|
if (param.format === 'multi') {
|
|
918
|
-
throw new
|
|
991
|
+
throw new CodegenError('InternalError', 'multi should have been handled outside getHeaderPathQueryParamValue');
|
|
919
992
|
}
|
|
920
|
-
else if (
|
|
993
|
+
else if (paramType.kind === 'String' || paramType.kind === 'str') {
|
|
921
994
|
return `${paramName}.join("${getCollectionDelimiter(param.format)}")`;
|
|
922
995
|
}
|
|
923
996
|
// convert the items to strings
|
|
924
997
|
let strConv;
|
|
925
|
-
switch (
|
|
998
|
+
switch (paramType.kind) {
|
|
926
999
|
case 'encodedBytes':
|
|
927
|
-
strConv = encodeBytes(
|
|
1000
|
+
strConv = encodeBytes(paramType);
|
|
928
1001
|
break;
|
|
929
1002
|
case 'offsetDateTime':
|
|
930
|
-
strConv = `|i| ${encodeDateTime(
|
|
1003
|
+
strConv = `|i| ${encodeDateTime(paramType, 'i')}`;
|
|
931
1004
|
break;
|
|
932
1005
|
default:
|
|
933
1006
|
strConv = '|i| i.to_string()';
|
|
934
1007
|
}
|
|
935
1008
|
return `${param.name}.iter().map(${strConv}).collect::<Vec<String>>().join("${getCollectionDelimiter(param.format)}")`;
|
|
936
1009
|
}
|
|
937
|
-
switch (
|
|
1010
|
+
switch (paramType.kind) {
|
|
938
1011
|
case 'String':
|
|
939
1012
|
case 'str':
|
|
940
1013
|
return paramName;
|
|
1014
|
+
case 'decimal':
|
|
1015
|
+
return `${param.name}.to_string()`;
|
|
941
1016
|
case 'encodedBytes':
|
|
942
|
-
return encodeBytes(
|
|
1017
|
+
return encodeBytes(paramType, paramName);
|
|
943
1018
|
case 'enum':
|
|
944
1019
|
case 'scalar':
|
|
945
|
-
if (
|
|
1020
|
+
if (paramType.kind === 'enum' && param.kind === 'query') {
|
|
946
1021
|
// append_pair wants a reference to the string
|
|
947
1022
|
// TODO: https://github.com/Azure/typespec-rust/issues/25
|
|
948
1023
|
return `${paramName}.as_ref()`;
|
|
949
1024
|
}
|
|
950
1025
|
return `${paramName}.to_string()`;
|
|
951
1026
|
case 'enumValue':
|
|
952
|
-
return `${
|
|
953
|
-
case 'implTrait':
|
|
954
|
-
return `${paramName}.into()`;
|
|
1027
|
+
return `${paramType.type.name}::${paramType.name}.to_string()`;
|
|
955
1028
|
case 'literal':
|
|
956
|
-
return `"${
|
|
1029
|
+
return `"${paramType.value}"`;
|
|
957
1030
|
case 'offsetDateTime':
|
|
958
|
-
return encodeDateTime(
|
|
1031
|
+
return encodeDateTime(paramType, param.name);
|
|
959
1032
|
default:
|
|
960
|
-
throw new
|
|
1033
|
+
throw new CodegenError('InternalError', `unhandled ${param.kind} param type kind ${paramType.kind}`);
|
|
961
1034
|
}
|
|
962
1035
|
}
|
|
963
1036
|
/**
|