UNPKG

6.59 kBPlain TextView Raw
1#!/usr/bin/env node
2
3'use strict';
4
5var resolve = require('resolve-protobuf-schema');
6
7if (process.argv.length > 2) {
8 console.log('\'use strict\';');
9 compileMessages(resolve.sync(process.argv[2]),
10 process.argv.indexOf('--browser') !== -1 ? 'window' : 'exports', {},
11 process.argv.indexOf('--no-read') === -1,
12 process.argv.indexOf('--no-write') === -1);
13} else {
14 console.warn('Error: no path to proto file given.');
15}
16
17function compileMessage(message, parentName, enums, read, write) {
18 var name = message.name,
19 nameLow = name.toLowerCase(),
20 nameCap = name.charAt(0).toUpperCase() + name.substr(1),
21 i, field, part;
22
23 console.log('\n// %s ========================================\n', name);
24
25 var methods = [];
26 if (read) methods.push('read: read' + nameCap);
27 if (write) methods.push('write: write' + nameCap);
28
29 console.log((message.messages.length ? 'var ' + name + ' = ' : '') +
30 '%s.%s = {%s};\n', parentName, name, methods.join(', '));
31
32 if (message.enums.length) {
33 for (i = 0; i < message.enums.length; i++) {
34 var en = message.enums[i];
35 enums[en.name] = true;
36 console.log('%s.%s = ' + JSON.stringify(en.values, null, 4) + ';\n', name, en.name);
37 }
38 }
39
40 if (read) {
41 console.log('function read%s(pbf, end) {', nameCap);
42 part = 'pbf.readFields(read' + nameCap + 'Field, ' + repeatedDest(message.fields) + ', end);';
43 var hasDefaults = false;
44 for (i = 0; i < message.fields.length; i++) {
45 field = message.fields[i];
46 if (enums[field.type] && field.options.default !== undefined) {
47 hasDefaults = true;
48 break;
49 }
50 }
51 if (hasDefaults) {
52 console.log(' var ' + nameLow + ' = ' + part);
53 for (i = 0; i < message.fields.length; i++) {
54 field = message.fields[i];
55 if (enums[field.type] && field.options.default !== undefined) {
56 console.log(' if (%s.%s === undefined) %s.%s = ' + JSON.stringify(field.options.default) + ';',
57 nameLow, field.name, nameLow, field.name);
58 }
59 }
60 console.log(' return %s;', nameLow);
61 } else {
62 console.log(' return ' + part);
63 }
64 console.log('}\n');
65
66 console.log('function read%sField(tag, %s, pbf) {', nameCap, nameLow);
67
68 for (i = 0; i < message.fields.length; i++) {
69 field = message.fields[i];
70 part = field.repeated && !field.options.packed ? '.push(' + readMethod(field, enums) + ')' :
71 ' = ' + readMethod(field, enums);
72 console.log(' ' + (i ? 'else if' : 'if') + ' (tag === %d) %s.%s%s;',
73 field.tag, nameLow, field.name, part);
74 }
75 console.log('}');
76 }
77
78 if (read && write) console.log('');
79
80 if (write) {
81 console.log('function write%s(%s, pbf) {', nameCap, nameLow);
82 var iDeclared;
83 for (i = 0; i < message.fields.length; i++) {
84 field = message.fields[i];
85 if (!iDeclared && field.repeated && !field.options.packed) {
86 console.log(' var i;');
87 iDeclared = true;
88 }
89 console.log(' if (%s.%s !== undefined) %s;', nameLow, field.name,
90 writeMethod(field.tag, field.type, nameLow + '.' + field.name,
91 field.repeated, field.options.packed, enums));
92 }
93 console.log('}');
94 }
95
96 compileMessages(message, name, enums, read, write);
97}
98
99function compileMessages(parent, parentName, enums, read, write) {
100 for (var i = 0; i < parent.messages.length; i++) {
101 compileMessage(parent.messages[i], parentName, enums, read, write);
102 }
103}
104
105function repeatedDest(fields) {
106 var repeated = [];
107 for (var i = 0; i < fields.length; i++) {
108 if (fields[i].repeated && !fields[i].options.packed) repeated.push('"' + fields[i].name + '": []');
109 }
110 return '{' + repeated.join(', ') + '}';
111}
112
113function readMethod(field, enums) {
114 var type = field.type;
115
116 var prefix = 'pbf.read';
117 if (field.options.packed) prefix += 'Packed';
118
119 switch (field.type) {
120 case 'string': return prefix + 'String()';
121 case 'float': return prefix + 'Float()';
122 case 'double': return prefix + 'Double()';
123 case 'bool': return prefix + 'Boolean()';
124 case 'enum':
125 case 'uint32':
126 case 'uint64':
127 case 'int32':
128 case 'int64': return prefix + 'Varint()';
129 case 'sint32':
130 case 'sint64': return prefix + 'SVarint()';
131 case 'fixed32': return prefix + 'Fixed32()';
132 case 'fixed64': return prefix + 'Fixed64()';
133 case 'sfixed32': return prefix + 'SFixed32()';
134 case 'sfixed64': return prefix + 'SFixed64()';
135 case 'bytes': return prefix + 'Bytes()';
136 default: return enums[field.type] ? prefix + 'Varint()' :
137 'read' + type.charAt(0).toUpperCase() + type.substr(1) + '(pbf, pbf.readVarint() + pbf.pos)';
138 }
139}
140
141function writeMethod(tag, type, name, repeated, packed, enums) {
142 if (repeated && !packed) return repeatedWriteMethod(tag, type, name, enums);
143
144 var prefix = 'pbf.write';
145 if (packed) prefix += 'Packed';
146
147 var postfix = (packed ? '' : 'Field') + '(' + tag + ', ' + name + ')';
148
149 switch (type) {
150 case 'string': return prefix + 'String' + postfix;
151 case 'float': return prefix + 'Float' + postfix;
152 case 'double': return prefix + 'Double' + postfix;
153 case 'bool': return prefix + 'Boolean' + postfix;
154 case 'enum':
155 case 'uint32':
156 case 'uint64':
157 case 'int32':
158 case 'int64': return prefix + 'Varint' + postfix;
159 case 'sint32':
160 case 'sint64': return prefix + 'SVarint' + postfix;
161 case 'fixed32': return prefix + 'Fixed32' + postfix;
162 case 'fixed64': return prefix + 'Fixed64' + postfix;
163 case 'sfixed32': return prefix + 'SFixed32' + postfix;
164 case 'sfixed64': return prefix + 'SFixed64' + postfix;
165 case 'bytes': return prefix + 'Bytes' + postfix;
166 default: return enums[type] ? prefix + 'Varint' + postfix :
167 prefix + 'Message(' + tag + ', write' +
168 type.charAt(0).toUpperCase() + type.substr(1) + ', ' + name + ')';
169 }
170}
171
172function repeatedWriteMethod(tag, type, name, enums) {
173 return 'for (i = 0; i < ' + name + '.length; i++) ' + writeMethod(tag, type, name + '[i]', false, false, enums);
174}