Skip to content

Commit

Permalink
added support for js_type at compile time (#121)
Browse files Browse the repository at this point in the history
  • Loading branch information
UlysseM committed Jun 30, 2020
1 parent 89ed773 commit bfaaa5d
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 2 deletions.
40 changes: 38 additions & 2 deletions compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,27 @@ function getType(ctx, field) {
return path.reduce(function(ctx, name) { return ctx && ctx[name]; }, ctx);
}

function fieldShouldUseStringAsNumber(field) {
if (field.options.jstype === 'JS_STRING') {
switch (field.type) {
case 'float':
case 'double':
case 'uint32':
case 'uint64':
case 'int32':
case 'int64':
case 'sint32':
case 'sint64':
case 'fixed32':
case 'fixed64':
case 'sfixed32':
case 'sfixed64': return true;
default: return false;
}
}
return false;
}

function compileFieldRead(ctx, field) {
var type = getType(ctx, field);
if (type) {
Expand All @@ -137,6 +158,10 @@ function compileFieldRead(ctx, field) {
suffix = '(obj.' + field.name + (signed ? ', ' + signed : '') + ')';
}

if (fieldShouldUseStringAsNumber(field)) {
suffix += '.toString()';
}

switch (fieldType) {
case 'string': return prefix + 'String' + suffix;
case 'float': return prefix + 'Float' + suffix;
Expand All @@ -162,6 +187,13 @@ function compileFieldWrite(ctx, field, name) {
var prefix = 'pbf.write';
if (isPacked(field)) prefix += 'Packed';

if (fieldShouldUseStringAsNumber(field)) {
if (field.type === 'float' || field.type === 'double') {
name = 'parseFloat(' + name + ')';
} else {
name = 'parseInt(' + name + ', 10)';
}
}
var postfix = (isPacked(field) ? '' : 'Field') + '(' + field.tag + ', ' + name + ')';

var type = getType(ctx, field);
Expand Down Expand Up @@ -278,10 +310,14 @@ function buildContext(proto, parent) {
function getDefaultValue(field, value) {
// Defaults not supported for repeated fields
if (field.repeated) return [];
var convertToStringIfNeeded = function(val) { return val; };
if (fieldShouldUseStringAsNumber(field)) {
convertToStringIfNeeded = function(val) { return val.toString(); };
}

switch (field.type) {
case 'float':
case 'double': return value ? parseFloat(value) : 0;
case 'double': return convertToStringIfNeeded(value ? parseFloat(value) : 0);
case 'uint32':
case 'uint64':
case 'int32':
Expand All @@ -291,7 +327,7 @@ function getDefaultValue(field, value) {
case 'fixed32':
case 'fixed64':
case 'sfixed32':
case 'sfixed64': return value ? parseInt(value, 10) : 0;
case 'sfixed64': return convertToStringIfNeeded(value ? parseInt(value, 10) : 0);
case 'string': return value || '';
case 'bool': return value === 'true';
case 'map': return {};
Expand Down
32 changes: 32 additions & 0 deletions test/compile.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,38 @@ test('sets oneof field name', function(t) {
t.end();
});

test('handles jstype=JS_STRING', function(t) {
var proto = resolve(path.join(__dirname, './fixtures/type_string.proto'));
var TypeString = compile(proto).TypeString;
var TypeNotString = compile(proto).TypeNotString;
var pbf = new Pbf();

TypeString.write({
int: '-5',
long: '10000',
boolVal: true,
float: '12',
}, pbf);

var buf = pbf.finish();
var data = TypeString.read(new Pbf(buf));

t.equals(data.int, '-5');
t.equals(data.long, '10000');
t.equals(data.boolVal, true);
t.equals(data.float, '12');
t.equals(data.default_implicit, '0');
t.equals(data.default_explicit, '42');

data = TypeNotString.read(new Pbf(buf));
t.equals(data.int, -5);
t.equals(data.long, 10000);
t.equals(data.boolVal, true);
t.equals(data.float, 12);

t.end();
});

test('handles negative varint', function(t) {
var proto = resolve(path.join(__dirname, './fixtures/varint.proto'));
var Envelope = compile(proto).Envelope;
Expand Down
17 changes: 17 additions & 0 deletions test/fixtures/type_string.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
syntax = "proto2";

message TypeString {
int32 int = 1 [jstype = JS_STRING];
int64 long = 2 [jstype = JS_STRING];
bool boolVal = 3 [jstype = JS_STRING];
float float = 4 [jstype = JS_STRING];
int32 default_implicit = 5 [jstype = JS_STRING];
int32 default_explicit = 6 [jstype = JS_STRING, default = 42];
}

message TypeNotString {
int32 int = 1;
int64 long = 2;
bool boolVal = 3;
float float = 4;
}

0 comments on commit bfaaa5d

Please sign in to comment.