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.
@@ -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 namesDiffer = this.sourcelikeToString(propName) !== escapedName;
217
- if (namesDiffer || this._options.density === Density.Normal) {
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.forEachObject("leading-and-interposing", (c, name) => this.emitStructDefinition(c, name));
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quicktype-core",
3
- "version": "23.0.32",
3
+ "version": "23.0.34",
4
4
  "description": "The quicktype engine as a library",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.js",