Created
January 6, 2016 07:17
-
-
Save stelcheck/5db7cd36964728f2e740 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var ByteBuffer = require('bytebuffer'); | |
var flatbuffers = require('./flatbuffers').flatbuffers; | |
var schema = require('./schema_generated.js').MyGame; | |
var count = 100000; | |
var builder = new flatbuffers.Builder(); | |
var name = builder.createString('Holtzinger'); | |
schema.Monster.startMonster(builder); | |
schema.Monster.addPos(builder, schema.Vec3.createVec3(builder, 1, 2, 3)) | |
schema.Monster.addMana(builder, 150); | |
schema.Monster.addHp(builder, 100); | |
schema.Monster.addName(builder, name); | |
schema.Monster.addColor(builder, 1); | |
var pos = schema.Monster.endMonster(builder); | |
schema.Monster.finishMonsterBuffer(builder, pos); | |
var serialized = new Buffer(builder.asUint8Array()); | |
console.log('Byte size:', serialized.length + 'B'); | |
console.log('Count:', count); | |
console.time('deserialize'); | |
for (var i = 0; i < count; i += 1) { | |
var ba = new Uint8Array(serialized); | |
var bb = new flatbuffers.ByteBuffer(ba); | |
var monster = schema.Monster.getRootAsMonster(bb); | |
} | |
console.timeEnd('deserialize'); | |
console.time('serialize'); | |
for (var i = 0; i < count; i += 1) { | |
var name = builder.createString('Holtzinger'); | |
schema.Monster.startMonster(builder); | |
schema.Monster.addPos(builder, schema.Vec3.createVec3(builder, 1, 2, 3)) | |
schema.Monster.addMana(builder, 150); | |
schema.Monster.addHp(builder, 100); | |
schema.Monster.addName(builder, name); | |
schema.Monster.addColor(builder, 1); | |
var pos = schema.Monster.endMonster(builder); | |
schema.Monster.finishMonsterBuffer(builder, pos); | |
} | |
console.timeEnd('serialize'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var count = 100000; | |
var deserialized = { | |
pos: { | |
x: 1, | |
y: 2, | |
z: 3 | |
}, | |
mana: 150, | |
hp: 100, | |
name: "Holtzinger", | |
color: 1 | |
}; | |
var serialized = JSON.stringify(deserialized); | |
console.log('Byte size:', new Buffer(serialized).length + 'B'); | |
console.log('Count:', count); | |
console.time('deserialize'); | |
for (var i = 0; i < count; i += 1) { | |
JSON.parse(serialized); | |
} | |
console.timeEnd('deserialize'); | |
console.time('serialize'); | |
for (var i = 0; i < count; i += 1) { | |
JSON.stringify(deserialized); | |
} | |
console.timeEnd('serialize'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var flatbuffers = {}; | |
/** | |
* @typedef {number} | |
*/ | |
flatbuffers.Offset; | |
/** | |
* @typedef {{ | |
* bb: flatbuffers.ByteBuffer, | |
* bb_pos: number | |
* }} | |
*/ | |
flatbuffers.Table; | |
/** | |
* @type {number} | |
* @const | |
*/ | |
flatbuffers.SIZEOF_SHORT = 2; | |
/** | |
* @type {number} | |
* @const | |
*/ | |
flatbuffers.SIZEOF_INT = 4; | |
/** | |
* @type {number} | |
* @const | |
*/ | |
flatbuffers.FILE_IDENTIFIER_LENGTH = 4; | |
/** | |
* @enum {number} | |
*/ | |
flatbuffers.Encoding = { | |
UTF8_BYTES: 1, | |
UTF16_STRING: 2 | |
}; | |
/** | |
* @type {Int32Array} | |
* @const | |
*/ | |
flatbuffers.int32 = new Int32Array(2); | |
/** | |
* @type {Float32Array} | |
* @const | |
*/ | |
flatbuffers.float32 = new Float32Array(flatbuffers.int32.buffer); | |
/** | |
* @type {Float64Array} | |
* @const | |
*/ | |
flatbuffers.float64 = new Float64Array(flatbuffers.int32.buffer); | |
/** | |
* @type {boolean} | |
* @const | |
*/ | |
flatbuffers.isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1; | |
//////////////////////////////////////////////////////////////////////////////// | |
/** | |
* @constructor | |
* @param {number} high | |
* @param {number} low | |
*/ | |
flatbuffers.Long = function(low, high) { | |
/** | |
* @type {number} | |
* @const | |
*/ | |
this.low = low | 0; | |
/** | |
* @type {number} | |
* @const | |
*/ | |
this.high = high | 0; | |
}; | |
/** | |
* @returns {number} | |
*/ | |
flatbuffers.Long.prototype.toFloat64 = function() { | |
return this.low + this.high * 0x100000000; | |
}; | |
/** | |
* @param {flatbuffers.Long} other | |
* @returns {boolean} | |
*/ | |
flatbuffers.Long.prototype.equals = function(other) { | |
return this.low == other.low && this.high == other.high; | |
}; | |
/** | |
* @type {flatbuffers.Long} | |
* @const | |
*/ | |
flatbuffers.Long.ZERO = new flatbuffers.Long(0, 0); | |
//////////////////////////////////////////////////////////////////////////////// | |
/** | |
* @constructor | |
* @param {number=} initial_size | |
*/ | |
flatbuffers.Builder = function(initial_size) { | |
if (!initial_size) { | |
initial_size = 1024; | |
} | |
/** | |
* @type {flatbuffers.ByteBuffer} | |
* @private | |
*/ | |
this.bb = flatbuffers.ByteBuffer.allocate(initial_size); | |
/** | |
* Remaining space in the ByteBuffer. | |
* | |
* @type {number} | |
* @private | |
*/ | |
this.space = initial_size; | |
/** | |
* Minimum alignment encountered so far. | |
* | |
* @type {number} | |
* @private | |
*/ | |
this.minalign = 1; | |
/** | |
* The vtable for the current table. | |
* | |
* @type {Array.<number>} | |
* @private | |
*/ | |
this.vtable = null; | |
/** | |
* The amount of fields we're actually using. | |
* | |
* @type {number} | |
* @private | |
*/ | |
this.vtable_in_use = 0; | |
/** | |
* Whether we are currently serializing a table. | |
* | |
* @type {boolean} | |
* @private | |
*/ | |
this.isNested = false; | |
/** | |
* Starting offset of the current struct/table. | |
* | |
* @type {number} | |
* @private | |
*/ | |
this.object_start = 0; | |
/** | |
* List of offsets of all vtables. | |
* | |
* @type {Array.<number>} | |
* @private | |
*/ | |
this.vtables = []; | |
/** | |
* For the current vector being built. | |
* | |
* @type {number} | |
* @private | |
*/ | |
this.vector_num_elems = 0; | |
/** | |
* False omits default values from the serialized data | |
* | |
* @type {boolean} | |
* @private | |
*/ | |
this.force_defaults = false; | |
}; | |
/** | |
* In order to save space, fields that are set to their default value | |
* don't get serialized into the buffer. Forcing defaults provides a | |
* way to manually disable this optimization. | |
* | |
* @param {boolean} forceDefaults true always serializes default values | |
*/ | |
flatbuffers.Builder.prototype.forceDefaults = function(forceDefaults) { | |
this.force_defaults = forceDefaults; | |
}; | |
/** | |
* Get the ByteBuffer representing the FlatBuffer. Only call this after you've | |
* called finish(). The actual data starts at the ByteBuffer's current position, | |
* not necessarily at 0. | |
* | |
* @returns {flatbuffers.ByteBuffer} | |
*/ | |
flatbuffers.Builder.prototype.dataBuffer = function() { | |
return this.bb; | |
}; | |
/** | |
* Get the ByteBuffer representing the FlatBuffer. Only call this after you've | |
* called finish(). The actual data starts at the ByteBuffer's current position, | |
* not necessarily at 0. | |
* | |
* @returns {Uint8Array} | |
*/ | |
flatbuffers.Builder.prototype.asUint8Array = function() { | |
return this.bb.bytes().subarray(this.bb.position(), this.bb.position() + this.offset()); | |
}; | |
/** | |
* Prepare to write an element of `size` after `additional_bytes` have been | |
* written, e.g. if you write a string, you need to align such the int length | |
* field is aligned to 4 bytes, and the string data follows it directly. If all | |
* you need to do is alignment, `additional_bytes` will be 0. | |
* | |
* @param {number} size This is the of the new element to write | |
* @param {number} additional_bytes The padding size | |
*/ | |
flatbuffers.Builder.prototype.prep = function(size, additional_bytes) { | |
// Track the biggest thing we've ever aligned to. | |
if (size > this.minalign) { | |
this.minalign = size; | |
} | |
// Find the amount of alignment needed such that `size` is properly | |
// aligned after `additional_bytes` | |
var align_size = ((~(this.bb.capacity() - this.space + additional_bytes)) + 1) & (size - 1); | |
// Reallocate the buffer if needed. | |
while (this.space < align_size + size + additional_bytes) { | |
var old_buf_size = this.bb.capacity(); | |
this.bb = flatbuffers.Builder.growByteBuffer(this.bb); | |
this.space += this.bb.capacity() - old_buf_size; | |
} | |
this.pad(align_size); | |
}; | |
/** | |
* @param {number} byte_size | |
*/ | |
flatbuffers.Builder.prototype.pad = function(byte_size) { | |
for (var i = 0; i < byte_size; i++) { | |
this.bb.writeInt8(--this.space, 0); | |
} | |
}; | |
/** | |
* @param {number} value | |
*/ | |
flatbuffers.Builder.prototype.writeInt8 = function(value) { | |
this.bb.writeInt8(this.space -= 1, value); | |
}; | |
/** | |
* @param {number} value | |
*/ | |
flatbuffers.Builder.prototype.writeInt16 = function(value) { | |
this.bb.writeInt16(this.space -= 2, value); | |
}; | |
/** | |
* @param {number} value | |
*/ | |
flatbuffers.Builder.prototype.writeInt32 = function(value) { | |
this.bb.writeInt32(this.space -= 4, value); | |
}; | |
/** | |
* @param {flatbuffers.Long} value | |
*/ | |
flatbuffers.Builder.prototype.writeInt64 = function(value) { | |
this.bb.writeInt64(this.space -= 8, value); | |
}; | |
/** | |
* @param {number} value | |
*/ | |
flatbuffers.Builder.prototype.writeFloat32 = function(value) { | |
this.bb.writeFloat32(this.space -= 4, value); | |
}; | |
/** | |
* @param {number} value | |
*/ | |
flatbuffers.Builder.prototype.writeFloat64 = function(value) { | |
this.bb.writeFloat64(this.space -= 8, value); | |
}; | |
/** | |
* @param {number} value | |
*/ | |
flatbuffers.Builder.prototype.addInt8 = function(value) { | |
this.prep(1, 0); | |
this.writeInt8(value); | |
}; | |
/** | |
* @param {number} value | |
*/ | |
flatbuffers.Builder.prototype.addInt16 = function(value) { | |
this.prep(2, 0); | |
this.writeInt16(value); | |
}; | |
/** | |
* @param {number} value | |
*/ | |
flatbuffers.Builder.prototype.addInt32 = function(value) { | |
this.prep(4, 0); | |
this.writeInt32(value); | |
}; | |
/** | |
* @param {flatbuffers.Long} value | |
*/ | |
flatbuffers.Builder.prototype.addInt64 = function(value) { | |
this.prep(8, 0); | |
this.writeInt64(value); | |
}; | |
/** | |
* @param {number} value | |
*/ | |
flatbuffers.Builder.prototype.addFloat32 = function(value) { | |
this.prep(4, 0); | |
this.writeFloat32(value); | |
}; | |
/** | |
* @param {number} value | |
*/ | |
flatbuffers.Builder.prototype.addFloat64 = function(value) { | |
this.prep(8, 0); | |
this.writeFloat64(value); | |
}; | |
/** | |
* @param {number} voffset | |
* @param {number} value | |
* @param {number} defaultValue | |
*/ | |
flatbuffers.Builder.prototype.addFieldInt8 = function(voffset, value, defaultValue) { | |
if (this.force_defaults || value != defaultValue) { | |
this.addInt8(value); | |
this.slot(voffset); | |
} | |
}; | |
/** | |
* @param {number} voffset | |
* @param {number} value | |
* @param {number} defaultValue | |
*/ | |
flatbuffers.Builder.prototype.addFieldInt16 = function(voffset, value, defaultValue) { | |
if (this.force_defaults || value != defaultValue) { | |
this.addInt16(value); | |
this.slot(voffset); | |
} | |
}; | |
/** | |
* @param {number} voffset | |
* @param {number} value | |
* @param {number} defaultValue | |
*/ | |
flatbuffers.Builder.prototype.addFieldInt32 = function(voffset, value, defaultValue) { | |
if (this.force_defaults || value != defaultValue) { | |
this.addInt32(value); | |
this.slot(voffset); | |
} | |
}; | |
/** | |
* @param {number} voffset | |
* @param {flatbuffers.Long} value | |
* @param {flatbuffers.Long} defaultValue | |
*/ | |
flatbuffers.Builder.prototype.addFieldInt64 = function(voffset, value, defaultValue) { | |
if (this.force_defaults || !value.equals(defaultValue)) { | |
this.addInt64(value); | |
this.slot(voffset); | |
} | |
}; | |
/** | |
* @param {number} voffset | |
* @param {number} value | |
* @param {number} defaultValue | |
*/ | |
flatbuffers.Builder.prototype.addFieldFloat32 = function(voffset, value, defaultValue) { | |
if (this.force_defaults || value != defaultValue) { | |
this.addFloat32(value); | |
this.slot(voffset); | |
} | |
}; | |
/** | |
* @param {number} voffset | |
* @param {number} value | |
* @param {number} defaultValue | |
*/ | |
flatbuffers.Builder.prototype.addFieldFloat64 = function(voffset, value, defaultValue) { | |
if (this.force_defaults || value != defaultValue) { | |
this.addFloat64(value); | |
this.slot(voffset); | |
} | |
}; | |
/** | |
* @param {number} voffset | |
* @param {flatbuffers.Offset} value | |
* @param {flatbuffers.Offset} defaultValue | |
*/ | |
flatbuffers.Builder.prototype.addFieldOffset = function(voffset, value, defaultValue) { | |
if (this.force_defaults || value != defaultValue) { | |
this.addOffset(value); | |
this.slot(voffset); | |
} | |
}; | |
/** | |
* Structs are stored inline, so nothing additional is being added. `d` is always 0. | |
* | |
* @param {number} voffset | |
* @param {flatbuffers.Offset} value | |
* @param {flatbuffers.Offset} defaultValue | |
*/ | |
flatbuffers.Builder.prototype.addFieldStruct = function(voffset, value, defaultValue) { | |
if (value != defaultValue) { | |
this.nested(value); | |
this.slot(voffset); | |
} | |
}; | |
/** | |
* Structures are always stored inline, they need to be created right | |
* where they're used. You'll get this assertion failure if you | |
* created it elsewhere. | |
* | |
* @param {flatbuffers.Offset} obj The offset of the created object | |
*/ | |
flatbuffers.Builder.prototype.nested = function(obj) { | |
if (obj != this.offset()) { | |
throw new Error('FlatBuffers: struct must be serialized inline.'); | |
} | |
}; | |
/** | |
* Should not be creating any other object, string or vector | |
* while an object is being constructed | |
*/ | |
flatbuffers.Builder.prototype.notNested = function() { | |
if (this.isNested) { | |
throw new Error('FlatBuffers: object serialization must not be nested.'); | |
} | |
}; | |
/** | |
* Set the current vtable at `voffset` to the current location in the buffer. | |
* | |
* @param {number} voffset | |
*/ | |
flatbuffers.Builder.prototype.slot = function(voffset) { | |
this.vtable[voffset] = this.offset(); | |
}; | |
/** | |
* @returns {flatbuffers.Offset} Offset relative to the end of the buffer. | |
*/ | |
flatbuffers.Builder.prototype.offset = function() { | |
return this.bb.capacity() - this.space; | |
}; | |
/** | |
* Doubles the size of the backing ByteBuffer and copies the old data towards | |
* the end of the new buffer (since we build the buffer backwards). | |
* | |
* @param {flatbuffers.ByteBuffer} bb The current buffer with the existing data | |
* @returns {flatbuffers.ByteBuffer} A new byte buffer with the old data copied | |
* to it. The data is located at the end of the buffer. | |
*/ | |
flatbuffers.Builder.growByteBuffer = function(bb) { | |
var old_buf_size = bb.capacity(); | |
// Ensure we don't grow beyond what fits in an int. | |
if (old_buf_size & 0xC0000000) { | |
throw new Error('FlatBuffers: cannot grow buffer beyond 2 gigabytes.'); | |
} | |
var new_buf_size = old_buf_size << 1; | |
var nbb = flatbuffers.ByteBuffer.allocate(new_buf_size); | |
nbb.setPosition(new_buf_size - old_buf_size); | |
nbb.bytes().set(bb.bytes(), new_buf_size - old_buf_size); | |
return nbb; | |
}; | |
/** | |
* Adds on offset, relative to where it will be written. | |
* | |
* @param {flatbuffers.Offset} offset The offset to add | |
*/ | |
flatbuffers.Builder.prototype.addOffset = function(offset) { | |
this.prep(flatbuffers.SIZEOF_INT, 0); // Ensure alignment is already done. | |
this.writeInt32(this.offset() - offset + flatbuffers.SIZEOF_INT); | |
}; | |
/** | |
* Start encoding a new object in the buffer. Users will not usually need to | |
* call this directly. The FlatBuffers compiler will generate helper methods | |
* that call this method internally. | |
* | |
* @param {number} numfields | |
*/ | |
flatbuffers.Builder.prototype.startObject = function(numfields) { | |
this.notNested(); | |
if (this.vtable == null) { | |
this.vtable = []; | |
} | |
this.vtable_in_use = numfields; | |
for (var i = 0; i < numfields; i++) { | |
this.vtable[i] = 0; // This will push additional elements as needed | |
} | |
this.isNested = true; | |
this.object_start = this.offset(); | |
}; | |
/** | |
* Finish off writing the object that is under construction. | |
* | |
* @returns {flatbuffers.Offset} The offset to the object inside `dataBuffer` | |
*/ | |
flatbuffers.Builder.prototype.endObject = function() { | |
if (this.vtable == null || !this.isNested) { | |
throw new Error('FlatBuffers: endObject called without startObject'); | |
} | |
this.addInt32(0); | |
var vtableloc = this.offset(); | |
// Write out the current vtable. | |
for (var i = this.vtable_in_use - 1; i >= 0; i--) { | |
// Offset relative to the start of the table. | |
this.addInt16(this.vtable[i] != 0 ? vtableloc - this.vtable[i] : 0); | |
} | |
var standard_fields = 2; // The fields below: | |
this.addInt16(vtableloc - this.object_start); | |
this.addInt16((this.vtable_in_use + standard_fields) * flatbuffers.SIZEOF_SHORT); | |
// Search for an existing vtable that matches the current one. | |
var existing_vtable = 0; | |
outer_loop: | |
for (var i = 0; i < this.vtables.length; i++) { | |
var vt1 = this.bb.capacity() - this.vtables[i]; | |
var vt2 = this.space; | |
var len = this.bb.readInt16(vt1); | |
if (len == this.bb.readInt16(vt2)) { | |
for (var j = flatbuffers.SIZEOF_SHORT; j < len; j += flatbuffers.SIZEOF_SHORT) { | |
if (this.bb.readInt16(vt1 + j) != this.bb.readInt16(vt2 + j)) { | |
continue outer_loop; | |
} | |
} | |
existing_vtable = this.vtables[i]; | |
break; | |
} | |
} | |
if (existing_vtable) { | |
// Found a match: | |
// Remove the current vtable. | |
this.space = this.bb.capacity() - vtableloc; | |
// Point table to existing vtable. | |
this.bb.writeInt32(this.space, existing_vtable - vtableloc); | |
} else { | |
// No match: | |
// Add the location of the current vtable to the list of vtables. | |
this.vtables.push(this.offset()); | |
// Point table to current vtable. | |
this.bb.writeInt32(this.bb.capacity() - vtableloc, this.offset() - vtableloc); | |
} | |
this.isNested = false; | |
return vtableloc; | |
}; | |
/** | |
* @param {flatbuffers.Offset} root_table | |
* @param {string=} file_identifier | |
*/ | |
flatbuffers.Builder.prototype.finish = function(root_table, file_identifier) { | |
if (file_identifier) { | |
this.prep(this.minalign, flatbuffers.SIZEOF_INT + | |
flatbuffers.FILE_IDENTIFIER_LENGTH); | |
if (file_identifier.length != flatbuffers.FILE_IDENTIFIER_LENGTH) { | |
throw new Error('FlatBuffers: file identifier must be length ' + | |
flatbuffers.FILE_IDENTIFIER_LENGTH); | |
} | |
for (var i = flatbuffers.FILE_IDENTIFIER_LENGTH - 1; i >= 0; i--) { | |
this.writeInt8(file_identifier.charCodeAt(i)); | |
} | |
} | |
this.prep(this.minalign, flatbuffers.SIZEOF_INT); | |
this.addOffset(root_table); | |
this.bb.setPosition(this.space); | |
}; | |
/** | |
* This checks a required field has been set in a given table that has | |
* just been constructed. | |
* | |
* @param {flatbuffers.Offset} table | |
* @param {number} field | |
*/ | |
flatbuffers.Builder.prototype.requiredField = function(table, field) { | |
var table_start = this.bb.capacity() - table; | |
var vtable_start = table_start - this.bb.readInt32(table_start); | |
var ok = this.bb.readInt16(vtable_start + field) != 0; | |
// If this fails, the caller will show what field needs to be set. | |
if (!ok) { | |
throw new Error('FlatBuffers: field ' + field + ' must be set'); | |
} | |
}; | |
/** | |
* Start a new array/vector of objects. Users usually will not call | |
* this directly. The FlatBuffers compiler will create a start/end | |
* method for vector types in generated code. | |
* | |
* @param {number} elem_size The size of each element in the array | |
* @param {number} num_elems The number of elements in the array | |
* @param {number} alignment The alignment of the array | |
*/ | |
flatbuffers.Builder.prototype.startVector = function(elem_size, num_elems, alignment) { | |
this.notNested(); | |
this.vector_num_elems = num_elems; | |
this.prep(flatbuffers.SIZEOF_INT, elem_size * num_elems); | |
this.prep(alignment, elem_size * num_elems); // Just in case alignment > int. | |
}; | |
/** | |
* Finish off the creation of an array and all its elements. The array must be | |
* created with `startVector`. | |
* | |
* @returns {flatbuffers.Offset} The offset at which the newly created array | |
* starts. | |
*/ | |
flatbuffers.Builder.prototype.endVector = function() { | |
this.writeInt32(this.vector_num_elems); | |
return this.offset(); | |
}; | |
/** | |
* Encode the string `s` in the buffer using UTF-8. If a Uint8Array is passed | |
* instead of a string, it is assumed to contain valid UTF-8 encoded data. | |
* | |
* @param {string|Uint8Array} s The string to encode | |
* @return {flatbuffers.Offset} The offset in the buffer where the encoded string starts | |
*/ | |
flatbuffers.Builder.prototype.createString = function(s) { | |
if (s instanceof Uint8Array) { | |
var utf8 = s; | |
} else { | |
var utf8 = []; | |
var i = 0; | |
while (i < s.length) { | |
var codePoint; | |
// Decode UTF-16 | |
var a = s.charCodeAt(i++); | |
if (a < 0xD800 || a >= 0xDC00) { | |
codePoint = a; | |
} else { | |
var b = s.charCodeAt(i++); | |
codePoint = (a << 10) + b + (0x10000 - (0xD800 << 10) - 0xDC00); | |
} | |
// Encode UTF-8 | |
if (codePoint < 0x80) { | |
utf8.push(codePoint); | |
} else { | |
if (codePoint < 0x800) { | |
utf8.push(((codePoint >> 6) & 0x1F) | 0xC0); | |
} else { | |
if (codePoint < 0x10000) { | |
utf8.push(((codePoint >> 12) & 0x0F) | 0xE0); | |
} else { | |
utf8.push( | |
((codePoint >> 18) & 0x07) | 0xF0, | |
((codePoint >> 12) & 0x3F) | 0x80); | |
} | |
utf8.push(((codePoint >> 6) & 0x3F) | 0x80); | |
} | |
utf8.push((codePoint & 0x3F) | 0x80); | |
} | |
} | |
} | |
this.addInt8(0); | |
this.startVector(1, utf8.length, 1); | |
this.bb.setPosition(this.space -= utf8.length); | |
for (var i = 0, offset = this.space, bytes = this.bb.bytes(); i < utf8.length; i++) { | |
bytes[offset++] = utf8[i]; | |
} | |
return this.endVector(); | |
}; | |
//////////////////////////////////////////////////////////////////////////////// | |
/** | |
* @constructor | |
* @param {Uint8Array} bytes | |
*/ | |
flatbuffers.ByteBuffer = function(bytes) { | |
/** | |
* @type {Uint8Array} | |
* @private | |
*/ | |
this.bytes_ = bytes; | |
/** | |
* @type {number} | |
* @private | |
*/ | |
this.position_ = 0; | |
}; | |
/** | |
* @param {number} byte_size | |
* @returns {flatbuffers.ByteBuffer} | |
*/ | |
flatbuffers.ByteBuffer.allocate = function(byte_size) { | |
return new flatbuffers.ByteBuffer(new Uint8Array(byte_size)); | |
}; | |
/** | |
* @returns {Uint8Array} | |
*/ | |
flatbuffers.ByteBuffer.prototype.bytes = function() { | |
return this.bytes_; | |
}; | |
/** | |
* @returns {number} | |
*/ | |
flatbuffers.ByteBuffer.prototype.position = function() { | |
return this.position_; | |
}; | |
/** | |
* @param {number} position | |
*/ | |
flatbuffers.ByteBuffer.prototype.setPosition = function(position) { | |
this.position_ = position; | |
}; | |
/** | |
* @returns {number} | |
*/ | |
flatbuffers.ByteBuffer.prototype.capacity = function() { | |
return this.bytes_.length; | |
}; | |
/** | |
* @param {number} offset | |
* @returns {number} | |
*/ | |
flatbuffers.ByteBuffer.prototype.readInt8 = function(offset) { | |
return this.readUint8(offset) << 24 >> 24; | |
}; | |
/** | |
* @param {number} offset | |
* @returns {number} | |
*/ | |
flatbuffers.ByteBuffer.prototype.readUint8 = function(offset) { | |
return this.bytes_[offset]; | |
}; | |
/** | |
* @param {number} offset | |
* @returns {number} | |
*/ | |
flatbuffers.ByteBuffer.prototype.readInt16 = function(offset) { | |
return this.readUint16(offset) << 16 >> 16; | |
}; | |
/** | |
* @param {number} offset | |
* @returns {number} | |
*/ | |
flatbuffers.ByteBuffer.prototype.readUint16 = function(offset) { | |
return this.bytes_[offset] | this.bytes_[offset + 1] << 8; | |
}; | |
/** | |
* @param {number} offset | |
* @returns {number} | |
*/ | |
flatbuffers.ByteBuffer.prototype.readInt32 = function(offset) { | |
return this.bytes_[offset] | this.bytes_[offset + 1] << 8 | this.bytes_[offset + 2] << 16 | this.bytes_[offset + 3] << 24; | |
}; | |
/** | |
* @param {number} offset | |
* @returns {number} | |
*/ | |
flatbuffers.ByteBuffer.prototype.readUint32 = function(offset) { | |
return this.readInt32(offset) >>> 0; | |
}; | |
/** | |
* @param {number} offset | |
* @returns {flatbuffers.Long} | |
*/ | |
flatbuffers.ByteBuffer.prototype.readInt64 = function(offset) { | |
return new flatbuffers.Long(this.readInt32(offset), this.readInt32(offset + 4)); | |
}; | |
/** | |
* @param {number} offset | |
* @returns {flatbuffers.Long} | |
*/ | |
flatbuffers.ByteBuffer.prototype.readUint64 = function(offset) { | |
return new flatbuffers.Long(this.readUint32(offset), this.readUint32(offset + 4)); | |
}; | |
/** | |
* @param {number} offset | |
* @returns {number} | |
*/ | |
flatbuffers.ByteBuffer.prototype.readFloat32 = function(offset) { | |
flatbuffers.int32[0] = this.readInt32(offset); | |
return flatbuffers.float32[0]; | |
}; | |
/** | |
* @param {number} offset | |
* @returns {number} | |
*/ | |
flatbuffers.ByteBuffer.prototype.readFloat64 = function(offset) { | |
flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1] = this.readInt32(offset); | |
flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0] = this.readInt32(offset + 4); | |
return flatbuffers.float64[0]; | |
}; | |
/** | |
* @param {number} offset | |
* @param {number} value | |
*/ | |
flatbuffers.ByteBuffer.prototype.writeInt8 = function(offset, value) { | |
this.bytes_[offset] = value; | |
}; | |
/** | |
* @param {number} offset | |
* @param {number} value | |
*/ | |
flatbuffers.ByteBuffer.prototype.writeInt16 = function(offset, value) { | |
this.bytes_[offset] = value; | |
this.bytes_[offset + 1] = value >> 8; | |
}; | |
/** | |
* @param {number} offset | |
* @param {number} value | |
*/ | |
flatbuffers.ByteBuffer.prototype.writeInt32 = function(offset, value) { | |
this.bytes_[offset] = value; | |
this.bytes_[offset + 1] = value >> 8; | |
this.bytes_[offset + 2] = value >> 16; | |
this.bytes_[offset + 3] = value >> 24; | |
}; | |
/** | |
* @param {number} offset | |
* @param {flatbuffers.Long} value | |
*/ | |
flatbuffers.ByteBuffer.prototype.writeInt64 = function(offset, value) { | |
this.writeInt32(offset, value.low); | |
this.writeInt32(offset + 4, value.high); | |
}; | |
/** | |
* @param {number} offset | |
* @param {number} value | |
*/ | |
flatbuffers.ByteBuffer.prototype.writeFloat32 = function(offset, value) { | |
flatbuffers.float32[0] = value; | |
this.writeInt32(offset, flatbuffers.int32[0]); | |
}; | |
/** | |
* @param {number} offset | |
* @param {number} value | |
*/ | |
flatbuffers.ByteBuffer.prototype.writeFloat64 = function(offset, value) { | |
flatbuffers.float64[0] = value; | |
this.writeInt32(offset, flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1]); | |
this.writeInt32(offset + 4, flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0]); | |
}; | |
/** | |
* Look up a field in the vtable, return an offset into the object, or 0 if the | |
* field is not present. | |
* | |
* @param {number} bb_pos | |
* @param {number} vtable_offset | |
* @returns {number} | |
*/ | |
flatbuffers.ByteBuffer.prototype.__offset = function(bb_pos, vtable_offset) { | |
var vtable = bb_pos - this.readInt32(bb_pos); | |
return vtable_offset < this.readInt16(vtable) ? this.readInt16(vtable + vtable_offset) : 0; | |
}; | |
/** | |
* Initialize any Table-derived type to point to the union at the given offset. | |
* | |
* @param {flatbuffers.Table} t | |
* @param {number} offset | |
* @returns {flatbuffers.Table} | |
*/ | |
flatbuffers.ByteBuffer.prototype.__union = function(t, offset) { | |
t.bb_pos = offset + this.readInt32(offset); | |
t.bb = this; | |
return t; | |
}; | |
/** | |
* Create a JavaScript string from UTF-8 data stored inside the FlatBuffer. | |
* This allocates a new string and converts to wide chars upon each access. | |
* | |
* To avoid the conversion to UTF-16, pass flatbuffers.Encoding.UTF8_BYTES as | |
* the "optionalEncoding" argument. This is useful for avoiding conversion to | |
* and from UTF-16 when the data will just be packaged back up in another | |
* FlatBuffer later on. | |
* | |
* @param {number} offset | |
* @param {flatbuffers.Encoding=} optionalEncoding Defaults to UTF16_STRING | |
* @returns {string|Uint8Array} | |
*/ | |
flatbuffers.ByteBuffer.prototype.__string = function(offset, optionalEncoding) { | |
offset += this.readInt32(offset); | |
var length = this.readInt32(offset); | |
var result = ''; | |
var i = 0; | |
offset += flatbuffers.SIZEOF_INT; | |
if (optionalEncoding === flatbuffers.Encoding.UTF8_BYTES) { | |
return this.bytes_.subarray(offset, offset + length); | |
} | |
while (i < length) { | |
var codePoint; | |
// Decode UTF-8 | |
var a = this.readUint8(offset + i++); | |
if (a < 0xC0) { | |
codePoint = a; | |
} else { | |
var b = this.readUint8(offset + i++); | |
if (a < 0xE0) { | |
codePoint = | |
((a & 0x1F) << 6) | | |
(b & 0x3F); | |
} else { | |
var c = this.readUint8(offset + i++); | |
if (a < 0xF0) { | |
codePoint = | |
((a & 0x0F) << 12) | | |
((b & 0x3F) << 6) | | |
(c & 0x3F); | |
} else { | |
var d = this.readUint8(offset + i++); | |
codePoint = | |
((a & 0x07) << 18) | | |
((b & 0x3F) << 12) | | |
((c & 0x3F) << 6) | | |
(d & 0x3F); | |
} | |
} | |
} | |
// Encode UTF-16 | |
if (codePoint < 0x10000) { | |
result += String.fromCharCode(codePoint); | |
} else { | |
codePoint -= 0x10000; | |
result += String.fromCharCode( | |
(codePoint >> 10) + 0xD800, | |
(codePoint & ((1 << 10) - 1)) + 0xDC00); | |
} | |
} | |
return result; | |
}; | |
/** | |
* Retrieve the relative offset stored at "offset" | |
* @param {number} offset | |
* @returns {number} | |
*/ | |
flatbuffers.ByteBuffer.prototype.__indirect = function(offset) { | |
return offset + this.readInt32(offset); | |
}; | |
/** | |
* Get the start of data of a vector whose offset is stored at "offset" in this object. | |
* | |
* @param {number} offset | |
* @returns {number} | |
*/ | |
flatbuffers.ByteBuffer.prototype.__vector = function(offset) { | |
return offset + this.readInt32(offset) + flatbuffers.SIZEOF_INT; // data starts after the length | |
}; | |
/** | |
* Get the length of a vector whose offset is stored at "offset" in this object. | |
* | |
* @param {number} offset | |
* @returns {number} | |
*/ | |
flatbuffers.ByteBuffer.prototype.__vector_len = function(offset) { | |
return this.readInt32(offset + this.readInt32(offset)); | |
}; | |
/** | |
* @param {string} ident | |
* @returns {boolean} | |
*/ | |
flatbuffers.ByteBuffer.prototype.__has_identifier = function(ident) { | |
if (ident.length != flatbuffers.FILE_IDENTIFIER_LENGTH) { | |
throw new Error('FlatBuffers: file identifier must be length ' + | |
flatbuffers.FILE_IDENTIFIER_LENGTH); | |
} | |
for (var i = 0; i < flatbuffers.FILE_IDENTIFIER_LENGTH; i++) { | |
if (ident.charCodeAt(i) != this.readInt8(this.position_ + flatbuffers.SIZEOF_INT + i)) { | |
return false; | |
} | |
} | |
return true; | |
}; | |
// Exports for Node.js and RequireJS | |
this.flatbuffers = flatbuffers; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// example IDL file | |
namespace MyGame; | |
attribute "priority"; | |
enum Color : byte { Red = 1, Green, Blue } | |
struct Vec3 { | |
x:float; | |
y:float; | |
z:float; | |
} | |
table Monster { | |
pos:Vec3; | |
mana:short = 150; | |
hp:short = 100; | |
name:string; | |
friendly:bool = false (deprecated, priority: 1); | |
inventory:[ubyte]; | |
color:Color = Blue; | |
} | |
root_type Monster; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// automatically generated by the FlatBuffers compiler, do not modify | |
/** | |
* @const | |
*/ | |
var MyGame = MyGame || {}; | |
/** | |
* @enum | |
*/ | |
MyGame.Color = { | |
Red: 1, | |
Green: 2, | |
Blue: 3 | |
}; | |
/** | |
* @constructor | |
*/ | |
MyGame.Vec3 = function() { | |
/** | |
* @type {flatbuffers.ByteBuffer} | |
*/ | |
this.bb = null; | |
/** | |
* @type {number} | |
*/ | |
this.bb_pos = 0; | |
}; | |
/** | |
* @param {number} i | |
* @param {flatbuffers.ByteBuffer} bb | |
* @returns {MyGame.Vec3} | |
*/ | |
MyGame.Vec3.prototype.__init = function(i, bb) { | |
this.bb_pos = i; | |
this.bb = bb; | |
return this; | |
}; | |
/** | |
* @returns {number} | |
*/ | |
MyGame.Vec3.prototype.x = function() { | |
return this.bb.readFloat32(this.bb_pos); | |
}; | |
/** | |
* @returns {number} | |
*/ | |
MyGame.Vec3.prototype.y = function() { | |
return this.bb.readFloat32(this.bb_pos + 4); | |
}; | |
/** | |
* @returns {number} | |
*/ | |
MyGame.Vec3.prototype.z = function() { | |
return this.bb.readFloat32(this.bb_pos + 8); | |
}; | |
/** | |
* @param {flatbuffers.Builder} builder | |
* @param {number} x | |
* @param {number} y | |
* @param {number} z | |
* @returns {flatbuffers.Offset} | |
*/ | |
MyGame.Vec3.createVec3 = function(builder, x, y, z) { | |
builder.prep(4, 12); | |
builder.writeFloat32(z); | |
builder.writeFloat32(y); | |
builder.writeFloat32(x); | |
return builder.offset(); | |
}; | |
/** | |
* @constructor | |
*/ | |
MyGame.Monster = function() { | |
/** | |
* @type {flatbuffers.ByteBuffer} | |
*/ | |
this.bb = null; | |
/** | |
* @type {number} | |
*/ | |
this.bb_pos = 0; | |
}; | |
/** | |
* @param {number} i | |
* @param {flatbuffers.ByteBuffer} bb | |
* @returns {MyGame.Monster} | |
*/ | |
MyGame.Monster.prototype.__init = function(i, bb) { | |
this.bb_pos = i; | |
this.bb = bb; | |
return this; | |
}; | |
/** | |
* @param {flatbuffers.ByteBuffer} bb | |
* @param {MyGame.Monster=} obj | |
* @returns {MyGame.Monster} | |
*/ | |
MyGame.Monster.getRootAsMonster = function(bb, obj) { | |
return (obj || new MyGame.Monster).__init(bb.readInt32(bb.position()) + bb.position(), bb); | |
}; | |
/** | |
* @param {MyGame.Vec3=} obj | |
* @returns {MyGame.Vec3} | |
*/ | |
MyGame.Monster.prototype.pos = function(obj) { | |
var offset = this.bb.__offset(this.bb_pos, 4); | |
return offset ? (obj || new MyGame.Vec3).__init(this.bb_pos + offset, this.bb) : null; | |
}; | |
/** | |
* @returns {number} | |
*/ | |
MyGame.Monster.prototype.mana = function() { | |
var offset = this.bb.__offset(this.bb_pos, 6); | |
return offset ? this.bb.readInt16(this.bb_pos + offset) : 150; | |
}; | |
/** | |
* @returns {number} | |
*/ | |
MyGame.Monster.prototype.hp = function() { | |
var offset = this.bb.__offset(this.bb_pos, 8); | |
return offset ? this.bb.readInt16(this.bb_pos + offset) : 100; | |
}; | |
/** | |
* @param {flatbuffers.Encoding=} optionalEncoding | |
* @returns {string|Uint8Array} | |
*/ | |
MyGame.Monster.prototype.name = function(optionalEncoding) { | |
var offset = this.bb.__offset(this.bb_pos, 10); | |
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; | |
}; | |
/** | |
* @param {number} index | |
* @returns {number} | |
*/ | |
MyGame.Monster.prototype.inventory = function(index) { | |
var offset = this.bb.__offset(this.bb_pos, 14); | |
return offset ? this.bb.readUint8(this.bb.__vector(this.bb_pos + offset) + index) : 0; | |
}; | |
/** | |
* @returns {number} | |
*/ | |
MyGame.Monster.prototype.inventoryLength = function() { | |
var offset = this.bb.__offset(this.bb_pos, 14); | |
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; | |
}; | |
/** | |
* @returns {MyGame.Color} | |
*/ | |
MyGame.Monster.prototype.color = function() { | |
var offset = this.bb.__offset(this.bb_pos, 16); | |
return offset ? /** @type {MyGame.Color} */ (this.bb.readInt8(this.bb_pos + offset)) : MyGame.Color.Blue; | |
}; | |
/** | |
* @param {flatbuffers.Builder} builder | |
*/ | |
MyGame.Monster.startMonster = function(builder) { | |
builder.startObject(7); | |
}; | |
/** | |
* @param {flatbuffers.Builder} builder | |
* @param {flatbuffers.Offset} posOffset | |
*/ | |
MyGame.Monster.addPos = function(builder, posOffset) { | |
builder.addFieldStruct(0, posOffset, 0); | |
}; | |
/** | |
* @param {flatbuffers.Builder} builder | |
* @param {number} mana | |
*/ | |
MyGame.Monster.addMana = function(builder, mana) { | |
builder.addFieldInt16(1, mana, 150); | |
}; | |
/** | |
* @param {flatbuffers.Builder} builder | |
* @param {number} hp | |
*/ | |
MyGame.Monster.addHp = function(builder, hp) { | |
builder.addFieldInt16(2, hp, 100); | |
}; | |
/** | |
* @param {flatbuffers.Builder} builder | |
* @param {flatbuffers.Offset} nameOffset | |
*/ | |
MyGame.Monster.addName = function(builder, nameOffset) { | |
builder.addFieldOffset(3, nameOffset, 0); | |
}; | |
/** | |
* @param {flatbuffers.Builder} builder | |
* @param {flatbuffers.Offset} inventoryOffset | |
*/ | |
MyGame.Monster.addInventory = function(builder, inventoryOffset) { | |
builder.addFieldOffset(5, inventoryOffset, 0); | |
}; | |
/** | |
* @param {flatbuffers.Builder} builder | |
* @param {Array.<number>} data | |
* @returns {flatbuffers.Offset} | |
*/ | |
MyGame.Monster.createInventoryVector = function(builder, data) { | |
builder.startVector(1, data.length, 1); | |
for (var i = data.length - 1; i >= 0; i--) { | |
builder.addInt8(data[i]); | |
} | |
return builder.endVector(); | |
}; | |
/** | |
* @param {flatbuffers.Builder} builder | |
* @param {number} numElems | |
*/ | |
MyGame.Monster.startInventoryVector = function(builder, numElems) { | |
builder.startVector(1, numElems, 1); | |
}; | |
/** | |
* @param {flatbuffers.Builder} builder | |
* @param {MyGame.Color} color | |
*/ | |
MyGame.Monster.addColor = function(builder, color) { | |
builder.addFieldInt8(6, color, MyGame.Color.Blue); | |
}; | |
/** | |
* @param {flatbuffers.Builder} builder | |
* @returns {flatbuffers.Offset} | |
*/ | |
MyGame.Monster.endMonster = function(builder) { | |
var offset = builder.endObject(); | |
return offset; | |
}; | |
/** | |
* @param {flatbuffers.Builder} builder | |
* @param {flatbuffers.Offset} offset | |
*/ | |
MyGame.Monster.finishMonsterBuffer = function(builder, offset) { | |
builder.finish(offset); | |
}; | |
// Exports for Node.js and RequireJS | |
this.MyGame = MyGame; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment