@azure-tools/typespec-go 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +16 -0
  3. package/dist/codegen.go/src/clientFactory.d.ts +3 -0
  4. package/dist/codegen.go/src/clientFactory.d.ts.map +1 -0
  5. package/dist/codegen.go/src/clientFactory.js +77 -0
  6. package/dist/codegen.go/src/clientFactory.js.map +1 -0
  7. package/dist/codegen.go/src/constants.d.ts +3 -0
  8. package/dist/codegen.go/src/constants.d.ts.map +1 -0
  9. package/dist/codegen.go/src/constants.js +59 -0
  10. package/dist/codegen.go/src/constants.js.map +1 -0
  11. package/dist/codegen.go/src/fake/factory.d.ts +3 -0
  12. package/dist/codegen.go/src/fake/factory.d.ts.map +1 -0
  13. package/dist/codegen.go/src/fake/factory.js +69 -0
  14. package/dist/codegen.go/src/fake/factory.js.map +1 -0
  15. package/dist/codegen.go/src/fake/internal.d.ts +14 -0
  16. package/dist/codegen.go/src/fake/internal.d.ts.map +1 -0
  17. package/dist/codegen.go/src/fake/internal.js +197 -0
  18. package/dist/codegen.go/src/fake/internal.js.map +1 -0
  19. package/dist/codegen.go/src/fake/servers.d.ts +14 -0
  20. package/dist/codegen.go/src/fake/servers.d.ts.map +1 -0
  21. package/dist/codegen.go/src/fake/servers.js +1255 -0
  22. package/dist/codegen.go/src/fake/servers.js.map +1 -0
  23. package/dist/codegen.go/src/gomod.d.ts +3 -0
  24. package/dist/codegen.go/src/gomod.d.ts.map +1 -0
  25. package/dist/codegen.go/src/gomod.js +55 -0
  26. package/dist/codegen.go/src/gomod.js.map +1 -0
  27. package/dist/codegen.go/src/helpers.d.ts +32 -0
  28. package/dist/codegen.go/src/helpers.d.ts.map +1 -0
  29. package/dist/codegen.go/src/helpers.js +586 -0
  30. package/dist/codegen.go/src/helpers.js.map +1 -0
  31. package/dist/codegen.go/src/imports.d.ts +11 -0
  32. package/dist/codegen.go/src/imports.d.ts.map +1 -0
  33. package/dist/codegen.go/src/imports.js +65 -0
  34. package/dist/codegen.go/src/imports.js.map +1 -0
  35. package/dist/codegen.go/src/interfaces.d.ts +3 -0
  36. package/dist/codegen.go/src/interfaces.d.ts.map +1 -0
  37. package/dist/codegen.go/src/interfaces.js +36 -0
  38. package/dist/codegen.go/src/interfaces.js.map +1 -0
  39. package/dist/codegen.go/src/models.d.ts +9 -0
  40. package/dist/codegen.go/src/models.d.ts.map +1 -0
  41. package/dist/codegen.go/src/models.js +849 -0
  42. package/dist/codegen.go/src/models.js.map +1 -0
  43. package/dist/codegen.go/src/operations.d.ts +9 -0
  44. package/dist/codegen.go/src/operations.d.ts.map +1 -0
  45. package/dist/codegen.go/src/operations.js +1337 -0
  46. package/dist/codegen.go/src/operations.js.map +1 -0
  47. package/dist/codegen.go/src/options.d.ts +3 -0
  48. package/dist/codegen.go/src/options.d.ts.map +1 -0
  49. package/dist/codegen.go/src/options.js +64 -0
  50. package/dist/codegen.go/src/options.js.map +1 -0
  51. package/dist/codegen.go/src/polymorphics.d.ts +3 -0
  52. package/dist/codegen.go/src/polymorphics.d.ts.map +1 -0
  53. package/dist/codegen.go/src/polymorphics.js +169 -0
  54. package/dist/codegen.go/src/polymorphics.js.map +1 -0
  55. package/dist/codegen.go/src/responses.d.ts +7 -0
  56. package/dist/codegen.go/src/responses.d.ts.map +1 -0
  57. package/dist/codegen.go/src/responses.js +167 -0
  58. package/dist/codegen.go/src/responses.js.map +1 -0
  59. package/dist/codegen.go/src/time.d.ts +8 -0
  60. package/dist/codegen.go/src/time.d.ts.map +1 -0
  61. package/dist/codegen.go/src/time.js +511 -0
  62. package/dist/codegen.go/src/time.js.map +1 -0
  63. package/dist/codemodel.go/src/client.d.ts +96 -0
  64. package/dist/codemodel.go/src/client.d.ts.map +1 -0
  65. package/dist/codemodel.go/src/client.js +114 -0
  66. package/dist/codemodel.go/src/client.js.map +1 -0
  67. package/dist/codemodel.go/src/index.d.ts +6 -0
  68. package/dist/codemodel.go/src/index.d.ts.map +1 -0
  69. package/dist/codemodel.go/src/index.js +10 -0
  70. package/dist/codemodel.go/src/index.js.map +1 -0
  71. package/dist/codemodel.go/src/package.d.ts +49 -0
  72. package/dist/codemodel.go/src/package.d.ts.map +1 -0
  73. package/dist/codemodel.go/src/package.js +86 -0
  74. package/dist/codemodel.go/src/package.js.map +1 -0
  75. package/dist/codemodel.go/src/param.d.ts +162 -0
  76. package/dist/codemodel.go/src/param.d.ts.map +1 -0
  77. package/dist/codemodel.go/src/param.js +189 -0
  78. package/dist/codemodel.go/src/param.js.map +1 -0
  79. package/dist/codemodel.go/src/result.d.ts +102 -0
  80. package/dist/codemodel.go/src/result.d.ts.map +1 -0
  81. package/dist/codemodel.go/src/result.js +119 -0
  82. package/dist/codemodel.go/src/result.js.map +1 -0
  83. package/dist/codemodel.go/src/type.d.ts +181 -0
  84. package/dist/codemodel.go/src/type.d.ts.map +1 -0
  85. package/dist/codemodel.go/src/type.js +242 -0
  86. package/dist/codemodel.go/src/type.js.map +1 -0
  87. package/dist/naming.go/src/mappings.d.ts +3 -0
  88. package/dist/naming.go/src/mappings.d.ts.map +1 -0
  89. package/dist/naming.go/src/mappings.js +128 -0
  90. package/dist/naming.go/src/mappings.js.map +1 -0
  91. package/dist/naming.go/src/naming.d.ts +10 -0
  92. package/dist/naming.go/src/naming.d.ts.map +1 -0
  93. package/dist/naming.go/src/naming.js +114 -0
  94. package/dist/naming.go/src/naming.js.map +1 -0
  95. package/dist/typespec-go/src/emitter.d.ts +5 -0
  96. package/dist/typespec-go/src/emitter.d.ts.map +1 -0
  97. package/dist/typespec-go/src/emitter.js +122 -0
  98. package/dist/typespec-go/src/emitter.js.map +1 -0
  99. package/dist/typespec-go/src/index.d.ts +3 -0
  100. package/dist/typespec-go/src/index.d.ts.map +1 -0
  101. package/dist/typespec-go/src/index.js +7 -0
  102. package/dist/typespec-go/src/index.js.map +1 -0
  103. package/dist/typespec-go/src/lib.d.ts +25 -0
  104. package/dist/typespec-go/src/lib.d.ts.map +1 -0
  105. package/dist/typespec-go/src/lib.js +36 -0
  106. package/dist/typespec-go/src/lib.js.map +1 -0
  107. package/dist/typespec-go/src/tcgcadapter/adapter.d.ts +5 -0
  108. package/dist/typespec-go/src/tcgcadapter/adapter.d.ts.map +1 -0
  109. package/dist/typespec-go/src/tcgcadapter/adapter.js +119 -0
  110. package/dist/typespec-go/src/tcgcadapter/adapter.js.map +1 -0
  111. package/dist/typespec-go/src/tcgcadapter/clients.d.ts +26 -0
  112. package/dist/typespec-go/src/tcgcadapter/clients.d.ts.map +1 -0
  113. package/dist/typespec-go/src/tcgcadapter/clients.js +621 -0
  114. package/dist/typespec-go/src/tcgcadapter/clients.js.map +1 -0
  115. package/dist/typespec-go/src/tcgcadapter/types.d.ts +29 -0
  116. package/dist/typespec-go/src/tcgcadapter/types.d.ts.map +1 -0
  117. package/dist/typespec-go/src/tcgcadapter/types.js +975 -0
  118. package/dist/typespec-go/src/tcgcadapter/types.js.map +1 -0
  119. package/package.json +77 -0
@@ -0,0 +1,849 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import * as go from '../../codemodel.go/src/index.js';
6
+ import { capitalize, comment } from '@azure-tools/codegen';
7
+ import { values } from '@azure-tools/linq';
8
+ import { commentLength, contentPreamble, formatLiteralValue, recursiveUnwrapMapSlice, sortAscending } from './helpers.js';
9
+ import { ImportManager } from './imports.js';
10
+ // Creates the content in models.go
11
+ export async function generateModels(codeModel) {
12
+ if (codeModel.models.length === 0) {
13
+ return {
14
+ models: '',
15
+ serDe: ''
16
+ };
17
+ }
18
+ // this list of packages to import
19
+ const modelImports = new ImportManager();
20
+ const serdeImports = new ImportManager();
21
+ let modelText = contentPreamble(codeModel);
22
+ // we do model generation first as it can add imports to the imports list
23
+ const modelDefs = generateModelDefs(modelImports, serdeImports, codeModel);
24
+ modelText += modelImports.text();
25
+ // structs
26
+ let needsJSONPopulate = false;
27
+ let needsJSONUnpopulate = false;
28
+ let needsJSONPopulateByteArray = false;
29
+ let needsJSONPopulateAny = false;
30
+ let needsJSONPopulateMultipart = false;
31
+ let serdeTextBody = '';
32
+ for (const modelDef of values(modelDefs)) {
33
+ modelText += modelDef.text();
34
+ modelDef.Methods.sort((a, b) => { return sortAscending(a.name, b.name); });
35
+ for (const method of values(modelDef.Methods)) {
36
+ if (method.desc.length > 0) {
37
+ modelText += `${comment(method.desc, '// ', undefined, commentLength)}\n`;
38
+ }
39
+ modelText += method.text;
40
+ }
41
+ modelDef.SerDe.methods.sort((a, b) => { return sortAscending(a.name, b.name); });
42
+ for (const method of values(modelDef.SerDe.methods)) {
43
+ if (method.desc.length > 0) {
44
+ serdeTextBody += `${comment(method.desc, '// ', undefined, commentLength)}\n`;
45
+ }
46
+ serdeTextBody += method.text;
47
+ }
48
+ if (modelDef.SerDe.needsJSONPopulate) {
49
+ needsJSONPopulate = true;
50
+ }
51
+ if (modelDef.SerDe.needsJSONUnpopulate) {
52
+ needsJSONUnpopulate = true;
53
+ }
54
+ if (modelDef.SerDe.needsJSONPopulateByteArray) {
55
+ needsJSONPopulateByteArray = true;
56
+ }
57
+ if (modelDef.SerDe.needsJSONPopulateAny) {
58
+ needsJSONPopulateAny = true;
59
+ }
60
+ if (modelDef.SerDe.needsJSONPopulateMultipart) {
61
+ needsJSONPopulateMultipart = true;
62
+ }
63
+ }
64
+ if (needsJSONPopulate) {
65
+ serdeImports.add('reflect');
66
+ serdeImports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore');
67
+ serdeTextBody += 'func populate(m map[string]any, k string, v any) {\n';
68
+ serdeTextBody += '\tif v == nil {\n';
69
+ serdeTextBody += '\t\treturn\n';
70
+ serdeTextBody += '\t} else if azcore.IsNullValue(v) {\n';
71
+ serdeTextBody += '\t\tm[k] = nil\n';
72
+ serdeTextBody += '\t} else if !reflect.ValueOf(v).IsNil() {\n';
73
+ serdeTextBody += '\t\tm[k] = v\n';
74
+ serdeTextBody += '\t}\n';
75
+ serdeTextBody += '}\n\n';
76
+ }
77
+ if (needsJSONPopulateAny) {
78
+ serdeImports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore');
79
+ serdeTextBody += 'func populateAny(m map[string]any, k string, v any) {\n';
80
+ serdeTextBody += '\tif v == nil {\n';
81
+ serdeTextBody += '\t\treturn\n';
82
+ serdeTextBody += '\t} else if azcore.IsNullValue(v) {\n';
83
+ serdeTextBody += '\t\tm[k] = nil\n';
84
+ serdeTextBody += '\t} else {\n';
85
+ serdeTextBody += '\t\tm[k] = v\n';
86
+ serdeTextBody += '\t}\n';
87
+ serdeTextBody += '}\n\n';
88
+ }
89
+ if (needsJSONPopulateByteArray) {
90
+ serdeImports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore');
91
+ serdeImports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime');
92
+ serdeTextBody += 'func populateByteArray[T any](m map[string]any, k string, b []T, convert func() any) {\n';
93
+ serdeTextBody += '\tif azcore.IsNullValue(b) {\n';
94
+ serdeTextBody += '\t\tm[k] = nil\n';
95
+ serdeTextBody += '\t} else if len(b) == 0 {\n';
96
+ serdeTextBody += '\t\treturn\n';
97
+ serdeTextBody += '\t} else {\n';
98
+ serdeTextBody += '\t\tm[k] = convert()\n';
99
+ serdeTextBody += '\t}\n';
100
+ serdeTextBody += '}\n\n';
101
+ }
102
+ if (needsJSONUnpopulate) {
103
+ serdeImports.add('fmt');
104
+ serdeTextBody += 'func unpopulate(data json.RawMessage, fn string, v any) error {\n';
105
+ serdeTextBody += '\tif data == nil || string(data) == "null" {\n';
106
+ serdeTextBody += '\t\treturn nil\n';
107
+ serdeTextBody += '\t}\n';
108
+ serdeTextBody += '\tif err := json.Unmarshal(data, v); err != nil {\n';
109
+ serdeTextBody += '\t\treturn fmt.Errorf("struct field %s: %v", fn, err)\n';
110
+ serdeTextBody += '\t}\n';
111
+ serdeTextBody += '\treturn nil\n';
112
+ serdeTextBody += '}\n\n';
113
+ }
114
+ if (needsJSONPopulateMultipart) {
115
+ serdeImports.add('encoding/json');
116
+ serdeTextBody += 'func populateMultipartJSON(m map[string]any, k string, v any) error {\n';
117
+ serdeTextBody += '\tdata, err := json.Marshal(v)\n';
118
+ serdeTextBody += '\tif err != nil {\n\t\treturn err\n\t}\n';
119
+ serdeTextBody += '\tm[k] = data\n\treturn nil\n';
120
+ serdeTextBody += '}\n\n';
121
+ }
122
+ let serdeText = '';
123
+ if (serdeTextBody.length > 0) {
124
+ serdeText = contentPreamble(codeModel);
125
+ serdeText += serdeImports.text();
126
+ serdeText += serdeTextBody;
127
+ }
128
+ return {
129
+ models: modelText,
130
+ serDe: serdeText
131
+ };
132
+ }
133
+ function generateModelDefs(modelImports, serdeImports, codeModel) {
134
+ var _a;
135
+ const models = codeModel.models;
136
+ const modelDefs = new Array();
137
+ for (const model of models) {
138
+ for (const field of model.fields) {
139
+ const descriptionMods = new Array();
140
+ if (field.annotations.readOnly) {
141
+ descriptionMods.push('READ-ONLY');
142
+ }
143
+ else if (field.annotations.required && (!go.isLiteralValue(field.type) || model.usage === go.UsageFlags.Output)) {
144
+ descriptionMods.push('REQUIRED');
145
+ }
146
+ else if (go.isLiteralValue(field.type)) {
147
+ if (!field.annotations.required) {
148
+ descriptionMods.push('FLAG');
149
+ }
150
+ descriptionMods.push('CONSTANT');
151
+ }
152
+ if (go.isLiteralValue(field.type) && model.usage !== go.UsageFlags.Output) {
153
+ // add a comment with the const value for const properties that are sent over the wire
154
+ if (field.description) {
155
+ field.description += '\n';
156
+ }
157
+ field.description += `Field has constant value ${formatLiteralValue(field.type, false)}, any specified value is ignored.`;
158
+ }
159
+ if (field.description) {
160
+ descriptionMods.push(field.description);
161
+ }
162
+ else if (go.isSliceType(field.type) && field.type.rawJSONAsBytes) {
163
+ // add a basic description if one isn't available
164
+ descriptionMods.push('The contents of this field are raw JSON.');
165
+ }
166
+ field.description = descriptionMods.join('; ');
167
+ }
168
+ const modelDef = new ModelDef(model.name, model.format, model.fields, model.description);
169
+ for (const field of values(modelDef.Fields)) {
170
+ modelImports.addImportForType(field.type);
171
+ }
172
+ if (go.isModelType(model) && model.format === 'xml' && !model.annotations.omitSerDeMethods) {
173
+ serdeImports.add('encoding/xml');
174
+ let needsDateTimeMarshalling = false;
175
+ let byteArrayFormat = false;
176
+ for (const field of values(model.fields)) {
177
+ serdeImports.addImportForType(field.type);
178
+ if (go.isTimeType(field.type)) {
179
+ needsDateTimeMarshalling = true;
180
+ }
181
+ else if (go.isBytesType(field.type)) {
182
+ byteArrayFormat = true;
183
+ }
184
+ }
185
+ // due to differences in XML marshallers/unmarshallers, we use different codegen than for JSON
186
+ if (needsDateTimeMarshalling || ((_a = model.xml) === null || _a === void 0 ? void 0 : _a.wrapper) || needsXMLArrayMarshalling(model) || byteArrayFormat) {
187
+ generateXMLMarshaller(model, modelDef, serdeImports);
188
+ if (needsDateTimeMarshalling || byteArrayFormat) {
189
+ generateXMLUnmarshaller(model, modelDef, serdeImports);
190
+ }
191
+ }
192
+ else if (needsXMLDictionaryUnmarshalling(model)) {
193
+ generateXMLUnmarshaller(model, modelDef, serdeImports);
194
+ }
195
+ modelDefs.push(modelDef);
196
+ continue;
197
+ }
198
+ if (go.isPolymorphicType(model)) {
199
+ generateDiscriminatorMarkerMethod(model.interface, modelDef);
200
+ for (let parent = model.interface.parent; parent !== undefined; parent = parent.parent) {
201
+ generateDiscriminatorMarkerMethod(parent, modelDef);
202
+ }
203
+ }
204
+ if (model.annotations.multipartFormData) {
205
+ generateToMultipartForm(modelDef);
206
+ modelDef.SerDe.needsJSONPopulateMultipart = true;
207
+ }
208
+ else if (!model.annotations.omitSerDeMethods) {
209
+ generateJSONMarshaller(model, modelDef, serdeImports);
210
+ generateJSONUnmarshaller(model, modelDef, serdeImports, codeModel.options);
211
+ }
212
+ modelDefs.push(modelDef);
213
+ }
214
+ return modelDefs;
215
+ }
216
+ function needsXMLDictionaryUnmarshalling(modelType) {
217
+ for (const field of values(modelType.fields)) {
218
+ // additional properties uses an internal wrapper type with its own unmarshaller
219
+ if (go.isMapType(field.type) && !field.annotations.isAdditionalProperties) {
220
+ return true;
221
+ }
222
+ }
223
+ return false;
224
+ }
225
+ function needsXMLArrayMarshalling(modelType) {
226
+ for (const prop of values(modelType.fields)) {
227
+ if (go.isSliceType(prop.type)) {
228
+ return true;
229
+ }
230
+ }
231
+ return false;
232
+ }
233
+ // generates discriminator marker method
234
+ function generateDiscriminatorMarkerMethod(type, modelDef) {
235
+ const typeName = type.rootType.name;
236
+ const receiver = modelDef.receiverName();
237
+ const interfaceMethod = `Get${typeName}`;
238
+ let method = `func (${receiver} *${modelDef.Name}) ${interfaceMethod}() *${typeName} {`;
239
+ if (type.rootType.name === modelDef.Name) {
240
+ // the marker method is on the discriminator itself, so just return the receiver
241
+ method += ` return ${receiver} }\n\n`;
242
+ }
243
+ else {
244
+ // the marker method is on a child type, so return an instance of the parent
245
+ // type by copying the parent values into a new instance.
246
+ method += `\n\treturn &${type.rootType.name}{\n`;
247
+ for (const field of values(type.rootType.fields)) {
248
+ method += `\t\t${field.name}: ${modelDef.receiverName()}.${field.name},\n`;
249
+ }
250
+ method += '\t}\n}\n\n';
251
+ }
252
+ modelDef.Methods.push({ name: interfaceMethod, desc: `${interfaceMethod} implements the ${type.name} interface for type ${modelDef.Name}.`, text: method });
253
+ }
254
+ function generateToMultipartForm(modelDef) {
255
+ const receiver = modelDef.receiverName();
256
+ let method = `func (${receiver} ${modelDef.Name}) toMultipartFormData() (map[string]any, error) {\n`;
257
+ method += '\tobjectMap := make(map[string]any)\n';
258
+ for (const field of modelDef.Fields) {
259
+ const fieldType = recursiveUnwrapMapSlice(field.type);
260
+ let setField;
261
+ let star = '';
262
+ if (!field.byValue) {
263
+ star = '*';
264
+ }
265
+ if (go.isModelType(fieldType) && !fieldType.annotations.multipartFormData) {
266
+ setField = `\tif err := populateMultipartJSON(objectMap, "${field.serializedName}", ${star}${receiver}.${field.name}); err != nil {\n\t\treturn nil, err\n\t}\n`;
267
+ }
268
+ else {
269
+ setField = `\tobjectMap["${field.serializedName}"] = ${star}${receiver}.${field.name}\n`;
270
+ }
271
+ if (!field.byValue) {
272
+ setField = `\tif ${receiver}.${field.name} != nil {\n\t\t${setField}\t}\n`;
273
+ }
274
+ method += setField;
275
+ }
276
+ method += '\treturn objectMap, nil\n}\n\n';
277
+ modelDef.SerDe.methods.push({ name: 'toMultipartFormData', desc: `toMultipartFormData converts ${modelDef.Name} to multipart/form data.`, text: method });
278
+ }
279
+ function generateJSONMarshaller(modelType, modelDef, imports) {
280
+ if (go.isModelType(modelType) && modelType.fields.length === 0) {
281
+ // non-discriminated types without content don't need a custom marshaller.
282
+ // there is a case in network where child is allOf base and child has no properties.
283
+ return;
284
+ }
285
+ imports.add('encoding/json');
286
+ const typeName = modelDef.Name;
287
+ const receiver = modelDef.receiverName();
288
+ let marshaller = `func (${receiver} ${typeName}) MarshalJSON() ([]byte, error) {\n`;
289
+ marshaller += '\tobjectMap := make(map[string]any)\n';
290
+ marshaller += generateJSONMarshallerBody(modelType, modelDef, receiver, imports);
291
+ marshaller += '\treturn json.Marshal(objectMap)\n';
292
+ marshaller += '}\n\n';
293
+ modelDef.SerDe.methods.push({ name: 'MarshalJSON', desc: `MarshalJSON implements the json.Marshaller interface for type ${typeName}.`, text: marshaller });
294
+ }
295
+ function generateJSONMarshallerBody(modelType, modelDef, receiver, imports) {
296
+ let marshaller = '';
297
+ let addlProps;
298
+ for (const field of values(modelType.fields)) {
299
+ if (go.isMapType(field.type) && field.annotations.isAdditionalProperties) {
300
+ addlProps = field.type;
301
+ continue;
302
+ }
303
+ if (field.annotations.isDiscriminator) {
304
+ if (field.defaultValue) {
305
+ marshaller += `\tobjectMap["${field.serializedName}"] = ${formatLiteralValue(field.defaultValue, true)}\n`;
306
+ }
307
+ else {
308
+ // if there's no discriminator value (e.g. Fish in test server), use the field's value.
309
+ // this will enable support for custom types that aren't (yet) described in the swagger.
310
+ marshaller += `\tobjectMap["${field.serializedName}"] = ${receiver}.${field.name}\n`;
311
+ }
312
+ }
313
+ else if (go.isBytesType(field.type)) {
314
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime');
315
+ marshaller += `\tpopulateByteArray(objectMap, "${field.serializedName}", ${receiver}.${field.name}, func() any {\n`;
316
+ marshaller += `\t\treturn runtime.EncodeByteArray(${receiver}.${field.name}, runtime.Base64${field.type.encoding}Format)\n\t})\n`;
317
+ modelDef.SerDe.needsJSONPopulateByteArray = true;
318
+ }
319
+ else if (go.isSliceType(field.type) && go.isBytesType(field.type.elementType)) {
320
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime');
321
+ marshaller += `\tpopulateByteArray(objectMap, "${field.serializedName}", ${receiver}.${field.name}, func() any {\n`;
322
+ marshaller += `\t\tencodedValue := make([]string, len(${receiver}.${field.name}))\n`;
323
+ marshaller += `\t\tfor i := 0; i < len(${receiver}.${field.name}); i++ {\n`;
324
+ marshaller += `\t\t\tencodedValue[i] = runtime.EncodeByteArray(${receiver}.${field.name}[i], runtime.Base64${field.type.elementType.encoding}Format)\n\t\t}\n`;
325
+ marshaller += '\t\treturn encodedValue\n\t})\n';
326
+ modelDef.SerDe.needsJSONPopulateByteArray = true;
327
+ }
328
+ else if (go.isSliceType(field.type) && go.isTimeType(field.type.elementType)) {
329
+ const source = `${receiver}.${field.name}`;
330
+ let elementPtr = '*';
331
+ if (field.type.elementTypeByValue) {
332
+ elementPtr = '';
333
+ }
334
+ marshaller += `\taux := make([]${elementPtr}${field.type.elementType.dateTimeFormat}, len(${source}), len(${source}))\n`;
335
+ marshaller += `\tfor i := 0; i < len(${source}); i++ {\n`;
336
+ marshaller += `\t\taux[i] = (${elementPtr}${field.type.elementType.dateTimeFormat})(${source}[i])\n`;
337
+ marshaller += '\t}\n';
338
+ marshaller += `\tpopulate(objectMap, "${field.serializedName}", aux)\n`;
339
+ modelDef.SerDe.needsJSONPopulate = true;
340
+ }
341
+ else if (go.isLiteralValue(field.type)) {
342
+ const setter = `objectMap["${field.serializedName}"] = ${formatLiteralValue(field.type, true)}`;
343
+ if (!field.annotations.required) {
344
+ marshaller += `\tif ${receiver}.${field.name} != nil {\n\t\t${setter}\n\t}\n`;
345
+ }
346
+ else {
347
+ marshaller += `\t${setter}\n`;
348
+ }
349
+ }
350
+ else if (go.isSliceType(field.type) && field.type.rawJSONAsBytes) {
351
+ marshaller += `\tpopulate(objectMap, "${field.serializedName}", json.RawMessage(${receiver}.${field.name}))\n`;
352
+ modelDef.SerDe.needsJSONPopulate = true;
353
+ }
354
+ else {
355
+ if (field.defaultValue) {
356
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/to');
357
+ marshaller += `\tif ${receiver}.${field.name} == nil {\n\t\t${receiver}.${field.name} = to.Ptr(${formatLiteralValue(field.defaultValue, true)})\n\t}\n`;
358
+ }
359
+ let populate = 'populate';
360
+ if (go.isTimeType(field.type)) {
361
+ populate += capitalize(field.type.dateTimeFormat);
362
+ modelDef.SerDe.needsJSONPopulate = true;
363
+ }
364
+ else if (go.isPrimitiveType(field.type) && field.type.typeName === 'any') {
365
+ populate += 'Any';
366
+ modelDef.SerDe.needsJSONPopulateAny = true;
367
+ }
368
+ else {
369
+ modelDef.SerDe.needsJSONPopulate = true;
370
+ }
371
+ marshaller += `\t${populate}(objectMap, "${field.serializedName}", ${receiver}.${field.name})\n`;
372
+ }
373
+ }
374
+ if (addlProps) {
375
+ marshaller += `\tif ${receiver}.AdditionalProperties != nil {\n`;
376
+ marshaller += `\t\tfor key, val := range ${receiver}.AdditionalProperties {\n`;
377
+ let assignment = 'val';
378
+ if (go.isTimeType(addlProps.valueType)) {
379
+ assignment = `(*${addlProps.valueType.dateTimeFormat})(val)`;
380
+ }
381
+ marshaller += `\t\t\tobjectMap[key] = ${assignment}\n`;
382
+ marshaller += '\t\t}\n';
383
+ marshaller += '\t}\n';
384
+ }
385
+ return marshaller;
386
+ }
387
+ function generateJSONUnmarshaller(modelType, modelDef, imports, options) {
388
+ // there's a corner-case where a derived type might not add any new fields (Cookiecuttershark).
389
+ // in this case skip adding the unmarshaller as it's not necessary and doesn't compile.
390
+ if (modelDef.Fields.length === 0) {
391
+ return;
392
+ }
393
+ imports.add('encoding/json');
394
+ imports.add('fmt');
395
+ const typeName = modelDef.Name;
396
+ const receiver = modelDef.receiverName();
397
+ let unmarshaller = `func (${receiver} *${typeName}) UnmarshalJSON(data []byte) error {\n`;
398
+ unmarshaller += '\tvar rawMsg map[string]json.RawMessage\n';
399
+ unmarshaller += '\tif err := json.Unmarshal(data, &rawMsg); err != nil {\n';
400
+ unmarshaller += `\t\treturn fmt.Errorf("unmarshalling type %T: %v", ${receiver}, err)\n`;
401
+ unmarshaller += '\t}\n';
402
+ unmarshaller += generateJSONUnmarshallerBody(modelType, modelDef, receiver, imports, options);
403
+ unmarshaller += '}\n\n';
404
+ modelDef.SerDe.methods.push({ name: 'UnmarshalJSON', desc: `UnmarshalJSON implements the json.Unmarshaller interface for type ${typeName}.`, text: unmarshaller });
405
+ }
406
+ function generateJSONUnmarshallerBody(modelType, modelDef, receiver, imports, options) {
407
+ const emitAddlProps = function (tab, addlProps) {
408
+ let addlPropsText = `${tab}\t\tif ${receiver}.AdditionalProperties == nil {\n`;
409
+ let ref = '';
410
+ if (!addlProps.valueTypeByValue) {
411
+ ref = '&';
412
+ }
413
+ addlPropsText += `${tab}\t\t\t${receiver}.AdditionalProperties = ${go.getTypeDeclaration(addlProps)}{}\n`;
414
+ addlPropsText += `${tab}\t\t}\n`;
415
+ addlPropsText += `${tab}\t\tif val != nil {\n`;
416
+ let auxType = go.getTypeDeclaration(addlProps.valueType);
417
+ let assignment = `${ref}aux`;
418
+ if (go.isTimeType(addlProps.valueType)) {
419
+ imports.add('time');
420
+ auxType = addlProps.valueType.dateTimeFormat;
421
+ assignment = `(*time.Time)(${assignment})`;
422
+ }
423
+ addlPropsText += `${tab}\t\t\tvar aux ${auxType}\n`;
424
+ addlPropsText += `${tab}\t\t\terr = json.Unmarshal(val, &aux)\n`;
425
+ addlPropsText += `${tab}\t\t\t${receiver}.AdditionalProperties[key] = ${assignment}\n`;
426
+ addlPropsText += `${tab}\t\t}\n`;
427
+ addlPropsText += `${tab}\t\tdelete(rawMsg, key)\n`;
428
+ return addlPropsText;
429
+ };
430
+ let unmarshalBody = '';
431
+ unmarshalBody = '\tfor key, val := range rawMsg {\n';
432
+ unmarshalBody += '\t\tvar err error\n';
433
+ unmarshalBody += '\t\tswitch key {\n';
434
+ let addlProps;
435
+ for (const field of values(modelType.fields)) {
436
+ if (go.isMapType(field.type) && field.annotations.isAdditionalProperties) {
437
+ addlProps = field.type;
438
+ continue;
439
+ }
440
+ unmarshalBody += `\t\tcase "${field.serializedName}":\n`;
441
+ if (hasDiscriminatorInterface(field.type)) {
442
+ unmarshalBody += generateDiscriminatorUnmarshaller(field, receiver);
443
+ }
444
+ else if (go.isTimeType(field.type)) {
445
+ unmarshalBody += `\t\t\t\terr = unpopulate${capitalize(field.type.dateTimeFormat)}(val, "${field.name}", &${receiver}.${field.name})\n`;
446
+ modelDef.SerDe.needsJSONUnpopulate = true;
447
+ }
448
+ else if (go.isSliceType(field.type) && go.isTimeType(field.type.elementType)) {
449
+ imports.add('time');
450
+ let elementPtr = '*';
451
+ if (field.type.elementTypeByValue) {
452
+ elementPtr = '';
453
+ }
454
+ unmarshalBody += `\t\t\tvar aux []${elementPtr}${field.type.elementType.dateTimeFormat}\n`;
455
+ unmarshalBody += `\t\t\terr = unpopulate(val, "${field.name}", &aux)\n`;
456
+ unmarshalBody += '\t\t\tfor _, au := range aux {\n';
457
+ unmarshalBody += `\t\t\t\t${receiver}.${field.name} = append(${receiver}.${field.name}, (${elementPtr}time.Time)(au))\n`;
458
+ unmarshalBody += '\t\t\t}\n';
459
+ modelDef.SerDe.needsJSONUnpopulate = true;
460
+ }
461
+ else if (go.isBytesType(field.type)) {
462
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime');
463
+ unmarshalBody += '\t\tif val != nil && string(val) != "null" {\n';
464
+ unmarshalBody += `\t\t\t\terr = runtime.DecodeByteArray(string(val), &${receiver}.${field.name}, runtime.Base64${field.type.encoding}Format)\n\t\t}\n`;
465
+ }
466
+ else if (go.isSliceType(field.type) && go.isBytesType(field.type.elementType)) {
467
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime');
468
+ unmarshalBody += '\t\t\tvar encodedValue []string\n';
469
+ unmarshalBody += `\t\t\terr = unpopulate(val, "${field.name}", &encodedValue)\n`;
470
+ unmarshalBody += '\t\t\tif err == nil && len(encodedValue) > 0 {\n';
471
+ unmarshalBody += `\t\t\t\t${receiver}.${field.name} = make([][]byte, len(encodedValue))\n`;
472
+ unmarshalBody += '\t\t\t\tfor i := 0; i < len(encodedValue) && err == nil; i++ {\n';
473
+ unmarshalBody += `\t\t\t\t\terr = runtime.DecodeByteArray(encodedValue[i], &${receiver}.${field.name}[i], runtime.Base64${field.type.elementType.encoding}Format)\n`;
474
+ unmarshalBody += '\t\t\t\t}\n\t\t\t}\n';
475
+ modelDef.SerDe.needsJSONUnpopulate = true;
476
+ }
477
+ else if (go.isSliceType(field.type) && field.type.rawJSONAsBytes) {
478
+ unmarshalBody += '\t\t\tif string(val) != "null" {\n';
479
+ unmarshalBody += `\t\t\t\t${receiver}.${field.name} = val\n\t\t\t}\n`;
480
+ }
481
+ else {
482
+ unmarshalBody += `\t\t\t\terr = unpopulate(val, "${field.name}", &${receiver}.${field.name})\n`;
483
+ modelDef.SerDe.needsJSONUnpopulate = true;
484
+ }
485
+ unmarshalBody += '\t\t\tdelete(rawMsg, key)\n';
486
+ }
487
+ if (addlProps) {
488
+ unmarshalBody += '\t\tdefault:\n';
489
+ unmarshalBody += emitAddlProps('\t', addlProps);
490
+ }
491
+ else if (options.disallowUnknownFields) {
492
+ unmarshalBody += '\t\tdefault:\n';
493
+ unmarshalBody += `\t\t\terr = fmt.Errorf("unmarshalling type %T, unknown field %q", ${receiver}, key)\n`;
494
+ }
495
+ unmarshalBody += '\t\t}\n';
496
+ unmarshalBody += '\t\tif err != nil {\n';
497
+ unmarshalBody += `\t\t\treturn fmt.Errorf("unmarshalling type %T: %v", ${receiver}, err)\n`;
498
+ unmarshalBody += '\t\t}\n';
499
+ unmarshalBody += '\t}\n'; // end for key, val := range rawMsg
500
+ unmarshalBody += '\treturn nil\n';
501
+ return unmarshalBody;
502
+ }
503
+ // returns true if item has a discriminator interface.
504
+ // recursively called for arrays and dictionaries.
505
+ function hasDiscriminatorInterface(item) {
506
+ if (go.isInterfaceType(item)) {
507
+ return true;
508
+ }
509
+ else if (go.isMapType(item)) {
510
+ return hasDiscriminatorInterface(item.valueType);
511
+ }
512
+ else if (go.isSliceType(item)) {
513
+ return hasDiscriminatorInterface(item.elementType);
514
+ }
515
+ return false;
516
+ }
517
+ // returns the text for unmarshalling a discriminated type
518
+ function generateDiscriminatorUnmarshaller(field, receiver) {
519
+ const startingIndentation = '\t\t\t';
520
+ const propertyName = field.name;
521
+ // these are the simple, non-nested cases (e.g. IterfaceType, []InterfaceType, map[string]InterfaceType)
522
+ if (go.isInterfaceType(field.type)) {
523
+ return `${startingIndentation}${receiver}.${propertyName}, err = unmarshal${field.type.name}(val)\n`;
524
+ }
525
+ else if (go.isSliceType(field.type) && go.isInterfaceType(field.type.elementType)) {
526
+ return `${startingIndentation}${receiver}.${propertyName}, err = unmarshal${field.type.elementType.name}Array(val)\n`;
527
+ }
528
+ else if (go.isMapType(field.type) && go.isInterfaceType(field.type.valueType)) {
529
+ return `${startingIndentation}${receiver}.${propertyName}, err = unmarshal${field.type.valueType.name}Map(val)\n`;
530
+ }
531
+ // nested case (e.g. [][]InterfaceType, map[string]map[string]InterfaceType etc)
532
+ // first, unmarshal the raw data
533
+ const rawTargetVar = `${field.serializedName}Raw`;
534
+ let text = `${startingIndentation}var ${rawTargetVar} ${recursiveGetDiscriminatorTypeName(field.type, true)}\n`;
535
+ text += `${startingIndentation}if err = json.Unmarshal(val, &${rawTargetVar}); err != nil {\n`;
536
+ text += `${startingIndentation}\treturn err\n${startingIndentation}}\n`;
537
+ // create a local instantiation of the final type
538
+ const finalTargetVar = field.serializedName;
539
+ let finalTargetCtor = recursiveGetDiscriminatorTypeName(field.type, false);
540
+ if (go.isSliceType(field.type)) {
541
+ finalTargetCtor = `make(${finalTargetCtor}, len(${rawTargetVar}))`;
542
+ }
543
+ else {
544
+ // must be a dictionary
545
+ finalTargetCtor = `${finalTargetCtor}{}`;
546
+ }
547
+ text += `${startingIndentation}${finalTargetVar} := ${finalTargetCtor}\n`;
548
+ // now populate the final type
549
+ text += recursivePopulateDiscriminator(field.type, receiver, rawTargetVar, finalTargetVar, startingIndentation, 1);
550
+ // finally, assign the final target to the property
551
+ text += `${startingIndentation}${receiver}.${propertyName} = ${finalTargetVar}\n`;
552
+ return text;
553
+ }
554
+ // constructs the type name for a nested discriminated type
555
+ // raw e.g. map[string]json.RawMessage, []json.RawMessage etc
556
+ // !raw e.g. map[string]map[string]InterfaceType, [][]InterfaceType etc
557
+ function recursiveGetDiscriminatorTypeName(item, raw) {
558
+ // when raw is true, stop recursing at the level before the leaf schema
559
+ if (go.isSliceType(item)) {
560
+ if (!raw || !go.isInterfaceType(item.elementType)) {
561
+ return `[]${recursiveGetDiscriminatorTypeName(item.elementType, raw)}`;
562
+ }
563
+ }
564
+ else if (go.isMapType(item)) {
565
+ if (!raw || !go.isInterfaceType(item.valueType)) {
566
+ return `map[string]${recursiveGetDiscriminatorTypeName(item.valueType, raw)}`;
567
+ }
568
+ }
569
+ if (raw) {
570
+ return 'json.RawMessage';
571
+ }
572
+ return go.getTypeDeclaration(item);
573
+ }
574
+ // recursively constructs the text to populate a nested discriminator
575
+ function recursivePopulateDiscriminator(item, receiver, rawSrc, dest, indent, nesting) {
576
+ let text = '';
577
+ let interfaceName = '';
578
+ let targetType = '';
579
+ if (go.isSliceType(item)) {
580
+ if (!go.isInterfaceType(item.elementType)) {
581
+ if (nesting > 1) {
582
+ // at nestling level 1, the destination var was already created in generateDiscriminatorUnmarshaller()
583
+ text += `${indent}${dest} = make(${recursiveGetDiscriminatorTypeName(item, false)}, len(${rawSrc}))\n`;
584
+ }
585
+ text += `${indent}for i${nesting} := range ${rawSrc} {\n`;
586
+ rawSrc = `${rawSrc}[i${nesting}]`; // source becomes each element in the source slice
587
+ dest = `${dest}[i${nesting}]`; // update destination to each element in the destination slice
588
+ text += recursivePopulateDiscriminator(item.elementType, receiver, rawSrc, dest, indent + '\t', nesting + 1);
589
+ text += `${indent}}\n`;
590
+ return text;
591
+ }
592
+ // we're at leaf node - 1, so get the interface from the element's type
593
+ interfaceName = go.getTypeDeclaration(item.elementType);
594
+ targetType = 'Array';
595
+ }
596
+ else if (go.isMapType(item)) {
597
+ if (!go.isInterfaceType(item.valueType)) {
598
+ if (nesting > 1) {
599
+ // at nestling level 1, the destination var was already created in generateDiscriminatorUnmarshaller()
600
+ text += `${indent}${dest} = ${recursiveGetDiscriminatorTypeName(item, false)}{}\n`;
601
+ }
602
+ text += `${indent}for k${nesting}, v${nesting} := range ${rawSrc} {\n`;
603
+ rawSrc = `v${nesting}`; // source becomes the current value in the source map
604
+ dest = `${dest}[k${nesting}]`; // update destination to the destination map's value for the current key
605
+ text += recursivePopulateDiscriminator(item.valueType, receiver, rawSrc, dest, indent + '\t', nesting + 1);
606
+ text += `${indent}}\n`;
607
+ return text;
608
+ }
609
+ // we're at leaf node - 1, so get the interface from the element's type
610
+ interfaceName = go.getTypeDeclaration(item.valueType);
611
+ targetType = 'Map';
612
+ }
613
+ text += `${indent}${dest}, err = unmarshal${interfaceName}${targetType}(${rawSrc})\n`;
614
+ text += `${indent}if err != nil {\n${indent}\treturn fmt.Errorf("unmarshalling type %T: %v", ${receiver}, err)\n${indent}}\n`;
615
+ return text;
616
+ }
617
+ function generateXMLMarshaller(modelType, modelDef, imports) {
618
+ var _a;
619
+ // only needed for types with time.Time or where the XML name doesn't match the type name
620
+ const receiver = modelDef.receiverName();
621
+ const desc = `MarshalXML implements the xml.Marshaller interface for type ${modelDef.Name}.`;
622
+ let text = `func (${receiver} ${modelDef.Name}) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {\n`;
623
+ if ((_a = modelType.xml) === null || _a === void 0 ? void 0 : _a.wrapper) {
624
+ text += `\tstart.Name.Local = "${modelType.xml.wrapper}"\n`;
625
+ }
626
+ text += generateAliasType(modelType, receiver, true);
627
+ for (const field of values(modelDef.Fields)) {
628
+ if (go.isSliceType(field.type)) {
629
+ text += `\tif ${receiver}.${field.name} != nil {\n`;
630
+ text += `\t\taux.${field.name} = &${receiver}.${field.name}\n`;
631
+ text += '\t}\n';
632
+ }
633
+ else if (go.isBytesType(field.type)) {
634
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime');
635
+ text += `\tif ${receiver}.${field.name} != nil {\n`;
636
+ text += `\t\tencoded${field.name} := runtime.EncodeByteArray(${receiver}.${field.name}, runtime.Base64${field.type.encoding}Format)\n`;
637
+ text += `\t\taux.${field.name} = &encoded${field.name}\n`;
638
+ text += '\t}\n';
639
+ }
640
+ }
641
+ text += '\treturn enc.EncodeElement(aux, start)\n';
642
+ text += '}\n\n';
643
+ modelDef.SerDe.methods.push({ name: 'MarshalXML', desc: desc, text: text });
644
+ }
645
+ function generateXMLUnmarshaller(modelType, modelDef, imports) {
646
+ // non-polymorphic case, must be something with time.Time
647
+ const receiver = modelDef.receiverName();
648
+ const desc = `UnmarshalXML implements the xml.Unmarshaller interface for type ${modelDef.Name}.`;
649
+ let text = `func (${receiver} *${modelDef.Name}) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error {\n`;
650
+ text += generateAliasType(modelType, receiver, false);
651
+ text += '\tif err := dec.DecodeElement(aux, &start); err != nil {\n';
652
+ text += '\t\treturn err\n';
653
+ text += '\t}\n';
654
+ for (const field of values(modelDef.Fields)) {
655
+ if (go.isTimeType(field.type)) {
656
+ text += `\tif aux.${field.name} != nil && !(*time.Time)(aux.${field.name}).IsZero() {\n`;
657
+ text += `\t\t${receiver}.${field.name} = (*time.Time)(aux.${field.name})\n\t}\n`;
658
+ }
659
+ else if (field.annotations.isAdditionalProperties || go.isMapType(field.type)) {
660
+ text += `\t${receiver}.${field.name} = (map[string]*string)(aux.${field.name})\n`;
661
+ }
662
+ else if (go.isBytesType(field.type)) {
663
+ imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime');
664
+ text += `\tif aux.${field.name} != nil {\n`;
665
+ text += `\t\tif err := runtime.DecodeByteArray(*aux.${field.name}, &${receiver}.${field.name}, runtime.Base64${field.type.encoding}Format); err != nil {\n`;
666
+ text += '\t\t\treturn err\n';
667
+ text += '\t\t}\n';
668
+ text += '\t}\n';
669
+ }
670
+ }
671
+ text += '\treturn nil\n';
672
+ text += '}\n\n';
673
+ modelDef.SerDe.methods.push({ name: 'UnmarshalXML', desc: desc, text: text });
674
+ }
675
+ // generates an alias type used by custom XML marshaller/unmarshaller
676
+ function generateAliasType(modelType, receiver, forMarshal) {
677
+ let text = `\ttype alias ${modelType.name}\n`;
678
+ text += '\taux := &struct {\n';
679
+ text += '\t\t*alias\n';
680
+ for (const field of values(modelType.fields)) {
681
+ const sn = getXMLSerialization(field, false);
682
+ if (go.isTimeType(field.type)) {
683
+ text += `\t\t${field.name} *${field.type.dateTimeFormat} \`${modelType.format}:"${sn}"\`\n`;
684
+ }
685
+ else if (field.annotations.isAdditionalProperties || go.isMapType(field.type)) {
686
+ text += `\t\t${field.name} additionalProperties \`${modelType.format}:"${sn}"\`\n`;
687
+ }
688
+ else if (go.isSliceType(field.type)) {
689
+ text += `\t\t${field.name} *${go.getTypeDeclaration(field.type)} \`${modelType.format}:"${sn}"\`\n`;
690
+ }
691
+ else if (go.isBytesType(field.type)) {
692
+ text += `\t\t${field.name} *string \`${modelType.format}:"${sn}"\`\n`;
693
+ }
694
+ }
695
+ text += '\t}{\n';
696
+ let rec = receiver;
697
+ if (forMarshal) {
698
+ rec = '&' + rec;
699
+ }
700
+ text += `\t\talias: (*alias)(${rec}),\n`;
701
+ if (forMarshal) {
702
+ // emit code to initialize time fields
703
+ for (const field of modelType.fields) {
704
+ if (!go.isTimeType(field.type)) {
705
+ continue;
706
+ }
707
+ text += `\t\t${field.name}: (*${field.type.dateTimeFormat})(${receiver}.${field.name}),\n`;
708
+ }
709
+ }
710
+ text += '\t}\n';
711
+ return text;
712
+ }
713
+ class SerDeInfo {
714
+ constructor() {
715
+ this.methods = new Array();
716
+ this.needsJSONPopulate = false;
717
+ this.needsJSONUnpopulate = false;
718
+ this.needsJSONPopulateByteArray = false;
719
+ this.needsJSONPopulateAny = false;
720
+ this.needsJSONPopulateMultipart = false;
721
+ }
722
+ }
723
+ // represents model definition as a Go struct
724
+ class ModelDef {
725
+ constructor(name, format, fields, description) {
726
+ this.Name = name;
727
+ this.Format = format;
728
+ this.Description = description;
729
+ this.Fields = fields;
730
+ this.SerDe = new SerDeInfo();
731
+ this.Methods = new Array();
732
+ }
733
+ text() {
734
+ var _a;
735
+ let text = '';
736
+ if (this.Description) {
737
+ text += `${comment(this.Description, '// ', undefined, commentLength)}\n`;
738
+ }
739
+ text += `type ${this.Name} struct {\n`;
740
+ // group fields by required/optional/read-only in that order
741
+ (_a = this.Fields) === null || _a === void 0 ? void 0 : _a.sort((lhs, rhs) => {
742
+ if ((lhs.annotations.required && !rhs.annotations.required) || (!lhs.annotations.readOnly && rhs.annotations.readOnly)) {
743
+ return -1;
744
+ }
745
+ else if ((rhs.annotations.readOnly && !lhs.annotations.readOnly) || (!rhs.annotations.readOnly && lhs.annotations.readOnly)) {
746
+ return 1;
747
+ }
748
+ else {
749
+ return 0;
750
+ }
751
+ });
752
+ // used to track when to add an extra \n between fields that have comments
753
+ let first = true;
754
+ for (const field of values(this.Fields)) {
755
+ if (field.description) {
756
+ if (!first) {
757
+ // add an extra new-line between fields IFF the field
758
+ // has a comment and it's not the very first one.
759
+ text += '\n';
760
+ }
761
+ text += `\t${comment(field.description, '// ', undefined, commentLength)}\n`;
762
+ }
763
+ let typeName = go.getTypeDeclaration(field.type);
764
+ if (go.isLiteralValue(field.type)) {
765
+ // for constants we use the underlying type name
766
+ typeName = go.getLiteralValueTypeName(field.type.type);
767
+ }
768
+ let serialization = field.serializedName;
769
+ if (this.Format === 'json') {
770
+ serialization += ',omitempty';
771
+ }
772
+ else if (this.Format === 'xml') {
773
+ serialization = getXMLSerialization(field, false);
774
+ }
775
+ let tag = '';
776
+ // only emit tags for XML; JSON uses custom marshallers/unmarshallers
777
+ if (this.Format === 'xml' && !field.annotations.isAdditionalProperties) {
778
+ tag = ` \`${this.Format}:"${serialization}"\``;
779
+ }
780
+ text += `\t${field.name} ${getStar(field.byValue)}${typeName}${tag}\n`;
781
+ first = false;
782
+ }
783
+ text += '}\n\n';
784
+ return text;
785
+ }
786
+ receiverName() {
787
+ const typeName = this.Name;
788
+ return typeName[0].toLowerCase();
789
+ }
790
+ }
791
+ export function getXMLSerialization(field, isResponseEnvelope) {
792
+ var _a, _b, _c, _d, _e;
793
+ let serialization = field.serializedName;
794
+ // default to using the serialization name
795
+ if ((_a = field.xml) === null || _a === void 0 ? void 0 : _a.name) {
796
+ // xml can specifiy its own name, prefer that if available
797
+ serialization = field.xml.name;
798
+ }
799
+ else if ((_b = field.xml) === null || _b === void 0 ? void 0 : _b.text) {
800
+ // type has the x-ms-text attribute applied so it should be character data, not a node (https://github.com/Azure/autorest/tree/main/docs/extensions#x-ms-text)
801
+ // see https://pkg.go.dev/encoding/xml#Unmarshal for what ,chardata actually means
802
+ serialization = ',chardata';
803
+ }
804
+ if ((_c = field.xml) === null || _c === void 0 ? void 0 : _c.attribute) {
805
+ // value comes from an xml attribute
806
+ serialization += ',attr';
807
+ }
808
+ else if (go.isSliceType(field.type)) {
809
+ // start with the serialized name of the element, preferring xml name if available
810
+ let inner = go.getTypeDeclaration(field.type.elementType);
811
+ if ((_d = field.xml) === null || _d === void 0 ? void 0 : _d.name) {
812
+ inner = field.xml.name;
813
+ }
814
+ // arrays can be wrapped or unwrapped. here's a wrapped example
815
+ // note how the array of apple objects is "wrapped" in GoodApples
816
+ // <AppleBarrel>
817
+ // <GoodApples>
818
+ // <Apple>Fuji</Apple>
819
+ // <Apple>Gala</Apple>
820
+ // </GoodApples>
821
+ // </AppleBarrel>
822
+ // here's an unwrapped example, the array of slide objects
823
+ // is embedded directly in the object (no "wrapping")
824
+ // <slideshow>
825
+ // <slide>
826
+ // <title>Wake up to WonderWidgets!</title>
827
+ // </slide>
828
+ // <slide>
829
+ // <title>Overview</title>
830
+ // </slide>
831
+ // </slideshow>
832
+ // arrays in the response type are handled slightly different as we
833
+ // unmarshal directly into them so no need to add the unwrapping.
834
+ if (((_e = field.xml) === null || _e === void 0 ? void 0 : _e.wraps) && !isResponseEnvelope) {
835
+ serialization += `>${field.xml.wraps}`;
836
+ }
837
+ else {
838
+ serialization = inner;
839
+ }
840
+ }
841
+ return serialization;
842
+ }
843
+ export function getStar(byValue) {
844
+ if (byValue === true) {
845
+ return '';
846
+ }
847
+ return '*';
848
+ }
849
+ //# sourceMappingURL=models.js.map