quicktype-core 23.0.31 → 23.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/language/Rust.js +106 -8
- package/package.json +1 -1
package/dist/language/Rust.js
CHANGED
|
@@ -37,6 +37,54 @@ exports.rustOptions = {
|
|
|
37
37
|
edition2018: new RendererOptions_1.BooleanOption("edition-2018", "Edition 2018", true),
|
|
38
38
|
leadingComments: new RendererOptions_1.BooleanOption("leading-comments", "Leading Comments", true)
|
|
39
39
|
};
|
|
40
|
+
const namingStyles = {
|
|
41
|
+
"snake_case": {
|
|
42
|
+
regex: /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/,
|
|
43
|
+
toParts: (name) => name.split('_'),
|
|
44
|
+
fromParts: (parts) => parts.map(p => p.toLowerCase()).join('_'),
|
|
45
|
+
},
|
|
46
|
+
"SCREAMING_SNAKE_CASE": {
|
|
47
|
+
regex: /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/,
|
|
48
|
+
toParts: (name) => name.split('_'),
|
|
49
|
+
fromParts: (parts) => parts.map(p => p.toUpperCase()).join('_'),
|
|
50
|
+
},
|
|
51
|
+
"camelCase": {
|
|
52
|
+
regex: /^[a-z]+([A-Z0-9][a-z]*)*$/,
|
|
53
|
+
toParts: (name) => namingStyles.snake_case.toParts(name.replace(/(.)([A-Z])/g, "$1_$2")),
|
|
54
|
+
fromParts: (parts) => parts
|
|
55
|
+
.map((p, i) => i === 0
|
|
56
|
+
? p.toLowerCase()
|
|
57
|
+
: p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase())
|
|
58
|
+
.join(''),
|
|
59
|
+
},
|
|
60
|
+
"PascalCase": {
|
|
61
|
+
regex: /^[A-Z][a-z]*([A-Z0-9][a-z]*)*$/,
|
|
62
|
+
toParts: (name) => namingStyles.snake_case.toParts(name.replace(/(.)([A-Z])/g, "$1_$2")),
|
|
63
|
+
fromParts: (parts) => parts
|
|
64
|
+
.map(p => p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase())
|
|
65
|
+
.join(''),
|
|
66
|
+
},
|
|
67
|
+
"kebab-case": {
|
|
68
|
+
regex: /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/,
|
|
69
|
+
toParts: (name) => name.split('-'),
|
|
70
|
+
fromParts: (parts) => parts.map(p => p.toLowerCase()).join('-'),
|
|
71
|
+
},
|
|
72
|
+
"SCREAMING-KEBAB-CASE": {
|
|
73
|
+
regex: /^[A-Z][A-Z0-9]*(-[A-Z0-9]+)*$/,
|
|
74
|
+
toParts: (name) => name.split('-'),
|
|
75
|
+
fromParts: (parts) => parts.map(p => p.toUpperCase()).join('-'),
|
|
76
|
+
},
|
|
77
|
+
"lowercase": {
|
|
78
|
+
regex: /^[a-z][a-z0-9]*$/,
|
|
79
|
+
toParts: (name) => [name],
|
|
80
|
+
fromParts: (parts) => parts.map(p => p.toLowerCase()).join(''),
|
|
81
|
+
},
|
|
82
|
+
"UPPERCASE": {
|
|
83
|
+
regex: /^[A-Z][A-Z0-9]*$/,
|
|
84
|
+
toParts: (name) => [name],
|
|
85
|
+
fromParts: (parts) => parts.map(p => p.toUpperCase()).join(''),
|
|
86
|
+
},
|
|
87
|
+
};
|
|
40
88
|
class RustTargetLanguage extends TargetLanguage_1.TargetLanguage {
|
|
41
89
|
makeRenderer(renderContext, untypedOptionValues) {
|
|
42
90
|
return new RustRenderer(this, renderContext, (0, RendererOptions_1.getOptionValues)(exports.rustOptions, untypedOptionValues));
|
|
@@ -211,10 +259,12 @@ class RustRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
211
259
|
const isCycleBreaker = this.isCycleBreakerType(t);
|
|
212
260
|
return isCycleBreaker ? ["Box<", rustType, ">"] : rustType;
|
|
213
261
|
}
|
|
214
|
-
emitRenameAttribute(propName, jsonName) {
|
|
262
|
+
emitRenameAttribute(propName, jsonName, defaultNamingStyle, preferedNamingStyle) {
|
|
215
263
|
const escapedName = rustStringEscape(jsonName);
|
|
216
|
-
const
|
|
217
|
-
|
|
264
|
+
const name = namingStyles[defaultNamingStyle].fromParts(this.sourcelikeToString(propName).split(" "));
|
|
265
|
+
const styledName = nameToNamingStyle(name, preferedNamingStyle);
|
|
266
|
+
const namesDiffer = escapedName !== styledName;
|
|
267
|
+
if (namesDiffer) {
|
|
218
268
|
this.emitLine('#[serde(rename = "', escapedName, '")]');
|
|
219
269
|
}
|
|
220
270
|
}
|
|
@@ -230,10 +280,21 @@ class RustRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
230
280
|
emitStructDefinition(c, className) {
|
|
231
281
|
this.emitDescription(this.descriptionForType(c));
|
|
232
282
|
this.emitLine("#[derive(", this._options.deriveDebug ? "Debug, " : "", this._options.deriveClone ? "Clone, " : "", "Serialize, Deserialize)]");
|
|
283
|
+
// List the possible naming styles for every class property
|
|
284
|
+
const propertiesNamingStyles = {};
|
|
285
|
+
this.forEachClassProperty(c, "none", (_name, jsonName, _prop) => {
|
|
286
|
+
propertiesNamingStyles[jsonName] = listMatchingNamingStyles(jsonName);
|
|
287
|
+
});
|
|
288
|
+
// Set the default naming style on the struct
|
|
289
|
+
const defaultStyle = "snake_case";
|
|
290
|
+
const preferedNamingStyle = getPreferedNamingStyle(Object.values(propertiesNamingStyles).flat(), defaultStyle);
|
|
291
|
+
if (preferedNamingStyle !== defaultStyle) {
|
|
292
|
+
this.emitLine(`#[serde(rename_all = "${preferedNamingStyle}")]`);
|
|
293
|
+
}
|
|
233
294
|
const blankLines = this._options.density === Density.Dense ? "none" : "interposing";
|
|
234
295
|
const structBody = () => this.forEachClassProperty(c, blankLines, (name, jsonName, prop) => {
|
|
235
296
|
this.emitDescription(this.descriptionForClassProperty(c, jsonName));
|
|
236
|
-
this.emitRenameAttribute(name, jsonName);
|
|
297
|
+
this.emitRenameAttribute(name, jsonName, defaultStyle, preferedNamingStyle);
|
|
237
298
|
this.emitLine(this.visibility, name, ": ", this.breakCycle(prop.type, true), ",");
|
|
238
299
|
});
|
|
239
300
|
this.emitBlock(["pub struct ", className], structBody);
|
|
@@ -261,9 +322,20 @@ class RustRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
261
322
|
emitEnumDefinition(e, enumName) {
|
|
262
323
|
this.emitDescription(this.descriptionForType(e));
|
|
263
324
|
this.emitLine("#[derive(", this._options.deriveDebug ? "Debug, " : "", this._options.deriveClone ? "Clone, " : "", "Serialize, Deserialize)]");
|
|
325
|
+
// List the possible naming styles for every enum case
|
|
326
|
+
const enumCasesNamingStyles = {};
|
|
327
|
+
this.forEachEnumCase(e, "none", (_name, jsonName) => {
|
|
328
|
+
enumCasesNamingStyles[jsonName] = listMatchingNamingStyles(jsonName);
|
|
329
|
+
});
|
|
330
|
+
// Set the default naming style on the enum
|
|
331
|
+
const defaultStyle = "PascalCase";
|
|
332
|
+
const preferedNamingStyle = getPreferedNamingStyle(Object.values(enumCasesNamingStyles).flat(), defaultStyle);
|
|
333
|
+
if (preferedNamingStyle !== defaultStyle) {
|
|
334
|
+
this.emitLine(`#[serde(rename_all = "${preferedNamingStyle}")]`);
|
|
335
|
+
}
|
|
264
336
|
const blankLines = this._options.density === Density.Dense ? "none" : "interposing";
|
|
265
337
|
this.emitBlock(["pub enum ", enumName], () => this.forEachEnumCase(e, blankLines, (name, jsonName) => {
|
|
266
|
-
this.emitRenameAttribute(name, jsonName);
|
|
338
|
+
this.emitRenameAttribute(name, jsonName, defaultStyle, preferedNamingStyle);
|
|
267
339
|
this.emitLine([name, ","]);
|
|
268
340
|
}));
|
|
269
341
|
}
|
|
@@ -304,9 +376,35 @@ class RustRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
304
376
|
this.emitLine("use std::collections::HashMap;");
|
|
305
377
|
}
|
|
306
378
|
this.forEachTopLevel("leading", (t, name) => this.emitTopLevelAlias(t, name), t => this.namedTypeToNameForTopLevel(t) === undefined);
|
|
307
|
-
this.
|
|
308
|
-
this.forEachUnion("leading-and-interposing", (u, name) => this.emitUnion(u, name));
|
|
309
|
-
this.forEachEnum("leading-and-interposing", (e, name) => this.emitEnumDefinition(e, name));
|
|
379
|
+
this.forEachNamedType("leading-and-interposing", (c, name) => this.emitStructDefinition(c, name), (e, name) => this.emitEnumDefinition(e, name), (u, name) => this.emitUnion(u, name));
|
|
310
380
|
}
|
|
311
381
|
}
|
|
312
382
|
exports.RustRenderer = RustRenderer;
|
|
383
|
+
function getPreferedNamingStyle(namingStyleOccurences, defaultStyle) {
|
|
384
|
+
const occurrences = Object.fromEntries(Object.keys(namingStyles).map(key => [key, 0]));
|
|
385
|
+
namingStyleOccurences
|
|
386
|
+
.forEach(style => ++occurrences[style]);
|
|
387
|
+
const max = Math.max(...Object.values(occurrences));
|
|
388
|
+
const preferedStyles = Object.entries(occurrences)
|
|
389
|
+
.filter(([_style, num]) => num === max)
|
|
390
|
+
.map(([style, _num]) => style);
|
|
391
|
+
if (preferedStyles.includes(defaultStyle)) {
|
|
392
|
+
return defaultStyle;
|
|
393
|
+
}
|
|
394
|
+
return preferedStyles[0];
|
|
395
|
+
}
|
|
396
|
+
function listMatchingNamingStyles(name) {
|
|
397
|
+
return Object.entries(namingStyles)
|
|
398
|
+
.filter(([_, { regex }]) => regex.test(name))
|
|
399
|
+
.map(([namingStyle, _]) => namingStyle);
|
|
400
|
+
}
|
|
401
|
+
function nameToNamingStyle(name, style) {
|
|
402
|
+
if (namingStyles[style].regex.test(name)) {
|
|
403
|
+
return name;
|
|
404
|
+
}
|
|
405
|
+
const fromStyle = listMatchingNamingStyles(name)[0];
|
|
406
|
+
if (fromStyle === undefined) {
|
|
407
|
+
return name;
|
|
408
|
+
}
|
|
409
|
+
return namingStyles[style].fromParts(namingStyles[fromStyle].toParts(name));
|
|
410
|
+
}
|