quicktype-core 23.0.32 → 23.0.34
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 +101 -8
- package/package.json +1 -1
package/dist/language/Rust.js
CHANGED
|
@@ -37,6 +37,50 @@ 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 ? p.toLowerCase() : p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase())
|
|
56
|
+
.join("")
|
|
57
|
+
},
|
|
58
|
+
PascalCase: {
|
|
59
|
+
regex: /^[A-Z][a-z]*([A-Z0-9][a-z]*)*$/,
|
|
60
|
+
toParts: (name) => namingStyles.snake_case.toParts(name.replace(/(.)([A-Z])/g, "$1_$2")),
|
|
61
|
+
fromParts: (parts) => parts.map(p => p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase()).join("")
|
|
62
|
+
},
|
|
63
|
+
"kebab-case": {
|
|
64
|
+
regex: /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/,
|
|
65
|
+
toParts: (name) => name.split("-"),
|
|
66
|
+
fromParts: (parts) => parts.map(p => p.toLowerCase()).join("-")
|
|
67
|
+
},
|
|
68
|
+
"SCREAMING-KEBAB-CASE": {
|
|
69
|
+
regex: /^[A-Z][A-Z0-9]*(-[A-Z0-9]+)*$/,
|
|
70
|
+
toParts: (name) => name.split("-"),
|
|
71
|
+
fromParts: (parts) => parts.map(p => p.toUpperCase()).join("-")
|
|
72
|
+
},
|
|
73
|
+
lowercase: {
|
|
74
|
+
regex: /^[a-z][a-z0-9]*$/,
|
|
75
|
+
toParts: (name) => [name],
|
|
76
|
+
fromParts: (parts) => parts.map(p => p.toLowerCase()).join("")
|
|
77
|
+
},
|
|
78
|
+
UPPERCASE: {
|
|
79
|
+
regex: /^[A-Z][A-Z0-9]*$/,
|
|
80
|
+
toParts: (name) => [name],
|
|
81
|
+
fromParts: (parts) => parts.map(p => p.toUpperCase()).join("")
|
|
82
|
+
}
|
|
83
|
+
};
|
|
40
84
|
class RustTargetLanguage extends TargetLanguage_1.TargetLanguage {
|
|
41
85
|
makeRenderer(renderContext, untypedOptionValues) {
|
|
42
86
|
return new RustRenderer(this, renderContext, (0, RendererOptions_1.getOptionValues)(exports.rustOptions, untypedOptionValues));
|
|
@@ -211,10 +255,12 @@ class RustRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
211
255
|
const isCycleBreaker = this.isCycleBreakerType(t);
|
|
212
256
|
return isCycleBreaker ? ["Box<", rustType, ">"] : rustType;
|
|
213
257
|
}
|
|
214
|
-
emitRenameAttribute(propName, jsonName) {
|
|
258
|
+
emitRenameAttribute(propName, jsonName, defaultNamingStyle, preferedNamingStyle) {
|
|
215
259
|
const escapedName = rustStringEscape(jsonName);
|
|
216
|
-
const
|
|
217
|
-
|
|
260
|
+
const name = namingStyles[defaultNamingStyle].fromParts(this.sourcelikeToString(propName).split(" "));
|
|
261
|
+
const styledName = nameToNamingStyle(name, preferedNamingStyle);
|
|
262
|
+
const namesDiffer = escapedName !== styledName;
|
|
263
|
+
if (namesDiffer) {
|
|
218
264
|
this.emitLine('#[serde(rename = "', escapedName, '")]');
|
|
219
265
|
}
|
|
220
266
|
}
|
|
@@ -230,10 +276,21 @@ class RustRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
230
276
|
emitStructDefinition(c, className) {
|
|
231
277
|
this.emitDescription(this.descriptionForType(c));
|
|
232
278
|
this.emitLine("#[derive(", this._options.deriveDebug ? "Debug, " : "", this._options.deriveClone ? "Clone, " : "", "Serialize, Deserialize)]");
|
|
279
|
+
// List the possible naming styles for every class property
|
|
280
|
+
const propertiesNamingStyles = {};
|
|
281
|
+
this.forEachClassProperty(c, "none", (_name, jsonName, _prop) => {
|
|
282
|
+
propertiesNamingStyles[jsonName] = listMatchingNamingStyles(jsonName);
|
|
283
|
+
});
|
|
284
|
+
// Set the default naming style on the struct
|
|
285
|
+
const defaultStyle = "snake_case";
|
|
286
|
+
const preferedNamingStyle = getPreferedNamingStyle(Object.values(propertiesNamingStyles).flat(), defaultStyle);
|
|
287
|
+
if (preferedNamingStyle !== defaultStyle) {
|
|
288
|
+
this.emitLine(`#[serde(rename_all = "${preferedNamingStyle}")]`);
|
|
289
|
+
}
|
|
233
290
|
const blankLines = this._options.density === Density.Dense ? "none" : "interposing";
|
|
234
291
|
const structBody = () => this.forEachClassProperty(c, blankLines, (name, jsonName, prop) => {
|
|
235
292
|
this.emitDescription(this.descriptionForClassProperty(c, jsonName));
|
|
236
|
-
this.emitRenameAttribute(name, jsonName);
|
|
293
|
+
this.emitRenameAttribute(name, jsonName, defaultStyle, preferedNamingStyle);
|
|
237
294
|
this.emitLine(this.visibility, name, ": ", this.breakCycle(prop.type, true), ",");
|
|
238
295
|
});
|
|
239
296
|
this.emitBlock(["pub struct ", className], structBody);
|
|
@@ -261,9 +318,20 @@ class RustRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
261
318
|
emitEnumDefinition(e, enumName) {
|
|
262
319
|
this.emitDescription(this.descriptionForType(e));
|
|
263
320
|
this.emitLine("#[derive(", this._options.deriveDebug ? "Debug, " : "", this._options.deriveClone ? "Clone, " : "", "Serialize, Deserialize)]");
|
|
321
|
+
// List the possible naming styles for every enum case
|
|
322
|
+
const enumCasesNamingStyles = {};
|
|
323
|
+
this.forEachEnumCase(e, "none", (_name, jsonName) => {
|
|
324
|
+
enumCasesNamingStyles[jsonName] = listMatchingNamingStyles(jsonName);
|
|
325
|
+
});
|
|
326
|
+
// Set the default naming style on the enum
|
|
327
|
+
const defaultStyle = "PascalCase";
|
|
328
|
+
const preferedNamingStyle = getPreferedNamingStyle(Object.values(enumCasesNamingStyles).flat(), defaultStyle);
|
|
329
|
+
if (preferedNamingStyle !== defaultStyle) {
|
|
330
|
+
this.emitLine(`#[serde(rename_all = "${preferedNamingStyle}")]`);
|
|
331
|
+
}
|
|
264
332
|
const blankLines = this._options.density === Density.Dense ? "none" : "interposing";
|
|
265
333
|
this.emitBlock(["pub enum ", enumName], () => this.forEachEnumCase(e, blankLines, (name, jsonName) => {
|
|
266
|
-
this.emitRenameAttribute(name, jsonName);
|
|
334
|
+
this.emitRenameAttribute(name, jsonName, defaultStyle, preferedNamingStyle);
|
|
267
335
|
this.emitLine([name, ","]);
|
|
268
336
|
}));
|
|
269
337
|
}
|
|
@@ -304,9 +372,34 @@ class RustRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
|
304
372
|
this.emitLine("use std::collections::HashMap;");
|
|
305
373
|
}
|
|
306
374
|
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));
|
|
375
|
+
this.forEachNamedType("leading-and-interposing", (c, name) => this.emitStructDefinition(c, name), (e, name) => this.emitEnumDefinition(e, name), (u, name) => this.emitUnion(u, name));
|
|
310
376
|
}
|
|
311
377
|
}
|
|
312
378
|
exports.RustRenderer = RustRenderer;
|
|
379
|
+
function getPreferedNamingStyle(namingStyleOccurences, defaultStyle) {
|
|
380
|
+
const occurrences = Object.fromEntries(Object.keys(namingStyles).map(key => [key, 0]));
|
|
381
|
+
namingStyleOccurences.forEach(style => ++occurrences[style]);
|
|
382
|
+
const max = Math.max(...Object.values(occurrences));
|
|
383
|
+
const preferedStyles = Object.entries(occurrences)
|
|
384
|
+
.filter(([_style, num]) => num === max)
|
|
385
|
+
.map(([style, _num]) => style);
|
|
386
|
+
if (preferedStyles.includes(defaultStyle)) {
|
|
387
|
+
return defaultStyle;
|
|
388
|
+
}
|
|
389
|
+
return preferedStyles[0];
|
|
390
|
+
}
|
|
391
|
+
function listMatchingNamingStyles(name) {
|
|
392
|
+
return Object.entries(namingStyles)
|
|
393
|
+
.filter(([_, { regex }]) => regex.test(name))
|
|
394
|
+
.map(([namingStyle, _]) => namingStyle);
|
|
395
|
+
}
|
|
396
|
+
function nameToNamingStyle(name, style) {
|
|
397
|
+
if (namingStyles[style].regex.test(name)) {
|
|
398
|
+
return name;
|
|
399
|
+
}
|
|
400
|
+
const fromStyle = listMatchingNamingStyles(name)[0];
|
|
401
|
+
if (fromStyle === undefined) {
|
|
402
|
+
return name;
|
|
403
|
+
}
|
|
404
|
+
return namingStyles[style].fromParts(namingStyles[fromStyle].toParts(name));
|
|
405
|
+
}
|