@cicctencent/tars2node-cli 0.0.1

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.
@@ -0,0 +1,383 @@
1
+ 'use strict';
2
+
3
+ const BaseDef = require('./base');
4
+ const util = require('../util');
5
+
6
+ class StructDef extends BaseDef {
7
+ /**
8
+ *
9
+ * 声明JCE-Struct节点类型
10
+ * @typedef { refType | vecType | string | mapType } tarsType
11
+ *
12
+ * @typedef {object} refType
13
+ * @property {string} target
14
+ * @property {string[]} nested
15
+ *
16
+ * @typedef {object} vecType
17
+ * @property {'vector'} type
18
+ * @property {tarsType} target
19
+ *
20
+ * @typedef {object} mapType
21
+ * @property {'map'} type
22
+ * @property {tarsType} key
23
+ * @property {tarsType} value
24
+ *
25
+ * @typedef {object} member
26
+ * @property {number} index
27
+ * @property {string} id
28
+ * @property {boolean} require
29
+ * @property {tarsType} type
30
+ * @property {null|string} init
31
+ *
32
+ * @typedef {object} TarsStructNode
33
+ * @property {string} id
34
+ * @property {'struct'} type
35
+ * @property {member[]} members
36
+ *
37
+ * 工具类类型
38
+ * @typedef {import("../printer")} Printer
39
+ * @typedef {import("../typing")} Typing
40
+ *
41
+ * @typedef {object} CompilerOptions
42
+ * @property {'all'|'client'|'service'} mode
43
+ * @property {'string'|'number'|'bigint'} long
44
+ * @property {boolean} withReturn
45
+ * @property {boolean} gather
46
+ * @property {boolean} interface
47
+ * @property {string} [output]
48
+ *
49
+ * 创建Struct解析实例
50
+ * @constructor
51
+ * @param {Printer} printer - print类实例
52
+ * @param {Typing} typing - Typing类实例
53
+ * @param {CompilerOptions} options - 编译配置选项
54
+ */
55
+ constructor(printer, typing, options) {
56
+ super('', printer, typing, options);
57
+ this._id = '';
58
+ this._chainName = '';
59
+ /** @type {member[]} */
60
+ this._members = [];
61
+ this._beforeComment = '';
62
+ }
63
+
64
+ /**
65
+ * @param {string} name
66
+ */
67
+ setModuleName(name) {
68
+ super.setModuleName(name);
69
+ this._chainName = `${name}.${this._id}`;
70
+ }
71
+
72
+ /**
73
+ * @param {TarsStructNode} node
74
+ */
75
+ setNode({ id, members, beforeComment = '' }) {
76
+ this._members = members;
77
+ this._id = id;
78
+ this._chainName = `${this._moduleName}.${id}`;
79
+ this._beforeComment = beforeComment;
80
+ }
81
+
82
+ /**
83
+ * @param {string} name
84
+ * @param {TarsStructNode} node
85
+ */
86
+ reset(name, node) {
87
+ this.setModuleName(name);
88
+ this.setNode(node);
89
+
90
+ return this;
91
+ }
92
+
93
+ build() {
94
+ this._interface();
95
+ if (this._options.mode !== 'web') {
96
+ this._class();
97
+ }
98
+ }
99
+
100
+ _interface() {
101
+ this
102
+ ._printer
103
+ .word(this._beforeComment)
104
+ .newline()
105
+ .word('export', 'R')
106
+ .word('interface', 'R')
107
+ .word(`${this._id}${this._options.mode !== 'web' ? '$OBJ' : ''}`, 'R')
108
+ .word('{')
109
+ .indent();
110
+ this._members.forEach(this._interfaceItem.bind(this));
111
+ this._printer.dedent().newline().word('}');
112
+ }
113
+
114
+ /**
115
+ * @param {member} member
116
+ */
117
+ _interfaceItem({
118
+ id, type, require, comment = '',
119
+ }) {
120
+ const tsType = this._typing.toTSObjectType(type, this._moduleName);
121
+ const item = `${util.toMultilineComment(comment)}${id}${require ? '' : '?'}: ${tsType};`;
122
+ this._printer.newline().word(item);
123
+ }
124
+
125
+ /**
126
+ * 类的处理
127
+ */
128
+ _class() {
129
+ this
130
+ ._printer
131
+ .newline()
132
+ .word('export', 'R')
133
+ .word('class', 'R')
134
+ .word(this._id, 'R')
135
+ .word('{')
136
+ .indent();
137
+ this._classProps();
138
+ this._classConstructor();
139
+ this._classMethods();
140
+ this
141
+ ._printer
142
+ .dedent()
143
+ .line('}');
144
+ }
145
+
146
+ _classProps() {
147
+ this._members.forEach(({ id, type, require }) => {
148
+ const tsType = this._typing.toTSType(type, this._moduleName);
149
+ const item = `${id}${require ? '' : '?'}: ${tsType};`;
150
+ this._printer.newline().word(item);
151
+ });
152
+ // this._members.forEach(this._interfaceItem.bind(this));
153
+ }
154
+
155
+ /** 给类成员赋初值
156
+ * @param {member} member
157
+ * @return {string}
158
+ */
159
+ _getInitValue({ type, init }) {
160
+ if (init !== undefined && init !== null && typeof init !== 'object') return init;
161
+
162
+ if (!this._typing.isNotObjectType(type, this._moduleName)) {
163
+ return this._typing.toTarsStreamType(type, this._moduleName).tafType;
164
+ }
165
+
166
+ const { tafType, source } = this._typing.toTarsStreamType(type, this._moduleName);
167
+
168
+ if (source && source.type === 'enum') {
169
+ // @ts-ignore
170
+ if (init && init.target) {
171
+ // @ts-ignore
172
+ return `${tafType}.${init.target}`;
173
+ }
174
+ return `${tafType}.${source.value[0].id}`;
175
+ }
176
+
177
+ return /** @type {string} */ (this._typing.toDefaultValue(/** @type {string} */ (type)));
178
+ }
179
+
180
+ /** 生成 _readFrom 默认值
181
+ * @param {member} member
182
+ * @return {string}
183
+ */
184
+ _getIOValue({ type, init }) {
185
+ if (init !== undefined && init !== null && typeof init !== 'object') return init;
186
+
187
+ if (!this._typing.isNotObjectType(type, this._moduleName)) {
188
+ return this._typing.toTarsStreamType(type, this._moduleName).tafType;
189
+ }
190
+
191
+ const { tafType, source } = this._typing.toTarsStreamType(type, this._moduleName);
192
+
193
+
194
+ if (source && source.type === 'enum') {
195
+ // @ts-ignore
196
+ if (init && init.target) {
197
+ // @ts-ignore
198
+ return `${tafType}.${init.target}`;
199
+ }
200
+ return `${tafType}.${source.value[0].id}`;
201
+ }
202
+
203
+ return /** @type {string} */ (this._typing.toIOValue(/** @type {string} */ (type)));
204
+ }
205
+
206
+ _classConstructor() {
207
+ this._printer
208
+ .classMethod({
209
+ name: 'constructor',
210
+ params: [],
211
+ callback: () => {
212
+ this._members.map(this._classConstructorMemberInit.bind(this));
213
+ this._printer.line(`this._classname = "${this._chainName}";`);
214
+ },
215
+ });
216
+ }
217
+
218
+ /**
219
+ * @param {member} member
220
+ */
221
+ _classConstructorMemberInit(member) {
222
+ const { id, type } = member;
223
+ const needNew = this._typing.isNotObjectType(type, this._moduleName) ? '' : 'new ';
224
+ /** @type {(value: string) => Printer} */
225
+ const generate = value => this._printer.line(`this.${id} = ${needNew}${value};`);
226
+
227
+ generate(this._getInitValue(member));
228
+ }
229
+
230
+ _classMethods() {
231
+ this._printer
232
+ .classProps({
233
+ name: '_classname',
234
+ valueType: 'string',
235
+ value: "''",
236
+ type: 'protected',
237
+ })
238
+ .classProps({
239
+ name: '_proto_struct_name_',
240
+ valueType: 'string',
241
+ value: "''",
242
+ type: 'protected',
243
+ })
244
+ .classProps({
245
+ name: '_classname',
246
+ valueType: 'string',
247
+ value: `"${this._chainName}"`,
248
+ type: 'protected static',
249
+ })
250
+ .classMethod({
251
+ name: '_write',
252
+ params: [['os', 'TarsStream.TarsOutputStream'], ['tag', 'number'], ['value', 'any']],
253
+ type: 'protected static',
254
+ callback: () => {
255
+ this._printer.line('os.writeStruct(tag, value);');
256
+ },
257
+ })
258
+ .classMethod({
259
+ name: '_read',
260
+ params: [['is', 'TarsStream.TarsInputStream'], ['tag', 'number'], ['def', 'any']],
261
+ type: 'protected static',
262
+ callback: () => {
263
+ this._printer.line('return is.readStruct(tag, true, def);');
264
+ },
265
+ })
266
+ .classMethod({
267
+ name: '_readFrom',
268
+ params: [['is', 'TarsStream.TarsInputStream']],
269
+ type: 'protected static',
270
+ returnType: this._id,
271
+ callback: () => {
272
+ this._printer.line(`const tmp = new ${this._chainName};`);
273
+ this._members.forEach(this._readerMemberInit.bind(this));
274
+ this._printer.line('return tmp;');
275
+ },
276
+ })
277
+ .classMethod({
278
+ name: '_writeTo',
279
+ params: [['os', 'TarsStream.TarsOutputStream']],
280
+ type: 'protected',
281
+ callback: () => {
282
+ this._printer.line(`const that: Required<${this._id}> = <Required<${this._id}>>this;`);
283
+ this._members.forEach(({ index, id, type }) => {
284
+ const ioType = this._typing.toIOType(type, this._moduleName);
285
+ this._printer.line(`os.write${ioType}(${index}, that.${id});`);
286
+ });
287
+ },
288
+ })
289
+ .classMethod({
290
+ name: 'toObject',
291
+ params: [],
292
+ returnType: `${this._id}$OBJ`,
293
+ callback: () => {
294
+ this._printer.line(`const that: Required<${this._id}> = <Required<${this._id}>>this;`);
295
+ this._printer.line('return').space(1).scope(() => {
296
+ this._members.forEach(({ id, type }) => {
297
+ const suffix = this._typing.isNotObjectType(type, this._moduleName)
298
+ ? '' : '.toObject()';
299
+ this._printer.line(`"${id}": that.${id}${suffix},`);
300
+ });
301
+ }).semicolon();
302
+ },
303
+ })
304
+ .classMethod({
305
+ name: 'readFromObject',
306
+ params: [['json', `${this._id}$OBJ`]],
307
+ returnType: this._id,
308
+ callback: () => {
309
+ this._printer
310
+ .line(`const tmp: Required<${this._id}$OBJ> = <Required<${this._id}$OBJ>>json;`)
311
+ .line(`const that: Required<${this._id}> = <Required<${this._id}>>this;`);
312
+ this._members.forEach(({ id, type }) => {
313
+ this._printer.newline();
314
+ const suffix = this._typing.isNotObjectType(type, this._moduleName)
315
+ ? `that.${id} = tmp.${id}`
316
+ : `that.${id}.readFromObject(tmp.${id})`;
317
+ this._printer.word(`_hasOwnProperty.call(json, "${id}") && (${suffix});`);
318
+ });
319
+ this._printer.line('return this;');
320
+ },
321
+ })
322
+ .classMethod({
323
+ name: 'toBinBuffer',
324
+ params: [],
325
+ returnType: 'TarsStream.BinBuffer',
326
+ callback: () => {
327
+ this._printer
328
+ .line('const os = new TarsStream.TarsOutputStream();')
329
+ .line('this._writeTo(os);')
330
+ .line('return os.getBinBuffer();');
331
+ },
332
+ })
333
+ .classMethod({
334
+ name: 'new',
335
+ params: [],
336
+ type: 'static',
337
+ returnType: this._id,
338
+ callback: () => {
339
+ this._printer.line(`return new ${this._chainName}();`);
340
+ },
341
+ })
342
+ .classMethod({
343
+ name: 'create',
344
+ params: [['is', 'TarsStream.TarsInputStream']],
345
+ type: 'static',
346
+ returnType: this._id,
347
+ callback: () => {
348
+ this._printer.line(`return ${this._chainName}._readFrom(is);`);
349
+ },
350
+ });
351
+ }
352
+
353
+ /** 生成_readFrom函数
354
+ * @param {member} member
355
+ */
356
+ _readerMemberInit(member) {
357
+ const {
358
+ id,
359
+ index,
360
+ require,
361
+ type,
362
+ } = member;
363
+ const tsType = this._typing.toTSType(type, this._moduleName);
364
+ const ioType = this._typing.toIOType(type, this._moduleName);
365
+ /** @type {(value: string) => void} */
366
+ const generate = (value) => {
367
+ this
368
+ ._printer
369
+ .newline()
370
+ .word(`tmp.${id} = <${tsType}>is.read${ioType}`)
371
+ .word(`(${index}, ${require}, ${value}`);
372
+
373
+ const longLastParam = type === 'long' && this.generateLastParamForLong();
374
+ if (longLastParam) {
375
+ this._printer.word(`, ${longLastParam}`);
376
+ }
377
+ this._printer.word(')').semicolon();
378
+ };
379
+ generate(this._getIOValue(member));
380
+ }
381
+ }
382
+
383
+ module.exports = StructDef;