Skip to content

Commit

Permalink
Ranges and names support for reserved fields, see #676
Browse files Browse the repository at this point in the history
  • Loading branch information
dcodeIO committed Feb 24, 2017
1 parent 487f892 commit cbd4c62
Show file tree
Hide file tree
Showing 18 changed files with 161 additions and 42 deletions.
36 changes: 33 additions & 3 deletions dist/light/protobuf.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/light/protobuf.js.map

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions dist/light/protobuf.min.js

Large diffs are not rendered by default.

Binary file modified dist/light/protobuf.min.js.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion dist/light/protobuf.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/minimal/protobuf.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/minimal/protobuf.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified dist/minimal/protobuf.min.js.gz
Binary file not shown.
54 changes: 43 additions & 11 deletions dist/protobuf.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/protobuf.js.map

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions dist/protobuf.min.js

Large diffs are not rendered by default.

Binary file modified dist/protobuf.min.js.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion dist/protobuf.min.js.map

Large diffs are not rendered by default.

18 changes: 16 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1673,9 +1673,9 @@ export class Type extends NamespaceBase {

/**
* Reserved ranges, if any.
* @type {number[][]}
* @type {Array.<number[]|string>}
*/
reserved: number[][];
reserved: (number[]|string)[];

/**
* Message fields by id.
Expand Down Expand Up @@ -1726,6 +1726,20 @@ export class Type extends NamespaceBase {
*/
remove(object: ReflectionObject): Type;

/**
* Tests if the specified id is reserved.
* @param {number} id Id to test
* @returns {boolean} `true` if reserved, otherwise `false`
*/
isReservedId(id: number): boolean;

/**
* Tests if the specified name is reserved.
* @param {string} name Name to test
* @returns {boolean} `true` if reserved, otherwise `false`
*/
isReservedName(name: string): boolean;

/**
* Creates a new message of this type using the specified properties.
* @param {Object.<string,*>} [properties] Properties to set
Expand Down
18 changes: 10 additions & 8 deletions src/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,15 @@ function parse(source, root, options) {
}
}

function readRange() {
var start = parseId(next());
var end = start;
if (skip("to", true))
end = parseId(next());
function readRanges(target, acceptStrings) {
var token, start;
do {
if (acceptStrings && ((token = peek()) === "\"" || token === "'"))
target.push(readString());
else
target.push([ start = parseId(next()), skip("to", true) ? parseId(next()) : start ]);
} while (skip(",", true));
skip(";");
return [ start, end ];
}

function parseNumber(token, insideTryCatch) {
Expand Down Expand Up @@ -290,11 +292,11 @@ function parse(source, root, options) {
break;

case "extensions":
(type.extensions || (type.extensions = [])).push(readRange(type, tokenLower));
readRanges(type.extensions || (type.extensions = []));
break;

case "reserved":
(type.reserved || (type.reserved = [])).push(readRange(type, tokenLower));
readRanges(type.reserved || (type.reserved = []), true);
break;

default:
Expand Down
34 changes: 32 additions & 2 deletions src/type.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function Type(name, options) {

/**
* Reserved ranges, if any.
* @type {number[][]}
* @type {Array.<number[]|string>}
*/
this.reserved = undefined; // toJSON

Expand Down Expand Up @@ -273,7 +273,11 @@ Type.prototype.add = function add(object) {
// avoids calling the getter if not absolutely necessary because it's called quite frequently
if (this._fieldsById ? /* istanbul ignore next */ this._fieldsById[object.id] : this.fieldsById[object.id])
throw Error("duplicate id " + object.id + " in " + this);

if (this.isReservedId(object.id))
throw Error("id " + object.id + " is reserved in " + this);
if (this.isReservedName(object.name))
throw Error("name '" + object.name + "' is reserved in " + this);

if (object.parent)
object.parent.remove(object);
this.fields[object.name] = object;
Expand Down Expand Up @@ -321,6 +325,32 @@ Type.prototype.remove = function remove(object) {
return Namespace.prototype.remove.call(this, object);
};

/**
* Tests if the specified id is reserved.
* @param {number} id Id to test
* @returns {boolean} `true` if reserved, otherwise `false`
*/
Type.prototype.isReservedId = function isReservedId(id) {
if (this.reserved)
for (var i = 0; i < this.reserved.length; ++i)
if (typeof this.reserved[i] !== "string" && this.reserved[i][0] <= id && this.reserved[i][1] >= id)
return true;
return false;
};

/**
* Tests if the specified name is reserved.
* @param {string} name Name to test
* @returns {boolean} `true` if reserved, otherwise `false`
*/
Type.prototype.isReservedName = function isReservedName(name) {
if (this.reserved)
for (var i = 0; i < this.reserved.length; ++i)
if (this.reserved[i] === name)
return true;
return false;
};

/**
* Creates a new message of this type using the specified properties.
* @param {Object.<string,*>} [properties] Properties to set
Expand Down
16 changes: 13 additions & 3 deletions tests/api_type.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ var def2 = {
oneof: ["a"]
}
},
extensions: [1000, 2000],
reserved: [999],
extensions: [[1000, 2000]],
reserved: [[900, 999], "b"],
nested: {
Type: {
values: { ONE: 1, TWO: 2 }
Expand Down Expand Up @@ -65,6 +65,7 @@ tape.test("reflected types", function(test) {
id: 1
}
},
reserved: [[900, 999], "b"],
nested: {
Type: { fields: {} },
Enum: { values: {} },
Expand All @@ -79,7 +80,7 @@ tape.test("reflected types", function(test) {
},
oneofs: undefined,
extensions: undefined,
reserved: undefined,
reserved: [[900, 999], "b"],
group: undefined,
nested: {
Type: { extensions: undefined, fields: {}, group: undefined, nested: undefined, oneofs: undefined, options: undefined, reserved: undefined },
Expand All @@ -99,5 +100,14 @@ tape.test("reflected types", function(test) {
type.add(new protobuf.Field("c", 1, "uint32"));
}, Error, "should throw when trying to add duplicate ids");

test.throws(function() {
type.add(new protobuf.Field("c", 900, "uint32"));
}, Error, "should throw when trying to add reserved ids");

test.throws(function() {
type.add(new protobuf.Field("b", 2, "uint32"));
}, Error, "should throw when trying to add reserved names");


test.end();
});
1 change: 1 addition & 0 deletions tests/comp_extend.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ message A {\
message B {\
message One {\
extensions 1000 to max;\
reserved 900 to 999, 899, \"a\", 'b';\
}\
}\
message C {\
Expand Down

0 comments on commit cbd4c62

Please sign in to comment.