@arrirpc/codegen-rust 0.52.0

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.cjs ADDED
@@ -0,0 +1,1988 @@
1
+ 'use strict';
2
+
3
+ const node_child_process = require('node:child_process');
4
+ const fs = require('node:fs');
5
+ const codegenUtils = require('@arrirpc/codegen-utils');
6
+ const path = require('pathe');
7
+ const assert = require('assert');
8
+
9
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
10
+
11
+ const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
12
+ const path__default = /*#__PURE__*/_interopDefaultCompat(path);
13
+ const assert__default = /*#__PURE__*/_interopDefaultCompat(assert);
14
+
15
+ const reservedKeywords = [
16
+ "as",
17
+ "break",
18
+ "const",
19
+ "continue",
20
+ "crate",
21
+ "else",
22
+ "enum",
23
+ "extern",
24
+ "false",
25
+ "fn",
26
+ "for",
27
+ "if",
28
+ "impl",
29
+ "in",
30
+ "let",
31
+ "loop",
32
+ "match",
33
+ "mod",
34
+ "move",
35
+ "mut",
36
+ "pub",
37
+ "ref",
38
+ "return",
39
+ "self",
40
+ "Self",
41
+ "static",
42
+ "struct",
43
+ "super",
44
+ "trait",
45
+ "true",
46
+ "type",
47
+ "unsafe",
48
+ "use",
49
+ "where",
50
+ "while",
51
+ "async",
52
+ "await",
53
+ "dyn",
54
+ "abstract",
55
+ "become",
56
+ "box",
57
+ "do",
58
+ "final",
59
+ "macro",
60
+ "override",
61
+ "priv",
62
+ "typeof",
63
+ "unsized",
64
+ "virtual",
65
+ "yield",
66
+ "try",
67
+ "macro_rules",
68
+ "union",
69
+ "'static",
70
+ "dyn"
71
+ ];
72
+ const illegalChars = `.!@#$%^&*()-+=\\][{}'";?`;
73
+ const numberChars = "0123456789";
74
+ function validRustIdentifier(key) {
75
+ const output = codegenUtils.removeDisallowedChars(codegenUtils.snakeCase(key), illegalChars);
76
+ if (numberChars.includes(output.charAt(0))) {
77
+ return `r#_${output}`;
78
+ }
79
+ if (reservedKeywords.includes(output)) {
80
+ return `r#${output}`;
81
+ }
82
+ return output;
83
+ }
84
+ function validRustName(name) {
85
+ const output = codegenUtils.removeDisallowedChars(
86
+ codegenUtils.pascalCase(name, { normalize: true }),
87
+ illegalChars
88
+ );
89
+ if (numberChars.includes(output.charAt(0))) {
90
+ return `r#_${output}`;
91
+ }
92
+ if (reservedKeywords.includes(output)) {
93
+ return `r#${output}`;
94
+ }
95
+ return output;
96
+ }
97
+ path__default.resolve(__dirname, "../.temp");
98
+ function outputIsOptionType(schema, context) {
99
+ return schema.nullable === true || context.isOptional === true;
100
+ }
101
+ function getTypeName(schema, context) {
102
+ if (schema.metadata?.id) {
103
+ return validRustName(schema.metadata.id);
104
+ }
105
+ if (context.discriminatorKey && context.discriminatorValue) {
106
+ const parts = context.instancePath.split("/");
107
+ const name = validRustName(
108
+ `${parts.join("_")}_${context.discriminatorValue}`
109
+ );
110
+ return name;
111
+ }
112
+ return validRustName(context.instancePath.split("/").join("_"));
113
+ }
114
+ function formatDescriptionComment(description, leading = "") {
115
+ return description.split("\n").map((line) => `${leading}/// ${line}`).join("\n");
116
+ }
117
+
118
+ function rustAnyFromSchema(schema, context) {
119
+ return {
120
+ typeName: context.isOptional ? `Option<serde_json::Value>` : "serde_json::Value",
121
+ defaultValue: context.isOptional ? `None` : `serde_json::Value::Null`,
122
+ isNullable: false,
123
+ fromJsonTemplate(input, key) {
124
+ const innerKey = validRustIdentifier(`${key}_val`);
125
+ if (context.isOptional) {
126
+ return `match ${input} {
127
+ Some(${innerKey}) => Some(${innerKey}.to_owned()),
128
+ _ => None,
129
+ }`;
130
+ }
131
+ return `match ${input} {
132
+ Some(${innerKey}) => ${innerKey}.to_owned(),
133
+ _ => serde_json::Value::Null,
134
+ }`;
135
+ },
136
+ toJsonTemplate(input, target) {
137
+ return `${target}.push_str(
138
+ serde_json::to_string(${input})
139
+ .unwrap_or("null".to_string())
140
+ .as_str(),
141
+ )`;
142
+ },
143
+ toQueryStringTemplate() {
144
+ return `println!("[WARNING] cannot serialize any's to query params. Skipping field at ${context.instancePath}.")`;
145
+ },
146
+ content: ""
147
+ };
148
+ }
149
+
150
+ function rustArrayFromSchema(schema, context) {
151
+ const innerType = rustTypeFromSchema(schema.elements, {
152
+ instancePath: `${context.instancePath}/element`,
153
+ schemaPath: `${context.schemaPath}/elements`,
154
+ clientVersion: context.clientVersion,
155
+ clientName: context.clientName,
156
+ typeNamePrefix: context.typeNamePrefix,
157
+ generatedTypes: context.generatedTypes
158
+ });
159
+ const isOptionType = outputIsOptionType(schema, context);
160
+ const typeName = isOptionType ? `Option<Vec<${innerType.typeName}>>` : `Vec<${innerType.typeName}>`;
161
+ const defaultValue = isOptionType ? `None` : `Vec::new()`;
162
+ return {
163
+ typeName,
164
+ defaultValue,
165
+ isNullable: schema.nullable ?? false,
166
+ fromJsonTemplate(input, key) {
167
+ const innerKey = validRustIdentifier(`${key}_val`);
168
+ if (isOptionType) {
169
+ return `match ${input} {
170
+ Some(serde_json::Value::Array(${innerKey})) => {
171
+ let mut ${innerKey}_result: Vec<${innerType.typeName}> = Vec::new();
172
+ for ${innerKey}_element in ${innerKey} {
173
+ ${innerKey}_result.push(${innerType.fromJsonTemplate(`Some(${innerKey}_element)`, `${innerKey}_element`)});
174
+ }
175
+ Some(${innerKey}_result)
176
+ }
177
+ _ => None,
178
+ }`;
179
+ }
180
+ return `match ${input} {
181
+ Some(serde_json::Value::Array(${innerKey})) => {
182
+ let mut ${innerKey}_result: Vec<${innerType.typeName}> = Vec::new();
183
+ for ${innerKey}_element in ${innerKey} {
184
+ ${innerKey}_result.push(${innerType.fromJsonTemplate(`Some(${innerKey}_element)`, `${innerKey}_element`)});
185
+ }
186
+ ${innerKey}_result
187
+ }
188
+ _ => Vec::new(),
189
+ }`;
190
+ },
191
+ toJsonTemplate(input, target) {
192
+ let innerTypeToJson = innerType.toJsonTemplate(`_element_`, target);
193
+ if (innerType.isNullable) {
194
+ innerTypeToJson = `match _element_ {
195
+ Some(_element_val_) => {
196
+ ${innerType.toJsonTemplate(`_element_val_`, target)};
197
+ },
198
+ _ => {
199
+ ${target}.push_str("null");
200
+ }
201
+ }`;
202
+ }
203
+ return `${target}.push('[');
204
+ for (_index_, _element_) in ${input}.iter().enumerate() {
205
+ if _index_ != 0 {
206
+ ${target}.push(',');
207
+ }
208
+ ${innerTypeToJson};
209
+ }
210
+ ${target}.push(']')`;
211
+ },
212
+ toQueryStringTemplate() {
213
+ return `println!("[WARNING] cannot serialize arrays to query params. Skipping field at ${context.instancePath}.")`;
214
+ },
215
+ content: innerType.content
216
+ };
217
+ }
218
+
219
+ function rustTaggedUnionFromSchema(schema, context) {
220
+ const enumName = `${context.typeNamePrefix}${getTypeName(schema, context)}`;
221
+ const isOptionType = outputIsOptionType(schema, context);
222
+ const defaultValue = isOptionType ? "None" : `${enumName}::new()`;
223
+ const result = {
224
+ typeName: isOptionType ? `Option<${enumName}>` : enumName,
225
+ defaultValue,
226
+ isNullable: isOptionType,
227
+ fromJsonTemplate(input, key) {
228
+ const innerKey = validRustIdentifier(`${key}_val`);
229
+ if (isOptionType) {
230
+ return `match ${input} {
231
+ Some(${innerKey}) => match ${innerKey} {
232
+ serde_json::Value::Object(_) => {
233
+ Some(${enumName}::from_json(${innerKey}.to_owned()))
234
+ }
235
+ _ => None,
236
+ },
237
+ _ => None,
238
+ }`;
239
+ }
240
+ return `match ${input} {
241
+ Some(${innerKey}) => match ${innerKey} {
242
+ serde_json::Value::Object(_) => {
243
+ ${enumName}::from_json(${innerKey}.to_owned())
244
+ }
245
+ _ => ${enumName}::new(),
246
+ },
247
+ _ => ${enumName}::new(),
248
+ }`;
249
+ },
250
+ toJsonTemplate(input, target) {
251
+ return `${target}.push_str(${input}.to_json_string().as_str())`;
252
+ },
253
+ toQueryStringTemplate() {
254
+ return `println!("[WARNING] cannot serialize nested objects to query params. Skipping field at ${context.instancePath}.")`;
255
+ },
256
+ content: ""
257
+ };
258
+ if (context.generatedTypes.includes(enumName)) {
259
+ return result;
260
+ }
261
+ const discriminatorKey = schema.discriminator;
262
+ const discriminatorValues = Object.keys(schema.mapping);
263
+ if (discriminatorValues.length === 0)
264
+ throw new Error(
265
+ `Discriminator schemas must have at least one subtype. Issue at ${context.schemaPath}.`
266
+ );
267
+ const subTypes = [];
268
+ const subTypeContent = [];
269
+ const discriminatorKeyProperty = validRustIdentifier(discriminatorKey);
270
+ const fromJsonParts = [];
271
+ for (const discriminatorValue of discriminatorValues) {
272
+ const subTypeName = validRustName(discriminatorValue);
273
+ const subSchema = schema.mapping[discriminatorValue];
274
+ const subType = {
275
+ name: subTypeName,
276
+ properties: [],
277
+ toJsonParts: [],
278
+ toQueryParts: [],
279
+ isDeprecated: subSchema.metadata?.isDeprecated ?? false,
280
+ description: subSchema.metadata?.description ?? ""
281
+ };
282
+ fromJsonParts.push(`"${discriminatorValue}" => {`);
283
+ subType.toJsonParts.push(
284
+ ` _json_output_.push_str("\\"${discriminatorKey}\\":\\"${discriminatorValue}\\"");`
285
+ );
286
+ subType.toQueryParts.push(
287
+ `_query_parts_.push(format!("${discriminatorKey}=${discriminatorValue}"));`
288
+ );
289
+ for (const key of Object.keys(subSchema.properties)) {
290
+ const keySchema = subSchema.properties[key];
291
+ const keyType = rustTypeFromSchema(keySchema, {
292
+ clientVersion: context.clientVersion,
293
+ clientName: context.clientName,
294
+ typeNamePrefix: context.typeNamePrefix,
295
+ instancePath: `${context.instancePath}/${key}`,
296
+ schemaPath: `${context.schemaPath}/mapping/${key}`,
297
+ generatedTypes: context.generatedTypes,
298
+ discriminatorKey,
299
+ discriminatorValue
300
+ });
301
+ if (keyType.content)
302
+ subTypeContent.push(keyType.content);
303
+ const keyName = validRustIdentifier(key);
304
+ subType.properties.push({
305
+ name: keyName,
306
+ defaultValue: keyType.defaultValue,
307
+ typeName: keyType.typeName,
308
+ isDeprecated: keySchema.metadata?.isDeprecated ?? false,
309
+ description: keySchema.metadata?.description ?? ""
310
+ });
311
+ fromJsonParts.push(
312
+ `let ${keyName} = ${keyType.fromJsonTemplate(`_val_.get("${key}")`, key)};`
313
+ );
314
+ subType.toJsonParts.push(
315
+ ` _json_output_.push_str(",\\"${key}\\":");`
316
+ );
317
+ if (keyType.isNullable) {
318
+ const innerKey = validRustIdentifier(`${key}_val`);
319
+ subType.toJsonParts.push(`match ${keyName} {
320
+ Some(${innerKey}) => {
321
+ ${keyType.toJsonTemplate(innerKey, "_json_output_")};
322
+ }
323
+ _ => {
324
+ _json_output_.push_str("null");
325
+ }
326
+ };`);
327
+ } else {
328
+ subType.toJsonParts.push(
329
+ `${keyType.toJsonTemplate(keyName, "_json_output_")};`
330
+ );
331
+ }
332
+ subType.toQueryParts.push(
333
+ `${keyType.toQueryStringTemplate(keyName, key, "_query_parts_")};`
334
+ );
335
+ }
336
+ for (const key of Object.keys(subSchema.optionalProperties ?? {})) {
337
+ const keySchema = subSchema.optionalProperties[key];
338
+ const keyType = rustTypeFromSchema(keySchema, {
339
+ clientVersion: context.clientVersion,
340
+ clientName: context.clientName,
341
+ typeNamePrefix: context.typeNamePrefix,
342
+ instancePath: `${context.instancePath}/key`,
343
+ schemaPath: `${context.schemaPath}/mapping/${key}`,
344
+ generatedTypes: context.generatedTypes,
345
+ discriminatorKey,
346
+ discriminatorValue
347
+ });
348
+ if (keyType.content)
349
+ subTypeContent.push(keyType.content);
350
+ const keyName = validRustIdentifier(key);
351
+ subType.properties.push({
352
+ name: keyName,
353
+ defaultValue: keyType.defaultValue,
354
+ typeName: keyType.typeName,
355
+ isDeprecated: keySchema.metadata?.isDeprecated ?? false,
356
+ description: keySchema.metadata?.description ?? ""
357
+ });
358
+ fromJsonParts.push(
359
+ `let ${keyName} = ${keyType.fromJsonTemplate(`_val_.get("${key}")`, key)};`
360
+ );
361
+ subType.toJsonParts.push(
362
+ ` _json_output_.push_str(",\\"${key}\\":");`
363
+ );
364
+ if (keyType.isNullable) {
365
+ const innerKey = validRustIdentifier(`${key}_val`);
366
+ subType.toJsonParts.push(`match ${keyName} {
367
+ Some(${innerKey}) => {
368
+ ${keyType.toJsonTemplate(innerKey, "_json_output_")};
369
+ }
370
+ _ => {
371
+ _json_output_.push_str("null");
372
+ }
373
+ };`);
374
+ } else {
375
+ subType.toJsonParts.push(
376
+ `${keyType.toJsonTemplate(keyName, "_json_output_")};`
377
+ );
378
+ }
379
+ }
380
+ fromJsonParts.push(`Self::${subTypeName} {
381
+ ${subType.properties.map((prop) => `${prop.name},`).join("\n")}
382
+ }`);
383
+ fromJsonParts.push(`}`);
384
+ subTypes.push(subType);
385
+ }
386
+ let leading = "";
387
+ if (schema.metadata?.description) {
388
+ leading += formatDescriptionComment(schema.metadata.description);
389
+ leading += "\n";
390
+ }
391
+ if (schema.metadata?.isDeprecated) {
392
+ leading += "#[deprecated]\n";
393
+ }
394
+ result.content = `${leading}#[derive(Clone, Debug, PartialEq)]
395
+ pub enum ${enumName} {
396
+ ${subTypes.map((type) => {
397
+ let leading2 = "";
398
+ if (type.description) {
399
+ leading2 += formatDescriptionComment(type.description);
400
+ leading2 += "\n";
401
+ }
402
+ if (type.isDeprecated) {
403
+ leading2 += "#[deprecated]\n";
404
+ }
405
+ return `${leading2}${type.name} {
406
+ ${type.properties.map((prop) => {
407
+ let leading3 = "";
408
+ if (prop.description) {
409
+ leading3 += formatDescriptionComment(prop.description);
410
+ leading3 += "\n";
411
+ }
412
+ if (prop.isDeprecated) {
413
+ leading3 += "#[deprecated]\n";
414
+ }
415
+ return `${leading3}${prop.name}: ${prop.typeName},`;
416
+ }).join("\n")}
417
+ },`;
418
+ }).join("\n")}
419
+ }
420
+
421
+ impl ArriModel for ${enumName} {
422
+ fn new() -> Self {
423
+ Self::${subTypes[0].name} {
424
+ ${subTypes[0]?.properties.map((prop) => `${prop.name}: ${prop.defaultValue},`).join("\n")}
425
+ }
426
+ }
427
+
428
+ fn from_json(input: serde_json::Value) -> Self {
429
+ match input {
430
+ serde_json::Value::Object(_val_) => {
431
+ let ${discriminatorKeyProperty} = match _val_.get("${discriminatorKey}") {
432
+ Some(serde_json::Value::String(${discriminatorKeyProperty}_val)) => ${discriminatorKeyProperty}_val.to_owned(),
433
+ _ => "".to_string(),
434
+ };
435
+ match ${discriminatorKeyProperty}.as_str() {
436
+ ${fromJsonParts.join("\n")}
437
+ _ => Self::new(),
438
+ }
439
+ }
440
+ _ => Self::new(),
441
+ }
442
+ }
443
+
444
+ fn from_json_string(input: String) -> Self {
445
+ match serde_json::from_str(input.as_str()) {
446
+ Ok(val) => Self::from_json(val),
447
+ _ => Self::new(),
448
+ }
449
+ }
450
+
451
+ fn to_json_string(&self) -> String {
452
+ let mut _json_output_ = "{".to_string();
453
+ match &self {
454
+ ${subTypes.map(
455
+ (type) => `Self::${type.name} { ${type.properties.map((prop) => `${prop.name},`).join("\n")}} => {
456
+ ${type.toJsonParts.join("\n")}
457
+ }`
458
+ )}
459
+ }
460
+ _json_output_.push('}');
461
+ _json_output_
462
+ }
463
+
464
+ fn to_query_params_string(&self) -> String {
465
+ let mut _query_parts_: Vec<String> = Vec::new();
466
+ match &self {
467
+ ${subTypes.map(
468
+ (type) => `Self::${type.name} { ${type.properties.map((prop) => `${prop.name},`).join("\n")}} => {
469
+ ${type.toQueryParts.join("\n")}
470
+ }`
471
+ )}
472
+ }
473
+ _query_parts_.join("&")
474
+ }
475
+ }
476
+
477
+ ${subTypeContent.join("\n\n")}`;
478
+ context.generatedTypes.push(enumName);
479
+ return result;
480
+ }
481
+
482
+ function rustEnumFromSchema(schema, context) {
483
+ const enumName = `${context.typeNamePrefix}${getTypeName(schema, context)}`;
484
+ const isOptionType = outputIsOptionType(schema, context);
485
+ const typeName = isOptionType ? `Option<${enumName}>` : enumName;
486
+ const defaultValue = isOptionType ? "None" : `${enumName}::default()`;
487
+ const result = {
488
+ typeName,
489
+ defaultValue,
490
+ isNullable: schema.nullable ?? false,
491
+ fromJsonTemplate(input, key) {
492
+ const innerKey = validRustIdentifier(`${key}_val`);
493
+ if (isOptionType) {
494
+ return `match ${input} {
495
+ Some(serde_json::Value::String(${innerKey})) => {
496
+ Some(${enumName}::from_string(${innerKey}.to_owned()))
497
+ }
498
+ _ => None,
499
+ }`;
500
+ }
501
+ return `match ${input} {
502
+ Some(serde_json::Value::String(${innerKey})) => {
503
+ ${enumName}::from_string(${innerKey}.to_owned())
504
+ }
505
+ _ => ${enumName}::default(),
506
+ }`;
507
+ },
508
+ toJsonTemplate(input, target) {
509
+ return `${target}.push_str(format!("\\"{}\\"", ${input}.serial_value()).as_str())`;
510
+ },
511
+ toQueryStringTemplate(input, key, target) {
512
+ const innerKey = validRustIdentifier(`${key}_val`);
513
+ if (context.isOptional) {
514
+ return `match ${input} {
515
+ Some(${innerKey}) => {
516
+ ${target}.push(format!("${key}={}", ${innerKey}.serial_value()));
517
+ }
518
+ _ => {}
519
+ }`;
520
+ }
521
+ if (schema.nullable) {
522
+ return `match ${input} {
523
+ Some(${innerKey}) => {
524
+ ${target}.push(format!("${key}={}", ${innerKey}.serial_value()));
525
+ }
526
+ _ => {
527
+ ${target}.push("${key}=null".to_string());
528
+ }
529
+ }`;
530
+ }
531
+ return `${target}.push(format!("${key}={}", ${input}.serial_value()))`;
532
+ },
533
+ content: ""
534
+ };
535
+ if (context.generatedTypes.includes(enumName)) {
536
+ return result;
537
+ }
538
+ let defaultEnumValue = "";
539
+ const initializationParts = [];
540
+ const fromStringParts = [];
541
+ const serialValueParts = [];
542
+ for (let i = 0; i < schema.enum.length; i++) {
543
+ const val = schema.enum[i];
544
+ const valName = validRustName(val);
545
+ if (i === 0) {
546
+ defaultEnumValue = valName;
547
+ }
548
+ initializationParts.push(` ${valName},`);
549
+ fromStringParts.push(` "${val}" => Self::${valName},`);
550
+ serialValueParts.push(
551
+ ` ${enumName}::${valName} => "${val}".to_string(),`
552
+ );
553
+ }
554
+ let leading = "";
555
+ if (schema.metadata?.description) {
556
+ leading += `${formatDescriptionComment(schema.metadata.description)}
557
+ `;
558
+ }
559
+ if (schema.metadata?.isDeprecated) {
560
+ leading += `#[deprecated]
561
+ `;
562
+ }
563
+ result.content = `${leading}#[derive(Clone, Debug, PartialEq)]
564
+ pub enum ${enumName} {
565
+ ${initializationParts.join("\n")}
566
+ }
567
+
568
+ impl ArriEnum for ${enumName} {
569
+ fn default() -> Self {
570
+ ${enumName}::${defaultEnumValue}
571
+ }
572
+ fn from_string(input: String) -> Self {
573
+ match input.as_str() {
574
+ ${fromStringParts.join("\n")}
575
+ _ => Self::default(),
576
+ }
577
+ }
578
+ fn serial_value(&self) -> String {
579
+ match &self {
580
+ ${serialValueParts.join("\n")}
581
+ }
582
+ }
583
+ }`;
584
+ context.generatedTypes.push(enumName);
585
+ return result;
586
+ }
587
+
588
+ function rustObjectFromSchema(schema, context) {
589
+ const isOptionType = outputIsOptionType(schema, context);
590
+ const structName = `${context.typeNamePrefix}${getTypeName(schema, context)}`;
591
+ const typeName = isOptionType ? `Option<${structName}>` : structName;
592
+ const defaultValue = isOptionType ? `None` : `${structName}::new()`;
593
+ const result = {
594
+ typeName,
595
+ defaultValue,
596
+ isNullable: schema.nullable ?? false,
597
+ fromJsonTemplate(input, key) {
598
+ const innerKey = validRustIdentifier(`${key}_val`);
599
+ if (isOptionType) {
600
+ return `match ${input} {
601
+ Some(${innerKey}) => match ${innerKey} {
602
+ serde_json::Value::Object(_) => {
603
+ Some(${structName}::from_json(${innerKey}.to_owned()))
604
+ }
605
+ _ => None,
606
+ },
607
+ _ => None,
608
+ }`;
609
+ }
610
+ return `match ${input} {
611
+ Some(${innerKey}) => ${structName}::from_json(${innerKey}.to_owned()),
612
+ _ => ${structName}::new(),
613
+ }`;
614
+ },
615
+ toJsonTemplate(input, target) {
616
+ return `${target}.push_str(${input}.to_json_string().as_str())`;
617
+ },
618
+ toQueryStringTemplate() {
619
+ return `println!("[WARNING] cannot serialize nested objects to query params. Skipping field at ${context.instancePath}.")`;
620
+ },
621
+ content: ""
622
+ };
623
+ if (context.generatedTypes.includes(structName)) {
624
+ return result;
625
+ }
626
+ const fieldNames = [];
627
+ const fieldDeclarationParts = [];
628
+ const defaultParts = [];
629
+ const fromJsonParts = [];
630
+ const toJsonParts = [];
631
+ const toQueryParamParams = [];
632
+ const subContent = [];
633
+ const requiredKeys = Object.keys(schema.properties);
634
+ const optionalKeys = Object.keys(schema.optionalProperties ?? {});
635
+ const hasKeys = requiredKeys.length > 0;
636
+ for (let i = 0; i < requiredKeys.length; i++) {
637
+ const key = requiredKeys[i];
638
+ const prop = schema.properties[key];
639
+ const innerType = rustTypeFromSchema(prop, {
640
+ clientVersion: context.clientVersion,
641
+ clientName: context.clientName,
642
+ typeNamePrefix: context.typeNamePrefix,
643
+ instancePath: `/${structName}/${key}`,
644
+ schemaPath: `${context.schemaPath}/properties/${key}`,
645
+ generatedTypes: context.generatedTypes
646
+ });
647
+ if (innerType.content) {
648
+ subContent.push(innerType.content);
649
+ }
650
+ const fieldName = validRustIdentifier(key);
651
+ fieldNames.push(fieldName);
652
+ let leading2 = "";
653
+ if (prop.metadata?.description) {
654
+ leading2 += formatDescriptionComment(prop.metadata.description);
655
+ leading2 += "\n";
656
+ }
657
+ if (prop.metadata?.isDeprecated) {
658
+ leading2 += ` #[deprecated]
659
+ `;
660
+ }
661
+ fieldDeclarationParts.push(
662
+ `${leading2} pub ${fieldName}: ${innerType.typeName}`
663
+ );
664
+ defaultParts.push(` ${fieldName}: ${innerType.defaultValue}`);
665
+ fromJsonParts.push(
666
+ ` let ${fieldName} = ${innerType.fromJsonTemplate(`_val_.get("${key}")`, key)};`
667
+ );
668
+ if (i === 0) {
669
+ toJsonParts.push(` _json_output_.push_str("\\"${key}\\":");`);
670
+ } else {
671
+ toJsonParts.push(` _json_output_.push_str(",\\"${key}\\":");`);
672
+ }
673
+ if (innerType.isNullable) {
674
+ const innerKey = validRustIdentifier(`${key}_val`);
675
+ toJsonParts.push(` match &self.${fieldName} {
676
+ Some(${innerKey}) => {
677
+ ${innerType.toJsonTemplate(innerKey, "_json_output_")};
678
+ }
679
+ _ => {
680
+ _json_output_.push_str("null");
681
+ }
682
+ };`);
683
+ } else {
684
+ const leading3 = codegenUtils.isSchemaFormElements(prop) || codegenUtils.isSchemaFormValues(prop) ? "" : "&";
685
+ toJsonParts.push(
686
+ ` ${innerType.toJsonTemplate(`${leading3}self.${fieldName}`, "_json_output_")};`
687
+ );
688
+ }
689
+ toQueryParamParams.push(
690
+ ` ${innerType.toQueryStringTemplate(`&self.${fieldName}`, key, "_query_parts_")};`
691
+ );
692
+ }
693
+ for (let i = 0; i < optionalKeys.length; i++) {
694
+ const key = optionalKeys[i];
695
+ const prop = schema.optionalProperties[key];
696
+ const innerType = rustTypeFromSchema(prop, {
697
+ clientVersion: context.clientVersion,
698
+ clientName: context.clientName,
699
+ typeNamePrefix: context.typeNamePrefix,
700
+ instancePath: `/${structName}/${key}`,
701
+ schemaPath: `${context.schemaPath}/optionalProperties/${key}`,
702
+ generatedTypes: context.generatedTypes,
703
+ isOptional: true
704
+ });
705
+ if (innerType.content) {
706
+ subContent.push(innerType.content);
707
+ }
708
+ const fieldName = validRustIdentifier(key);
709
+ fieldNames.push(fieldName);
710
+ let leading2 = prop.metadata?.description ? `${prop.metadata.description.split("\n").map((line) => ` /// ${line}`).join("\n")}
711
+ ` : "";
712
+ if (prop.metadata?.isDeprecated) {
713
+ leading2 += ` #[deprecated]
714
+ `;
715
+ }
716
+ fieldDeclarationParts.push(
717
+ `${leading2} pub ${fieldName}: ${innerType.typeName}`
718
+ );
719
+ defaultParts.push(` ${fieldName}: ${innerType.defaultValue}`);
720
+ fromJsonParts.push(
721
+ ` let ${fieldName} = ${innerType.fromJsonTemplate(`_val_.get("${key}")`, key)};`
722
+ );
723
+ if (hasKeys) {
724
+ const innerKey = validRustIdentifier(`${key}_val`);
725
+ toJsonParts.push(`match &self.${fieldName} {
726
+ Some(${innerKey}) => {
727
+ _json_output_.push_str(",\\"${key}\\":");
728
+ ${innerType.toJsonTemplate(innerKey, "_json_output_")}
729
+ },
730
+ _ => {}
731
+ };`);
732
+ } else {
733
+ const innerKey = validRustIdentifier(`${key}_val`);
734
+ toJsonParts.push(` match &self.${fieldName} {
735
+ Some(${innerKey}) => {
736
+ ${i !== 0 ? `if _has_keys_ {
737
+ _json_output_.push(',');
738
+ }` : ""}
739
+ _json_output_.push_str("\\"${key}\\":");
740
+ ${innerType.toJsonTemplate(innerKey, "_json_output_")};
741
+ ${i !== optionalKeys.length - 1 ? "_has_keys_ = true;" : ""}
742
+ }
743
+ _ => {}
744
+ };`);
745
+ }
746
+ toQueryParamParams.push(
747
+ ` ${innerType.toQueryStringTemplate(`&self.${fieldName}`, key, "_query_parts_")};`
748
+ );
749
+ }
750
+ context.generatedTypes.push(structName);
751
+ let selfDeclaration = `Self {
752
+ ${fieldNames.join(",\n ")},
753
+ }`;
754
+ if (fieldNames.length < 4) {
755
+ selfDeclaration = `Self { ${fieldNames.join(", ")} }`;
756
+ }
757
+ let leading = "";
758
+ if (schema.metadata?.description) {
759
+ leading += `${schema.metadata.description.split("\n").map((line) => `/// ${line}`).join("\n")}
760
+ `;
761
+ }
762
+ if (schema.metadata?.isDeprecated) {
763
+ leading += `#[deprecated]
764
+ `;
765
+ }
766
+ result.content = `${leading}#[derive(Clone, Debug, PartialEq)]
767
+ pub struct ${structName} {
768
+ ${fieldDeclarationParts.join(",\n")},
769
+ }
770
+
771
+ impl ArriModel for ${structName} {
772
+ fn new() -> Self {
773
+ Self {
774
+ ${defaultParts.join(",\n")},
775
+ }
776
+ }
777
+ fn from_json(input: serde_json::Value) -> Self {
778
+ match input {
779
+ serde_json::Value::Object(_val_) => {
780
+ ${fromJsonParts.join("\n")}
781
+ ${selfDeclaration}
782
+ }
783
+ _ => Self::new(),
784
+ }
785
+ }
786
+ fn from_json_string(input: String) -> Self {
787
+ match serde_json::from_str(input.as_str()) {
788
+ Ok(val) => Self::from_json(val),
789
+ _ => Self::new(),
790
+ }
791
+ }
792
+ fn to_json_string(&self) -> String {
793
+ let mut _json_output_ = "{".to_string();
794
+ ${!hasKeys ? `let mut _has_keys_ = false;` : ""}
795
+ ${toJsonParts.join("\n")}
796
+ _json_output_.push('}');
797
+ _json_output_
798
+ }
799
+ fn to_query_params_string(&self) -> String {
800
+ let mut _query_parts_: Vec<String> = Vec::new();
801
+ ${toQueryParamParams.join("\n")}
802
+ _query_parts_.join("&")
803
+ }
804
+ }
805
+
806
+ ${subContent.join("\n\n")}`;
807
+ return result;
808
+ }
809
+
810
+ function rustStringFromSchema(schema, context) {
811
+ const isOptionType = outputIsOptionType(schema, context);
812
+ const defaultValue = isOptionType ? "None" : '"".to_string()';
813
+ const typeName = isOptionType ? "Option<String>" : "String";
814
+ return {
815
+ typeName,
816
+ defaultValue,
817
+ isNullable: schema.nullable ?? false,
818
+ fromJsonTemplate(input, key) {
819
+ const innerKey = validRustIdentifier(`${key}_val`);
820
+ if (isOptionType) {
821
+ return `match ${input} {
822
+ Some(serde_json::Value::String(${innerKey})) => Some(${innerKey}.to_owned()),
823
+ _ => None,
824
+ }`;
825
+ }
826
+ return `match ${input} {
827
+ Some(serde_json::Value::String(${innerKey})) => ${innerKey}.to_owned(),
828
+ _ => "".to_string(),
829
+ }`;
830
+ },
831
+ toJsonTemplate(input, target) {
832
+ return `${target}.push_str(serialize_string(${input}).as_str())`;
833
+ },
834
+ toQueryStringTemplate(input, key, target) {
835
+ const innerKey = validRustIdentifier(`${key}_val`);
836
+ if (context.isOptional) {
837
+ return `match ${input} {
838
+ Some(${innerKey}) => {
839
+ ${target}.push(format!("${key}={}", ${innerKey}));
840
+ }
841
+ _ => {}
842
+ }`;
843
+ }
844
+ if (schema.nullable) {
845
+ return `match ${input} {
846
+ Some(${innerKey}) => {
847
+ ${target}.push(format!("${key}={}", ${innerKey}));
848
+ }
849
+ _ => {
850
+ ${target}.push("${key}=null".to_string());
851
+ }
852
+ }`;
853
+ }
854
+ return `${target}.push(format!("${key}={}", ${input}))`;
855
+ },
856
+ content: ""
857
+ };
858
+ }
859
+ function rustBooleanFromSchema(schema, context) {
860
+ const isOptionType = outputIsOptionType(schema, context);
861
+ const defaultValue = isOptionType ? "None" : "false";
862
+ const typeName = isOptionType ? "Option<bool>" : "bool";
863
+ return {
864
+ typeName,
865
+ defaultValue,
866
+ isNullable: schema.nullable ?? false,
867
+ fromJsonTemplate(input, key) {
868
+ const innerKey = validRustIdentifier(`${key}_val`);
869
+ if (isOptionType) {
870
+ return `match ${input} {
871
+ Some(serde_json::Value::Bool(${innerKey})) => Some(${innerKey}.to_owned()),
872
+ _ => None,
873
+ }`;
874
+ }
875
+ return `match ${input} {
876
+ Some(serde_json::Value::Bool(${innerKey})) => ${innerKey}.to_owned(),
877
+ _ => false,
878
+ }`;
879
+ },
880
+ toJsonTemplate(input, target) {
881
+ return `${target}.push_str(${input}.to_string().as_str())`;
882
+ },
883
+ toQueryStringTemplate(input, key, target) {
884
+ const innerKey = validRustIdentifier(`${key}_val`);
885
+ if (context.isOptional) {
886
+ return `match ${input} {
887
+ Some(${innerKey}) => {
888
+ ${target}.push(format!("${key}={}", ${innerKey}));
889
+ }
890
+ _ => {}
891
+ }`;
892
+ }
893
+ if (schema.nullable) {
894
+ return `match ${input} {
895
+ Some(${innerKey}) => {
896
+ ${target}.push(format!("${key}={}", ${innerKey}));
897
+ }
898
+ _ => {
899
+ ${target}.push("${key}=null".to_string());
900
+ }
901
+ }`;
902
+ }
903
+ return `${target}.push(format!("${key}={}", ${input}))`;
904
+ },
905
+ content: ""
906
+ };
907
+ }
908
+ function rustTimestampFromSchema(schema, context) {
909
+ const isOptionType = outputIsOptionType(schema, context);
910
+ const typeName = isOptionType ? "Option<DateTime<FixedOffset>>" : "DateTime<FixedOffset>";
911
+ const defaultValue = isOptionType ? "None" : "DateTime::default()";
912
+ return {
913
+ typeName,
914
+ defaultValue,
915
+ isNullable: schema.nullable ?? false,
916
+ fromJsonTemplate(input, key) {
917
+ const innerKey = validRustIdentifier(`${key}_val`);
918
+ if (isOptionType) {
919
+ return `match ${input} {
920
+ Some(serde_json::Value::String(${innerKey})) => {
921
+ match DateTime::<FixedOffset>::parse_from_rfc3339(${innerKey}) {
922
+ Ok(${innerKey}_result) => Some(${innerKey}_result),
923
+ Err(_) => None,
924
+ }
925
+ }
926
+ _ => None,
927
+ }`;
928
+ }
929
+ return `match ${input} {
930
+ Some(serde_json::Value::String(${innerKey})) => {
931
+ DateTime::<FixedOffset>::parse_from_rfc3339(${innerKey})
932
+ .unwrap_or(DateTime::default())
933
+ }
934
+ _ => DateTime::default(),
935
+ }`;
936
+ },
937
+ toJsonTemplate(input, target) {
938
+ return `${target}.push_str(serialize_date_time(${input}, true).as_str())`;
939
+ },
940
+ toQueryStringTemplate(input, key, target) {
941
+ const innerKey = validRustIdentifier(`${key}_val`);
942
+ if (context.isOptional) {
943
+ return `match ${input} {
944
+ Some(${innerKey}) => {
945
+ ${target}.push(format!(
946
+ "${key}={}",
947
+ serialize_date_time(${innerKey}, false)
948
+ ));
949
+ }
950
+ _ => {}
951
+ }`;
952
+ }
953
+ if (schema.nullable) {
954
+ return `match ${input} {
955
+ Some(${innerKey}) => {
956
+ ${target}.push(format!(
957
+ "${key}={}",
958
+ serialize_date_time(${innerKey}, false)
959
+ ));
960
+ }
961
+ _ => {
962
+ ${target}.push("${key}=null".to_string());
963
+ }
964
+ }`;
965
+ }
966
+ return `${target}.push(format!(
967
+ "${key}={}",
968
+ serialize_date_time(${input}, false)
969
+ ))`;
970
+ },
971
+ content: ""
972
+ };
973
+ }
974
+ function rustF32FromSchema(schema, context) {
975
+ const isOptionType = outputIsOptionType(schema, context);
976
+ const typeName = isOptionType ? `Option<f32>` : "f32";
977
+ const defaultValue = isOptionType ? `None` : "0.0";
978
+ return {
979
+ typeName,
980
+ defaultValue,
981
+ isNullable: schema.nullable ?? false,
982
+ fromJsonTemplate(input, key) {
983
+ const innerKey = validRustIdentifier(`${key}_val`);
984
+ if (isOptionType) {
985
+ return `match ${input} {
986
+ Some(serde_json::Value::Number(${innerKey})) => match ${innerKey}.as_f64() {
987
+ Some(${innerKey}_result) => Some(${innerKey}_result as f32),
988
+ _ => None,
989
+ },
990
+ _ => None,
991
+ }`;
992
+ }
993
+ return `match ${input} {
994
+ Some(serde_json::Value::Number(${innerKey})) => {
995
+ ${innerKey}.as_f64().unwrap_or(0.0) as f32
996
+ }
997
+ _ => 0.0,
998
+ }`;
999
+ },
1000
+ toJsonTemplate(input, target) {
1001
+ return `${target}.push_str(${input}.to_string().as_str())`;
1002
+ },
1003
+ toQueryStringTemplate(input, key, target) {
1004
+ const innerKey = validRustIdentifier(`${key}_val`);
1005
+ if (context.isOptional) {
1006
+ return `match ${input} {
1007
+ Some(${innerKey}) => {
1008
+ ${target}.push(format!("${key}={}", ${innerKey}));
1009
+ }
1010
+ _ => {}
1011
+ }`;
1012
+ }
1013
+ if (schema.nullable) {
1014
+ return `match ${input} {
1015
+ Some(${innerKey}) => {
1016
+ ${target}.push(format!("${key}={}", ${innerKey}));
1017
+ }
1018
+ _ => {
1019
+ ${target}.push("${key}=null".to_string());
1020
+ }
1021
+ }`;
1022
+ }
1023
+ return `${target}.push(format!("${key}={}", ${input}))`;
1024
+ },
1025
+ content: ""
1026
+ };
1027
+ }
1028
+ function rustF64FromSchema(schema, context) {
1029
+ const isOptionType = outputIsOptionType(schema, context);
1030
+ const typeName = isOptionType ? `Option<f64>` : "f64";
1031
+ const defaultValue = isOptionType ? `None` : "0.0";
1032
+ return {
1033
+ typeName,
1034
+ defaultValue,
1035
+ isNullable: schema.nullable ?? false,
1036
+ fromJsonTemplate(input, key) {
1037
+ const innerKey = validRustIdentifier(`${key}_val`);
1038
+ if (isOptionType) {
1039
+ return `match ${input} {
1040
+ Some(serde_json::Value::Number(${innerKey})) => match ${innerKey}.as_f64() {
1041
+ Some(${innerKey}_result) => Some(${innerKey}_result),
1042
+ _ => None,
1043
+ },
1044
+ _ => None,
1045
+ }`;
1046
+ }
1047
+ return `match ${input} {
1048
+ Some(serde_json::Value::Number(${innerKey})) => {
1049
+ ${innerKey}.as_f64().unwrap_or(0.0)
1050
+ }
1051
+ _ => 0.0,
1052
+ }`;
1053
+ },
1054
+ toJsonTemplate(input, target) {
1055
+ return `${target}.push_str(${input}.to_string().as_str())`;
1056
+ },
1057
+ toQueryStringTemplate(input, key, target) {
1058
+ const innerKey = validRustIdentifier(`${key}_val`);
1059
+ if (context.isOptional) {
1060
+ return `match ${input} {
1061
+ Some(${innerKey}) => {
1062
+ ${target}.push(format!("${key}={}", ${innerKey}));
1063
+ }
1064
+ _ => {}
1065
+ }`;
1066
+ }
1067
+ if (schema.nullable) {
1068
+ return `match ${input} {
1069
+ Some(${innerKey}) => {
1070
+ ${target}.push(format!("${key}={}", ${innerKey}));
1071
+ }
1072
+ _ => {
1073
+ ${target}.push("${key}=null".to_string());
1074
+ }
1075
+ }`;
1076
+ }
1077
+ return `${target}.push(format!("${key}={}", ${input}))`;
1078
+ },
1079
+ content: ""
1080
+ };
1081
+ }
1082
+ function rustI8FromSchema(schema, context) {
1083
+ const isOptionType = outputIsOptionType(schema, context);
1084
+ const typeName = isOptionType ? `Option<i8>` : "i8";
1085
+ const defaultValue = isOptionType ? `None` : "0";
1086
+ return {
1087
+ typeName,
1088
+ defaultValue,
1089
+ isNullable: schema.nullable ?? false,
1090
+ fromJsonTemplate(input, key) {
1091
+ const innerKey = validRustIdentifier(`${key}_val`);
1092
+ if (isOptionType) {
1093
+ return `match ${input} {
1094
+ Some(serde_json::Value::Number(${innerKey})) => match ${innerKey}.as_i64() {
1095
+ Some(${innerKey}_result) => match i8::try_from(${innerKey}_result) {
1096
+ Ok(${innerKey}_result_val) => Some(${innerKey}_result_val),
1097
+ Err(_) => None,
1098
+ },
1099
+ _ => None,
1100
+ },
1101
+ _ => None,
1102
+ }`;
1103
+ }
1104
+ return `match ${input} {
1105
+ Some(serde_json::Value::Number(${innerKey})) => {
1106
+ i8::try_from(${innerKey}.as_i64().unwrap_or(0)).unwrap_or(0)
1107
+ }
1108
+ _ => 0,
1109
+ }`;
1110
+ },
1111
+ toJsonTemplate(input, target) {
1112
+ return `${target}.push_str(${input}.to_string().as_str())`;
1113
+ },
1114
+ toQueryStringTemplate(input, key, target) {
1115
+ const innerKey = validRustIdentifier(`${key}_val`);
1116
+ if (context.isOptional) {
1117
+ return `match ${input} {
1118
+ Some(${innerKey}) => {
1119
+ ${target}.push(format!("${key}={}", ${innerKey}));
1120
+ }
1121
+ _ => {}
1122
+ }`;
1123
+ }
1124
+ if (schema.nullable) {
1125
+ return `match ${input} {
1126
+ Some(${innerKey}) => {
1127
+ ${target}.push(format!("${key}={}", ${innerKey}));
1128
+ }
1129
+ _ => {
1130
+ ${target}.push("${key}=null".to_string());
1131
+ }
1132
+ }`;
1133
+ }
1134
+ return `${target}.push(format!("${key}={}", ${input}))`;
1135
+ },
1136
+ content: ""
1137
+ };
1138
+ }
1139
+ function rustU8FromSchema(schema, context) {
1140
+ const isOptionType = outputIsOptionType(schema, context);
1141
+ const typeName = isOptionType ? "Option<u8>" : "u8";
1142
+ const defaultValue = isOptionType ? "None" : "0";
1143
+ return {
1144
+ typeName,
1145
+ defaultValue,
1146
+ isNullable: schema.nullable ?? false,
1147
+ fromJsonTemplate(input, key) {
1148
+ const innerKey = validRustIdentifier(`${key}_val`);
1149
+ if (isOptionType) {
1150
+ return `match ${input} {
1151
+ Some(serde_json::Value::Number(${innerKey})) => match ${innerKey}.as_u64() {
1152
+ Some(${innerKey}_result) => match u8::try_from(${innerKey}_result) {
1153
+ Ok(${innerKey}_result_val) => Some(${innerKey}_result_val),
1154
+ Err(_) => None,
1155
+ },
1156
+ _ => None,
1157
+ },
1158
+ _ => None,
1159
+ }`;
1160
+ }
1161
+ return `match ${input} {
1162
+ Some(serde_json::Value::Number(${innerKey})) => {
1163
+ u8::try_from(${innerKey}.as_u64().unwrap_or(0)).unwrap_or(0)
1164
+ }
1165
+ _ => 0,
1166
+ }`;
1167
+ },
1168
+ toJsonTemplate(input, target) {
1169
+ return `${target}.push_str(${input}.to_string().as_str())`;
1170
+ },
1171
+ toQueryStringTemplate(input, key, target) {
1172
+ const innerKey = validRustIdentifier(`${key}_val`);
1173
+ if (context.isOptional) {
1174
+ return `match ${input} {
1175
+ Some(${innerKey}) => {
1176
+ ${target}.push(format!("${key}={}", ${innerKey}));
1177
+ }
1178
+ _ => {}
1179
+ }`;
1180
+ }
1181
+ if (schema.nullable) {
1182
+ return `match ${input} {
1183
+ Some(${innerKey}) => {
1184
+ ${target}.push(format!("${key}={}", ${innerKey}));
1185
+ }
1186
+ _ => {
1187
+ ${target}.push("${key}=null".to_string());
1188
+ }
1189
+ }`;
1190
+ }
1191
+ return `${target}.push(format!("${key}={}", ${input}))`;
1192
+ },
1193
+ content: ""
1194
+ };
1195
+ }
1196
+ function rustI16FromSchema(schema, context) {
1197
+ const isOptionType = outputIsOptionType(schema, context);
1198
+ const typeName = isOptionType ? "Option<i16>" : "i16";
1199
+ const defaultValue = isOptionType ? "None" : "0";
1200
+ return {
1201
+ typeName,
1202
+ defaultValue,
1203
+ isNullable: schema.nullable ?? false,
1204
+ fromJsonTemplate(input, key) {
1205
+ const innerKey = validRustIdentifier(`${key}_val`);
1206
+ if (isOptionType) {
1207
+ return `match ${input} {
1208
+ Some(serde_json::Value::Number(${innerKey})) => match ${innerKey}.as_i64() {
1209
+ Some(${innerKey}_result) => match i16::try_from(${innerKey}_result) {
1210
+ Ok(${innerKey}_result_val) => Some(${innerKey}_result_val),
1211
+ Err(_) => None,
1212
+ },
1213
+ _ => None,
1214
+ },
1215
+ _ => None,
1216
+ }`;
1217
+ }
1218
+ return `match ${input} {
1219
+ Some(serde_json::Value::Number(${innerKey})) => {
1220
+ i16::try_from(${innerKey}.as_i64().unwrap_or(0)).unwrap_or(0)
1221
+ }
1222
+ _ => 0,
1223
+ }`;
1224
+ },
1225
+ toJsonTemplate(input, target) {
1226
+ return `${target}.push_str(${input}.to_string().as_str())`;
1227
+ },
1228
+ toQueryStringTemplate(input, key, target) {
1229
+ const innerKey = validRustIdentifier(`${key}_val`);
1230
+ if (context.isOptional) {
1231
+ return `match ${input} {
1232
+ Some(${innerKey}) => {
1233
+ ${target}.push(format!("${key}={}", ${innerKey}));
1234
+ }
1235
+ _ => {}
1236
+ }`;
1237
+ }
1238
+ if (schema.nullable) {
1239
+ return `match ${input} {
1240
+ Some(${innerKey}) => {
1241
+ ${target}.push(format!("${key}={}", ${innerKey}));
1242
+ }
1243
+ _ => {
1244
+ ${target}.push("${key}=null".to_string());
1245
+ }
1246
+ }`;
1247
+ }
1248
+ return `${target}.push(format!("${key}={}", ${input}))`;
1249
+ },
1250
+ content: ""
1251
+ };
1252
+ }
1253
+ function rustU16FromSchema(schema, context) {
1254
+ const isOptionType = outputIsOptionType(schema, context);
1255
+ const typeName = isOptionType ? "Option<u16>" : "u16";
1256
+ const defaultValue = isOptionType ? "None" : "0";
1257
+ return {
1258
+ typeName,
1259
+ defaultValue,
1260
+ isNullable: schema.nullable ?? false,
1261
+ fromJsonTemplate(input, key) {
1262
+ const innerKey = validRustIdentifier(`${key}_val`);
1263
+ if (isOptionType) {
1264
+ return `match ${input} {
1265
+ Some(serde_json::Value::Number(${innerKey})) => match ${innerKey}.as_u64() {
1266
+ Some(${innerKey}_result) => match u16::try_from(${innerKey}_result) {
1267
+ Ok(${innerKey}_result_val) => Some(${innerKey}_result_val),
1268
+ Err(_) => None,
1269
+ },
1270
+ _ => None,
1271
+ },
1272
+ _ => None,
1273
+ }`;
1274
+ }
1275
+ return `match ${input} {
1276
+ Some(serde_json::Value::Number(${innerKey})) => {
1277
+ u16::try_from(${innerKey}.as_u64().unwrap_or(0)).unwrap_or(0)
1278
+ }
1279
+ _ => 0,
1280
+ }`;
1281
+ },
1282
+ toJsonTemplate(input, target) {
1283
+ return `${target}.push_str(${input}.to_string().as_str())`;
1284
+ },
1285
+ toQueryStringTemplate(input, key, target) {
1286
+ const innerKey = validRustIdentifier(`${key}_val`);
1287
+ if (context.isOptional) {
1288
+ return `match ${input} {
1289
+ Some(${innerKey}) => {
1290
+ ${target}.push(format!("${key}={}", ${innerKey}));
1291
+ }
1292
+ _ => {}
1293
+ }`;
1294
+ }
1295
+ if (schema.nullable) {
1296
+ return `match ${input} {
1297
+ Some(${innerKey}) => {
1298
+ ${target}.push(format!("${key}={}", ${innerKey}));
1299
+ }
1300
+ _ => {
1301
+ ${target}.push("${key}=null".to_string());
1302
+ }
1303
+ }`;
1304
+ }
1305
+ return `${target}.push(format!("${key}={}", ${input}))`;
1306
+ },
1307
+ content: ""
1308
+ };
1309
+ }
1310
+ function rustI32FromSchema(schema, context) {
1311
+ const isOptionType = outputIsOptionType(schema, context);
1312
+ const typeName = isOptionType ? "Option<i32>" : "i32";
1313
+ const defaultValue = isOptionType ? "None" : "0";
1314
+ return {
1315
+ typeName,
1316
+ defaultValue,
1317
+ isNullable: schema.nullable ?? false,
1318
+ fromJsonTemplate(input, key) {
1319
+ const innerKey = validRustIdentifier(`${key}_val`);
1320
+ if (isOptionType) {
1321
+ return `match ${input} {
1322
+ Some(serde_json::Value::Number(${innerKey})) => match ${innerKey}.as_i64() {
1323
+ Some(${innerKey}_result) => match i32::try_from(${innerKey}_result) {
1324
+ Ok(${innerKey}_result_val) => Some(${innerKey}_result_val),
1325
+ Err(_) => None,
1326
+ },
1327
+ _ => None,
1328
+ },
1329
+ _ => None,
1330
+ }`;
1331
+ }
1332
+ return `match ${input} {
1333
+ Some(serde_json::Value::Number(${innerKey})) => {
1334
+ i32::try_from(${innerKey}.as_i64().unwrap_or(0)).unwrap_or(0)
1335
+ }
1336
+ _ => 0,
1337
+ }`;
1338
+ },
1339
+ toJsonTemplate(input, target) {
1340
+ return `${target}.push_str(${input}.to_string().as_str())`;
1341
+ },
1342
+ toQueryStringTemplate(input, key, target) {
1343
+ const innerKey = validRustIdentifier(`${key}_val`);
1344
+ if (context.isOptional) {
1345
+ return `match ${input} {
1346
+ Some(${innerKey}) => {
1347
+ ${target}.push(format!("${key}={}", ${innerKey}));
1348
+ }
1349
+ _ => {}
1350
+ }`;
1351
+ }
1352
+ if (schema.nullable) {
1353
+ return `match ${input} {
1354
+ Some(${innerKey}) => {
1355
+ ${target}.push(format!("${key}={}", ${innerKey}));
1356
+ }
1357
+ _ => {
1358
+ ${target}.push("${key}=null".to_string());
1359
+ }
1360
+ }`;
1361
+ }
1362
+ return `${target}.push(format!("${key}={}", ${input}))`;
1363
+ },
1364
+ content: ""
1365
+ };
1366
+ }
1367
+ function rustU32FromSchema(schema, context) {
1368
+ const isOptionType = outputIsOptionType(schema, context);
1369
+ const typeName = isOptionType ? "Option<u32>" : "u32";
1370
+ const defaultValue = isOptionType ? "None" : "0";
1371
+ return {
1372
+ typeName,
1373
+ defaultValue,
1374
+ isNullable: schema.nullable ?? false,
1375
+ fromJsonTemplate(input, key) {
1376
+ const innerKey = validRustIdentifier(`${key}_val`);
1377
+ if (isOptionType) {
1378
+ return `match ${input} {
1379
+ Some(serde_json::Value::Number(${innerKey})) => match ${innerKey}.as_u64() {
1380
+ Some(${innerKey}_result) => match u32::try_from(${innerKey}_result) {
1381
+ Ok(${innerKey}_result_val) => Some(${innerKey}_result_val),
1382
+ Err(_) => None,
1383
+ },
1384
+ _ => None,
1385
+ },
1386
+ _ => None,
1387
+ }`;
1388
+ }
1389
+ return `match ${input} {
1390
+ Some(serde_json::Value::Number(${innerKey})) => {
1391
+ u32::try_from(${innerKey}.as_u64().unwrap_or(0)).unwrap_or(0)
1392
+ }
1393
+ _ => 0,
1394
+ }`;
1395
+ },
1396
+ toJsonTemplate(input, target) {
1397
+ return `${target}.push_str(${input}.to_string().as_str())`;
1398
+ },
1399
+ toQueryStringTemplate(input, key, target) {
1400
+ const innerKey = validRustIdentifier(`${key}_val`);
1401
+ if (context.isOptional) {
1402
+ return `match ${input} {
1403
+ Some(${innerKey}) => {
1404
+ ${target}.push(format!("${key}={}", ${innerKey}));
1405
+ }
1406
+ _ => {}
1407
+ }`;
1408
+ }
1409
+ if (schema.nullable) {
1410
+ return `match ${input} {
1411
+ Some(${innerKey}) => {
1412
+ ${target}.push(format!("${key}={}", ${innerKey}));
1413
+ }
1414
+ _ => {
1415
+ ${target}.push("${key}=null".to_string());
1416
+ }
1417
+ }`;
1418
+ }
1419
+ return `${target}.push(format!("${key}={}", ${input}))`;
1420
+ },
1421
+ content: ""
1422
+ };
1423
+ }
1424
+ function rustI64FromSchema(schema, context) {
1425
+ const isOptionType = outputIsOptionType(schema, context);
1426
+ const typeName = isOptionType ? "Option<i64>" : "i64";
1427
+ const defaultValue = isOptionType ? "None" : "0";
1428
+ return {
1429
+ typeName,
1430
+ defaultValue,
1431
+ isNullable: schema.nullable ?? false,
1432
+ fromJsonTemplate(input, key) {
1433
+ const innerKey = validRustIdentifier(`${key}_val`);
1434
+ if (isOptionType) {
1435
+ return `match ${input} {
1436
+ Some(serde_json::Value::String(${innerKey})) => match ${innerKey}.parse::<i64>() {
1437
+ Ok(${innerKey}_result) => Some(${innerKey}_result),
1438
+ Err(_) => None,
1439
+ },
1440
+ _ => None,
1441
+ }`;
1442
+ }
1443
+ return `match ${input} {
1444
+ Some(serde_json::Value::String(${innerKey})) => {
1445
+ ${innerKey}.parse::<i64>().unwrap_or(0)
1446
+ }
1447
+ _ => 0,
1448
+ }`;
1449
+ },
1450
+ toJsonTemplate(input, target) {
1451
+ return `${target}.push_str(format!("\\"{}\\"", ${input}).as_str())`;
1452
+ },
1453
+ toQueryStringTemplate(input, key, target) {
1454
+ const innerKey = validRustIdentifier(`${key}_val`);
1455
+ if (context.isOptional) {
1456
+ return `match ${input} {
1457
+ Some(${innerKey}) => {
1458
+ ${target}.push(format!("${key}={}", ${innerKey}));
1459
+ }
1460
+ _ => {}
1461
+ }`;
1462
+ }
1463
+ if (schema.nullable) {
1464
+ return `match ${input} {
1465
+ Some(${innerKey}) => {
1466
+ ${target}.push(format!("${key}={}", ${innerKey}));
1467
+ }
1468
+ _ => {
1469
+ ${target}.push("${key}=null".to_string());
1470
+ }
1471
+ }`;
1472
+ }
1473
+ return `${target}.push(format!("${key}={}", ${input}))`;
1474
+ },
1475
+ content: ""
1476
+ };
1477
+ }
1478
+ function rustU64FromSchema(schema, context) {
1479
+ const isOptionType = outputIsOptionType(schema, context);
1480
+ const typeName = isOptionType ? "Option<u64>" : "u64";
1481
+ const defaultValue = isOptionType ? "None" : "0";
1482
+ return {
1483
+ typeName,
1484
+ defaultValue,
1485
+ isNullable: schema.nullable ?? false,
1486
+ fromJsonTemplate(input, key) {
1487
+ const innerKey = validRustIdentifier(`${key}_val`);
1488
+ if (isOptionType) {
1489
+ return `match ${input} {
1490
+ Some(serde_json::Value::String(${innerKey})) => match ${innerKey}.parse::<u64>() {
1491
+ Ok(${innerKey}_result) => Some(${innerKey}_result),
1492
+ Err(_) => None,
1493
+ },
1494
+ _ => None,
1495
+ }`;
1496
+ }
1497
+ return `match ${input} {
1498
+ Some(serde_json::Value::String(${innerKey})) => {
1499
+ ${innerKey}.parse::<u64>().unwrap_or(0)
1500
+ }
1501
+ _ => 0,
1502
+ }`;
1503
+ },
1504
+ toJsonTemplate(input, target) {
1505
+ return `${target}.push_str(format!("\\"{}\\"", ${input}).as_str())`;
1506
+ },
1507
+ toQueryStringTemplate(input, key, target) {
1508
+ const innerKey = validRustIdentifier(`${key}_val`);
1509
+ if (context.isOptional) {
1510
+ return `match ${input} {
1511
+ Some(${innerKey}) => {
1512
+ ${target}.push(format!("${key}={}", ${innerKey}));
1513
+ }
1514
+ _ => {}
1515
+ }`;
1516
+ }
1517
+ if (schema.nullable) {
1518
+ return `match ${input} {
1519
+ Some(${innerKey}) => {
1520
+ ${target}.push(format!("${key}={}", ${innerKey}));
1521
+ }
1522
+ _ => {
1523
+ ${target}.push("${key}=null".to_string());
1524
+ }
1525
+ }`;
1526
+ }
1527
+ return `${target}.push(format!("${key}={}", ${input}))`;
1528
+ },
1529
+ content: ""
1530
+ };
1531
+ }
1532
+
1533
+ function rustRpcFromSchema(schema, context) {
1534
+ switch (schema.transport) {
1535
+ case "http":
1536
+ return rustHttpRpcFromSchema(schema, context);
1537
+ case "ws":
1538
+ return rustWsRpcFromSchema(schema, context);
1539
+ default:
1540
+ console.warn(
1541
+ `[rust-codegen] Unknown transport type "${schema.transport}". Skipping ${context.instancePath}.`
1542
+ );
1543
+ return "";
1544
+ }
1545
+ }
1546
+ function rustHttpRpcFromSchema(schema, context) {
1547
+ if (schema.isEventStream) {
1548
+ console.warn(
1549
+ `[rust-codegen] SSE is not supported at this time. Skipping ${context.instancePath}.`
1550
+ );
1551
+ return "";
1552
+ }
1553
+ const functionName = getFunctionName(context.instancePath);
1554
+ const params = schema.params ? validRustName(schema.params) : void 0;
1555
+ const response = schema.response ? validRustName(schema.response) : void 0;
1556
+ let leading = "";
1557
+ if (schema.description) {
1558
+ leading += formatDescriptionComment(schema.description);
1559
+ leading += "\n";
1560
+ }
1561
+ if (schema.isDeprecated) {
1562
+ leading += "#[deprecated]\n";
1563
+ }
1564
+ return `${leading}pub async fn ${functionName} (
1565
+ self: &Self,
1566
+ ${params ? `params: ${context.typeNamePrefix}${params},` : ""}
1567
+ ) -> Result<${context.typeNamePrefix}${response ?? "()"}, ArriServerError> {
1568
+ parsed_arri_request(
1569
+ ArriParsedRequestOptions {
1570
+ http_client: &self.config.http_client,
1571
+ url: format!("{}${schema.path}", &self.config.base_url),
1572
+ method: reqwest::Method::${schema.method.toUpperCase()},
1573
+ headers: self.config.headers,
1574
+ client_version: "${context.clientVersion}".to_string(),
1575
+ },
1576
+ ${params ? `Some(params)` : "None::<EmptyArriModel>"},
1577
+ |body| ${response ? `return ${context.typeNamePrefix}${response}::from_json_string(body)` : "{}"},
1578
+ )
1579
+ .await
1580
+ }`;
1581
+ }
1582
+ function rustWsRpcFromSchema(schema, context) {
1583
+ console.warn(
1584
+ `[rust-codegen] WS RPCs are not supported at this time. Skipping ${context.instancePath}.`
1585
+ );
1586
+ return "";
1587
+ }
1588
+ function getFunctionName(instancePath) {
1589
+ assert__default(instancePath.length > 0);
1590
+ const name = instancePath.split(".").pop() ?? "";
1591
+ return validRustIdentifier(name);
1592
+ }
1593
+ function getServiceName(instancePath, context) {
1594
+ assert__default(instancePath.length > 0);
1595
+ const name = instancePath.split(".").join("_");
1596
+ return validRustName(`${context.clientName}_${name}_Service`);
1597
+ }
1598
+ function rustServiceFromSchema(schema, context) {
1599
+ const serviceName = getServiceName(context.instancePath, context);
1600
+ const subServices = [];
1601
+ const subServiceContent = [];
1602
+ const rpcParts = [];
1603
+ for (const key of Object.keys(schema)) {
1604
+ const subSchema = schema[key];
1605
+ if (codegenUtils.isServiceDefinition(subSchema)) {
1606
+ const subService = rustServiceFromSchema(subSchema, {
1607
+ clientVersion: context.clientVersion,
1608
+ clientName: context.clientName,
1609
+ typeNamePrefix: context.typeNamePrefix,
1610
+ instancePath: `${context.instancePath}.${key}`,
1611
+ schemaPath: `${context.schemaPath}.${key}`,
1612
+ generatedTypes: context.generatedTypes
1613
+ });
1614
+ if (subService.content) {
1615
+ subServices.push({
1616
+ key: validRustIdentifier(key),
1617
+ name: subService.name
1618
+ });
1619
+ }
1620
+ continue;
1621
+ }
1622
+ if (codegenUtils.isRpcDefinition(subSchema)) {
1623
+ const rpc = rustRpcFromSchema(subSchema, {
1624
+ clientVersion: context.clientVersion,
1625
+ clientName: context.clientName,
1626
+ typeNamePrefix: context.typeNamePrefix,
1627
+ instancePath: `${context.instancePath}.${key}`,
1628
+ schemaPath: `${context.schemaPath}.${key}`,
1629
+ generatedTypes: context.generatedTypes
1630
+ });
1631
+ if (rpc) {
1632
+ rpcParts.push(rpc);
1633
+ }
1634
+ continue;
1635
+ }
1636
+ throw new Error(
1637
+ `[rust-codegen] Invalid schema at /procedures/${context.instancePath}.`
1638
+ );
1639
+ }
1640
+ return {
1641
+ name: serviceName,
1642
+ content: `pub struct ${serviceName}<'a> {
1643
+ config: &'a ArriClientConfig,
1644
+ ${subServices.map((service) => ` pub ${service.key}: ${service.name}<'a>,`).join("\n")}
1645
+ }
1646
+
1647
+ impl<'a> ArriClientService<'a> for ${serviceName}<'a> {
1648
+ fn create(config: &'a ArriClientConfig) -> Self {
1649
+ Self {
1650
+ config: &config,
1651
+ ${subServices.map((service) => ` ${service.key}: ${service.name}::create(config),`).join("\n")}
1652
+ }
1653
+ }
1654
+ }
1655
+
1656
+ impl ${serviceName}<'_> {
1657
+ ${rpcParts.join("\n")}
1658
+ }
1659
+
1660
+ ${subServiceContent.join("\n\n")}
1661
+ `
1662
+ };
1663
+ }
1664
+
1665
+ function rustRecordFromSchema(schema, context) {
1666
+ const innerType = rustTypeFromSchema(schema.values, {
1667
+ clientVersion: context.clientVersion,
1668
+ clientName: context.clientName,
1669
+ typeNamePrefix: context.typeNamePrefix,
1670
+ instancePath: `${context.instancePath}/value`,
1671
+ schemaPath: `${context.schemaPath}/values`,
1672
+ generatedTypes: context.generatedTypes
1673
+ });
1674
+ const isOptionType = outputIsOptionType(schema, context);
1675
+ const typeName = isOptionType ? `Option<BTreeMap<String, ${innerType.typeName}>>` : `BTreeMap<String, ${innerType.typeName}>`;
1676
+ const defaultValue = isOptionType ? `None` : `BTreeMap::new()`;
1677
+ return {
1678
+ typeName,
1679
+ defaultValue,
1680
+ isNullable: schema.nullable ?? false,
1681
+ fromJsonTemplate(input, key) {
1682
+ const innerKey = validRustIdentifier(`${key}_val`);
1683
+ if (isOptionType) {
1684
+ return `match ${input} {
1685
+ Some(serde_json::Value::Object(${innerKey})) => {
1686
+ let mut ${innerKey}_result: BTreeMap<String, ${innerType.typeName}> = BTreeMap::new();
1687
+ for (_key_, _value_) in ${innerKey}.into_iter() {
1688
+ ${innerKey}_result.insert(
1689
+ _key_.to_owned(),
1690
+ ${innerType.fromJsonTemplate(`Some(_value_.to_owned())`, `value`)},
1691
+ );
1692
+ }
1693
+ Some(${innerKey}_result)
1694
+ }
1695
+ _ => None,
1696
+ }`;
1697
+ }
1698
+ return `match ${input} {
1699
+ Some(serde_json::Value::Object(${innerKey})) => {
1700
+ let mut ${innerKey}_result: BTreeMap<String, ${innerType.typeName}> = BTreeMap::new();
1701
+ for (_key_, _value_) in ${innerKey}.into_iter() {
1702
+ ${innerKey}_result.insert(
1703
+ _key_.to_owned(),
1704
+ ${innerType.fromJsonTemplate(`Some(_value_.to_owned())`, `value`)},
1705
+ );
1706
+ }
1707
+ ${innerKey}_result
1708
+ }
1709
+ _ => BTreeMap::new(),
1710
+ }`;
1711
+ },
1712
+ toJsonTemplate(input, target) {
1713
+ if (innerType.isNullable) {
1714
+ return `${target}.push('{');
1715
+ for (_index_, (_key_, _value_)) in ${input}.iter().enumerate() {
1716
+ if _index_ != 0 {
1717
+ ${target}.push(',');
1718
+ }
1719
+ ${target}.push_str(format!("\\"{}\\":", _key_).as_str());
1720
+ match _value_ {
1721
+ Some(value_val) => {
1722
+ ${innerType.toJsonTemplate("value_val", target)};
1723
+ },
1724
+ _ => {
1725
+ ${target}.push_str("null");
1726
+ }
1727
+ }
1728
+ }
1729
+ ${target}.push('}')`;
1730
+ }
1731
+ return `${target}.push('{');
1732
+ for (_index_, (_key_, _value_)) in ${input}.iter().enumerate() {
1733
+ if _index_ != 0 {
1734
+ ${target}.push(',');
1735
+ }
1736
+ ${target}.push_str(format!("\\"{}\\":", _key_).as_str());
1737
+ ${innerType.toJsonTemplate(`_value_`, target)};
1738
+ }
1739
+ ${target}.push('}')`;
1740
+ },
1741
+ toQueryStringTemplate() {
1742
+ return `println!("[WARNING] cannot serialize nested objects to query params. Skipping field at ${context.instancePath}.")`;
1743
+ },
1744
+ content: innerType.content
1745
+ };
1746
+ }
1747
+
1748
+ function rustRefFromSchema(schema, context) {
1749
+ const innerTypeName = `${context.typeNamePrefix}${validRustName(schema.ref)}`;
1750
+ const isOptionType = outputIsOptionType(schema, context);
1751
+ let typeName = `Box<${innerTypeName}>`;
1752
+ if (isOptionType) {
1753
+ typeName = `Option<${typeName}>`;
1754
+ }
1755
+ let defaultValue;
1756
+ if (isOptionType) {
1757
+ defaultValue = "None";
1758
+ } else {
1759
+ defaultValue = `Box::new(${innerTypeName}::new())`;
1760
+ }
1761
+ return {
1762
+ typeName,
1763
+ defaultValue,
1764
+ isNullable: schema.nullable ?? false,
1765
+ fromJsonTemplate(input, key) {
1766
+ const innerKey = validRustIdentifier(`${key}_val`);
1767
+ const valFromJson = (input2) => {
1768
+ {
1769
+ return `Box::new(${innerTypeName}::from_json(${input2}.to_owned()))`;
1770
+ }
1771
+ };
1772
+ if (isOptionType) {
1773
+ return `match ${input} {
1774
+ Some(${innerKey}) => match ${innerKey} {
1775
+ serde_json::Value::Object(_) => {
1776
+ Some(${valFromJson(innerKey)})
1777
+ }
1778
+ _ => None,
1779
+ },
1780
+ _ => None,
1781
+ }`;
1782
+ }
1783
+ return `match ${input} {
1784
+ Some(${innerKey}) => match ${innerKey} {
1785
+ serde_json::Value::Object(_) => {
1786
+ ${valFromJson(innerKey)}
1787
+ }
1788
+ _ => ${valFromJson(innerKey)},
1789
+ },
1790
+ _ => Box::new(${innerTypeName}::new()),
1791
+ }`;
1792
+ },
1793
+ toJsonTemplate(input, target) {
1794
+ return `${target}.push_str(${input}.to_json_string().as_str())`;
1795
+ },
1796
+ toQueryStringTemplate() {
1797
+ return `println!("[WARNING] cannot serialize nested objects to query params. Skipping field at ${context.instancePath}.")`;
1798
+ },
1799
+ content: ""
1800
+ };
1801
+ }
1802
+
1803
+ const rustClientGenerator = codegenUtils.defineGeneratorPlugin(
1804
+ (options) => {
1805
+ return {
1806
+ generator(def) {
1807
+ const context = {
1808
+ clientVersion: def.info?.version ?? "",
1809
+ clientName: options.clientName ?? "Client",
1810
+ typeNamePrefix: options.typePrefix ?? "",
1811
+ instancePath: "",
1812
+ schemaPath: "",
1813
+ generatedTypes: []
1814
+ };
1815
+ const client = createRustClient(def, {
1816
+ ...context
1817
+ });
1818
+ const outputFile = path__default.resolve(options.outputFile);
1819
+ fs__default.writeFileSync(outputFile, client);
1820
+ const shouldFormat = options.format ?? true;
1821
+ if (shouldFormat) {
1822
+ try {
1823
+ node_child_process.execSync(`rustfmt ${outputFile} --edition 2021`, {
1824
+ stdio: "inherit"
1825
+ });
1826
+ } catch (err) {
1827
+ console.error(`Error formatting`, err);
1828
+ }
1829
+ }
1830
+ },
1831
+ options
1832
+ };
1833
+ }
1834
+ );
1835
+ function createRustClient(def, context) {
1836
+ const services = codegenUtils.unflattenProcedures(def.procedures);
1837
+ const rpcParts = [];
1838
+ const subServices = [];
1839
+ const subServiceContent = [];
1840
+ for (const key of Object.keys(services)) {
1841
+ const subDef = services[key];
1842
+ if (codegenUtils.isServiceDefinition(subDef)) {
1843
+ const service = rustServiceFromSchema(subDef, {
1844
+ clientVersion: def.info?.version ?? "",
1845
+ clientName: context.clientName,
1846
+ typeNamePrefix: context.typeNamePrefix,
1847
+ instancePath: key,
1848
+ schemaPath: key,
1849
+ generatedTypes: context.generatedTypes
1850
+ });
1851
+ if (service.content) {
1852
+ subServices.push({
1853
+ key: validRustIdentifier(key),
1854
+ name: service.name
1855
+ });
1856
+ subServiceContent.push(service.content);
1857
+ }
1858
+ continue;
1859
+ }
1860
+ if (codegenUtils.isRpcDefinition(subDef)) {
1861
+ const rpc = rustRpcFromSchema(subDef, {
1862
+ clientVersion: def.info?.version ?? "",
1863
+ clientName: context.clientName,
1864
+ typeNamePrefix: context.typeNamePrefix,
1865
+ instancePath: key,
1866
+ schemaPath: key,
1867
+ generatedTypes: context.generatedTypes
1868
+ });
1869
+ if (rpc) {
1870
+ rpcParts.push(rpc);
1871
+ }
1872
+ continue;
1873
+ }
1874
+ }
1875
+ const modelParts = [];
1876
+ for (const key of Object.keys(def.definitions)) {
1877
+ const result = rustTypeFromSchema(def.definitions[key], {
1878
+ ...context,
1879
+ clientVersion: def.info?.version ?? "",
1880
+ instancePath: key,
1881
+ schemaPath: ""
1882
+ });
1883
+ if (result.content) {
1884
+ modelParts.push(result.content);
1885
+ }
1886
+ }
1887
+ if (rpcParts.length === 0 && subServiceContent.length === 0) {
1888
+ return `#![allow(dead_code, unused_imports, unused_variables, unconditional_recursion, deprecated)]
1889
+ use arri_client::{
1890
+ chrono::{DateTime, FixedOffset},
1891
+ serde_json::{self},
1892
+ utils::{serialize_date_time, serialize_string},
1893
+ ArriEnum, ArriModel,
1894
+ };
1895
+ use std::collections::BTreeMap;
1896
+ ${modelParts.join("\n\n")}`;
1897
+ }
1898
+ const clientName = validRustName(context.clientName);
1899
+ return `#![allow(dead_code, unused_imports, unused_variables, unconditional_recursion, deprecated)]
1900
+ use arri_client::{
1901
+ chrono::{DateTime, FixedOffset},
1902
+ parsed_arri_request, reqwest, serde_json,
1903
+ utils::{serialize_date_time, serialize_string},
1904
+ ArriClientConfig, ArriClientService, ArriEnum, ArriModel, ArriParsedRequestOptions,
1905
+ ArriServerError, EmptyArriModel,
1906
+ };
1907
+ use std::collections::BTreeMap;
1908
+
1909
+ pub struct ${clientName}<'a> {
1910
+ config: &'a ArriClientConfig,
1911
+ ${subServices.map((service) => ` pub ${service.key}: ${service.name}<'a>,`).join("\n")}
1912
+ }
1913
+
1914
+ impl<'a> ArriClientService<'a> for ${clientName}<'a> {
1915
+ fn create(config: &'a ArriClientConfig) -> Self {
1916
+ Self {
1917
+ config: &config,
1918
+ ${subServices.map((service) => ` ${service.key}: ${service.name}::create(config),`).join("\n")}
1919
+ }
1920
+ }
1921
+ }
1922
+
1923
+ impl ${clientName}<'_> {
1924
+ ${rpcParts.join("\n")}
1925
+ }
1926
+
1927
+ ${subServiceContent.join("\n\n")}
1928
+
1929
+ ${modelParts.join("\n\n")}`;
1930
+ }
1931
+ function rustTypeFromSchema(schema, context) {
1932
+ if (codegenUtils.isSchemaFormType(schema)) {
1933
+ switch (schema.type) {
1934
+ case "string":
1935
+ return rustStringFromSchema(schema, context);
1936
+ case "boolean":
1937
+ return rustBooleanFromSchema(schema, context);
1938
+ case "timestamp":
1939
+ return rustTimestampFromSchema(schema, context);
1940
+ case "float32":
1941
+ return rustF32FromSchema(schema, context);
1942
+ case "float64":
1943
+ return rustF64FromSchema(schema, context);
1944
+ case "int8":
1945
+ return rustI8FromSchema(schema, context);
1946
+ case "uint8":
1947
+ return rustU8FromSchema(schema, context);
1948
+ case "int16":
1949
+ return rustI16FromSchema(schema, context);
1950
+ case "uint16":
1951
+ return rustU16FromSchema(schema, context);
1952
+ case "int32":
1953
+ return rustI32FromSchema(schema, context);
1954
+ case "uint32":
1955
+ return rustU32FromSchema(schema, context);
1956
+ case "int64":
1957
+ return rustI64FromSchema(schema, context);
1958
+ case "uint64":
1959
+ return rustU64FromSchema(schema, context);
1960
+ default:
1961
+ schema.type;
1962
+ throw new Error(`Unhandled schema type: "${schema.type}"`);
1963
+ }
1964
+ }
1965
+ if (codegenUtils.isSchemaFormProperties(schema)) {
1966
+ return rustObjectFromSchema(schema, context);
1967
+ }
1968
+ if (codegenUtils.isSchemaFormEnum(schema)) {
1969
+ return rustEnumFromSchema(schema, context);
1970
+ }
1971
+ if (codegenUtils.isSchemaFormElements(schema)) {
1972
+ return rustArrayFromSchema(schema, context);
1973
+ }
1974
+ if (codegenUtils.isSchemaFormValues(schema)) {
1975
+ return rustRecordFromSchema(schema, context);
1976
+ }
1977
+ if (codegenUtils.isSchemaFormDiscriminator(schema)) {
1978
+ return rustTaggedUnionFromSchema(schema, context);
1979
+ }
1980
+ if (codegenUtils.isSchemaFormRef(schema)) {
1981
+ return rustRefFromSchema(schema, context);
1982
+ }
1983
+ return rustAnyFromSchema(schema, context);
1984
+ }
1985
+
1986
+ exports.createRustClient = createRustClient;
1987
+ exports.rustClientGenerator = rustClientGenerator;
1988
+ exports.rustTypeFromSchema = rustTypeFromSchema;