@azure-tools/typespec-rust 0.29.0 → 0.30.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.
- package/dist/src/codegen/clients.js +214 -97
- package/dist/src/codegen/clients.js.map +1 -1
- package/dist/src/codegen/codeGenerator.d.ts.map +1 -1
- package/dist/src/codegen/codeGenerator.js +3 -1
- package/dist/src/codegen/codeGenerator.js.map +1 -1
- package/dist/src/codegen/context.d.ts +1 -1
- package/dist/src/codegen/context.d.ts.map +1 -1
- package/dist/src/codegen/context.js +1 -1
- package/dist/src/codegen/context.js.map +1 -1
- package/dist/src/codegen/enums.js +0 -1
- package/dist/src/codegen/enums.js.map +1 -1
- package/dist/src/codegen/helpers.d.ts +4 -0
- package/dist/src/codegen/helpers.d.ts.map +1 -1
- package/dist/src/codegen/helpers.js +23 -2
- package/dist/src/codegen/helpers.js.map +1 -1
- package/dist/src/codegen/mod.d.ts.map +1 -1
- package/dist/src/codegen/mod.js +4 -1
- package/dist/src/codegen/mod.js.map +1 -1
- package/dist/src/codegen/unions.d.ts +8 -1
- package/dist/src/codegen/unions.d.ts.map +1 -1
- package/dist/src/codegen/unions.js +42 -13
- package/dist/src/codegen/unions.js.map +1 -1
- package/dist/src/codegen/use.d.ts.map +1 -1
- package/dist/src/codegen/use.js +2 -1
- package/dist/src/codegen/use.js.map +1 -1
- package/dist/src/codemodel/client.d.ts +5 -0
- package/dist/src/codemodel/client.d.ts.map +1 -1
- package/dist/src/codemodel/client.js +1 -0
- package/dist/src/codemodel/client.js.map +1 -1
- package/dist/src/codemodel/crate.d.ts +1 -1
- package/dist/src/codemodel/crate.d.ts.map +1 -1
- package/dist/src/codemodel/crate.js +1 -1
- package/dist/src/codemodel/crate.js.map +1 -1
- package/dist/src/codemodel/types.d.ts +20 -22
- package/dist/src/codemodel/types.d.ts.map +1 -1
- package/dist/src/codemodel/types.js +8 -10
- package/dist/src/codemodel/types.js.map +1 -1
- package/dist/src/emitter.d.ts.map +1 -1
- package/dist/src/emitter.js +18 -15
- package/dist/src/emitter.js.map +1 -1
- package/dist/src/lib.d.ts +2 -0
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +6 -0
- package/dist/src/lib.js.map +1 -1
- package/dist/src/tcgcadapter/adapter.d.ts +5 -13
- package/dist/src/tcgcadapter/adapter.d.ts.map +1 -1
- package/dist/src/tcgcadapter/adapter.js +73 -88
- package/dist/src/tcgcadapter/adapter.js.map +1 -1
- package/dist/src/tcgcadapter/naming.d.ts +2 -1
- package/dist/src/tcgcadapter/naming.d.ts.map +1 -1
- package/dist/src/tcgcadapter/naming.js +3 -2
- package/dist/src/tcgcadapter/naming.js.map +1 -1
- package/package.json +2 -2
|
@@ -10,6 +10,7 @@ import { CodegenError } from './errors.js';
|
|
|
10
10
|
import * as helpers from './helpers.js';
|
|
11
11
|
import queryString from 'query-string';
|
|
12
12
|
import { Use } from './use.js';
|
|
13
|
+
import * as rust from '../codemodel/index.js';
|
|
13
14
|
import * as shared from '../shared/shared.js';
|
|
14
15
|
/**
|
|
15
16
|
* emits the content for all client files
|
|
@@ -43,7 +44,7 @@ export function emitClients(crate) {
|
|
|
43
44
|
body += `${indent.get()}${helpers.emitVisibility(field.visibility)}${field.name}: ${helpers.getTypeDeclaration(field.type)},\n`;
|
|
44
45
|
}
|
|
45
46
|
body += '}\n\n'; // end client
|
|
46
|
-
if (client.constructable) {
|
|
47
|
+
if (client.constructable && !client.constructable.suppressed) {
|
|
47
48
|
// if client options doesn't require an impl for Default then just derive it
|
|
48
49
|
let deriveDefault = 'Default, ';
|
|
49
50
|
if (clientOptionsImplDefault(client.constructable)) {
|
|
@@ -67,7 +68,7 @@ export function emitClients(crate) {
|
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
70
|
body += `impl ${client.name} {\n`;
|
|
70
|
-
if (client.constructable) {
|
|
71
|
+
if (client.constructable && !client.constructable.suppressed) {
|
|
71
72
|
// this is an instantiable client, so we need to emit client options and constructors
|
|
72
73
|
use.add('azure_core', 'Result');
|
|
73
74
|
for (let i = 0; i < client.constructable.constructors.length; ++i) {
|
|
@@ -188,7 +189,7 @@ export function emitClients(crate) {
|
|
|
188
189
|
case 'lro':
|
|
189
190
|
isPublicApi = true;
|
|
190
191
|
methodBody = (indentation) => {
|
|
191
|
-
return getLroMethodBody(indentation, use, client, method);
|
|
192
|
+
return getLroMethodBody(crate, indentation, use, client, method);
|
|
192
193
|
};
|
|
193
194
|
break;
|
|
194
195
|
case 'clientaccessor':
|
|
@@ -657,14 +658,15 @@ function getMethodParamGroup(method) {
|
|
|
657
658
|
* @param indent the indentation helper currently in scope
|
|
658
659
|
* @param param the parameter to which the contents of setter apply
|
|
659
660
|
* @param setter the callback that emits the code to read from a param var
|
|
660
|
-
* @param
|
|
661
|
+
* @param optionsPrefix Syntax to access the options structure, including the dot
|
|
661
662
|
* @returns
|
|
662
663
|
*/
|
|
663
|
-
function getParamValueHelper(indent, param,
|
|
664
|
+
function getParamValueHelper(indent, param, setter, optionsPrefix = 'options.') {
|
|
664
665
|
if (param.optional && param.type.kind !== 'literal') {
|
|
666
|
+
const asRef = nonCopyableType(param.type) || isEnumString(param.type) ? '.as_ref()' : '';
|
|
665
667
|
// optional params are in the unwrapped options local var
|
|
666
668
|
const op = indent.get() + helpers.buildIfBlock(indent, {
|
|
667
|
-
condition: `let Some(${param.name}) = ${
|
|
669
|
+
condition: `let Some(${param.name}) = ${param.location === 'client' ? 'self.' : optionsPrefix}${param.name}${asRef}`,
|
|
668
670
|
body: setter,
|
|
669
671
|
});
|
|
670
672
|
return op + '\n';
|
|
@@ -777,7 +779,7 @@ function constructUrl(indent, use, method, paramGroups, urlVarName) {
|
|
|
777
779
|
}
|
|
778
780
|
}
|
|
779
781
|
if (pathParam.optional) {
|
|
780
|
-
body += `${indent.get()}${pathVarName} = ${helpers.buildMatch(indent, `options.${pathParam.name}`, [{
|
|
782
|
+
body += `${indent.get()}${pathVarName} = ${helpers.buildMatch(indent, `options.${pathParam.name}${nonCopyableType(pathParam.type) ? '.as_ref()' : ''}`, [{
|
|
781
783
|
pattern: `Some(${pathParam.name})`,
|
|
782
784
|
body: (indent) => wrapSortedVec(`${indent.get()}${pathVarName}.replace("{${pathParam.segment}}", ${paramExpression})\n`),
|
|
783
785
|
}, {
|
|
@@ -793,8 +795,15 @@ function constructUrl(indent, use, method, paramGroups, urlVarName) {
|
|
|
793
795
|
body += `${indent.get()}${urlVarName}.append_path(${path});\n`;
|
|
794
796
|
}
|
|
795
797
|
}
|
|
798
|
+
let hasQueryBuilder = false;
|
|
799
|
+
const getQueryBuilder = function () {
|
|
800
|
+
hasQueryBuilder = true;
|
|
801
|
+
use.add('azure_core::http', 'UrlExt');
|
|
802
|
+
return `${indent.get()}let mut query_builder = ${urlVarName}.query_builder();\n`;
|
|
803
|
+
};
|
|
796
804
|
if (pathChunks.length === 2) {
|
|
797
|
-
body +=
|
|
805
|
+
body += getQueryBuilder();
|
|
806
|
+
body += `${indent.get()}query_builder`;
|
|
798
807
|
// set the query params that were in the path
|
|
799
808
|
const qps = queryString.parse(pathChunks[1]);
|
|
800
809
|
for (const qp of Object.keys(qps)) {
|
|
@@ -815,39 +824,47 @@ function constructUrl(indent, use, method, paramGroups, urlVarName) {
|
|
|
815
824
|
}
|
|
816
825
|
body += ';\n';
|
|
817
826
|
}
|
|
827
|
+
if (paramGroups.query.length > 0 && !hasQueryBuilder) {
|
|
828
|
+
body += getQueryBuilder();
|
|
829
|
+
}
|
|
818
830
|
for (const queryParam of paramGroups.query) {
|
|
819
831
|
if (queryParam.kind === 'queryCollection' && queryParam.format === 'multi') {
|
|
820
|
-
body += getParamValueHelper(indent, queryParam,
|
|
832
|
+
body += getParamValueHelper(indent, queryParam, () => {
|
|
821
833
|
const valueVar = queryParam.name[0];
|
|
822
834
|
let text = `${indent.get()}for ${valueVar} in ${queryParam.name}.iter() {\n`;
|
|
823
|
-
|
|
835
|
+
// if queryParam is a &[&str] then we'll need to deref the iterator
|
|
836
|
+
const deref = shared.asTypeOf(queryParam.type, 'str', 'ref', 'slice', 'ref') ? '*' : '';
|
|
837
|
+
text += `${indent.push().get()}query_builder.append_pair("${queryParam.key}", ${deref}${getHeaderPathQueryParamValue(use, queryParam, !queryParam.optional, false, valueVar)});\n`;
|
|
824
838
|
text += `${indent.pop().get()}}\n`;
|
|
825
839
|
return text;
|
|
826
840
|
});
|
|
827
841
|
}
|
|
828
842
|
else if (queryParam.kind === 'queryHashMap') {
|
|
829
|
-
body += getParamValueHelper(indent, queryParam,
|
|
843
|
+
body += getParamValueHelper(indent, queryParam, () => {
|
|
830
844
|
let text = `${indent.get()}{\n`;
|
|
831
845
|
text += `${indent.push().get()}let mut ${queryParam.name}_vec = ${queryParam.name}.iter().collect::<Vec<_>>();\n`;
|
|
832
846
|
text += `${indent.get()}${queryParam.name}_vec.sort_by_key(|p| p.0);\n`;
|
|
833
847
|
if (queryParam.explode) {
|
|
834
848
|
text += `${indent.get()}for (k, v) in ${queryParam.name}_vec.iter() {\n`;
|
|
835
|
-
text += `${indent.push().get()}
|
|
849
|
+
text += `${indent.push().get()}query_builder.append_pair(*k, v.to_string());\n`;
|
|
836
850
|
text += `${indent.pop().get()}}\n`;
|
|
837
851
|
}
|
|
838
852
|
else {
|
|
839
|
-
text += `${indent.get()}
|
|
853
|
+
text += `${indent.get()}query_builder.set_pair("${queryParam.key}", ${queryParam.name}_vec.iter().map(|(k, v)| format!("{k},{v}")).collect::<Vec<String>>().join(","));\n`;
|
|
840
854
|
}
|
|
841
855
|
text += `${indent.pop().get()}}\n`;
|
|
842
856
|
return text;
|
|
843
857
|
});
|
|
844
858
|
}
|
|
845
859
|
else {
|
|
846
|
-
body += getParamValueHelper(indent, queryParam,
|
|
847
|
-
return `${indent.get()}
|
|
860
|
+
body += getParamValueHelper(indent, queryParam, () => {
|
|
861
|
+
return `${indent.get()}query_builder.set_pair("${queryParam.key}", ${getHeaderPathQueryParamValue(use, queryParam, !queryParam.optional, false)});\n`;
|
|
848
862
|
});
|
|
849
863
|
}
|
|
850
864
|
}
|
|
865
|
+
if (hasQueryBuilder) {
|
|
866
|
+
body += `${indent.get()}query_builder.build();\n`;
|
|
867
|
+
}
|
|
851
868
|
return body;
|
|
852
869
|
}
|
|
853
870
|
/**
|
|
@@ -858,9 +875,11 @@ function constructUrl(indent, use, method, paramGroups, urlVarName) {
|
|
|
858
875
|
* @param method the method for which we're building the body
|
|
859
876
|
* @param paramGroups the param groups for the provided method
|
|
860
877
|
* @param inClosure indicates if the request is being constructed within a closure (e.g. pageable methods)
|
|
878
|
+
* @param requestVarName name for the request variable
|
|
879
|
+
* @param optionsPrefix Syntax to access the options structure, including the dot
|
|
861
880
|
* @returns the code which sets HTTP headers for the request
|
|
862
881
|
*/
|
|
863
|
-
function applyHeaderParams(indent, use, method, paramGroups, inClosure, requestVarName) {
|
|
882
|
+
function applyHeaderParams(indent, use, method, paramGroups, inClosure, requestVarName, optionsPrefix = 'options.') {
|
|
864
883
|
var _a, _b, _c;
|
|
865
884
|
let body = '';
|
|
866
885
|
for (const headerParam of paramGroups.header) {
|
|
@@ -875,7 +894,7 @@ function applyHeaderParams(indent, use, method, paramGroups, inClosure, requestV
|
|
|
875
894
|
},
|
|
876
895
|
{
|
|
877
896
|
pattern: 'PagerState::Initial',
|
|
878
|
-
body: (indent) => `${indent.get()}
|
|
897
|
+
body: (indent) => `${indent.get()}&${optionsPrefix}${headerParam.name}\n`,
|
|
879
898
|
}
|
|
880
899
|
]) + ';\n';
|
|
881
900
|
body += indent.get() + helpers.buildIfBlock(indent, {
|
|
@@ -890,15 +909,15 @@ function applyHeaderParams(indent, use, method, paramGroups, inClosure, requestV
|
|
|
890
909
|
// this logic happens elsewhere so we skip it here.
|
|
891
910
|
continue;
|
|
892
911
|
}
|
|
893
|
-
body += getParamValueHelper(indent, headerParam,
|
|
912
|
+
body += getParamValueHelper(indent, headerParam, () => {
|
|
894
913
|
if (headerParam.kind === 'headerHashMap') {
|
|
895
|
-
let setter = `for (k, v) in ${headerParam.
|
|
914
|
+
let setter = `for (k, v) in ${headerParam.name} {\n`;
|
|
896
915
|
setter += `${indent.push().get()}${requestVarName}.insert_header(format!("${headerParam.header}-{k}"), v);\n`;
|
|
897
916
|
setter += `${indent.pop().get()}}\n`;
|
|
898
917
|
return setter;
|
|
899
918
|
}
|
|
900
919
|
return `${indent.get()}${requestVarName}.insert_header("${headerParam.header.toLowerCase()}", ${getHeaderPathQueryParamValue(use, headerParam, !inClosure, false)});\n`;
|
|
901
|
-
});
|
|
920
|
+
}, optionsPrefix);
|
|
902
921
|
}
|
|
903
922
|
return body;
|
|
904
923
|
}
|
|
@@ -936,7 +955,7 @@ function constructRequest(indent, use, method, paramGroups, inClosure, urlVarNam
|
|
|
936
955
|
}
|
|
937
956
|
const bodyParam = paramGroups.body;
|
|
938
957
|
if (bodyParam) {
|
|
939
|
-
body += getParamValueHelper(indent, bodyParam,
|
|
958
|
+
body += getParamValueHelper(indent, bodyParam, () => {
|
|
940
959
|
let bodyParamContent = '';
|
|
941
960
|
if (optionalContentTypeParam) {
|
|
942
961
|
bodyParamContent = `${indent.get()}${requestVarName}.insert_header("${optionalContentTypeParam.header.toLowerCase()}", ${getHeaderPathQueryParamValue(use, optionalContentTypeParam, !inClosure, false)});\n`;
|
|
@@ -1117,21 +1136,14 @@ function getPageableMethodBody(indent, use, client, method) {
|
|
|
1117
1136
|
// if the url already contains the token query param,
|
|
1118
1137
|
// e.g. we started on some page, then we need to remove
|
|
1119
1138
|
// it before appending the token for the next page.
|
|
1139
|
+
use.add('azure_core::http', 'UrlExt');
|
|
1120
1140
|
const reqTokenValue = method.strategy.requestToken.key;
|
|
1121
1141
|
body += `${indent.get()}${helpers.buildIfBlock(indent, {
|
|
1122
1142
|
condition: `let PagerState::More(${reqTokenParam}) = ${reqTokenParam}`,
|
|
1123
1143
|
body: (indent) => {
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
let body = `${indent.get()}let mut new_url = url.clone();\n`;
|
|
1128
|
-
body += `${indent.get()}new_url.query_pairs_mut().clear().extend_pairs(url.query_pairs().filter(|(name, _)| name.ne("${reqTokenValue}")));\n`;
|
|
1129
|
-
body += `${indent.get()}url = new_url;\n`;
|
|
1130
|
-
return body;
|
|
1131
|
-
},
|
|
1132
|
-
}) + '\n';
|
|
1133
|
-
body += `${indent.get()}url.query_pairs_mut().append_pair("${reqTokenValue}", &${reqTokenParam});\n`;
|
|
1134
|
-
return body;
|
|
1144
|
+
return `${indent.get()}let mut query_builder = url.query_builder();\n`
|
|
1145
|
+
+ `${indent.get()}query_builder.set_pair("${reqTokenValue}", &${reqTokenParam});\n`
|
|
1146
|
+
+ `${indent.get()}query_builder.build();\n`;
|
|
1135
1147
|
}
|
|
1136
1148
|
})}\n`;
|
|
1137
1149
|
}
|
|
@@ -1147,26 +1159,32 @@ function getPageableMethodBody(indent, use, client, method) {
|
|
|
1147
1159
|
body: (indent) => {
|
|
1148
1160
|
const cloneNextLink = `${indent.get()}let mut ${nextLinkName} = ${nextLinkName}.clone();\n`;
|
|
1149
1161
|
let content = '';
|
|
1162
|
+
let hasQueryBuilder = false;
|
|
1150
1163
|
if (paramGroups.apiVersion && paramGroups.apiVersion.kind === 'queryScalar') {
|
|
1151
|
-
const apiVersionKey = `"${paramGroups.apiVersion.key}"`;
|
|
1152
|
-
// there are no APIs to set/update an existing query parameter.
|
|
1153
|
-
// so, we filter the existing query params to remove the api-version
|
|
1154
|
-
// query param. we then add back the filtered set and then add the
|
|
1155
|
-
// api-version as specified on the client.
|
|
1156
|
-
content = `${indent.get()}let qp = ${nextLinkName}.query_pairs().filter(|(name, _)| name.ne(${apiVersionKey}));\n`;
|
|
1157
1164
|
content += cloneNextLink;
|
|
1158
|
-
|
|
1165
|
+
hasQueryBuilder = true;
|
|
1166
|
+
use.add('azure_core::http', 'UrlExt');
|
|
1167
|
+
content += `${indent.get()}let mut query_builder = ${nextLinkName}.query_builder();\n`;
|
|
1168
|
+
content += `${indent.get()}query_builder.set_pair("${paramGroups.apiVersion.key}", &${paramGroups.apiVersion.name});\n`;
|
|
1159
1169
|
}
|
|
1160
1170
|
else if (reinjectedParams.length > 0) {
|
|
1161
1171
|
// if we didn't clone it above, we'll need to clone it for this case
|
|
1162
1172
|
content += cloneNextLink;
|
|
1163
1173
|
}
|
|
1164
1174
|
// add query params for reinjection
|
|
1175
|
+
if (reinjectedParams.length > 0 && !hasQueryBuilder) {
|
|
1176
|
+
hasQueryBuilder = true;
|
|
1177
|
+
use.add('azure_core::http', 'UrlExt');
|
|
1178
|
+
content += `${indent.get()}let mut query_builder = ${nextLinkName}.query_builder();\n`;
|
|
1179
|
+
}
|
|
1165
1180
|
for (const reinjectedParam of reinjectedParams) {
|
|
1166
|
-
content += getParamValueHelper(indent, reinjectedParam,
|
|
1167
|
-
return `${indent.get()}
|
|
1181
|
+
content += getParamValueHelper(indent, reinjectedParam, () => {
|
|
1182
|
+
return `${indent.get()}query_builder.set_pair("${reinjectedParam.key}", ${getHeaderPathQueryParamValue(use, reinjectedParam, false, false)});\n`;
|
|
1168
1183
|
});
|
|
1169
1184
|
}
|
|
1185
|
+
if (hasQueryBuilder) {
|
|
1186
|
+
content += `${indent.get()}query_builder.build();\n`;
|
|
1187
|
+
}
|
|
1170
1188
|
content += `${indent.get()}${nextLinkName}\n`;
|
|
1171
1189
|
return content;
|
|
1172
1190
|
}
|
|
@@ -1284,18 +1302,22 @@ function getPageableMethodBody(indent, use, client, method) {
|
|
|
1284
1302
|
/**
|
|
1285
1303
|
* constructs the body for an LRO client method
|
|
1286
1304
|
*
|
|
1305
|
+
* @param crate the crate to which method belongs
|
|
1287
1306
|
* @param indent the indentation helper currently in scope
|
|
1288
1307
|
* @param use the use statement builder currently in scope
|
|
1289
1308
|
* @param client the client to which the method belongs
|
|
1290
1309
|
* @param method the method for the body to build
|
|
1291
1310
|
* @returns the contents of the method body
|
|
1292
1311
|
*/
|
|
1293
|
-
function getLroMethodBody(indent, use, client, method) {
|
|
1294
|
-
var _a
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1312
|
+
function getLroMethodBody(crate, indent, use, client, method) {
|
|
1313
|
+
var _a;
|
|
1314
|
+
let pollingStepHeaderName = undefined;
|
|
1315
|
+
for (const header of ['operation-location', 'azure-asyncoperation', 'location']) {
|
|
1316
|
+
if ((_a = method.responseHeaders) === null || _a === void 0 ? void 0 : _a.headers.some(h => h.header.toLowerCase() === header)) {
|
|
1317
|
+
pollingStepHeaderName = header;
|
|
1318
|
+
break;
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1299
1321
|
const bodyFormat = helpers.convertResponseFormat(method.returns.type.type.format);
|
|
1300
1322
|
use.add('azure_core::http', 'Method', 'RawResponse', 'Request', 'Url');
|
|
1301
1323
|
use.add('azure_core::http::headers', 'RETRY_AFTER', 'X_MS_RETRY_AFTER_MS', 'RETRY_AFTER_MS');
|
|
@@ -1319,39 +1341,46 @@ function getLroMethodBody(indent, use, client, method) {
|
|
|
1319
1341
|
const applyApiVersionParam = function (indent, paramGroups, newLinkVarName, existingLinkVarAccessor) {
|
|
1320
1342
|
var _a;
|
|
1321
1343
|
if (((_a = paramGroups.apiVersion) === null || _a === void 0 ? void 0 : _a.kind) === 'queryScalar') {
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
+ `${indent.get()}${newLinkVarName}.
|
|
1344
|
+
use.add('azure_core::http', 'UrlExt');
|
|
1345
|
+
return `${indent.get()}let mut ${newLinkVarName} = ${existingLinkVarAccessor}.clone();\n`
|
|
1346
|
+
+ `${indent.get()}let mut query_builder = ${newLinkVarName}.query_builder();\n`
|
|
1347
|
+
+ `${indent.get()}query_builder.set_pair("${paramGroups.apiVersion.key}", &${paramGroups.apiVersion.name});\n`
|
|
1348
|
+
+ `${indent.get()}query_builder.build();\n`;
|
|
1325
1349
|
}
|
|
1326
1350
|
return '';
|
|
1327
1351
|
};
|
|
1328
|
-
const declareRequest = function (indent, use, method, paramGroups, requestVarName,
|
|
1352
|
+
const declareRequest = function (indent, use, method, paramGroups, requestVarName, linkExpr, forceMut, optionsPrefix) {
|
|
1329
1353
|
let mutRequest = '';
|
|
1330
1354
|
// if the only header is optional Content-Type it will not be used
|
|
1331
1355
|
// by applyHeaderParams() in this case so don't make request mutable
|
|
1332
1356
|
if (forceMut || paramGroups.header.length > 1 || (paramGroups.header.length === 1 && !isOptionalContentTypeHeader(paramGroups.header[0]))) {
|
|
1333
1357
|
mutRequest = 'mut ';
|
|
1334
1358
|
}
|
|
1335
|
-
return `${indent.get()}let ${mutRequest}${requestVarName} = Request::new(${
|
|
1336
|
-
+ applyHeaderParams(indent, use, method, paramGroups, true, requestVarName);
|
|
1359
|
+
return `${indent.get()}let ${mutRequest}${requestVarName} = Request::new(${linkExpr}, Method::Get);\n`
|
|
1360
|
+
+ applyHeaderParams(indent, use, method, paramGroups, true, requestVarName, optionsPrefix);
|
|
1337
1361
|
};
|
|
1338
1362
|
let stateVarName = 'next_link';
|
|
1339
1363
|
let stateVarType = 'Url';
|
|
1340
1364
|
let progressVarName = 'next_link';
|
|
1341
1365
|
let stateNextLinkAccessor = 'next_link';
|
|
1342
1366
|
let pollerStateMoreReturn = 'next_link';
|
|
1343
|
-
let pollerStateInitialReturn =
|
|
1367
|
+
let pollerStateInitialReturn = `${urlVar}.clone()`;
|
|
1344
1368
|
let pollerStatusInProgressReturn = 'next_link';
|
|
1345
|
-
if (method.finalResultStrategy.kind === '
|
|
1346
|
-
|
|
1369
|
+
if (method.finalResultStrategy.kind === 'header' && method.finalResultStrategy.headerName !== pollingStepHeaderName) {
|
|
1370
|
+
// A case when the initial response contains two headers - one (usually, 'azure-asyncoperation') to poll operation status
|
|
1371
|
+
// and another (usually, 'location') to collect the final result. Both values are URLs.
|
|
1372
|
+
// But only the initial response will have these headers, i.e. responses from 'azure-asyncoperation' URL won't have the 'location'.
|
|
1373
|
+
// Therefore, we need to preserve both URLs and pass them between poller states, up to the moment when the operation status
|
|
1374
|
+
// is Succeeded, so that when operation is Succeeded, the poller can send a request to 'location' to collect the result.
|
|
1375
|
+
body += `${indent.get()}struct Progress{ next_link: Url, final_link: Url, }`;
|
|
1347
1376
|
body += `${indent.get()}impl AsRef<str> for Progress{ fn as_ref(&self) -> &str{ self.next_link.as_ref() }}\n`;
|
|
1348
1377
|
stateVarName = 'state';
|
|
1349
1378
|
stateVarType = 'Progress';
|
|
1350
1379
|
progressVarName = 'progress';
|
|
1351
1380
|
stateNextLinkAccessor = 'progress.next_link';
|
|
1352
|
-
pollerStateMoreReturn = 'Progress{next_link,
|
|
1353
|
-
pollerStateInitialReturn =
|
|
1354
|
-
pollerStatusInProgressReturn = 'Progress{next_link,
|
|
1381
|
+
pollerStateMoreReturn = 'Progress{next_link, final_link: progress.final_link}';
|
|
1382
|
+
pollerStateInitialReturn = `Progress{next_link: ${urlVar}.clone(), final_link: ${urlVar}.clone()}`;
|
|
1383
|
+
pollerStatusInProgressReturn = 'Progress{next_link, final_link}';
|
|
1355
1384
|
}
|
|
1356
1385
|
body += `${indent.get()}Ok(${method.returns.type.name}::from_callback(\n`;
|
|
1357
1386
|
body += `${indent.push().get()}move |${stateVarName}: PollerState<${stateVarType}>, poller_options| {\n`;
|
|
@@ -1359,7 +1388,7 @@ function getLroMethodBody(indent, use, client, method) {
|
|
|
1359
1388
|
pattern: `PollerState::More(${progressVarName})`,
|
|
1360
1389
|
body: (indent) => {
|
|
1361
1390
|
return applyApiVersionParam(indent, paramGroups, 'next_link', stateNextLinkAccessor)
|
|
1362
|
-
+ declareRequest(indent, use, method, paramGroups, initialRequestResult.requestVarName, 'next_link')
|
|
1391
|
+
+ declareRequest(indent, use, method, paramGroups, initialRequestResult.requestVarName, 'next_link.clone()')
|
|
1363
1392
|
+ `${indent.get()}(${initialRequestResult.requestVarName}, ${pollerStateMoreReturn})\n`;
|
|
1364
1393
|
},
|
|
1365
1394
|
}, {
|
|
@@ -1372,12 +1401,72 @@ function getLroMethodBody(indent, use, client, method) {
|
|
|
1372
1401
|
}])};\n`;
|
|
1373
1402
|
body += `${indent.get()}let ctx = poller_options.context.clone();\n`;
|
|
1374
1403
|
body += `${indent.get()}let pipeline = pipeline.clone();\n`;
|
|
1404
|
+
if (method.finalResultStrategy.kind === 'originalUri') {
|
|
1405
|
+
body += `${indent.get()}let final_link = url.clone();\n`;
|
|
1406
|
+
for (const headerParam of paramGroups.header.filter(h => h.type.kind !== 'literal' && !isOptionalContentTypeHeader(h))) {
|
|
1407
|
+
if (headerParam.type.kind !== 'enum') {
|
|
1408
|
+
const optionsPrefix = headerParam.optional ? 'options.' : '';
|
|
1409
|
+
body += `${indent.get()}let ${headerParam.name} = ${optionsPrefix}${headerParam.name}.clone();\n`;
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
// Match an ARM PUT operation ("create or update"), which may have immediate 200 OK response with no headers and no poller status
|
|
1414
|
+
const isArmPutLro = bodyFormat === 'json'
|
|
1415
|
+
&& method.httpMethod === 'put'
|
|
1416
|
+
&& method.returns.type.resultType !== undefined
|
|
1417
|
+
&& method.finalResultStrategy.kind === 'header'
|
|
1418
|
+
&& method.finalResultStrategy.headerName === 'azure-asyncoperation'
|
|
1419
|
+
&& pollingStepHeaderName === 'azure-asyncoperation'
|
|
1420
|
+
&& method.statusCodes.some(sc => sc == 200)
|
|
1421
|
+
&& method.statusCodes.some(sc => sc == 201);
|
|
1422
|
+
// Match an ARM PATCH operation ("update"), which may have immediate 200 OK response with no headers and no poller status
|
|
1423
|
+
const isArmPatchLro = bodyFormat === 'json'
|
|
1424
|
+
&& method.httpMethod === 'patch'
|
|
1425
|
+
&& method.returns.type.resultType !== undefined
|
|
1426
|
+
&& method.finalResultStrategy.kind === 'header'
|
|
1427
|
+
&& method.finalResultStrategy.headerName === 'location'
|
|
1428
|
+
&& pollingStepHeaderName === 'location'
|
|
1429
|
+
&& method.statusCodes.some(sc => sc == 200)
|
|
1430
|
+
&& method.statusCodes.some(sc => sc == 202);
|
|
1431
|
+
// Match an ARM POST operation ("export"), which may have empty initial response
|
|
1432
|
+
const isArmPostLro = bodyFormat === 'json'
|
|
1433
|
+
&& method.httpMethod === 'post'
|
|
1434
|
+
&& method.returns.type.resultType !== undefined
|
|
1435
|
+
&& method.finalResultStrategy.kind === 'header'
|
|
1436
|
+
&& method.finalResultStrategy.headerName === 'location'
|
|
1437
|
+
&& pollingStepHeaderName === 'azure-asyncoperation'
|
|
1438
|
+
&& method.statusCodes.some(sc => sc == 200)
|
|
1439
|
+
&& method.statusCodes.some(sc => sc == 202);
|
|
1440
|
+
// Match an ARM DELETE operation, which may have empty responses and only communicate via status codes
|
|
1441
|
+
const isArmDeleteLro = bodyFormat === 'json'
|
|
1442
|
+
&& method.httpMethod === 'delete'
|
|
1443
|
+
&& method.returns.type.resultType === undefined
|
|
1444
|
+
&& method.finalResultStrategy.kind === 'header'
|
|
1445
|
+
&& method.finalResultStrategy.headerName === 'location'
|
|
1446
|
+
&& pollingStepHeaderName === 'location'
|
|
1447
|
+
&& method.statusCodes.some(sc => sc == 200)
|
|
1448
|
+
&& method.statusCodes.some(sc => sc == 202)
|
|
1449
|
+
&& method.statusCodes.some(sc => sc == 204);
|
|
1450
|
+
if (isArmPutLro || isArmPatchLro) {
|
|
1451
|
+
body += 'let original_url = url.clone();\n';
|
|
1452
|
+
}
|
|
1375
1453
|
body += `${indent.get()}async move {\n`;
|
|
1376
1454
|
body += `${indent.push().get()}let rsp = pipeline.send(&ctx, &mut ${initialRequestResult.requestVarName}, ${getPipelineOptions(indent, use, method)}).await?;\n`;
|
|
1377
|
-
|
|
1455
|
+
const needsMutBody = isArmPutLro || isArmPatchLro || isArmPostLro || isArmDeleteLro;
|
|
1456
|
+
body += `${indent.get()}let (status, headers, ${needsMutBody ? 'mut' : ''} body) = rsp.deconstruct();\n`;
|
|
1457
|
+
if (isArmPostLro || isArmDeleteLro) {
|
|
1458
|
+
body += `${indent.get()}if body.is_empty() {\n`;
|
|
1459
|
+
let emptyBodyExpr = '"{}"';
|
|
1460
|
+
if (isArmDeleteLro) {
|
|
1461
|
+
use.add('azure_core::http', 'StatusCode');
|
|
1462
|
+
emptyBodyExpr = `if status == StatusCode::NoContent { "{\\"status\\":\\"Succeeded\\"}" } else { "{}" }`;
|
|
1463
|
+
}
|
|
1464
|
+
body += `${indent.push().get()}body = azure_core::http::response::ResponseBody::from_bytes(${emptyBodyExpr});\n`;
|
|
1465
|
+
body += `${indent.pop().get()}}\n`;
|
|
1466
|
+
}
|
|
1378
1467
|
if (pollingStepHeaderName !== undefined) {
|
|
1379
1468
|
body += `${indent.get()}let next_link = ${helpers.buildMatch(indent, `headers.get_optional_string(&HeaderName::from_static("${pollingStepHeaderName}"))`, [{
|
|
1380
|
-
pattern:
|
|
1469
|
+
pattern: 'Some(operation_location)',
|
|
1381
1470
|
body: (indent) => {
|
|
1382
1471
|
return `${indent.get()}Url::parse(&operation_location)?\n`;
|
|
1383
1472
|
}
|
|
@@ -1388,32 +1477,48 @@ function getLroMethodBody(indent, use, client, method) {
|
|
|
1388
1477
|
}
|
|
1389
1478
|
}])};\n`;
|
|
1390
1479
|
}
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
body += `${indent.get()}let
|
|
1480
|
+
if (isArmPutLro || isArmPatchLro) {
|
|
1481
|
+
use.add('azure_core::http', 'StatusCode');
|
|
1482
|
+
body += `${indent.get()}let mut final_body = None;\n`;
|
|
1483
|
+
body += `${indent.get()}if status == StatusCode::Ok && next_link.as_str() == original_url.as_str() {\n`;
|
|
1484
|
+
body += `${indent.push().get()}final_body = Some(body);\n`;
|
|
1485
|
+
body += `${indent.get()}body = azure_core::http::response::ResponseBody::from_bytes("{\\"status\\":\\"Succeeded\\"}");\n`;
|
|
1486
|
+
body += `${indent.pop().get()}}\n`;
|
|
1394
1487
|
}
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1488
|
+
if (method.finalResultStrategy.kind === 'header' && method.finalResultStrategy.headerName !== pollingStepHeaderName) { // separate link for picking up the result
|
|
1489
|
+
body += `${indent.get()}let final_link = ${helpers.buildMatch(indent, `headers.get_optional_string(&HeaderName::from_static("${method.finalResultStrategy.headerName}"))`, [{
|
|
1490
|
+
pattern: 'Some(final_link)',
|
|
1491
|
+
body: (indent) => {
|
|
1492
|
+
return `${indent.get()}Url::parse(&final_link)?\n`;
|
|
1493
|
+
}
|
|
1494
|
+
}, {
|
|
1495
|
+
pattern: 'None',
|
|
1496
|
+
body: (indent) => {
|
|
1497
|
+
return `${indent.get()}progress.final_link`;
|
|
1498
|
+
}
|
|
1499
|
+
}])};\n`;
|
|
1399
1500
|
}
|
|
1400
1501
|
body += `${indent.get()}let retry_after = get_retry_after(&headers, &[X_MS_RETRY_AFTER_MS, RETRY_AFTER_MS, RETRY_AFTER], &poller_options);\n`;
|
|
1401
1502
|
const deserialize = `${bodyFormat}::from_${bodyFormat}`;
|
|
1402
1503
|
use.add('azure_core', bodyFormat);
|
|
1403
|
-
body += `${indent.get()}let res: ${helpers.getTypeDeclaration(helpers.unwrapType(method.returns.type))} = ${deserialize}(&body)?;\n`;
|
|
1404
|
-
if (method.finalResultStrategy.kind === 'header' && method.finalResultStrategy.headerName === pollingStepHeaderName) {
|
|
1405
|
-
|
|
1406
|
-
body +=
|
|
1407
|
-
body += `${indent.get()}if res.status() == PollerStatus::Succeeded {\n`;
|
|
1408
|
-
indent.push();
|
|
1504
|
+
body += `${indent.push().get()}let res: ${helpers.getTypeDeclaration(helpers.unwrapType(method.returns.type))} = ${deserialize}(&body)?;\n`;
|
|
1505
|
+
if (method.finalResultStrategy.kind === 'header' && method.finalResultStrategy.headerName === pollingStepHeaderName) {
|
|
1506
|
+
body += `${indent.get()}let mut final_rsp: Option<RawResponse> = None;\n`;
|
|
1507
|
+
body += `if res.status() == PollerStatus::Succeeded {\n`;
|
|
1409
1508
|
let responseBodyExpr = 'body.clone()';
|
|
1410
|
-
if (
|
|
1509
|
+
if (isArmPutLro || isArmPatchLro) {
|
|
1510
|
+
responseBodyExpr = 'if let Some(final_body) = final_body { final_body } else { body.clone() }';
|
|
1511
|
+
}
|
|
1512
|
+
else if (method.finalResultStrategy.propertyName !== undefined) {
|
|
1411
1513
|
responseBodyExpr = 'body';
|
|
1412
|
-
|
|
1413
|
-
|
|
1514
|
+
if (bodyFormat === 'json') {
|
|
1515
|
+
crate.addDependency(new rust.CrateDependency('serde_json'));
|
|
1516
|
+
body += `${indent.get()}let body = azure_core::http::response::ResponseBody::from_bytes(`
|
|
1517
|
+
+ `serde_json::from_str::<azure_core::Value>(body.clone().into_string()?.as_str())?["${method.finalResultStrategy.propertyName}"].to_string());\n`;
|
|
1518
|
+
}
|
|
1414
1519
|
}
|
|
1415
|
-
body += `${indent.get()}
|
|
1416
|
-
body +=
|
|
1520
|
+
body += `${indent.get()}final_rsp = Some(RawResponse::from_bytes(status, headers.clone(), ${responseBodyExpr}));\n`;
|
|
1521
|
+
body += `}\n`;
|
|
1417
1522
|
}
|
|
1418
1523
|
body += `${indent.get()}let rsp = RawResponse::from_bytes(status, headers, body).into();\n`;
|
|
1419
1524
|
const arms = [{
|
|
@@ -1426,19 +1531,24 @@ function getLroMethodBody(indent, use, client, method) {
|
|
|
1426
1531
|
arms.push({
|
|
1427
1532
|
pattern: `PollerStatus::Succeeded`,
|
|
1428
1533
|
body: (indent) => {
|
|
1429
|
-
|
|
1534
|
+
let body = `{\n`
|
|
1430
1535
|
+ `${indent.push().get()}PollerResult::Succeeded {\n`
|
|
1431
1536
|
+ `${indent.push().get()}response: rsp,\n`
|
|
1432
1537
|
+ `${indent.get()}target: Box::new(move || {\n`
|
|
1433
|
-
+ `${indent.push().get()}Box::pin(async move {\n
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1538
|
+
+ `${indent.push().get()}Box::pin(async move {\n`;
|
|
1539
|
+
if (method.finalResultStrategy.kind === 'header' && method.finalResultStrategy.headerName === pollingStepHeaderName) {
|
|
1540
|
+
use.add('azure_core::error', 'Error', 'ErrorKind');
|
|
1541
|
+
body += `Ok(final_rsp.ok_or_else(|| { Error::new(ErrorKind::Other, "missing final response")})?.into())\n`;
|
|
1542
|
+
}
|
|
1543
|
+
else {
|
|
1544
|
+
body += declareRequest(indent, use, method, paramGroups, initialRequestResult.requestVarName, 'final_link', true, '')
|
|
1545
|
+
+ `Ok(pipeline.send(&ctx, &mut ${initialRequestResult.requestVarName}, None).await?.into())\n`;
|
|
1546
|
+
}
|
|
1547
|
+
body += `${indent.pop().get()}})\n`
|
|
1439
1548
|
+ `${indent.get()}}),\n`
|
|
1440
1549
|
+ `${indent.pop().get()}}`
|
|
1441
1550
|
+ `${indent.pop().get()}}`;
|
|
1551
|
+
return body;
|
|
1442
1552
|
}
|
|
1443
1553
|
});
|
|
1444
1554
|
arms.push({
|
|
@@ -1494,9 +1604,10 @@ function getClientSupplementalEndpointParamValue(param) {
|
|
|
1494
1604
|
* @param param the param for which to get the value
|
|
1495
1605
|
* @param fromSelf applicable for client params. when true, the prefix "self." is included
|
|
1496
1606
|
* @param neverBorrow indicates that the borrowing calculation should be skipped
|
|
1607
|
+
* @param overrideParamName optional value to use as the parameter name instead of param.name
|
|
1497
1608
|
* @returns the code to use for the param's value
|
|
1498
1609
|
*/
|
|
1499
|
-
function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow) {
|
|
1610
|
+
function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow, overrideParamName) {
|
|
1500
1611
|
let paramName = param.name;
|
|
1501
1612
|
// when fromSelf is false we assume that there's a local with the same name.
|
|
1502
1613
|
// e.g. in pageable methods where we need to clone the params so they can be
|
|
@@ -1504,6 +1615,9 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow) {
|
|
|
1504
1615
|
if (param.location === 'client' && fromSelf) {
|
|
1505
1616
|
paramName = 'self.' + paramName;
|
|
1506
1617
|
}
|
|
1618
|
+
else if (overrideParamName) {
|
|
1619
|
+
paramName = overrideParamName;
|
|
1620
|
+
}
|
|
1507
1621
|
const encodeBytes = function (type, param) {
|
|
1508
1622
|
const encoding = helpers.getBytesEncodingMethod(type.encoding, 'encode', use);
|
|
1509
1623
|
if (param) {
|
|
@@ -1531,13 +1645,11 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow) {
|
|
|
1531
1645
|
let paramValue;
|
|
1532
1646
|
// contains the result from calculating if the
|
|
1533
1647
|
// param requires borrowing.
|
|
1534
|
-
let mustBorrow =
|
|
1648
|
+
let mustBorrow = !helpers.isQueryParameter(param);
|
|
1535
1649
|
const paramType = helpers.unwrapType(param.type);
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
}
|
|
1540
|
-
else if (paramType.kind === 'String' || paramType.kind === 'str') {
|
|
1650
|
+
// we want multi to hit the else case so the necessary conversions etc can happen
|
|
1651
|
+
if ((param.kind === 'headerCollection' || param.kind === 'queryCollection') && param.format !== 'multi') {
|
|
1652
|
+
if (paramType.kind === 'String' || paramType.kind === 'str') {
|
|
1541
1653
|
paramValue = `${paramName}.join("${getCollectionDelimiter(param.format)}")`;
|
|
1542
1654
|
}
|
|
1543
1655
|
else {
|
|
@@ -1560,8 +1672,8 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow) {
|
|
|
1560
1672
|
switch (paramType.kind) {
|
|
1561
1673
|
case 'String':
|
|
1562
1674
|
paramValue = paramName;
|
|
1563
|
-
// if the param is on the client,
|
|
1564
|
-
mustBorrow =
|
|
1675
|
+
// if the param is on the client, then we must borrow
|
|
1676
|
+
mustBorrow = param.location === 'client' && fromSelf;
|
|
1565
1677
|
break;
|
|
1566
1678
|
case 'str':
|
|
1567
1679
|
paramValue = paramName;
|
|
@@ -1576,7 +1688,7 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow) {
|
|
|
1576
1688
|
break;
|
|
1577
1689
|
case 'enum':
|
|
1578
1690
|
case 'scalar':
|
|
1579
|
-
if (paramType
|
|
1691
|
+
if (isEnumString(paramType) && (helpers.isPathParameter(param) || helpers.isQueryParameter(param))) {
|
|
1580
1692
|
// append_pair and path.replace() want a reference to the string
|
|
1581
1693
|
paramValue = `${paramName}.as_ref()`;
|
|
1582
1694
|
// as_ref() elides the need to borrow
|
|
@@ -1676,4 +1788,9 @@ function getPipelineOptions(indent, use, method) {
|
|
|
1676
1788
|
return 'None';
|
|
1677
1789
|
}
|
|
1678
1790
|
}
|
|
1791
|
+
/** narrows type to an Enum type IFF its underlying type is String within the conditional block */
|
|
1792
|
+
function isEnumString(type) {
|
|
1793
|
+
const unwrapped = helpers.unwrapType(type);
|
|
1794
|
+
return unwrapped.kind === 'enum' && unwrapped.type === 'String';
|
|
1795
|
+
}
|
|
1679
1796
|
//# sourceMappingURL=clients.js.map
|