├── .gitignore ├── History.md ├── LICENSE ├── README.md ├── index.js ├── lib ├── components │ └── flatbuffer.js ├── flatbuffers.js ├── index.js ├── reflection.fbs └── reflection_generated.js ├── package.json └── tests ├── FlatBufferTest.js ├── PomeloFlatBuffer.js ├── clientBFBS ├── ConnectorGateServer.bfbs └── clientFBCheck.json ├── clientProtos.json ├── exampleData.js ├── flatSchema ├── ConnectorGateServer.fbs └── ItemDistances.fbs ├── serverBFBS ├── ItemDistances.bfbs ├── MessageBoxInfo.bfbs └── serverFBCheck.json └── serverProtos.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2.0.0 / 2017-12-7 2 | ================= 3 | * update 支持flatbuffer version: 1.10.2 4 | 5 | 1.2.0 / 2017-12-7 6 | ================= 7 | * [FIX] 热更新文件变化bug 修复 8 | 9 | 10 | 1.1.0 / 2017-10-25 11 | ================= 12 | * update flatbuffer 13 | * remove pomelo-logger 14 | 15 | 1.0.1 / 2017-6-30 16 | ================= 17 | * nodejs 升级到 Node 8 18 | 19 | 0.0.3 / 2017-6-30 20 | ================= 21 | * [FIX] 支持flatbuffer version: 1.7.0 22 | * [FIX] 添加 使用说明 23 | * [FIX] 添加测试用例 24 | 25 | 0.0.2 / 2017-6-29 26 | ================= 27 | * [FIX] 添加 check 判断 28 | * [FIX] start 初始化传参错误 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 frank198 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [FlatBuffer](https://github.com/google/flatbuffers) 2 | 3 | # 使用说明 4 | 5 | ## pomelo 中安装与使用 6 | 7 | ### 安装 8 | ```bash 9 | npm install pomelo-flatbuffer --save 10 | ``` 11 | ### 使用 12 | 在 app.js 中添加一下脚本 13 | 14 | ```javascript 15 | // app configuration 16 | app.configure('development', 'gate|connector', () => 17 | { 18 | app.use(flatBuffer, { 19 | serverProtos : '/serverProtos.json', 20 | clientProtos : '/clientProtos.json', 21 | serverFBPath : '/serverBFBS/', 22 | clientFBPath : '/clientBFBS/' 23 | }); 24 | app.set('connectorConfig', 25 | { 26 | connector : pomelo.connectors.hybridconnector, 27 | // timeout:10, 28 | handshake : handshake, 29 | heartbeat : 5, 30 | useProtobuf : false, 31 | setNoDelay : true, 32 | // disconnectOnTimeOut : true 33 | // ,distinctHost:true 34 | }); 35 | }); 36 | ``` 37 | 38 | #### 参数说明 39 | - serverProtos dafault: config/serverProtos.json 服务器发送到客户端的消息 40 | - clientProtos default: config/clientProtos.json 客户端发送到服务器的消息 41 | - serverFBPath default: config/serverBFBS/ flatbuffer 序列化服务器发送的数据(bfbs 格式文件) 42 | - clientFBPath default: config/clientBFBS/ flatbuffer 反序列化服务器接受的数据(bfbs 格式文件) 43 | 44 | 45 | ## bfbs 文件生成 46 | ```sh 47 | # cd tests 48 | # flatc -o bfbsData -b --schema flatSchema/*.fbs 49 | ``` 50 | 51 | 52 | 53 | ## 实例使用 54 | 55 | ### 文件夹说明 56 | 57 | - serverBFBS 服务器发送到客户端的消息, 和 serverProtos.json 一致 58 | - .json route与class对照表 59 | - .bfbs flatc生成的数据 60 | 61 | - clientBFBS 客户端发送到服务器的消息, 和 clientProtos.json 一致 62 | - .json route与class对照表 63 | - .bfbs flatc生成的数据 64 | 65 | - flatSchema flat文件的消息格式 66 | 67 | ```javascript 68 | const FlatBuffer = require('../lib/components/flatbuffer'); 69 | const flatBufferInstance = FlatBuffer(app, { 70 | serverProtos : '/serverProtos.json', 71 | clientProtos : '/clientProtos.json', 72 | serverFBPath : '/serverBFBS/', 73 | clientFBPath : '/clientBFBS/' 74 | }); 75 | 76 | FlatBuffer.start(()=>{ 77 | // 序列化数据 78 | const data = flatBufferInstance.encode('ItemDistances', exampleData.ItemDistances); 79 | // 反序列化数据 80 | flatBufferInstance.decode('ItemDistances', data); 81 | }) 82 | ``` 83 | 84 | ### 测试 85 | 86 | ```bash 87 | node ./test/PomeloFlatBuffer.js 88 | node ./test/FlatBufferTest.js 89 | ``` 90 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | components: __dirname + '/lib/components/' 3 | }; -------------------------------------------------------------------------------- /lib/components/flatbuffer.js: -------------------------------------------------------------------------------- 1 | 2 | const SERVER = 'server'; 3 | const CLIENT = 'client'; 4 | const SERVERFB = 'serverFB'; 5 | const CLIENTFB = 'clientFB'; 6 | const FlatBufferIndex = require('../index'); 7 | const fs = require('fs'); 8 | const path = require('path'); 9 | const watchers = Symbol('watchers'); 10 | const publicKey = Symbol('publicKey'); 11 | const serverFlatBuffer = Symbol('serverFlatBuffer'); 12 | const clientFlatBuffer = Symbol('serverFlatBuffer'); 13 | 14 | class FlatBuffer 15 | { 16 | constructor(app, opts) 17 | { 18 | this.app = app; 19 | this.version = 0; 20 | this[watchers] = new Map(); 21 | this[serverFlatBuffer] = new Map(); 22 | this[clientFlatBuffer] = new Map(); 23 | this.serverFBCheck = {}; 24 | this.clientFBCheck = {}; 25 | opts = opts || {}; 26 | this.serverProtosPath = opts.serverProtos || '/config/serverProtos.json'; 27 | this.clientProtosPath = opts.clientProtos || '/config/clientProtos.json'; 28 | this.serverFBPath = opts.serverFBPath || '/config/serverBFBS'; 29 | this.clientFBPath = opts.clientFBPath || '/config/clientBFBS'; 30 | this.logger = opts.logger || console; 31 | this[publicKey] = opts.publicKey || ''; 32 | } 33 | 34 | start(cb) 35 | { 36 | this.setProtos(SERVER, path.join(this.app.getBase(), this.serverProtosPath)); 37 | this.setProtos(CLIENT, path.join(this.app.getBase(), this.clientProtosPath)); 38 | this.setProtos(SERVERFB, path.join(this.app.getBase(), this.serverFBPath)); 39 | this.setProtos(CLIENTFB, path.join(this.app.getBase(), this.clientFBPath)); 40 | process.nextTick(cb); 41 | } 42 | 43 | check(type, route) 44 | { 45 | let curRoute = route; 46 | let flatInstance = null; 47 | switch(type) { 48 | case SERVER: 49 | if (this.serverFBCheck[route]) 50 | { 51 | curRoute = this.serverFBCheck[route]; 52 | } 53 | flatInstance = this[serverFlatBuffer].get(curRoute); 54 | break; 55 | case CLIENT: 56 | if (this.clientFBCheck[route]) 57 | { 58 | curRoute = this.clientFBCheck[route]; 59 | } 60 | flatInstance = this[clientFlatBuffer].get(curRoute); 61 | break; 62 | default: 63 | throw new Error('decodeIO meet with error type of protos, type: ' + type + ' route: ' + route); 64 | break; 65 | } 66 | return flatInstance != null; 67 | } 68 | 69 | encode(route, message) 70 | { 71 | let curRoute = route; 72 | if (this.serverFBCheck[route]) 73 | { 74 | curRoute = this.serverFBCheck[route]; 75 | } 76 | const flatInstance = this[serverFlatBuffer].get(curRoute); 77 | if (flatInstance != null) 78 | { 79 | return flatInstance.generate(message); 80 | } 81 | return null; 82 | } 83 | 84 | decode(route, message) 85 | { 86 | let curRoute = route; 87 | if (this.clientFBCheck[route]) 88 | { 89 | curRoute = this.clientFBCheck[route]; 90 | } 91 | const flatInstance = this[clientFlatBuffer].get(curRoute); 92 | if (flatInstance != null) 93 | { 94 | return flatInstance.parse(message); 95 | } 96 | return null; 97 | } 98 | 99 | getProtos() 100 | { 101 | return { 102 | server : this.serverProtos, 103 | client : this.clientProtos, 104 | publicKey : this[publicKey], 105 | version : this.version 106 | }; 107 | } 108 | 109 | getVersion() 110 | { 111 | return this.version; 112 | } 113 | 114 | setProtos(type, filePath) 115 | { 116 | if (!fs.existsSync(filePath)) 117 | { 118 | return; 119 | } 120 | 121 | const stats = fs.statSync(filePath); 122 | if (stats.isFile()) 123 | { 124 | const baseName = path.basename(filePath); 125 | if (type === SERVER) 126 | { 127 | this.serverProtos = require(filePath); 128 | } 129 | else if (type === CLIENT) 130 | { 131 | this.clientProtos = require(filePath); 132 | } 133 | else 134 | { 135 | this.setFlatBufferData(type, filePath); 136 | } 137 | 138 | // Set version to modify time 139 | const time = stats.mtime.getTime(); 140 | if (this.version < time) 141 | { 142 | this.version = time; 143 | } 144 | 145 | // Watch file 146 | const watcher = fs.watch(filePath, this.onUpdate.bind(this, type, filePath)); 147 | if (this[watchers].has(baseName)) 148 | { 149 | this[watchers].get(baseName).close(); 150 | } 151 | this[watchers].set(baseName, watcher); 152 | } 153 | else if (stats.isDirectory()) 154 | { 155 | const files = fs.readdirSync(filePath); 156 | files.forEach((val, index) => 157 | { 158 | const fPath = path.join(filePath, val); 159 | const stats = fs.statSync(fPath); 160 | if (stats.isFile()) this.setProtos(type, fPath); 161 | }); 162 | } 163 | 164 | } 165 | 166 | onUpdate(type, filePath, event) 167 | { 168 | if (event !== 'change') 169 | { 170 | return; 171 | } 172 | try 173 | { 174 | if (type === SERVER || type === CLIENT) 175 | { 176 | const data = fs.readFileSync(filePath, 'utf8'); 177 | if (type === SERVER) 178 | { 179 | this.serverProtos = JSON.parse(data); 180 | } 181 | else if (type === CLIENT) 182 | { 183 | this.clientProtos = JSON.parse(data); 184 | } 185 | } 186 | else 187 | { 188 | this.setFlatBufferData(type, filePath); 189 | } 190 | this.version = fs.statSync(filePath).mtime.getTime(); 191 | this.logger && this.logger.debug('change proto file , type : %j, path : %j, version : %j', type, filePath, this.version); 192 | } 193 | catch (err) 194 | { 195 | this.logger && this.logger.warn('change proto file error! path : %j', filePath); 196 | this.logger && this.logger.warn(err); 197 | } 198 | } 199 | 200 | setFlatBufferData(type, filePath) 201 | { 202 | const extName = path.extname(filePath); 203 | const baseName = path.basename(filePath, extName); 204 | const data = fs.readFileSync(filePath); 205 | if (extName === '.json') 206 | { 207 | if (type === SERVERFB) 208 | { 209 | this.serverFBCheck = JSON.parse(data); 210 | } 211 | else if (type === CLIENTFB) 212 | { 213 | this.clientFBCheck = JSON.parse(data); 214 | } 215 | } 216 | else 217 | { 218 | const flatBuild = FlatBufferIndex.compileSchema(data); 219 | if (type === SERVERFB) 220 | { 221 | this[serverFlatBuffer].set(baseName, flatBuild); 222 | } 223 | else if (type === CLIENTFB) 224 | { 225 | this[clientFlatBuffer].set(baseName, flatBuild); 226 | } 227 | } 228 | } 229 | 230 | stop(force, cb) 231 | { 232 | for (const watcher of this[watchers].values()) 233 | { 234 | if (watcher) 235 | watcher.close(); 236 | } 237 | this[watchers].clear(); 238 | this[watchers] = null; 239 | process.nextTick(cb); 240 | } 241 | } 242 | 243 | module.exports = function(app, opts) 244 | { 245 | return new FlatBuffer(app, opts); 246 | }; 247 | FlatBuffer.prototype.name = '__decodeIO__protobuf__'; -------------------------------------------------------------------------------- /lib/flatbuffers.js: -------------------------------------------------------------------------------- 1 | /// @file 2 | /// @addtogroup flatbuffers_javascript_api 3 | /// @{ 4 | /// @cond FLATBUFFERS_INTERNAL 5 | 6 | /** 7 | * @fileoverview 8 | * 9 | * Need to suppress 'global this' error so the Node.js export line doesn't cause 10 | * closure compile to error out. 11 | * @suppress {globalThis} 12 | */ 13 | 14 | /** 15 | * @const 16 | * @namespace 17 | */ 18 | var flatbuffers = {}; 19 | 20 | /** 21 | * @typedef {number} 22 | */ 23 | flatbuffers.Offset; 24 | 25 | /** 26 | * @typedef {{ 27 | * bb: flatbuffers.ByteBuffer, 28 | * bb_pos: number 29 | * }} 30 | */ 31 | flatbuffers.Table; 32 | 33 | /** 34 | * @type {number} 35 | * @const 36 | */ 37 | flatbuffers.SIZEOF_SHORT = 2; 38 | 39 | /** 40 | * @type {number} 41 | * @const 42 | */ 43 | flatbuffers.SIZEOF_INT = 4; 44 | 45 | /** 46 | * @type {number} 47 | * @const 48 | */ 49 | flatbuffers.FILE_IDENTIFIER_LENGTH = 4; 50 | 51 | /** 52 | * @enum {number} 53 | */ 54 | flatbuffers.Encoding = { 55 | UTF8_BYTES: 1, 56 | UTF16_STRING: 2 57 | }; 58 | 59 | /** 60 | * @type {Int32Array} 61 | * @const 62 | */ 63 | flatbuffers.int32 = new Int32Array(2); 64 | 65 | /** 66 | * @type {Float32Array} 67 | * @const 68 | */ 69 | flatbuffers.float32 = new Float32Array(flatbuffers.int32.buffer); 70 | 71 | /** 72 | * @type {Float64Array} 73 | * @const 74 | */ 75 | flatbuffers.float64 = new Float64Array(flatbuffers.int32.buffer); 76 | 77 | /** 78 | * @type {boolean} 79 | * @const 80 | */ 81 | flatbuffers.isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1; 82 | 83 | //////////////////////////////////////////////////////////////////////////////// 84 | 85 | /** 86 | * @constructor 87 | * @param {number} low 88 | * @param {number} high 89 | */ 90 | flatbuffers.Long = function(low, high) { 91 | /** 92 | * @type {number} 93 | * @const 94 | */ 95 | this.low = low | 0; 96 | 97 | /** 98 | * @type {number} 99 | * @const 100 | */ 101 | this.high = high | 0; 102 | }; 103 | 104 | /** 105 | * @param {number} low 106 | * @param {number} high 107 | * @returns {flatbuffers.Long} 108 | */ 109 | flatbuffers.Long.create = function(low, high) { 110 | // Special-case zero to avoid GC overhead for default values 111 | return low == 0 && high == 0 ? flatbuffers.Long.ZERO : new flatbuffers.Long(low, high); 112 | }; 113 | 114 | /** 115 | * @returns {number} 116 | */ 117 | flatbuffers.Long.prototype.toFloat64 = function() { 118 | return (this.low >>> 0) + this.high * 0x100000000; 119 | }; 120 | 121 | /** 122 | * @param {flatbuffers.Long} other 123 | * @returns {boolean} 124 | */ 125 | flatbuffers.Long.prototype.equals = function(other) { 126 | return this.low == other.low && this.high == other.high; 127 | }; 128 | 129 | /** 130 | * @type {flatbuffers.Long} 131 | * @const 132 | */ 133 | flatbuffers.Long.ZERO = new flatbuffers.Long(0, 0); 134 | 135 | /// @endcond 136 | //////////////////////////////////////////////////////////////////////////////// 137 | /** 138 | * Create a FlatBufferBuilder. 139 | * 140 | * @constructor 141 | * @param {number=} opt_initial_size 142 | */ 143 | flatbuffers.Builder = function(opt_initial_size) { 144 | if (!opt_initial_size) { 145 | var initial_size = 1024; 146 | } else { 147 | var initial_size = opt_initial_size; 148 | } 149 | 150 | /** 151 | * @type {flatbuffers.ByteBuffer} 152 | * @private 153 | */ 154 | this.bb = flatbuffers.ByteBuffer.allocate(initial_size); 155 | 156 | /** 157 | * Remaining space in the ByteBuffer. 158 | * 159 | * @type {number} 160 | * @private 161 | */ 162 | this.space = initial_size; 163 | 164 | /** 165 | * Minimum alignment encountered so far. 166 | * 167 | * @type {number} 168 | * @private 169 | */ 170 | this.minalign = 1; 171 | 172 | /** 173 | * The vtable for the current table. 174 | * 175 | * @type {Array.} 176 | * @private 177 | */ 178 | this.vtable = null; 179 | 180 | /** 181 | * The amount of fields we're actually using. 182 | * 183 | * @type {number} 184 | * @private 185 | */ 186 | this.vtable_in_use = 0; 187 | 188 | /** 189 | * Whether we are currently serializing a table. 190 | * 191 | * @type {boolean} 192 | * @private 193 | */ 194 | this.isNested = false; 195 | 196 | /** 197 | * Starting offset of the current struct/table. 198 | * 199 | * @type {number} 200 | * @private 201 | */ 202 | this.object_start = 0; 203 | 204 | /** 205 | * List of offsets of all vtables. 206 | * 207 | * @type {Array.} 208 | * @private 209 | */ 210 | this.vtables = []; 211 | 212 | /** 213 | * For the current vector being built. 214 | * 215 | * @type {number} 216 | * @private 217 | */ 218 | this.vector_num_elems = 0; 219 | 220 | /** 221 | * False omits default values from the serialized data 222 | * 223 | * @type {boolean} 224 | * @private 225 | */ 226 | this.force_defaults = false; 227 | }; 228 | 229 | flatbuffers.Builder.prototype.clear = function() { 230 | this.bb.clear(); 231 | this.space = this.bb.capacity(); 232 | this.minalign = 1; 233 | this.vtable = null; 234 | this.vtable_in_use = 0; 235 | this.isNested = false; 236 | this.object_start = 0; 237 | this.vtables = []; 238 | this.vector_num_elems = 0; 239 | this.force_defaults = false; 240 | }; 241 | 242 | /** 243 | * In order to save space, fields that are set to their default value 244 | * don't get serialized into the buffer. Forcing defaults provides a 245 | * way to manually disable this optimization. 246 | * 247 | * @param {boolean} forceDefaults true always serializes default values 248 | */ 249 | flatbuffers.Builder.prototype.forceDefaults = function(forceDefaults) { 250 | this.force_defaults = forceDefaults; 251 | }; 252 | 253 | /** 254 | * Get the ByteBuffer representing the FlatBuffer. Only call this after you've 255 | * called finish(). The actual data starts at the ByteBuffer's current position, 256 | * not necessarily at 0. 257 | * 258 | * @returns {flatbuffers.ByteBuffer} 259 | */ 260 | flatbuffers.Builder.prototype.dataBuffer = function() { 261 | return this.bb; 262 | }; 263 | 264 | /** 265 | * Get the bytes representing the FlatBuffer. Only call this after you've 266 | * called finish(). 267 | * 268 | * @returns {Uint8Array} 269 | */ 270 | flatbuffers.Builder.prototype.asUint8Array = function() { 271 | return this.bb.bytes().subarray(this.bb.position(), this.bb.position() + this.offset()); 272 | }; 273 | 274 | /// @cond FLATBUFFERS_INTERNAL 275 | /** 276 | * Prepare to write an element of `size` after `additional_bytes` have been 277 | * written, e.g. if you write a string, you need to align such the int length 278 | * field is aligned to 4 bytes, and the string data follows it directly. If all 279 | * you need to do is alignment, `additional_bytes` will be 0. 280 | * 281 | * @param {number} size This is the of the new element to write 282 | * @param {number} additional_bytes The padding size 283 | */ 284 | flatbuffers.Builder.prototype.prep = function(size, additional_bytes) { 285 | // Track the biggest thing we've ever aligned to. 286 | if (size > this.minalign) { 287 | this.minalign = size; 288 | } 289 | 290 | // Find the amount of alignment needed such that `size` is properly 291 | // aligned after `additional_bytes` 292 | var align_size = ((~(this.bb.capacity() - this.space + additional_bytes)) + 1) & (size - 1); 293 | 294 | // Reallocate the buffer if needed. 295 | while (this.space < align_size + size + additional_bytes) { 296 | var old_buf_size = this.bb.capacity(); 297 | this.bb = flatbuffers.Builder.growByteBuffer(this.bb); 298 | this.space += this.bb.capacity() - old_buf_size; 299 | } 300 | 301 | this.pad(align_size); 302 | }; 303 | 304 | /** 305 | * @param {number} byte_size 306 | */ 307 | flatbuffers.Builder.prototype.pad = function(byte_size) { 308 | for (var i = 0; i < byte_size; i++) { 309 | this.bb.writeInt8(--this.space, 0); 310 | } 311 | }; 312 | 313 | /** 314 | * @param {number} value 315 | */ 316 | flatbuffers.Builder.prototype.writeInt8 = function(value) { 317 | this.bb.writeInt8(this.space -= 1, value); 318 | }; 319 | 320 | /** 321 | * @param {number} value 322 | */ 323 | flatbuffers.Builder.prototype.writeInt16 = function(value) { 324 | this.bb.writeInt16(this.space -= 2, value); 325 | }; 326 | 327 | /** 328 | * @param {number} value 329 | */ 330 | flatbuffers.Builder.prototype.writeInt32 = function(value) { 331 | this.bb.writeInt32(this.space -= 4, value); 332 | }; 333 | 334 | /** 335 | * @param {flatbuffers.Long} value 336 | */ 337 | flatbuffers.Builder.prototype.writeInt64 = function(value) { 338 | this.bb.writeInt64(this.space -= 8, value); 339 | }; 340 | 341 | /** 342 | * @param {number} value 343 | */ 344 | flatbuffers.Builder.prototype.writeFloat32 = function(value) { 345 | this.bb.writeFloat32(this.space -= 4, value); 346 | }; 347 | 348 | /** 349 | * @param {number} value 350 | */ 351 | flatbuffers.Builder.prototype.writeFloat64 = function(value) { 352 | this.bb.writeFloat64(this.space -= 8, value); 353 | }; 354 | /// @endcond 355 | 356 | /** 357 | * Add an `int8` to the buffer, properly aligned, and grows the buffer (if necessary). 358 | * @param {number} value The `int8` to add the the buffer. 359 | */ 360 | flatbuffers.Builder.prototype.addInt8 = function(value) { 361 | this.prep(1, 0); 362 | this.writeInt8(value); 363 | }; 364 | 365 | /** 366 | * Add an `int16` to the buffer, properly aligned, and grows the buffer (if necessary). 367 | * @param {number} value The `int16` to add the the buffer. 368 | */ 369 | flatbuffers.Builder.prototype.addInt16 = function(value) { 370 | this.prep(2, 0); 371 | this.writeInt16(value); 372 | }; 373 | 374 | /** 375 | * Add an `int32` to the buffer, properly aligned, and grows the buffer (if necessary). 376 | * @param {number} value The `int32` to add the the buffer. 377 | */ 378 | flatbuffers.Builder.prototype.addInt32 = function(value) { 379 | this.prep(4, 0); 380 | this.writeInt32(value); 381 | }; 382 | 383 | /** 384 | * Add an `int64` to the buffer, properly aligned, and grows the buffer (if necessary). 385 | * @param {flatbuffers.Long} value The `int64` to add the the buffer. 386 | */ 387 | flatbuffers.Builder.prototype.addInt64 = function(value) { 388 | this.prep(8, 0); 389 | this.writeInt64(value); 390 | }; 391 | 392 | /** 393 | * Add a `float32` to the buffer, properly aligned, and grows the buffer (if necessary). 394 | * @param {number} value The `float32` to add the the buffer. 395 | */ 396 | flatbuffers.Builder.prototype.addFloat32 = function(value) { 397 | this.prep(4, 0); 398 | this.writeFloat32(value); 399 | }; 400 | 401 | /** 402 | * Add a `float64` to the buffer, properly aligned, and grows the buffer (if necessary). 403 | * @param {number} value The `float64` to add the the buffer. 404 | */ 405 | flatbuffers.Builder.prototype.addFloat64 = function(value) { 406 | this.prep(8, 0); 407 | this.writeFloat64(value); 408 | }; 409 | 410 | /// @cond FLATBUFFERS_INTERNAL 411 | /** 412 | * @param {number} voffset 413 | * @param {number} value 414 | * @param {number} defaultValue 415 | */ 416 | flatbuffers.Builder.prototype.addFieldInt8 = function(voffset, value, defaultValue) { 417 | if (this.force_defaults || value != defaultValue) { 418 | this.addInt8(value); 419 | this.slot(voffset); 420 | } 421 | }; 422 | 423 | /** 424 | * @param {number} voffset 425 | * @param {number} value 426 | * @param {number} defaultValue 427 | */ 428 | flatbuffers.Builder.prototype.addFieldInt16 = function(voffset, value, defaultValue) { 429 | if (this.force_defaults || value != defaultValue) { 430 | this.addInt16(value); 431 | this.slot(voffset); 432 | } 433 | }; 434 | 435 | /** 436 | * @param {number} voffset 437 | * @param {number} value 438 | * @param {number} defaultValue 439 | */ 440 | flatbuffers.Builder.prototype.addFieldInt32 = function(voffset, value, defaultValue) { 441 | if (this.force_defaults || value != defaultValue) { 442 | this.addInt32(value); 443 | this.slot(voffset); 444 | } 445 | }; 446 | 447 | /** 448 | * @param {number} voffset 449 | * @param {flatbuffers.Long} value 450 | * @param {flatbuffers.Long} defaultValue 451 | */ 452 | flatbuffers.Builder.prototype.addFieldInt64 = function(voffset, value, defaultValue) { 453 | if (this.force_defaults || !value.equals(defaultValue)) { 454 | this.addInt64(value); 455 | this.slot(voffset); 456 | } 457 | }; 458 | 459 | /** 460 | * @param {number} voffset 461 | * @param {number} value 462 | * @param {number} defaultValue 463 | */ 464 | flatbuffers.Builder.prototype.addFieldFloat32 = function(voffset, value, defaultValue) { 465 | if (this.force_defaults || value != defaultValue) { 466 | this.addFloat32(value); 467 | this.slot(voffset); 468 | } 469 | }; 470 | 471 | /** 472 | * @param {number} voffset 473 | * @param {number} value 474 | * @param {number} defaultValue 475 | */ 476 | flatbuffers.Builder.prototype.addFieldFloat64 = function(voffset, value, defaultValue) { 477 | if (this.force_defaults || value != defaultValue) { 478 | this.addFloat64(value); 479 | this.slot(voffset); 480 | } 481 | }; 482 | 483 | /** 484 | * @param {number} voffset 485 | * @param {flatbuffers.Offset} value 486 | * @param {flatbuffers.Offset} defaultValue 487 | */ 488 | flatbuffers.Builder.prototype.addFieldOffset = function(voffset, value, defaultValue) { 489 | if (this.force_defaults || value != defaultValue) { 490 | this.addOffset(value); 491 | this.slot(voffset); 492 | } 493 | }; 494 | 495 | /** 496 | * Structs are stored inline, so nothing additional is being added. `d` is always 0. 497 | * 498 | * @param {number} voffset 499 | * @param {flatbuffers.Offset} value 500 | * @param {flatbuffers.Offset} defaultValue 501 | */ 502 | flatbuffers.Builder.prototype.addFieldStruct = function(voffset, value, defaultValue) { 503 | if (value != defaultValue) { 504 | this.nested(value); 505 | this.slot(voffset); 506 | } 507 | }; 508 | 509 | /** 510 | * Structures are always stored inline, they need to be created right 511 | * where they're used. You'll get this assertion failure if you 512 | * created it elsewhere. 513 | * 514 | * @param {flatbuffers.Offset} obj The offset of the created object 515 | */ 516 | flatbuffers.Builder.prototype.nested = function(obj) { 517 | if (obj != this.offset()) { 518 | throw new Error('FlatBuffers: struct must be serialized inline.'); 519 | } 520 | }; 521 | 522 | /** 523 | * Should not be creating any other object, string or vector 524 | * while an object is being constructed 525 | */ 526 | flatbuffers.Builder.prototype.notNested = function() { 527 | if (this.isNested) { 528 | throw new Error('FlatBuffers: object serialization must not be nested.'); 529 | } 530 | }; 531 | 532 | /** 533 | * Set the current vtable at `voffset` to the current location in the buffer. 534 | * 535 | * @param {number} voffset 536 | */ 537 | flatbuffers.Builder.prototype.slot = function(voffset) { 538 | this.vtable[voffset] = this.offset(); 539 | }; 540 | 541 | /** 542 | * @returns {flatbuffers.Offset} Offset relative to the end of the buffer. 543 | */ 544 | flatbuffers.Builder.prototype.offset = function() { 545 | return this.bb.capacity() - this.space; 546 | }; 547 | 548 | /** 549 | * Doubles the size of the backing ByteBuffer and copies the old data towards 550 | * the end of the new buffer (since we build the buffer backwards). 551 | * 552 | * @param {flatbuffers.ByteBuffer} bb The current buffer with the existing data 553 | * @returns {flatbuffers.ByteBuffer} A new byte buffer with the old data copied 554 | * to it. The data is located at the end of the buffer. 555 | * 556 | * uint8Array.set() formally takes {Array|ArrayBufferView}, so to pass 557 | * it a uint8Array we need to suppress the type check: 558 | * @suppress {checkTypes} 559 | */ 560 | flatbuffers.Builder.growByteBuffer = function(bb) { 561 | var old_buf_size = bb.capacity(); 562 | 563 | // Ensure we don't grow beyond what fits in an int. 564 | if (old_buf_size & 0xC0000000) { 565 | throw new Error('FlatBuffers: cannot grow buffer beyond 2 gigabytes.'); 566 | } 567 | 568 | var new_buf_size = old_buf_size << 1; 569 | var nbb = flatbuffers.ByteBuffer.allocate(new_buf_size); 570 | nbb.setPosition(new_buf_size - old_buf_size); 571 | nbb.bytes().set(bb.bytes(), new_buf_size - old_buf_size); 572 | return nbb; 573 | }; 574 | /// @endcond 575 | 576 | /** 577 | * Adds on offset, relative to where it will be written. 578 | * 579 | * @param {flatbuffers.Offset} offset The offset to add. 580 | */ 581 | flatbuffers.Builder.prototype.addOffset = function(offset) { 582 | this.prep(flatbuffers.SIZEOF_INT, 0); // Ensure alignment is already done. 583 | this.writeInt32(this.offset() - offset + flatbuffers.SIZEOF_INT); 584 | }; 585 | 586 | /// @cond FLATBUFFERS_INTERNAL 587 | /** 588 | * Start encoding a new object in the buffer. Users will not usually need to 589 | * call this directly. The FlatBuffers compiler will generate helper methods 590 | * that call this method internally. 591 | * 592 | * @param {number} numfields 593 | */ 594 | flatbuffers.Builder.prototype.startObject = function(numfields) { 595 | this.notNested(); 596 | if (this.vtable == null) { 597 | this.vtable = []; 598 | } 599 | this.vtable_in_use = numfields; 600 | for (var i = 0; i < numfields; i++) { 601 | this.vtable[i] = 0; // This will push additional elements as needed 602 | } 603 | this.isNested = true; 604 | this.object_start = this.offset(); 605 | }; 606 | 607 | /** 608 | * Finish off writing the object that is under construction. 609 | * 610 | * @returns {flatbuffers.Offset} The offset to the object inside `dataBuffer` 611 | */ 612 | flatbuffers.Builder.prototype.endObject = function() { 613 | if (this.vtable == null || !this.isNested) { 614 | throw new Error('FlatBuffers: endObject called without startObject'); 615 | } 616 | 617 | this.addInt32(0); 618 | var vtableloc = this.offset(); 619 | 620 | // Trim trailing zeroes. 621 | var i = this.vtable_in_use - 1; 622 | for (; i >= 0 && this.vtable[i] == 0; i--) {} 623 | var trimmed_size = i + 1; 624 | 625 | // Write out the current vtable. 626 | for (; i >= 0; i--) { 627 | // Offset relative to the start of the table. 628 | this.addInt16(this.vtable[i] != 0 ? vtableloc - this.vtable[i] : 0); 629 | } 630 | 631 | var standard_fields = 2; // The fields below: 632 | this.addInt16(vtableloc - this.object_start); 633 | var len = (trimmed_size + standard_fields) * flatbuffers.SIZEOF_SHORT; 634 | this.addInt16(len); 635 | 636 | // Search for an existing vtable that matches the current one. 637 | var existing_vtable = 0; 638 | var vt1 = this.space; 639 | outer_loop: 640 | for (i = 0; i < this.vtables.length; i++) { 641 | var vt2 = this.bb.capacity() - this.vtables[i]; 642 | if (len == this.bb.readInt16(vt2)) { 643 | for (var j = flatbuffers.SIZEOF_SHORT; j < len; j += flatbuffers.SIZEOF_SHORT) { 644 | if (this.bb.readInt16(vt1 + j) != this.bb.readInt16(vt2 + j)) { 645 | continue outer_loop; 646 | } 647 | } 648 | existing_vtable = this.vtables[i]; 649 | break; 650 | } 651 | } 652 | 653 | if (existing_vtable) { 654 | // Found a match: 655 | // Remove the current vtable. 656 | this.space = this.bb.capacity() - vtableloc; 657 | 658 | // Point table to existing vtable. 659 | this.bb.writeInt32(this.space, existing_vtable - vtableloc); 660 | } else { 661 | // No match: 662 | // Add the location of the current vtable to the list of vtables. 663 | this.vtables.push(this.offset()); 664 | 665 | // Point table to current vtable. 666 | this.bb.writeInt32(this.bb.capacity() - vtableloc, this.offset() - vtableloc); 667 | } 668 | 669 | this.isNested = false; 670 | return vtableloc; 671 | }; 672 | /// @endcond 673 | 674 | /** 675 | * Finalize a buffer, poiting to the given `root_table`. 676 | * 677 | * @param {flatbuffers.Offset} root_table 678 | * @param {string=} opt_file_identifier 679 | */ 680 | flatbuffers.Builder.prototype.finish = function(root_table, opt_file_identifier) { 681 | if (opt_file_identifier) { 682 | var file_identifier = opt_file_identifier; 683 | this.prep(this.minalign, flatbuffers.SIZEOF_INT + 684 | flatbuffers.FILE_IDENTIFIER_LENGTH); 685 | if (file_identifier.length != flatbuffers.FILE_IDENTIFIER_LENGTH) { 686 | throw new Error('FlatBuffers: file identifier must be length ' + 687 | flatbuffers.FILE_IDENTIFIER_LENGTH); 688 | } 689 | for (var i = flatbuffers.FILE_IDENTIFIER_LENGTH - 1; i >= 0; i--) { 690 | this.writeInt8(file_identifier.charCodeAt(i)); 691 | } 692 | } 693 | this.prep(this.minalign, flatbuffers.SIZEOF_INT); 694 | this.addOffset(root_table); 695 | this.bb.setPosition(this.space); 696 | }; 697 | 698 | /// @cond FLATBUFFERS_INTERNAL 699 | /** 700 | * This checks a required field has been set in a given table that has 701 | * just been constructed. 702 | * 703 | * @param {flatbuffers.Offset} table 704 | * @param {number} field 705 | */ 706 | flatbuffers.Builder.prototype.requiredField = function(table, field) { 707 | var table_start = this.bb.capacity() - table; 708 | var vtable_start = table_start - this.bb.readInt32(table_start); 709 | var ok = this.bb.readInt16(vtable_start + field) != 0; 710 | 711 | // If this fails, the caller will show what field needs to be set. 712 | if (!ok) { 713 | throw new Error('FlatBuffers: field ' + field + ' must be set'); 714 | } 715 | }; 716 | 717 | /** 718 | * Start a new array/vector of objects. Users usually will not call 719 | * this directly. The FlatBuffers compiler will create a start/end 720 | * method for vector types in generated code. 721 | * 722 | * @param {number} elem_size The size of each element in the array 723 | * @param {number} num_elems The number of elements in the array 724 | * @param {number} alignment The alignment of the array 725 | */ 726 | flatbuffers.Builder.prototype.startVector = function(elem_size, num_elems, alignment) { 727 | this.notNested(); 728 | this.vector_num_elems = num_elems; 729 | this.prep(flatbuffers.SIZEOF_INT, elem_size * num_elems); 730 | this.prep(alignment, elem_size * num_elems); // Just in case alignment > int. 731 | }; 732 | 733 | /** 734 | * Finish off the creation of an array and all its elements. The array must be 735 | * created with `startVector`. 736 | * 737 | * @returns {flatbuffers.Offset} The offset at which the newly created array 738 | * starts. 739 | */ 740 | flatbuffers.Builder.prototype.endVector = function() { 741 | this.writeInt32(this.vector_num_elems); 742 | return this.offset(); 743 | }; 744 | /// @endcond 745 | 746 | /** 747 | * Encode the string `s` in the buffer using UTF-8. If a Uint8Array is passed 748 | * instead of a string, it is assumed to contain valid UTF-8 encoded data. 749 | * 750 | * @param {string|Uint8Array} s The string to encode 751 | * @return {flatbuffers.Offset} The offset in the buffer where the encoded string starts 752 | */ 753 | flatbuffers.Builder.prototype.createString = function(s) { 754 | if (s instanceof Uint8Array) { 755 | var utf8 = s; 756 | } else { 757 | var utf8 = []; 758 | var i = 0; 759 | 760 | while (i < s.length) { 761 | var codePoint; 762 | 763 | // Decode UTF-16 764 | var a = s.charCodeAt(i++); 765 | if (a < 0xD800 || a >= 0xDC00) { 766 | codePoint = a; 767 | } else { 768 | var b = s.charCodeAt(i++); 769 | codePoint = (a << 10) + b + (0x10000 - (0xD800 << 10) - 0xDC00); 770 | } 771 | 772 | // Encode UTF-8 773 | if (codePoint < 0x80) { 774 | utf8.push(codePoint); 775 | } else { 776 | if (codePoint < 0x800) { 777 | utf8.push(((codePoint >> 6) & 0x1F) | 0xC0); 778 | } else { 779 | if (codePoint < 0x10000) { 780 | utf8.push(((codePoint >> 12) & 0x0F) | 0xE0); 781 | } else { 782 | utf8.push( 783 | ((codePoint >> 18) & 0x07) | 0xF0, 784 | ((codePoint >> 12) & 0x3F) | 0x80); 785 | } 786 | utf8.push(((codePoint >> 6) & 0x3F) | 0x80); 787 | } 788 | utf8.push((codePoint & 0x3F) | 0x80); 789 | } 790 | } 791 | } 792 | 793 | this.addInt8(0); 794 | this.startVector(1, utf8.length, 1); 795 | this.bb.setPosition(this.space -= utf8.length); 796 | for (var i = 0, offset = this.space, bytes = this.bb.bytes(); i < utf8.length; i++) { 797 | bytes[offset++] = utf8[i]; 798 | } 799 | return this.endVector(); 800 | }; 801 | 802 | /** 803 | * A helper function to avoid generated code depending on this file directly. 804 | * 805 | * @param {number} low 806 | * @param {number} high 807 | * @returns {flatbuffers.Long} 808 | */ 809 | flatbuffers.Builder.prototype.createLong = function(low, high) { 810 | return flatbuffers.Long.create(low, high); 811 | }; 812 | //////////////////////////////////////////////////////////////////////////////// 813 | /// @cond FLATBUFFERS_INTERNAL 814 | /** 815 | * Create a new ByteBuffer with a given array of bytes (`Uint8Array`). 816 | * 817 | * @constructor 818 | * @param {Uint8Array} bytes 819 | */ 820 | flatbuffers.ByteBuffer = function(bytes) { 821 | /** 822 | * @type {Uint8Array} 823 | * @private 824 | */ 825 | this.bytes_ = bytes; 826 | 827 | /** 828 | * @type {number} 829 | * @private 830 | */ 831 | this.position_ = 0; 832 | 833 | }; 834 | 835 | /** 836 | * Create and allocate a new ByteBuffer with a given size. 837 | * 838 | * @param {number} byte_size 839 | * @returns {flatbuffers.ByteBuffer} 840 | */ 841 | flatbuffers.ByteBuffer.allocate = function(byte_size) { 842 | return new flatbuffers.ByteBuffer(new Uint8Array(byte_size)); 843 | }; 844 | 845 | flatbuffers.ByteBuffer.prototype.clear = function() { 846 | this.position_ = 0; 847 | }; 848 | 849 | /** 850 | * Get the underlying `Uint8Array`. 851 | * 852 | * @returns {Uint8Array} 853 | */ 854 | flatbuffers.ByteBuffer.prototype.bytes = function() { 855 | return this.bytes_; 856 | }; 857 | 858 | /** 859 | * Get the buffer's position. 860 | * 861 | * @returns {number} 862 | */ 863 | flatbuffers.ByteBuffer.prototype.position = function() { 864 | return this.position_; 865 | }; 866 | 867 | /** 868 | * Set the buffer's position. 869 | * 870 | * @param {number} position 871 | */ 872 | flatbuffers.ByteBuffer.prototype.setPosition = function(position) { 873 | this.position_ = position; 874 | }; 875 | 876 | /** 877 | * Get the buffer's capacity. 878 | * 879 | * @returns {number} 880 | */ 881 | flatbuffers.ByteBuffer.prototype.capacity = function() { 882 | return this.bytes_.length; 883 | }; 884 | 885 | /** 886 | * @param {number} offset 887 | * @returns {number} 888 | */ 889 | flatbuffers.ByteBuffer.prototype.readInt8 = function(offset) { 890 | return this.readUint8(offset) << 24 >> 24; 891 | }; 892 | 893 | /** 894 | * @param {number} offset 895 | * @returns {number} 896 | */ 897 | flatbuffers.ByteBuffer.prototype.readUint8 = function(offset) { 898 | return this.bytes_[offset]; 899 | }; 900 | 901 | /** 902 | * @param {number} offset 903 | * @returns {number} 904 | */ 905 | flatbuffers.ByteBuffer.prototype.readInt16 = function(offset) { 906 | return this.readUint16(offset) << 16 >> 16; 907 | }; 908 | 909 | /** 910 | * @param {number} offset 911 | * @returns {number} 912 | */ 913 | flatbuffers.ByteBuffer.prototype.readUint16 = function(offset) { 914 | return this.bytes_[offset] | this.bytes_[offset + 1] << 8; 915 | }; 916 | 917 | /** 918 | * @param {number} offset 919 | * @returns {number} 920 | */ 921 | flatbuffers.ByteBuffer.prototype.readInt32 = function(offset) { 922 | return this.bytes_[offset] | this.bytes_[offset + 1] << 8 | this.bytes_[offset + 2] << 16 | this.bytes_[offset + 3] << 24; 923 | }; 924 | 925 | /** 926 | * @param {number} offset 927 | * @returns {number} 928 | */ 929 | flatbuffers.ByteBuffer.prototype.readUint32 = function(offset) { 930 | return this.readInt32(offset) >>> 0; 931 | }; 932 | 933 | /** 934 | * @param {number} offset 935 | * @returns {flatbuffers.Long} 936 | */ 937 | flatbuffers.ByteBuffer.prototype.readInt64 = function(offset) { 938 | return new flatbuffers.Long(this.readInt32(offset), this.readInt32(offset + 4)); 939 | }; 940 | 941 | /** 942 | * @param {number} offset 943 | * @returns {flatbuffers.Long} 944 | */ 945 | flatbuffers.ByteBuffer.prototype.readUint64 = function(offset) { 946 | return new flatbuffers.Long(this.readUint32(offset), this.readUint32(offset + 4)); 947 | }; 948 | 949 | /** 950 | * @param {number} offset 951 | * @returns {number} 952 | */ 953 | flatbuffers.ByteBuffer.prototype.readFloat32 = function(offset) { 954 | flatbuffers.int32[0] = this.readInt32(offset); 955 | return flatbuffers.float32[0]; 956 | }; 957 | 958 | /** 959 | * @param {number} offset 960 | * @returns {number} 961 | */ 962 | flatbuffers.ByteBuffer.prototype.readFloat64 = function(offset) { 963 | flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1] = this.readInt32(offset); 964 | flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0] = this.readInt32(offset + 4); 965 | return flatbuffers.float64[0]; 966 | }; 967 | 968 | /** 969 | * @param {number} offset 970 | * @param {number|boolean} value 971 | */ 972 | flatbuffers.ByteBuffer.prototype.writeInt8 = function(offset, value) { 973 | this.bytes_[offset] = /** @type {number} */(value); 974 | }; 975 | 976 | /** 977 | * @param {number} offset 978 | * @param {number} value 979 | */ 980 | flatbuffers.ByteBuffer.prototype.writeUint8 = function(offset, value) { 981 | this.bytes_[offset] = value; 982 | }; 983 | 984 | /** 985 | * @param {number} offset 986 | * @param {number} value 987 | */ 988 | flatbuffers.ByteBuffer.prototype.writeInt16 = function(offset, value) { 989 | this.bytes_[offset] = value; 990 | this.bytes_[offset + 1] = value >> 8; 991 | }; 992 | 993 | /** 994 | * @param {number} offset 995 | * @param {number} value 996 | */ 997 | flatbuffers.ByteBuffer.prototype.writeUint16 = function(offset, value) { 998 | this.bytes_[offset] = value; 999 | this.bytes_[offset + 1] = value >> 8; 1000 | }; 1001 | 1002 | /** 1003 | * @param {number} offset 1004 | * @param {number} value 1005 | */ 1006 | flatbuffers.ByteBuffer.prototype.writeInt32 = function(offset, value) { 1007 | this.bytes_[offset] = value; 1008 | this.bytes_[offset + 1] = value >> 8; 1009 | this.bytes_[offset + 2] = value >> 16; 1010 | this.bytes_[offset + 3] = value >> 24; 1011 | }; 1012 | 1013 | /** 1014 | * @param {number} offset 1015 | * @param {number} value 1016 | */ 1017 | flatbuffers.ByteBuffer.prototype.writeUint32 = function(offset, value) { 1018 | this.bytes_[offset] = value; 1019 | this.bytes_[offset + 1] = value >> 8; 1020 | this.bytes_[offset + 2] = value >> 16; 1021 | this.bytes_[offset + 3] = value >> 24; 1022 | }; 1023 | 1024 | /** 1025 | * @param {number} offset 1026 | * @param {flatbuffers.Long} value 1027 | */ 1028 | flatbuffers.ByteBuffer.prototype.writeInt64 = function(offset, value) { 1029 | this.writeInt32(offset, value.low); 1030 | this.writeInt32(offset + 4, value.high); 1031 | }; 1032 | 1033 | /** 1034 | * @param {number} offset 1035 | * @param {flatbuffers.Long} value 1036 | */ 1037 | flatbuffers.ByteBuffer.prototype.writeUint64 = function(offset, value) { 1038 | this.writeUint32(offset, value.low); 1039 | this.writeUint32(offset + 4, value.high); 1040 | }; 1041 | 1042 | /** 1043 | * @param {number} offset 1044 | * @param {number} value 1045 | */ 1046 | flatbuffers.ByteBuffer.prototype.writeFloat32 = function(offset, value) { 1047 | flatbuffers.float32[0] = value; 1048 | this.writeInt32(offset, flatbuffers.int32[0]); 1049 | }; 1050 | 1051 | /** 1052 | * @param {number} offset 1053 | * @param {number} value 1054 | */ 1055 | flatbuffers.ByteBuffer.prototype.writeFloat64 = function(offset, value) { 1056 | flatbuffers.float64[0] = value; 1057 | this.writeInt32(offset, flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1]); 1058 | this.writeInt32(offset + 4, flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0]); 1059 | }; 1060 | 1061 | /** 1062 | * Return the file identifier. Behavior is undefined for FlatBuffers whose 1063 | * schema does not include a file_identifier (likely points at padding or the 1064 | * start of a the root vtable). 1065 | * @returns {string} 1066 | */ 1067 | flatbuffers.ByteBuffer.prototype.getBufferIdentifier = function() { 1068 | if (this.bytes_.length < this.position_ + flatbuffers.SIZEOF_INT + 1069 | flatbuffers.FILE_IDENTIFIER_LENGTH) { 1070 | throw new Error( 1071 | 'FlatBuffers: ByteBuffer is too short to contain an identifier.'); 1072 | } 1073 | var result = ""; 1074 | for (var i = 0; i < flatbuffers.FILE_IDENTIFIER_LENGTH; i++) { 1075 | result += String.fromCharCode( 1076 | this.readInt8(this.position_ + flatbuffers.SIZEOF_INT + i)); 1077 | } 1078 | return result; 1079 | }; 1080 | 1081 | /** 1082 | * Look up a field in the vtable, return an offset into the object, or 0 if the 1083 | * field is not present. 1084 | * 1085 | * @param {number} bb_pos 1086 | * @param {number} vtable_offset 1087 | * @returns {number} 1088 | */ 1089 | flatbuffers.ByteBuffer.prototype.__offset = function(bb_pos, vtable_offset) { 1090 | var vtable = bb_pos - this.readInt32(bb_pos); 1091 | return vtable_offset < this.readInt16(vtable) ? this.readInt16(vtable + vtable_offset) : 0; 1092 | }; 1093 | 1094 | /** 1095 | * Initialize any Table-derived type to point to the union at the given offset. 1096 | * 1097 | * @param {flatbuffers.Table} t 1098 | * @param {number} offset 1099 | * @returns {flatbuffers.Table} 1100 | */ 1101 | flatbuffers.ByteBuffer.prototype.__union = function(t, offset) { 1102 | t.bb_pos = offset + this.readInt32(offset); 1103 | t.bb = this; 1104 | return t; 1105 | }; 1106 | 1107 | /** 1108 | * Create a JavaScript string from UTF-8 data stored inside the FlatBuffer. 1109 | * This allocates a new string and converts to wide chars upon each access. 1110 | * 1111 | * To avoid the conversion to UTF-16, pass flatbuffers.Encoding.UTF8_BYTES as 1112 | * the "optionalEncoding" argument. This is useful for avoiding conversion to 1113 | * and from UTF-16 when the data will just be packaged back up in another 1114 | * FlatBuffer later on. 1115 | * 1116 | * @param {number} offset 1117 | * @param {flatbuffers.Encoding=} opt_encoding Defaults to UTF16_STRING 1118 | * @returns {string|Uint8Array} 1119 | */ 1120 | flatbuffers.ByteBuffer.prototype.__string = function(offset, opt_encoding) { 1121 | offset += this.readInt32(offset); 1122 | 1123 | var length = this.readInt32(offset); 1124 | var result = ''; 1125 | var i = 0; 1126 | 1127 | offset += flatbuffers.SIZEOF_INT; 1128 | 1129 | if (opt_encoding === flatbuffers.Encoding.UTF8_BYTES) { 1130 | return this.bytes_.subarray(offset, offset + length); 1131 | } 1132 | 1133 | while (i < length) { 1134 | var codePoint; 1135 | 1136 | // Decode UTF-8 1137 | var a = this.readUint8(offset + i++); 1138 | if (a < 0xC0) { 1139 | codePoint = a; 1140 | } else { 1141 | var b = this.readUint8(offset + i++); 1142 | if (a < 0xE0) { 1143 | codePoint = 1144 | ((a & 0x1F) << 6) | 1145 | (b & 0x3F); 1146 | } else { 1147 | var c = this.readUint8(offset + i++); 1148 | if (a < 0xF0) { 1149 | codePoint = 1150 | ((a & 0x0F) << 12) | 1151 | ((b & 0x3F) << 6) | 1152 | (c & 0x3F); 1153 | } else { 1154 | var d = this.readUint8(offset + i++); 1155 | codePoint = 1156 | ((a & 0x07) << 18) | 1157 | ((b & 0x3F) << 12) | 1158 | ((c & 0x3F) << 6) | 1159 | (d & 0x3F); 1160 | } 1161 | } 1162 | } 1163 | 1164 | // Encode UTF-16 1165 | if (codePoint < 0x10000) { 1166 | result += String.fromCharCode(codePoint); 1167 | } else { 1168 | codePoint -= 0x10000; 1169 | result += String.fromCharCode( 1170 | (codePoint >> 10) + 0xD800, 1171 | (codePoint & ((1 << 10) - 1)) + 0xDC00); 1172 | } 1173 | } 1174 | 1175 | return result; 1176 | }; 1177 | 1178 | /** 1179 | * Retrieve the relative offset stored at "offset" 1180 | * @param {number} offset 1181 | * @returns {number} 1182 | */ 1183 | flatbuffers.ByteBuffer.prototype.__indirect = function(offset) { 1184 | return offset + this.readInt32(offset); 1185 | }; 1186 | 1187 | /** 1188 | * Get the start of data of a vector whose offset is stored at "offset" in this object. 1189 | * 1190 | * @param {number} offset 1191 | * @returns {number} 1192 | */ 1193 | flatbuffers.ByteBuffer.prototype.__vector = function(offset) { 1194 | return offset + this.readInt32(offset) + flatbuffers.SIZEOF_INT; // data starts after the length 1195 | }; 1196 | 1197 | /** 1198 | * Get the length of a vector whose offset is stored at "offset" in this object. 1199 | * 1200 | * @param {number} offset 1201 | * @returns {number} 1202 | */ 1203 | flatbuffers.ByteBuffer.prototype.__vector_len = function(offset) { 1204 | return this.readInt32(offset + this.readInt32(offset)); 1205 | }; 1206 | 1207 | /** 1208 | * @param {string} ident 1209 | * @returns {boolean} 1210 | */ 1211 | flatbuffers.ByteBuffer.prototype.__has_identifier = function(ident) { 1212 | if (ident.length != flatbuffers.FILE_IDENTIFIER_LENGTH) { 1213 | throw new Error('FlatBuffers: file identifier must be length ' + 1214 | flatbuffers.FILE_IDENTIFIER_LENGTH); 1215 | } 1216 | for (var i = 0; i < flatbuffers.FILE_IDENTIFIER_LENGTH; i++) { 1217 | if (ident.charCodeAt(i) != this.readInt8(this.position_ + flatbuffers.SIZEOF_INT + i)) { 1218 | return false; 1219 | } 1220 | } 1221 | return true; 1222 | }; 1223 | 1224 | /** 1225 | * A helper function to avoid generated code depending on this file directly. 1226 | * 1227 | * @param {number} low 1228 | * @param {number} high 1229 | * @returns {flatbuffers.Long} 1230 | */ 1231 | flatbuffers.ByteBuffer.prototype.createLong = function(low, high) { 1232 | return flatbuffers.Long.create(low, high); 1233 | }; 1234 | 1235 | // Exports for Node.js and RequireJS 1236 | this.flatbuffers = flatbuffers; 1237 | 1238 | /// @endcond 1239 | /// @} -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | var flatbuffers = require('./flatbuffers').flatbuffers; 2 | var reflection = require('./reflection_generated').reflection; 3 | 4 | var baseTypes = [ 5 | 'None', 6 | 'UType', 7 | 'Bool', 8 | 'Byte', 9 | 'UByte', 10 | 'Short', 11 | 'UShort', 12 | 'Int', 13 | 'UInt', 14 | 'Long', 15 | 'ULong', 16 | 'Float', 17 | 'Double', 18 | 'String', 19 | 'Vector', 20 | 'Obj', 21 | 'Union', 22 | ]; 23 | 24 | var scalarSizes = { 25 | 'Bool': 1, 26 | 'Byte': 1, 27 | 'UByte': 1, 28 | 'Short': 2, 29 | 'UShort': 2, 30 | 'Int': 4, 31 | 'UInt': 4, 32 | 'Long': 8, 33 | 'ULong': 8, 34 | 'Float': 4, 35 | 'Double': 8, 36 | }; 37 | 38 | var scalarGetters = { 39 | 'Bool': '!!bb.readUint8', 40 | 'Byte': 'bb.readInt8', 41 | 'UByte': 'bb.readUint8', 42 | 'Short': 'bb.readInt16', 43 | 'UShort': 'bb.readUint16', 44 | 'Int': 'bb.readInt32', 45 | 'UInt': 'bb.readUint32', 46 | 'Long': 'bb.readInt64', 47 | 'ULong': 'bb.readUint64', 48 | 'Float': 'bb.readFloat32', 49 | 'Double': 'bb.readFloat64', 50 | }; 51 | 52 | var scalarSetters = { 53 | 'Bool': 'fbb.writeInt8', 54 | 'Byte': 'fbb.writeInt8', 55 | 'UByte': 'fbb.writeInt8', 56 | 'Short': 'fbb.writeInt16', 57 | 'UShort': 'fbb.writeInt16', 58 | 'Int': 'fbb.writeInt32', 59 | 'UInt': 'fbb.writeInt32', 60 | 'Float': 'fbb.writeFloat32', 61 | 'Double': 'fbb.writeFloat64', 62 | }; 63 | 64 | var scalarAdders = { 65 | 'Bool': 'fbb.addFieldInt8', 66 | 'Byte': 'fbb.addFieldInt8', 67 | 'UByte': 'fbb.addFieldInt8', 68 | 'Short': 'fbb.addFieldInt16', 69 | 'UShort': 'fbb.addFieldInt16', 70 | 'Int': 'fbb.addFieldInt32', 71 | 'UInt': 'fbb.addFieldInt32', 72 | 'Float': 'fbb.addFieldFloat32', 73 | 'Double': 'fbb.addFieldFloat64', 74 | }; 75 | 76 | function notReached() { 77 | throw new Error('Internal error'); 78 | } 79 | 80 | function requireUint8Array(bytes) { 81 | if (bytes instanceof Uint8Array) { 82 | return bytes; 83 | } 84 | 85 | if (typeof Buffer !== 'undefined' && bytes instanceof Buffer) { 86 | return new Uint8Array(bytes); 87 | } 88 | 89 | throw new Error('Not a valid Uint8Array'); 90 | } 91 | 92 | function requireObject(json) { 93 | if (json instanceof Object) { 94 | return json; 95 | } 96 | 97 | throw new Error('Not a valid JSON object'); 98 | } 99 | 100 | function parseValue(integer, real, type) { 101 | switch (type.baseType) { 102 | case 'Bool': return !!integer.low; 103 | case 'Byte': return integer.low << 24 >> 24; 104 | case 'UByte': case 'UType': return integer.low & 0xFF; 105 | case 'Short': return integer.low << 16 >> 16; 106 | case 'UShort': return integer.low & 0xFFFF; 107 | case 'Int': return integer.low | 0; 108 | case 'UInt': return integer.low >>> 0; 109 | case 'Long': return { low: integer.low | 0, high: integer.high | 0 }; 110 | case 'ULong': return { low: integer.low >>> 0, high: integer.high >>> 0 }; 111 | case 'Float': case 'Double': return real; 112 | } 113 | 114 | return null; 115 | } 116 | 117 | function parseType(type) { 118 | return { 119 | baseType: baseTypes[type.baseType()], 120 | element: baseTypes[type.element()], 121 | index: type.index(), 122 | }; 123 | } 124 | 125 | function parseObject(object) { 126 | var result = { 127 | name: object.name(), 128 | isStruct: object.isStruct(), 129 | minalign: object.minalign(), 130 | bytesize: object.bytesize(), 131 | fields: [], 132 | }; 133 | 134 | for (var i = 0, fieldsLength = object.fieldsLength(); i < fieldsLength; i++) { 135 | var field = object.fields(i); 136 | var type = parseType(field.type()); 137 | 138 | result.fields.push({ 139 | name: field.name(), 140 | type: type, 141 | id: field.id(), 142 | offset: field.offset(), 143 | deprecated: field.deprecated(), 144 | required: field.required(), 145 | key: field.key(), 146 | default: parseValue(field.defaultInteger(), field.defaultReal(), type), 147 | }); 148 | } 149 | 150 | // Sort fields in order of id 151 | result.fields.sort(function(a, b) { 152 | return a.id - b.id; 153 | }); 154 | 155 | return result; 156 | } 157 | 158 | function parseEnum(enumDef) { 159 | var type = parseType(enumDef.underlyingType()); 160 | var result = { 161 | name: enumDef.name(), 162 | is_union: enumDef.isUnion(), 163 | underlying_type: type, 164 | values: [], 165 | }; 166 | 167 | for (var i = 0, valuesLength = enumDef.valuesLength(); i < valuesLength; i++) { 168 | var value = enumDef.values(i); 169 | var object = value.object(); 170 | 171 | result.values.push({ 172 | name: value.name(), 173 | value: parseValue(value.value(), 0, type), 174 | object: object === null ? null : parseObject(object), 175 | }); 176 | } 177 | 178 | // Sort values in order of value 179 | result.values.sort(function(a, b) { 180 | return a.value - b.value; 181 | }); 182 | 183 | return result; 184 | } 185 | 186 | exports.parseSchema = function(bytes) { 187 | var bb = new flatbuffers.ByteBuffer(requireUint8Array(bytes)); 188 | 189 | // Must conform to reflection.fbs 190 | if (!reflection.Schema.bufferHasIdentifier(bb)) { 191 | throw new Error('Not a valid binary FlatBuffers schema'); 192 | } 193 | 194 | var schema = reflection.Schema.getRootAsSchema(bb); 195 | var result = { 196 | fileIdent: schema.fileIdent(), 197 | fileExt: schema.fileExt(), 198 | rootTable: parseObject(schema.rootTable()), 199 | objects: [], 200 | enums: [], 201 | }; 202 | 203 | for (var i = 0, objectsLength = schema.objectsLength(); i < objectsLength; i++) { 204 | result.objects.push(parseObject(schema.objects(i))); 205 | } 206 | 207 | for (var i = 0, enumsLength = schema.enumsLength(); i < enumsLength; i++) { 208 | result.enums.push(parseEnum(schema.enums(i))); 209 | } 210 | 211 | return result; 212 | }; 213 | 214 | function compileEnumGenerator(schema, context, enumDef) { 215 | var key = 'enumMap' + enumDef.name; 216 | var code = ''; 217 | 218 | if (key in context) { 219 | return key; 220 | } 221 | 222 | var map = {}; 223 | 224 | for (var i = 0; i < enumDef.values.length; i++) { 225 | var value = enumDef.values[i]; 226 | map[value.name] = value.value; 227 | } 228 | 229 | context[key] = map; 230 | 231 | return key; 232 | } 233 | 234 | function compileObjectGenerator(schema, context, object) { 235 | var key = 'generate' + object.name; 236 | var code = ''; 237 | 238 | if (key in context) { 239 | return key; 240 | } 241 | 242 | context[key] = null; 243 | 244 | // Structs 245 | if (object.isStruct) { 246 | code += 'fbb.prep(' + object.minalign + ', ' + object.bytesize + ');\n'; 247 | 248 | // Write out fields backwards so they will be read in forwards 249 | for (var i = object.fields.length - 1; i >= 0; i--) { 250 | var field = object.fields[i]; 251 | var type = field.type; 252 | var baseType = type.baseType; 253 | var setter = scalarSetters[baseType]; 254 | var inlineSize = baseType === 'Obj' ? schema.objects[type.index].bytesize : scalarSizes[baseType]; 255 | var nextOffset = i + 1 < object.fields.length ? object.fields[i + 1].offset : object.bytesize; 256 | var padding = nextOffset - field.offset - inlineSize; 257 | 258 | // Padding after the value 259 | if (padding) { 260 | code += 'fbb.pad(' + padding + ');\n'; 261 | } 262 | 263 | // Scalars 264 | if (setter) { 265 | var enumDef = schema.enums[type.index]; 266 | if (enumDef) { 267 | var nested = compileEnumGenerator(schema, context, enumDef); 268 | code += setter + '(context.' + nested + '[json.' + field.name + ']);\n'; 269 | } else { 270 | code += setter + '(json.' + field.name + ');\n'; 271 | } 272 | } 273 | 274 | // Longs 275 | else if (baseType === 'Long' || baseType === 'ULong') { 276 | code += 'fbb.writeInt64(fbb.createLong(json.' + field.name + '.low, json.' + field.name + '.high));\n'; 277 | } 278 | 279 | // Structs 280 | else if (baseType === 'Obj') { 281 | var def = schema.objects[type.index]; 282 | var nested = compileObjectGenerator(schema, context, def); 283 | code += 'context.' + nested + '(fbb, context, json.' + field.name + ');\n'; 284 | } 285 | 286 | // Sanity check 287 | else { 288 | notReached(); 289 | } 290 | } 291 | 292 | code += 'return fbb.offset();\n'; 293 | } 294 | 295 | // Tables 296 | else { 297 | for (var i = 0; i < object.fields.length; i++) { 298 | var field = object.fields[i]; 299 | var type = field.type; 300 | var baseType = type.baseType; 301 | 302 | // Skip deprecated fields 303 | if (field.deprecated) { 304 | continue; 305 | } 306 | 307 | // Strings 308 | if (baseType === 'String') { 309 | code += 'var offset' + field.id + ' = json.' + field.name + ' ? fbb.createString(json.' + field.name + ') : 0;\n'; 310 | } 311 | 312 | // Tables 313 | else if (baseType === 'Obj' && !schema.objects[type.index].isStruct) { 314 | var def = schema.objects[type.index]; 315 | var nested = compileObjectGenerator(schema, context, def); 316 | code += 'var offset' + field.id + ' = json.' + field.name + ' ? context.' + nested + '(fbb, context, json.' + field.name + ') : 0;\n'; 317 | } 318 | 319 | // Vectors 320 | else if (baseType === 'Vector') { 321 | var element = type.element; 322 | var elementSetter = scalarSetters[element]; 323 | 324 | // Check value 325 | code += 'var values = json.' + field.name + ';\n'; 326 | code += 'var offset' + field.id + ' = 0;\n'; 327 | code += 'if (values && values.length) {\n'; 328 | 329 | // Vectors of strings 330 | if (element === 'String') { 331 | code += ' var offsets = [];\n'; 332 | code += ' for (var i = 0; i < values.length; i++) {\n'; 333 | code += ' offsets.push(fbb.createString(values[i]));\n'; 334 | code += ' }\n'; 335 | } 336 | 337 | // Vectors of tables 338 | else if (element === 'Obj' && !schema.objects[type.index].isStruct) { 339 | var def = schema.objects[type.index]; 340 | var nested = compileObjectGenerator(schema, context, def); 341 | code += ' var offsets = [];\n'; 342 | code += ' for (var i = 0; i < values.length; i++) {\n'; 343 | code += ' offsets.push(context.' + nested + '(fbb, context, values[i]));\n'; 344 | code += ' }\n'; 345 | } 346 | 347 | // Begin vector (write out elements backwards so they will be read in forwards) 348 | code += ' fbb.startVector(8, values.length, 4);\n'; 349 | code += ' for (var i = values.length - 1; i >= 0; i--) {\n'; 350 | 351 | // Vectors of scalars 352 | if (elementSetter) { 353 | var enumDef = schema.enums[type.index]; 354 | if (enumDef) { 355 | var nested = compileEnumGenerator(schema, context, enumDef); 356 | code += ' ' + elementSetter + '(context.' + nested + '[values[i]]);\n'; 357 | } else { 358 | code += ' ' + elementSetter + '(values[i]);\n'; 359 | } 360 | } 361 | 362 | // Vectors of longs 363 | else if (element === 'Long' || element === 'ULong') { 364 | code += ' fbb.writeInt64(fbb.createLong(values[i].low, values[i].high));\n'; 365 | } 366 | 367 | // Vectors of structs 368 | else if (element === 'Obj' && schema.objects[type.index].isStruct) { 369 | var def = schema.objects[type.index]; 370 | var nested = compileObjectGenerator(schema, context, def); 371 | code += ' context.' + nested + '(fbb, context, values[i]);\n'; 372 | } 373 | 374 | // Vectors of strings or tables 375 | else if (element === 'String' || element === 'Obj') { 376 | code += ' fbb.addOffset(offsets[i]);\n'; 377 | } 378 | 379 | // Sanity check 380 | else { 381 | notReached(); 382 | } 383 | 384 | // End loop 385 | code += ' }\n'; 386 | code += ' offset' + field.id + ' = fbb.endVector();\n'; 387 | code += '}\n'; 388 | } 389 | 390 | // Unions 391 | else if (baseType === 'Union') { 392 | throw new Error('Unions are not supported yet'); 393 | } 394 | } 395 | 396 | code += 'fbb.startObject(' + object.fields.length + ');\n'; 397 | 398 | for (var i = 0; i < object.fields.length; i++) { 399 | var field = object.fields[i]; 400 | var type = field.type; 401 | var baseType = type.baseType; 402 | var adder = scalarAdders[baseType]; 403 | 404 | // Skip deprecated fields 405 | if (field.deprecated) { 406 | continue; 407 | } 408 | 409 | // Scalars 410 | if (adder) { 411 | code += 'if (' + JSON.stringify(field.name) + ' in json) {\n'; 412 | var enumDef = schema.enums[type.index]; 413 | if (enumDef) { 414 | var nested = compileEnumGenerator(schema, context, enumDef); 415 | code += ' ' + adder + '(' + field.id + ', context.' + nested + '[json.' + field.name + '], ' + JSON.stringify(field.default) + ');\n'; 416 | } else { 417 | code += ' ' + adder + '(' + field.id + ', json.' + field.name + ', ' + JSON.stringify(field.default) + ');\n'; 418 | } 419 | code += '}\n'; 420 | } 421 | 422 | // Longs 423 | else if (baseType === 'Long' || baseType === 'ULong') { 424 | code += 'if (json.' + field.name + ') {\n'; 425 | code += ' fbb.addFieldInt64(' + field.id + ',\n'; 426 | code += ' fbb.createLong(json.' + field.name + '.low, json.' + field.name + '.high),\n'; 427 | code += ' fbb.createLong(' + field.default.low + ', ' + field.default.high + '));\n'; 428 | code += '}\n'; 429 | } 430 | 431 | // Structs 432 | else if (baseType === 'Obj' && schema.objects[type.index].isStruct) { 433 | var def = schema.objects[type.index]; 434 | var nested = compileObjectGenerator(schema, context, def); 435 | code += 'fbb.addFieldStruct(' + field.id + ', json.' + field.name + ' ? context.' + nested + '(fbb, context, json.' + field.name + ') : 0, 0);\n'; 436 | } 437 | 438 | // Strings or tables or vectors 439 | else if (baseType === 'String' || baseType === 'Obj' || baseType === 'Vector') { 440 | code += 'fbb.addFieldOffset(' + field.id + ', offset' + field.id + ', 0);\n'; 441 | } 442 | 443 | // Unions 444 | else if (baseType === 'UType' || baseType === 'Union') { 445 | throw new Error('Unions are not supported yet'); 446 | } 447 | 448 | // Sanity check 449 | else { 450 | notReached(); 451 | } 452 | } 453 | 454 | code += 'var offset = fbb.endObject();\n'; 455 | 456 | // Required fields 457 | for (var i = 0; i < object.fields.length; i++) { 458 | var field = object.fields[i]; 459 | if (field.required) { 460 | code += 'fbb.requiredField(offset, ' + field.offset + ', ' + JSON.stringify(field.name) + ');\n'; 461 | } 462 | } 463 | 464 | code += 'return offset;\n'; 465 | } 466 | 467 | // Compile this code using the JIT 468 | context[key] = new Function('fbb', 'context', 'json', code); 469 | 470 | return key; 471 | } 472 | 473 | function compileEnumParser(schema, context, enumDef) { 474 | var key = 'enumArray' + enumDef.name; 475 | var code = ''; 476 | 477 | if (key in context) { 478 | return key; 479 | } 480 | 481 | var array = []; 482 | 483 | for (var i = 0; i < enumDef.values.length; i++) { 484 | var value = enumDef.values[i]; 485 | array[value.value] = value.name; 486 | } 487 | 488 | context[key] = array; 489 | 490 | return key; 491 | } 492 | 493 | function compileObjectParser(schema, context, object) { 494 | var key = 'parse' + object.name; 495 | var code = ''; 496 | 497 | if (key in context) { 498 | return key; 499 | } 500 | 501 | context[key] = null; 502 | code += 'var json = {};\n'; 503 | 504 | // Structs 505 | if (object.isStruct) { 506 | for (var i = 0; i < object.fields.length; i++) { 507 | var field = object.fields[i]; 508 | var type = field.type; 509 | var baseType = type.baseType; 510 | var getter = scalarGetters[baseType]; 511 | 512 | // Scalars 513 | if (getter) { 514 | var value = getter + '(bb_pos + ' + field.offset + ')'; 515 | var enumDef = schema.enums[type.index]; 516 | if (enumDef) { 517 | var nested = compileEnumParser(schema, context, enumDef); 518 | code += 'json.' + field.name + ' = context.' + nested + '[' + value + '];\n'; 519 | } else { 520 | code += 'json.' + field.name + ' = ' + value + ';\n'; 521 | } 522 | } 523 | 524 | // Structs 525 | else if (baseType === 'Obj') { 526 | var def = schema.objects[type.index]; 527 | var nested = compileObjectParser(schema, context, def); 528 | code += 'json.' + field.name + ' = context.' + nested + '(bb, context, bb_pos + ' + field.offset + ');\n'; 529 | } 530 | 531 | // Sanity check 532 | else { 533 | notReached(); 534 | } 535 | } 536 | } 537 | 538 | // Tables 539 | else { 540 | for (var i = 0; i < object.fields.length; i++) { 541 | var field = object.fields[i]; 542 | var type = field.type; 543 | var baseType = type.baseType; 544 | var getter = scalarGetters[baseType]; 545 | 546 | // Skip deprecated fields 547 | if (field.deprecated) { 548 | continue; 549 | } 550 | 551 | // Common vtable offset lookup 552 | code += 'var offset = bb.__offset(bb_pos, ' + field.offset + ');\n'; 553 | 554 | // Scalars 555 | if (getter) { 556 | var value = 'offset ? ' + getter + '(bb_pos + offset) : ' + JSON.stringify(field.default); 557 | var enumDef = schema.enums[type.index]; 558 | if (enumDef) { 559 | var nested = compileEnumParser(schema, context, enumDef); 560 | code += 'json.' + field.name + ' = context.' + nested + '[' + value + '];\n'; 561 | } else { 562 | code += 'json.' + field.name + ' = ' + value + ';\n'; 563 | } 564 | } 565 | 566 | // Strings 567 | else if (baseType === 'String') { 568 | code += 'json.' + field.name + ' = offset ? bb.__string(bb_pos + offset) : null;\n'; 569 | } 570 | 571 | // Tables or structs 572 | else if (baseType === 'Obj') { 573 | var def = schema.objects[type.index]; 574 | var value = def.isStruct ? 'bb_pos + offset' : 'bb.__indirect(bb_pos + offset)'; 575 | var nested = compileObjectParser(schema, context, def); 576 | code += 'json.' + field.name + ' = offset ? context.' + nested + '(bb, context, ' + value + ') : null;\n'; 577 | } 578 | 579 | // Vectors 580 | else if (baseType === 'Vector') { 581 | var element = type.element; 582 | var elementGetter = scalarGetters[element]; 583 | 584 | // Begin loop 585 | code += 'var values = [];\n'; 586 | code += 'if (offset) {\n'; 587 | code += ' for (var i = 0, n = bb.__vector_len(bb_pos + offset), item = bb.__vector(bb_pos + offset); i < n; i++) {\n'; 588 | 589 | // Vectors of scalars 590 | if (elementGetter) { 591 | var enumDef = schema.enums[type.index]; 592 | if (enumDef) { 593 | var nested = compileEnumParser(schema, context, enumDef); 594 | code += ' values.push(context.' + nested + '[' + elementGetter + '(item)]);\n'; 595 | } else { 596 | code += ' values.push(' + elementGetter + '(item));\n'; 597 | } 598 | code += ' item += ' + scalarSizes[element] + ';\n'; 599 | } 600 | 601 | // Vectors of strings 602 | else if (element === 'String') { 603 | code += ' values.push(bb.__string(item));\n'; 604 | code += ' item += 4;\n'; 605 | } 606 | 607 | // Vectors of tables or structs 608 | else if (element === 'Obj') { 609 | var def = schema.objects[type.index]; 610 | var nested = compileObjectParser(schema, context, def); 611 | var value = def.isStruct ? 'item' : 'bb.__indirect(item)'; 612 | code += ' values.push(context.' + nested + '(bb, context, ' + value + '));\n'; 613 | code += ' item += ' + (def.bytesize || 4) + ';\n'; 614 | } 615 | 616 | // Sanity check 617 | else { 618 | notReached(); 619 | } 620 | 621 | // End loop 622 | code += ' }\n'; 623 | code += '}\n'; 624 | code += 'json.' + field.name + ' = values;\n'; 625 | } 626 | 627 | // Unions 628 | else if (baseType === 'UType' || baseType === 'Union') { 629 | throw new Error('Unions are not supported yet'); 630 | } 631 | 632 | // Sanity check 633 | else { 634 | notReached(); 635 | } 636 | } 637 | } 638 | 639 | // Compile this code using the JIT 640 | code += 'return json;\n'; 641 | context[key] = new Function('bb', 'context', 'bb_pos', code); 642 | 643 | return key; 644 | } 645 | 646 | exports.compileSchema = function(bytesOrJson) { 647 | var schema = bytesOrJson; 648 | var bytes; 649 | 650 | // Allow passing the schema either as raw bytes or as a pre-parsed object literal 651 | try { bytes = requireUint8Array(bytesOrJson); } catch (e) {} 652 | if (bytes) schema = exports.parseSchema(bytes); 653 | 654 | // Quick sanity check to catch mistakes 655 | if (!(schema instanceof Object) || !('rootTable' in schema)) { 656 | throw new Error('Not a valid schema'); 657 | } 658 | 659 | var context = {}; 660 | var rootGenerator = context[compileObjectGenerator(schema, context, schema.rootTable)]; 661 | var rootParser = context[compileObjectParser(schema, context, schema.rootTable)]; 662 | 663 | return { 664 | generate: function(json) { 665 | var fbb = new flatbuffers.Builder(0); 666 | fbb.finish(rootGenerator(fbb, context, requireObject(json)), schema.fileIdent); 667 | return fbb.asUint8Array(); 668 | }, 669 | 670 | parse: function(bytes) { 671 | var bb = new flatbuffers.ByteBuffer(requireUint8Array(bytes)); 672 | return rootParser(bb, context, bb.readInt32(bb.position()) + bb.position()); 673 | }, 674 | }; 675 | }; 676 | -------------------------------------------------------------------------------- /lib/reflection.fbs: -------------------------------------------------------------------------------- 1 | // This schema defines objects that represent a parsed schema, like 2 | // the binary version of a .fbs file. 3 | // This could be used to operate on unknown FlatBuffers at runtime. 4 | // It can even ... represent itself (!) 5 | 6 | namespace reflection; 7 | 8 | // These must correspond to the enum in idl.h. 9 | enum BaseType : byte { 10 | None, 11 | UType, 12 | Bool, 13 | Byte, 14 | UByte, 15 | Short, 16 | UShort, 17 | Int, 18 | UInt, 19 | Long, 20 | ULong, 21 | Float, 22 | Double, 23 | String, 24 | Vector, 25 | Obj, // Used for tables & structs. 26 | Union 27 | } 28 | 29 | table Type { 30 | base_type:BaseType; 31 | element:BaseType = None; // Only if base_type == Vector. 32 | index:int = -1; // If base_type == Object, index into "objects" below. 33 | // If base_type == Union, UnionType, or integral derived 34 | // from an enum, index into "enums" below. 35 | } 36 | 37 | table KeyValue { 38 | key:string (required, key); 39 | value:string; 40 | } 41 | 42 | table EnumVal { 43 | name:string (required); 44 | value:long (key); 45 | object:Object; // Will be deprecated in favor of union_type in the future. 46 | union_type:Type; 47 | } 48 | 49 | table Enum { 50 | name:string (required, key); 51 | values:[EnumVal] (required); // In order of their values. 52 | is_union:bool = false; 53 | underlying_type:Type (required); 54 | attributes:[KeyValue]; 55 | documentation:[string]; 56 | } 57 | 58 | table Field { 59 | name:string (required, key); 60 | type:Type (required); 61 | id:ushort; 62 | offset:ushort; // Offset into the vtable for tables, or into the struct. 63 | default_integer:long = 0; 64 | default_real:double = 0.0; 65 | deprecated:bool = false; 66 | required:bool = false; 67 | key:bool = false; 68 | attributes:[KeyValue]; 69 | documentation:[string]; 70 | } 71 | 72 | table Object { // Used for both tables and structs. 73 | name:string (required, key); 74 | fields:[Field] (required); // Sorted. 75 | is_struct:bool = false; 76 | minalign:int; 77 | bytesize:int; // For structs. 78 | attributes:[KeyValue]; 79 | documentation:[string]; 80 | } 81 | 82 | table Schema { 83 | objects:[Object] (required); // Sorted. 84 | enums:[Enum] (required); // Sorted. 85 | file_ident:string; 86 | file_ext:string; 87 | root_table:Object; 88 | } 89 | 90 | root_type Schema; 91 | 92 | file_identifier "BFBS"; 93 | file_extension "bfbs"; 94 | -------------------------------------------------------------------------------- /lib/reflection_generated.js: -------------------------------------------------------------------------------- 1 | // automatically generated by the FlatBuffers compiler, do not modify 2 | 3 | /** 4 | * @const 5 | * @namespace 6 | */ 7 | var reflection = reflection || {}; 8 | 9 | /** 10 | * @enum 11 | */ 12 | reflection.BaseType = { 13 | None: 0, 14 | UType: 1, 15 | Bool: 2, 16 | Byte: 3, 17 | UByte: 4, 18 | Short: 5, 19 | UShort: 6, 20 | Int: 7, 21 | UInt: 8, 22 | Long: 9, 23 | ULong: 10, 24 | Float: 11, 25 | Double: 12, 26 | String: 13, 27 | Vector: 14, 28 | Obj: 15, 29 | Union: 16 30 | }; 31 | 32 | /** 33 | * @constructor 34 | */ 35 | reflection.Type = function() { 36 | /** 37 | * @type {flatbuffers.ByteBuffer} 38 | */ 39 | this.bb = null; 40 | 41 | /** 42 | * @type {number} 43 | */ 44 | this.bb_pos = 0; 45 | }; 46 | 47 | /** 48 | * @param {number} i 49 | * @param {flatbuffers.ByteBuffer} bb 50 | * @returns {reflection.Type} 51 | */ 52 | reflection.Type.prototype.__init = function(i, bb) { 53 | this.bb_pos = i; 54 | this.bb = bb; 55 | return this; 56 | }; 57 | 58 | /** 59 | * @param {flatbuffers.ByteBuffer} bb 60 | * @param {reflection.Type=} obj 61 | * @returns {reflection.Type} 62 | */ 63 | reflection.Type.getRootAsType = function(bb, obj) { 64 | return (obj || new reflection.Type).__init(bb.readInt32(bb.position()) + bb.position(), bb); 65 | }; 66 | 67 | /** 68 | * @returns {reflection.BaseType} 69 | */ 70 | reflection.Type.prototype.baseType = function() { 71 | var offset = this.bb.__offset(this.bb_pos, 4); 72 | return offset ? /** @type {reflection.BaseType} */ (this.bb.readInt8(this.bb_pos + offset)) : reflection.BaseType.None; 73 | }; 74 | 75 | /** 76 | * @returns {reflection.BaseType} 77 | */ 78 | reflection.Type.prototype.element = function() { 79 | var offset = this.bb.__offset(this.bb_pos, 6); 80 | return offset ? /** @type {reflection.BaseType} */ (this.bb.readInt8(this.bb_pos + offset)) : reflection.BaseType.None; 81 | }; 82 | 83 | /** 84 | * @returns {number} 85 | */ 86 | reflection.Type.prototype.index = function() { 87 | var offset = this.bb.__offset(this.bb_pos, 8); 88 | return offset ? this.bb.readInt32(this.bb_pos + offset) : -1; 89 | }; 90 | 91 | /** 92 | * @param {flatbuffers.Builder} builder 93 | */ 94 | reflection.Type.startType = function(builder) { 95 | builder.startObject(3); 96 | }; 97 | 98 | /** 99 | * @param {flatbuffers.Builder} builder 100 | * @param {reflection.BaseType} baseType 101 | */ 102 | reflection.Type.addBaseType = function(builder, baseType) { 103 | builder.addFieldInt8(0, baseType, reflection.BaseType.None); 104 | }; 105 | 106 | /** 107 | * @param {flatbuffers.Builder} builder 108 | * @param {reflection.BaseType} element 109 | */ 110 | reflection.Type.addElement = function(builder, element) { 111 | builder.addFieldInt8(1, element, reflection.BaseType.None); 112 | }; 113 | 114 | /** 115 | * @param {flatbuffers.Builder} builder 116 | * @param {number} index 117 | */ 118 | reflection.Type.addIndex = function(builder, index) { 119 | builder.addFieldInt32(2, index, -1); 120 | }; 121 | 122 | /** 123 | * @param {flatbuffers.Builder} builder 124 | * @returns {flatbuffers.Offset} 125 | */ 126 | reflection.Type.endType = function(builder) { 127 | var offset = builder.endObject(); 128 | return offset; 129 | }; 130 | 131 | /** 132 | * @constructor 133 | */ 134 | reflection.KeyValue = function() { 135 | /** 136 | * @type {flatbuffers.ByteBuffer} 137 | */ 138 | this.bb = null; 139 | 140 | /** 141 | * @type {number} 142 | */ 143 | this.bb_pos = 0; 144 | }; 145 | 146 | /** 147 | * @param {number} i 148 | * @param {flatbuffers.ByteBuffer} bb 149 | * @returns {reflection.KeyValue} 150 | */ 151 | reflection.KeyValue.prototype.__init = function(i, bb) { 152 | this.bb_pos = i; 153 | this.bb = bb; 154 | return this; 155 | }; 156 | 157 | /** 158 | * @param {flatbuffers.ByteBuffer} bb 159 | * @param {reflection.KeyValue=} obj 160 | * @returns {reflection.KeyValue} 161 | */ 162 | reflection.KeyValue.getRootAsKeyValue = function(bb, obj) { 163 | return (obj || new reflection.KeyValue).__init(bb.readInt32(bb.position()) + bb.position(), bb); 164 | }; 165 | 166 | /** 167 | * @param {flatbuffers.Encoding=} optionalEncoding 168 | * @returns {string|Uint8Array|null} 169 | */ 170 | reflection.KeyValue.prototype.key = function(optionalEncoding) { 171 | var offset = this.bb.__offset(this.bb_pos, 4); 172 | return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; 173 | }; 174 | 175 | /** 176 | * @param {flatbuffers.Encoding=} optionalEncoding 177 | * @returns {string|Uint8Array|null} 178 | */ 179 | reflection.KeyValue.prototype.value = function(optionalEncoding) { 180 | var offset = this.bb.__offset(this.bb_pos, 6); 181 | return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; 182 | }; 183 | 184 | /** 185 | * @param {flatbuffers.Builder} builder 186 | */ 187 | reflection.KeyValue.startKeyValue = function(builder) { 188 | builder.startObject(2); 189 | }; 190 | 191 | /** 192 | * @param {flatbuffers.Builder} builder 193 | * @param {flatbuffers.Offset} keyOffset 194 | */ 195 | reflection.KeyValue.addKey = function(builder, keyOffset) { 196 | builder.addFieldOffset(0, keyOffset, 0); 197 | }; 198 | 199 | /** 200 | * @param {flatbuffers.Builder} builder 201 | * @param {flatbuffers.Offset} valueOffset 202 | */ 203 | reflection.KeyValue.addValue = function(builder, valueOffset) { 204 | builder.addFieldOffset(1, valueOffset, 0); 205 | }; 206 | 207 | /** 208 | * @param {flatbuffers.Builder} builder 209 | * @returns {flatbuffers.Offset} 210 | */ 211 | reflection.KeyValue.endKeyValue = function(builder) { 212 | var offset = builder.endObject(); 213 | builder.requiredField(offset, 4); // key 214 | return offset; 215 | }; 216 | 217 | /** 218 | * @constructor 219 | */ 220 | reflection.EnumVal = function() { 221 | /** 222 | * @type {flatbuffers.ByteBuffer} 223 | */ 224 | this.bb = null; 225 | 226 | /** 227 | * @type {number} 228 | */ 229 | this.bb_pos = 0; 230 | }; 231 | 232 | /** 233 | * @param {number} i 234 | * @param {flatbuffers.ByteBuffer} bb 235 | * @returns {reflection.EnumVal} 236 | */ 237 | reflection.EnumVal.prototype.__init = function(i, bb) { 238 | this.bb_pos = i; 239 | this.bb = bb; 240 | return this; 241 | }; 242 | 243 | /** 244 | * @param {flatbuffers.ByteBuffer} bb 245 | * @param {reflection.EnumVal=} obj 246 | * @returns {reflection.EnumVal} 247 | */ 248 | reflection.EnumVal.getRootAsEnumVal = function(bb, obj) { 249 | return (obj || new reflection.EnumVal).__init(bb.readInt32(bb.position()) + bb.position(), bb); 250 | }; 251 | 252 | /** 253 | * @param {flatbuffers.Encoding=} optionalEncoding 254 | * @returns {string|Uint8Array|null} 255 | */ 256 | reflection.EnumVal.prototype.name = function(optionalEncoding) { 257 | var offset = this.bb.__offset(this.bb_pos, 4); 258 | return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; 259 | }; 260 | 261 | /** 262 | * @returns {flatbuffers.Long} 263 | */ 264 | reflection.EnumVal.prototype.value = function() { 265 | var offset = this.bb.__offset(this.bb_pos, 6); 266 | return offset ? this.bb.readInt64(this.bb_pos + offset) : this.bb.createLong(0, 0); 267 | }; 268 | 269 | /** 270 | * @param {reflection.Object=} obj 271 | * @returns {reflection.Object|null} 272 | */ 273 | reflection.EnumVal.prototype.object = function(obj) { 274 | var offset = this.bb.__offset(this.bb_pos, 8); 275 | return offset ? (obj || new reflection.Object).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null; 276 | }; 277 | 278 | /** 279 | * @param {reflection.Type=} obj 280 | * @returns {reflection.Type|null} 281 | */ 282 | reflection.EnumVal.prototype.unionType = function(obj) { 283 | var offset = this.bb.__offset(this.bb_pos, 10); 284 | return offset ? (obj || new reflection.Type).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null; 285 | }; 286 | 287 | /** 288 | * @param {flatbuffers.Builder} builder 289 | */ 290 | reflection.EnumVal.startEnumVal = function(builder) { 291 | builder.startObject(4); 292 | }; 293 | 294 | /** 295 | * @param {flatbuffers.Builder} builder 296 | * @param {flatbuffers.Offset} nameOffset 297 | */ 298 | reflection.EnumVal.addName = function(builder, nameOffset) { 299 | builder.addFieldOffset(0, nameOffset, 0); 300 | }; 301 | 302 | /** 303 | * @param {flatbuffers.Builder} builder 304 | * @param {flatbuffers.Long} value 305 | */ 306 | reflection.EnumVal.addValue = function(builder, value) { 307 | builder.addFieldInt64(1, value, builder.createLong(0, 0)); 308 | }; 309 | 310 | /** 311 | * @param {flatbuffers.Builder} builder 312 | * @param {flatbuffers.Offset} objectOffset 313 | */ 314 | reflection.EnumVal.addObject = function(builder, objectOffset) { 315 | builder.addFieldOffset(2, objectOffset, 0); 316 | }; 317 | 318 | /** 319 | * @param {flatbuffers.Builder} builder 320 | * @param {flatbuffers.Offset} unionTypeOffset 321 | */ 322 | reflection.EnumVal.addUnionType = function(builder, unionTypeOffset) { 323 | builder.addFieldOffset(3, unionTypeOffset, 0); 324 | }; 325 | 326 | /** 327 | * @param {flatbuffers.Builder} builder 328 | * @returns {flatbuffers.Offset} 329 | */ 330 | reflection.EnumVal.endEnumVal = function(builder) { 331 | var offset = builder.endObject(); 332 | builder.requiredField(offset, 4); // name 333 | return offset; 334 | }; 335 | 336 | /** 337 | * @constructor 338 | */ 339 | reflection.Enum = function() { 340 | /** 341 | * @type {flatbuffers.ByteBuffer} 342 | */ 343 | this.bb = null; 344 | 345 | /** 346 | * @type {number} 347 | */ 348 | this.bb_pos = 0; 349 | }; 350 | 351 | /** 352 | * @param {number} i 353 | * @param {flatbuffers.ByteBuffer} bb 354 | * @returns {reflection.Enum} 355 | */ 356 | reflection.Enum.prototype.__init = function(i, bb) { 357 | this.bb_pos = i; 358 | this.bb = bb; 359 | return this; 360 | }; 361 | 362 | /** 363 | * @param {flatbuffers.ByteBuffer} bb 364 | * @param {reflection.Enum=} obj 365 | * @returns {reflection.Enum} 366 | */ 367 | reflection.Enum.getRootAsEnum = function(bb, obj) { 368 | return (obj || new reflection.Enum).__init(bb.readInt32(bb.position()) + bb.position(), bb); 369 | }; 370 | 371 | /** 372 | * @param {flatbuffers.Encoding=} optionalEncoding 373 | * @returns {string|Uint8Array|null} 374 | */ 375 | reflection.Enum.prototype.name = function(optionalEncoding) { 376 | var offset = this.bb.__offset(this.bb_pos, 4); 377 | return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; 378 | }; 379 | 380 | /** 381 | * @param {number} index 382 | * @param {reflection.EnumVal=} obj 383 | * @returns {reflection.EnumVal} 384 | */ 385 | reflection.Enum.prototype.values = function(index, obj) { 386 | var offset = this.bb.__offset(this.bb_pos, 6); 387 | return offset ? (obj || new reflection.EnumVal).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; 388 | }; 389 | 390 | /** 391 | * @returns {number} 392 | */ 393 | reflection.Enum.prototype.valuesLength = function() { 394 | var offset = this.bb.__offset(this.bb_pos, 6); 395 | return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; 396 | }; 397 | 398 | /** 399 | * @returns {boolean} 400 | */ 401 | reflection.Enum.prototype.isUnion = function() { 402 | var offset = this.bb.__offset(this.bb_pos, 8); 403 | return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false; 404 | }; 405 | 406 | /** 407 | * @param {reflection.Type=} obj 408 | * @returns {reflection.Type|null} 409 | */ 410 | reflection.Enum.prototype.underlyingType = function(obj) { 411 | var offset = this.bb.__offset(this.bb_pos, 10); 412 | return offset ? (obj || new reflection.Type).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null; 413 | }; 414 | 415 | /** 416 | * @param {number} index 417 | * @param {reflection.KeyValue=} obj 418 | * @returns {reflection.KeyValue} 419 | */ 420 | reflection.Enum.prototype.attributes = function(index, obj) { 421 | var offset = this.bb.__offset(this.bb_pos, 12); 422 | return offset ? (obj || new reflection.KeyValue).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; 423 | }; 424 | 425 | /** 426 | * @returns {number} 427 | */ 428 | reflection.Enum.prototype.attributesLength = function() { 429 | var offset = this.bb.__offset(this.bb_pos, 12); 430 | return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; 431 | }; 432 | 433 | /** 434 | * @param {number} index 435 | * @param {flatbuffers.Encoding=} optionalEncoding 436 | * @returns {string|Uint8Array} 437 | */ 438 | reflection.Enum.prototype.documentation = function(index, optionalEncoding) { 439 | var offset = this.bb.__offset(this.bb_pos, 14); 440 | return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; 441 | }; 442 | 443 | /** 444 | * @returns {number} 445 | */ 446 | reflection.Enum.prototype.documentationLength = function() { 447 | var offset = this.bb.__offset(this.bb_pos, 14); 448 | return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; 449 | }; 450 | 451 | /** 452 | * @param {flatbuffers.Builder} builder 453 | */ 454 | reflection.Enum.startEnum = function(builder) { 455 | builder.startObject(6); 456 | }; 457 | 458 | /** 459 | * @param {flatbuffers.Builder} builder 460 | * @param {flatbuffers.Offset} nameOffset 461 | */ 462 | reflection.Enum.addName = function(builder, nameOffset) { 463 | builder.addFieldOffset(0, nameOffset, 0); 464 | }; 465 | 466 | /** 467 | * @param {flatbuffers.Builder} builder 468 | * @param {flatbuffers.Offset} valuesOffset 469 | */ 470 | reflection.Enum.addValues = function(builder, valuesOffset) { 471 | builder.addFieldOffset(1, valuesOffset, 0); 472 | }; 473 | 474 | /** 475 | * @param {flatbuffers.Builder} builder 476 | * @param {Array.} data 477 | * @returns {flatbuffers.Offset} 478 | */ 479 | reflection.Enum.createValuesVector = function(builder, data) { 480 | builder.startVector(4, data.length, 4); 481 | for (var i = data.length - 1; i >= 0; i--) { 482 | builder.addOffset(data[i]); 483 | } 484 | return builder.endVector(); 485 | }; 486 | 487 | /** 488 | * @param {flatbuffers.Builder} builder 489 | * @param {number} numElems 490 | */ 491 | reflection.Enum.startValuesVector = function(builder, numElems) { 492 | builder.startVector(4, numElems, 4); 493 | }; 494 | 495 | /** 496 | * @param {flatbuffers.Builder} builder 497 | * @param {boolean} isUnion 498 | */ 499 | reflection.Enum.addIsUnion = function(builder, isUnion) { 500 | builder.addFieldInt8(2, +isUnion, +false); 501 | }; 502 | 503 | /** 504 | * @param {flatbuffers.Builder} builder 505 | * @param {flatbuffers.Offset} underlyingTypeOffset 506 | */ 507 | reflection.Enum.addUnderlyingType = function(builder, underlyingTypeOffset) { 508 | builder.addFieldOffset(3, underlyingTypeOffset, 0); 509 | }; 510 | 511 | /** 512 | * @param {flatbuffers.Builder} builder 513 | * @param {flatbuffers.Offset} attributesOffset 514 | */ 515 | reflection.Enum.addAttributes = function(builder, attributesOffset) { 516 | builder.addFieldOffset(4, attributesOffset, 0); 517 | }; 518 | 519 | /** 520 | * @param {flatbuffers.Builder} builder 521 | * @param {Array.} data 522 | * @returns {flatbuffers.Offset} 523 | */ 524 | reflection.Enum.createAttributesVector = function(builder, data) { 525 | builder.startVector(4, data.length, 4); 526 | for (var i = data.length - 1; i >= 0; i--) { 527 | builder.addOffset(data[i]); 528 | } 529 | return builder.endVector(); 530 | }; 531 | 532 | /** 533 | * @param {flatbuffers.Builder} builder 534 | * @param {number} numElems 535 | */ 536 | reflection.Enum.startAttributesVector = function(builder, numElems) { 537 | builder.startVector(4, numElems, 4); 538 | }; 539 | 540 | /** 541 | * @param {flatbuffers.Builder} builder 542 | * @param {flatbuffers.Offset} documentationOffset 543 | */ 544 | reflection.Enum.addDocumentation = function(builder, documentationOffset) { 545 | builder.addFieldOffset(5, documentationOffset, 0); 546 | }; 547 | 548 | /** 549 | * @param {flatbuffers.Builder} builder 550 | * @param {Array.} data 551 | * @returns {flatbuffers.Offset} 552 | */ 553 | reflection.Enum.createDocumentationVector = function(builder, data) { 554 | builder.startVector(4, data.length, 4); 555 | for (var i = data.length - 1; i >= 0; i--) { 556 | builder.addOffset(data[i]); 557 | } 558 | return builder.endVector(); 559 | }; 560 | 561 | /** 562 | * @param {flatbuffers.Builder} builder 563 | * @param {number} numElems 564 | */ 565 | reflection.Enum.startDocumentationVector = function(builder, numElems) { 566 | builder.startVector(4, numElems, 4); 567 | }; 568 | 569 | /** 570 | * @param {flatbuffers.Builder} builder 571 | * @returns {flatbuffers.Offset} 572 | */ 573 | reflection.Enum.endEnum = function(builder) { 574 | var offset = builder.endObject(); 575 | builder.requiredField(offset, 4); // name 576 | builder.requiredField(offset, 6); // values 577 | builder.requiredField(offset, 10); // underlying_type 578 | return offset; 579 | }; 580 | 581 | /** 582 | * @constructor 583 | */ 584 | reflection.Field = function() { 585 | /** 586 | * @type {flatbuffers.ByteBuffer} 587 | */ 588 | this.bb = null; 589 | 590 | /** 591 | * @type {number} 592 | */ 593 | this.bb_pos = 0; 594 | }; 595 | 596 | /** 597 | * @param {number} i 598 | * @param {flatbuffers.ByteBuffer} bb 599 | * @returns {reflection.Field} 600 | */ 601 | reflection.Field.prototype.__init = function(i, bb) { 602 | this.bb_pos = i; 603 | this.bb = bb; 604 | return this; 605 | }; 606 | 607 | /** 608 | * @param {flatbuffers.ByteBuffer} bb 609 | * @param {reflection.Field=} obj 610 | * @returns {reflection.Field} 611 | */ 612 | reflection.Field.getRootAsField = function(bb, obj) { 613 | return (obj || new reflection.Field).__init(bb.readInt32(bb.position()) + bb.position(), bb); 614 | }; 615 | 616 | /** 617 | * @param {flatbuffers.Encoding=} optionalEncoding 618 | * @returns {string|Uint8Array|null} 619 | */ 620 | reflection.Field.prototype.name = function(optionalEncoding) { 621 | var offset = this.bb.__offset(this.bb_pos, 4); 622 | return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; 623 | }; 624 | 625 | /** 626 | * @param {reflection.Type=} obj 627 | * @returns {reflection.Type|null} 628 | */ 629 | reflection.Field.prototype.type = function(obj) { 630 | var offset = this.bb.__offset(this.bb_pos, 6); 631 | return offset ? (obj || new reflection.Type).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null; 632 | }; 633 | 634 | /** 635 | * @returns {number} 636 | */ 637 | reflection.Field.prototype.id = function() { 638 | var offset = this.bb.__offset(this.bb_pos, 8); 639 | return offset ? this.bb.readUint16(this.bb_pos + offset) : 0; 640 | }; 641 | 642 | /** 643 | * @returns {number} 644 | */ 645 | reflection.Field.prototype.offset = function() { 646 | var offset = this.bb.__offset(this.bb_pos, 10); 647 | return offset ? this.bb.readUint16(this.bb_pos + offset) : 0; 648 | }; 649 | 650 | /** 651 | * @returns {flatbuffers.Long} 652 | */ 653 | reflection.Field.prototype.defaultInteger = function() { 654 | var offset = this.bb.__offset(this.bb_pos, 12); 655 | return offset ? this.bb.readInt64(this.bb_pos + offset) : this.bb.createLong(0, 0); 656 | }; 657 | 658 | /** 659 | * @returns {number} 660 | */ 661 | reflection.Field.prototype.defaultReal = function() { 662 | var offset = this.bb.__offset(this.bb_pos, 14); 663 | return offset ? this.bb.readFloat64(this.bb_pos + offset) : 0.0; 664 | }; 665 | 666 | /** 667 | * @returns {boolean} 668 | */ 669 | reflection.Field.prototype.deprecated = function() { 670 | var offset = this.bb.__offset(this.bb_pos, 16); 671 | return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false; 672 | }; 673 | 674 | /** 675 | * @returns {boolean} 676 | */ 677 | reflection.Field.prototype.required = function() { 678 | var offset = this.bb.__offset(this.bb_pos, 18); 679 | return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false; 680 | }; 681 | 682 | /** 683 | * @returns {boolean} 684 | */ 685 | reflection.Field.prototype.key = function() { 686 | var offset = this.bb.__offset(this.bb_pos, 20); 687 | return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false; 688 | }; 689 | 690 | /** 691 | * @param {number} index 692 | * @param {reflection.KeyValue=} obj 693 | * @returns {reflection.KeyValue} 694 | */ 695 | reflection.Field.prototype.attributes = function(index, obj) { 696 | var offset = this.bb.__offset(this.bb_pos, 22); 697 | return offset ? (obj || new reflection.KeyValue).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; 698 | }; 699 | 700 | /** 701 | * @returns {number} 702 | */ 703 | reflection.Field.prototype.attributesLength = function() { 704 | var offset = this.bb.__offset(this.bb_pos, 22); 705 | return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; 706 | }; 707 | 708 | /** 709 | * @param {number} index 710 | * @param {flatbuffers.Encoding=} optionalEncoding 711 | * @returns {string|Uint8Array} 712 | */ 713 | reflection.Field.prototype.documentation = function(index, optionalEncoding) { 714 | var offset = this.bb.__offset(this.bb_pos, 24); 715 | return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; 716 | }; 717 | 718 | /** 719 | * @returns {number} 720 | */ 721 | reflection.Field.prototype.documentationLength = function() { 722 | var offset = this.bb.__offset(this.bb_pos, 24); 723 | return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; 724 | }; 725 | 726 | /** 727 | * @param {flatbuffers.Builder} builder 728 | */ 729 | reflection.Field.startField = function(builder) { 730 | builder.startObject(11); 731 | }; 732 | 733 | /** 734 | * @param {flatbuffers.Builder} builder 735 | * @param {flatbuffers.Offset} nameOffset 736 | */ 737 | reflection.Field.addName = function(builder, nameOffset) { 738 | builder.addFieldOffset(0, nameOffset, 0); 739 | }; 740 | 741 | /** 742 | * @param {flatbuffers.Builder} builder 743 | * @param {flatbuffers.Offset} typeOffset 744 | */ 745 | reflection.Field.addType = function(builder, typeOffset) { 746 | builder.addFieldOffset(1, typeOffset, 0); 747 | }; 748 | 749 | /** 750 | * @param {flatbuffers.Builder} builder 751 | * @param {number} id 752 | */ 753 | reflection.Field.addId = function(builder, id) { 754 | builder.addFieldInt16(2, id, 0); 755 | }; 756 | 757 | /** 758 | * @param {flatbuffers.Builder} builder 759 | * @param {number} offset 760 | */ 761 | reflection.Field.addOffset = function(builder, offset) { 762 | builder.addFieldInt16(3, offset, 0); 763 | }; 764 | 765 | /** 766 | * @param {flatbuffers.Builder} builder 767 | * @param {flatbuffers.Long} defaultInteger 768 | */ 769 | reflection.Field.addDefaultInteger = function(builder, defaultInteger) { 770 | builder.addFieldInt64(4, defaultInteger, builder.createLong(0, 0)); 771 | }; 772 | 773 | /** 774 | * @param {flatbuffers.Builder} builder 775 | * @param {number} defaultReal 776 | */ 777 | reflection.Field.addDefaultReal = function(builder, defaultReal) { 778 | builder.addFieldFloat64(5, defaultReal, 0.0); 779 | }; 780 | 781 | /** 782 | * @param {flatbuffers.Builder} builder 783 | * @param {boolean} deprecated 784 | */ 785 | reflection.Field.addDeprecated = function(builder, deprecated) { 786 | builder.addFieldInt8(6, +deprecated, +false); 787 | }; 788 | 789 | /** 790 | * @param {flatbuffers.Builder} builder 791 | * @param {boolean} required 792 | */ 793 | reflection.Field.addRequired = function(builder, required) { 794 | builder.addFieldInt8(7, +required, +false); 795 | }; 796 | 797 | /** 798 | * @param {flatbuffers.Builder} builder 799 | * @param {boolean} key 800 | */ 801 | reflection.Field.addKey = function(builder, key) { 802 | builder.addFieldInt8(8, +key, +false); 803 | }; 804 | 805 | /** 806 | * @param {flatbuffers.Builder} builder 807 | * @param {flatbuffers.Offset} attributesOffset 808 | */ 809 | reflection.Field.addAttributes = function(builder, attributesOffset) { 810 | builder.addFieldOffset(9, attributesOffset, 0); 811 | }; 812 | 813 | /** 814 | * @param {flatbuffers.Builder} builder 815 | * @param {Array.} data 816 | * @returns {flatbuffers.Offset} 817 | */ 818 | reflection.Field.createAttributesVector = function(builder, data) { 819 | builder.startVector(4, data.length, 4); 820 | for (var i = data.length - 1; i >= 0; i--) { 821 | builder.addOffset(data[i]); 822 | } 823 | return builder.endVector(); 824 | }; 825 | 826 | /** 827 | * @param {flatbuffers.Builder} builder 828 | * @param {number} numElems 829 | */ 830 | reflection.Field.startAttributesVector = function(builder, numElems) { 831 | builder.startVector(4, numElems, 4); 832 | }; 833 | 834 | /** 835 | * @param {flatbuffers.Builder} builder 836 | * @param {flatbuffers.Offset} documentationOffset 837 | */ 838 | reflection.Field.addDocumentation = function(builder, documentationOffset) { 839 | builder.addFieldOffset(10, documentationOffset, 0); 840 | }; 841 | 842 | /** 843 | * @param {flatbuffers.Builder} builder 844 | * @param {Array.} data 845 | * @returns {flatbuffers.Offset} 846 | */ 847 | reflection.Field.createDocumentationVector = function(builder, data) { 848 | builder.startVector(4, data.length, 4); 849 | for (var i = data.length - 1; i >= 0; i--) { 850 | builder.addOffset(data[i]); 851 | } 852 | return builder.endVector(); 853 | }; 854 | 855 | /** 856 | * @param {flatbuffers.Builder} builder 857 | * @param {number} numElems 858 | */ 859 | reflection.Field.startDocumentationVector = function(builder, numElems) { 860 | builder.startVector(4, numElems, 4); 861 | }; 862 | 863 | /** 864 | * @param {flatbuffers.Builder} builder 865 | * @returns {flatbuffers.Offset} 866 | */ 867 | reflection.Field.endField = function(builder) { 868 | var offset = builder.endObject(); 869 | builder.requiredField(offset, 4); // name 870 | builder.requiredField(offset, 6); // type 871 | return offset; 872 | }; 873 | 874 | /** 875 | * @constructor 876 | */ 877 | reflection.Object = function() { 878 | /** 879 | * @type {flatbuffers.ByteBuffer} 880 | */ 881 | this.bb = null; 882 | 883 | /** 884 | * @type {number} 885 | */ 886 | this.bb_pos = 0; 887 | }; 888 | 889 | /** 890 | * @param {number} i 891 | * @param {flatbuffers.ByteBuffer} bb 892 | * @returns {reflection.Object} 893 | */ 894 | reflection.Object.prototype.__init = function(i, bb) { 895 | this.bb_pos = i; 896 | this.bb = bb; 897 | return this; 898 | }; 899 | 900 | /** 901 | * @param {flatbuffers.ByteBuffer} bb 902 | * @param {reflection.Object=} obj 903 | * @returns {reflection.Object} 904 | */ 905 | reflection.Object.getRootAsObject = function(bb, obj) { 906 | return (obj || new reflection.Object).__init(bb.readInt32(bb.position()) + bb.position(), bb); 907 | }; 908 | 909 | /** 910 | * @param {flatbuffers.Encoding=} optionalEncoding 911 | * @returns {string|Uint8Array|null} 912 | */ 913 | reflection.Object.prototype.name = function(optionalEncoding) { 914 | var offset = this.bb.__offset(this.bb_pos, 4); 915 | return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; 916 | }; 917 | 918 | /** 919 | * @param {number} index 920 | * @param {reflection.Field=} obj 921 | * @returns {reflection.Field} 922 | */ 923 | reflection.Object.prototype.fields = function(index, obj) { 924 | var offset = this.bb.__offset(this.bb_pos, 6); 925 | return offset ? (obj || new reflection.Field).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; 926 | }; 927 | 928 | /** 929 | * @returns {number} 930 | */ 931 | reflection.Object.prototype.fieldsLength = function() { 932 | var offset = this.bb.__offset(this.bb_pos, 6); 933 | return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; 934 | }; 935 | 936 | /** 937 | * @returns {boolean} 938 | */ 939 | reflection.Object.prototype.isStruct = function() { 940 | var offset = this.bb.__offset(this.bb_pos, 8); 941 | return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false; 942 | }; 943 | 944 | /** 945 | * @returns {number} 946 | */ 947 | reflection.Object.prototype.minalign = function() { 948 | var offset = this.bb.__offset(this.bb_pos, 10); 949 | return offset ? this.bb.readInt32(this.bb_pos + offset) : 0; 950 | }; 951 | 952 | /** 953 | * @returns {number} 954 | */ 955 | reflection.Object.prototype.bytesize = function() { 956 | var offset = this.bb.__offset(this.bb_pos, 12); 957 | return offset ? this.bb.readInt32(this.bb_pos + offset) : 0; 958 | }; 959 | 960 | /** 961 | * @param {number} index 962 | * @param {reflection.KeyValue=} obj 963 | * @returns {reflection.KeyValue} 964 | */ 965 | reflection.Object.prototype.attributes = function(index, obj) { 966 | var offset = this.bb.__offset(this.bb_pos, 14); 967 | return offset ? (obj || new reflection.KeyValue).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; 968 | }; 969 | 970 | /** 971 | * @returns {number} 972 | */ 973 | reflection.Object.prototype.attributesLength = function() { 974 | var offset = this.bb.__offset(this.bb_pos, 14); 975 | return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; 976 | }; 977 | 978 | /** 979 | * @param {number} index 980 | * @param {flatbuffers.Encoding=} optionalEncoding 981 | * @returns {string|Uint8Array} 982 | */ 983 | reflection.Object.prototype.documentation = function(index, optionalEncoding) { 984 | var offset = this.bb.__offset(this.bb_pos, 16); 985 | return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; 986 | }; 987 | 988 | /** 989 | * @returns {number} 990 | */ 991 | reflection.Object.prototype.documentationLength = function() { 992 | var offset = this.bb.__offset(this.bb_pos, 16); 993 | return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; 994 | }; 995 | 996 | /** 997 | * @param {flatbuffers.Builder} builder 998 | */ 999 | reflection.Object.startObject = function(builder) { 1000 | builder.startObject(7); 1001 | }; 1002 | 1003 | /** 1004 | * @param {flatbuffers.Builder} builder 1005 | * @param {flatbuffers.Offset} nameOffset 1006 | */ 1007 | reflection.Object.addName = function(builder, nameOffset) { 1008 | builder.addFieldOffset(0, nameOffset, 0); 1009 | }; 1010 | 1011 | /** 1012 | * @param {flatbuffers.Builder} builder 1013 | * @param {flatbuffers.Offset} fieldsOffset 1014 | */ 1015 | reflection.Object.addFields = function(builder, fieldsOffset) { 1016 | builder.addFieldOffset(1, fieldsOffset, 0); 1017 | }; 1018 | 1019 | /** 1020 | * @param {flatbuffers.Builder} builder 1021 | * @param {Array.} data 1022 | * @returns {flatbuffers.Offset} 1023 | */ 1024 | reflection.Object.createFieldsVector = function(builder, data) { 1025 | builder.startVector(4, data.length, 4); 1026 | for (var i = data.length - 1; i >= 0; i--) { 1027 | builder.addOffset(data[i]); 1028 | } 1029 | return builder.endVector(); 1030 | }; 1031 | 1032 | /** 1033 | * @param {flatbuffers.Builder} builder 1034 | * @param {number} numElems 1035 | */ 1036 | reflection.Object.startFieldsVector = function(builder, numElems) { 1037 | builder.startVector(4, numElems, 4); 1038 | }; 1039 | 1040 | /** 1041 | * @param {flatbuffers.Builder} builder 1042 | * @param {boolean} isStruct 1043 | */ 1044 | reflection.Object.addIsStruct = function(builder, isStruct) { 1045 | builder.addFieldInt8(2, +isStruct, +false); 1046 | }; 1047 | 1048 | /** 1049 | * @param {flatbuffers.Builder} builder 1050 | * @param {number} minalign 1051 | */ 1052 | reflection.Object.addMinalign = function(builder, minalign) { 1053 | builder.addFieldInt32(3, minalign, 0); 1054 | }; 1055 | 1056 | /** 1057 | * @param {flatbuffers.Builder} builder 1058 | * @param {number} bytesize 1059 | */ 1060 | reflection.Object.addBytesize = function(builder, bytesize) { 1061 | builder.addFieldInt32(4, bytesize, 0); 1062 | }; 1063 | 1064 | /** 1065 | * @param {flatbuffers.Builder} builder 1066 | * @param {flatbuffers.Offset} attributesOffset 1067 | */ 1068 | reflection.Object.addAttributes = function(builder, attributesOffset) { 1069 | builder.addFieldOffset(5, attributesOffset, 0); 1070 | }; 1071 | 1072 | /** 1073 | * @param {flatbuffers.Builder} builder 1074 | * @param {Array.} data 1075 | * @returns {flatbuffers.Offset} 1076 | */ 1077 | reflection.Object.createAttributesVector = function(builder, data) { 1078 | builder.startVector(4, data.length, 4); 1079 | for (var i = data.length - 1; i >= 0; i--) { 1080 | builder.addOffset(data[i]); 1081 | } 1082 | return builder.endVector(); 1083 | }; 1084 | 1085 | /** 1086 | * @param {flatbuffers.Builder} builder 1087 | * @param {number} numElems 1088 | */ 1089 | reflection.Object.startAttributesVector = function(builder, numElems) { 1090 | builder.startVector(4, numElems, 4); 1091 | }; 1092 | 1093 | /** 1094 | * @param {flatbuffers.Builder} builder 1095 | * @param {flatbuffers.Offset} documentationOffset 1096 | */ 1097 | reflection.Object.addDocumentation = function(builder, documentationOffset) { 1098 | builder.addFieldOffset(6, documentationOffset, 0); 1099 | }; 1100 | 1101 | /** 1102 | * @param {flatbuffers.Builder} builder 1103 | * @param {Array.} data 1104 | * @returns {flatbuffers.Offset} 1105 | */ 1106 | reflection.Object.createDocumentationVector = function(builder, data) { 1107 | builder.startVector(4, data.length, 4); 1108 | for (var i = data.length - 1; i >= 0; i--) { 1109 | builder.addOffset(data[i]); 1110 | } 1111 | return builder.endVector(); 1112 | }; 1113 | 1114 | /** 1115 | * @param {flatbuffers.Builder} builder 1116 | * @param {number} numElems 1117 | */ 1118 | reflection.Object.startDocumentationVector = function(builder, numElems) { 1119 | builder.startVector(4, numElems, 4); 1120 | }; 1121 | 1122 | /** 1123 | * @param {flatbuffers.Builder} builder 1124 | * @returns {flatbuffers.Offset} 1125 | */ 1126 | reflection.Object.endObject = function(builder) { 1127 | var offset = builder.endObject(); 1128 | builder.requiredField(offset, 4); // name 1129 | builder.requiredField(offset, 6); // fields 1130 | return offset; 1131 | }; 1132 | 1133 | /** 1134 | * @constructor 1135 | */ 1136 | reflection.Schema = function() { 1137 | /** 1138 | * @type {flatbuffers.ByteBuffer} 1139 | */ 1140 | this.bb = null; 1141 | 1142 | /** 1143 | * @type {number} 1144 | */ 1145 | this.bb_pos = 0; 1146 | }; 1147 | 1148 | /** 1149 | * @param {number} i 1150 | * @param {flatbuffers.ByteBuffer} bb 1151 | * @returns {reflection.Schema} 1152 | */ 1153 | reflection.Schema.prototype.__init = function(i, bb) { 1154 | this.bb_pos = i; 1155 | this.bb = bb; 1156 | return this; 1157 | }; 1158 | 1159 | /** 1160 | * @param {flatbuffers.ByteBuffer} bb 1161 | * @param {reflection.Schema=} obj 1162 | * @returns {reflection.Schema} 1163 | */ 1164 | reflection.Schema.getRootAsSchema = function(bb, obj) { 1165 | return (obj || new reflection.Schema).__init(bb.readInt32(bb.position()) + bb.position(), bb); 1166 | }; 1167 | 1168 | /** 1169 | * @param {flatbuffers.ByteBuffer} bb 1170 | * @returns {boolean} 1171 | */ 1172 | reflection.Schema.bufferHasIdentifier = function(bb) { 1173 | return bb.__has_identifier('BFBS'); 1174 | }; 1175 | 1176 | /** 1177 | * @param {number} index 1178 | * @param {reflection.Object=} obj 1179 | * @returns {reflection.Object} 1180 | */ 1181 | reflection.Schema.prototype.objects = function(index, obj) { 1182 | var offset = this.bb.__offset(this.bb_pos, 4); 1183 | return offset ? (obj || new reflection.Object).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; 1184 | }; 1185 | 1186 | /** 1187 | * @returns {number} 1188 | */ 1189 | reflection.Schema.prototype.objectsLength = function() { 1190 | var offset = this.bb.__offset(this.bb_pos, 4); 1191 | return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; 1192 | }; 1193 | 1194 | /** 1195 | * @param {number} index 1196 | * @param {reflection.Enum=} obj 1197 | * @returns {reflection.Enum} 1198 | */ 1199 | reflection.Schema.prototype.enums = function(index, obj) { 1200 | var offset = this.bb.__offset(this.bb_pos, 6); 1201 | return offset ? (obj || new reflection.Enum).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; 1202 | }; 1203 | 1204 | /** 1205 | * @returns {number} 1206 | */ 1207 | reflection.Schema.prototype.enumsLength = function() { 1208 | var offset = this.bb.__offset(this.bb_pos, 6); 1209 | return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; 1210 | }; 1211 | 1212 | /** 1213 | * @param {flatbuffers.Encoding=} optionalEncoding 1214 | * @returns {string|Uint8Array|null} 1215 | */ 1216 | reflection.Schema.prototype.fileIdent = function(optionalEncoding) { 1217 | var offset = this.bb.__offset(this.bb_pos, 8); 1218 | return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; 1219 | }; 1220 | 1221 | /** 1222 | * @param {flatbuffers.Encoding=} optionalEncoding 1223 | * @returns {string|Uint8Array|null} 1224 | */ 1225 | reflection.Schema.prototype.fileExt = function(optionalEncoding) { 1226 | var offset = this.bb.__offset(this.bb_pos, 10); 1227 | return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; 1228 | }; 1229 | 1230 | /** 1231 | * @param {reflection.Object=} obj 1232 | * @returns {reflection.Object|null} 1233 | */ 1234 | reflection.Schema.prototype.rootTable = function(obj) { 1235 | var offset = this.bb.__offset(this.bb_pos, 12); 1236 | return offset ? (obj || new reflection.Object).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null; 1237 | }; 1238 | 1239 | /** 1240 | * @param {flatbuffers.Builder} builder 1241 | */ 1242 | reflection.Schema.startSchema = function(builder) { 1243 | builder.startObject(5); 1244 | }; 1245 | 1246 | /** 1247 | * @param {flatbuffers.Builder} builder 1248 | * @param {flatbuffers.Offset} objectsOffset 1249 | */ 1250 | reflection.Schema.addObjects = function(builder, objectsOffset) { 1251 | builder.addFieldOffset(0, objectsOffset, 0); 1252 | }; 1253 | 1254 | /** 1255 | * @param {flatbuffers.Builder} builder 1256 | * @param {Array.} data 1257 | * @returns {flatbuffers.Offset} 1258 | */ 1259 | reflection.Schema.createObjectsVector = function(builder, data) { 1260 | builder.startVector(4, data.length, 4); 1261 | for (var i = data.length - 1; i >= 0; i--) { 1262 | builder.addOffset(data[i]); 1263 | } 1264 | return builder.endVector(); 1265 | }; 1266 | 1267 | /** 1268 | * @param {flatbuffers.Builder} builder 1269 | * @param {number} numElems 1270 | */ 1271 | reflection.Schema.startObjectsVector = function(builder, numElems) { 1272 | builder.startVector(4, numElems, 4); 1273 | }; 1274 | 1275 | /** 1276 | * @param {flatbuffers.Builder} builder 1277 | * @param {flatbuffers.Offset} enumsOffset 1278 | */ 1279 | reflection.Schema.addEnums = function(builder, enumsOffset) { 1280 | builder.addFieldOffset(1, enumsOffset, 0); 1281 | }; 1282 | 1283 | /** 1284 | * @param {flatbuffers.Builder} builder 1285 | * @param {Array.} data 1286 | * @returns {flatbuffers.Offset} 1287 | */ 1288 | reflection.Schema.createEnumsVector = function(builder, data) { 1289 | builder.startVector(4, data.length, 4); 1290 | for (var i = data.length - 1; i >= 0; i--) { 1291 | builder.addOffset(data[i]); 1292 | } 1293 | return builder.endVector(); 1294 | }; 1295 | 1296 | /** 1297 | * @param {flatbuffers.Builder} builder 1298 | * @param {number} numElems 1299 | */ 1300 | reflection.Schema.startEnumsVector = function(builder, numElems) { 1301 | builder.startVector(4, numElems, 4); 1302 | }; 1303 | 1304 | /** 1305 | * @param {flatbuffers.Builder} builder 1306 | * @param {flatbuffers.Offset} fileIdentOffset 1307 | */ 1308 | reflection.Schema.addFileIdent = function(builder, fileIdentOffset) { 1309 | builder.addFieldOffset(2, fileIdentOffset, 0); 1310 | }; 1311 | 1312 | /** 1313 | * @param {flatbuffers.Builder} builder 1314 | * @param {flatbuffers.Offset} fileExtOffset 1315 | */ 1316 | reflection.Schema.addFileExt = function(builder, fileExtOffset) { 1317 | builder.addFieldOffset(3, fileExtOffset, 0); 1318 | }; 1319 | 1320 | /** 1321 | * @param {flatbuffers.Builder} builder 1322 | * @param {flatbuffers.Offset} rootTableOffset 1323 | */ 1324 | reflection.Schema.addRootTable = function(builder, rootTableOffset) { 1325 | builder.addFieldOffset(4, rootTableOffset, 0); 1326 | }; 1327 | 1328 | /** 1329 | * @param {flatbuffers.Builder} builder 1330 | * @returns {flatbuffers.Offset} 1331 | */ 1332 | reflection.Schema.endSchema = function(builder) { 1333 | var offset = builder.endObject(); 1334 | builder.requiredField(offset, 4); // objects 1335 | builder.requiredField(offset, 6); // enums 1336 | return offset; 1337 | }; 1338 | 1339 | /** 1340 | * @param {flatbuffers.Builder} builder 1341 | * @param {flatbuffers.Offset} offset 1342 | */ 1343 | reflection.Schema.finishSchemaBuffer = function(builder, offset) { 1344 | builder.finish(offset, 'BFBS'); 1345 | }; 1346 | 1347 | // Exports for Node.js and RequireJS 1348 | this.reflection = reflection; 1349 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pomelo-flatbuffer", 3 | "version": "2.0.0", 4 | "description": "flatbuffer for pomelo", 5 | "keywords": [ 6 | "pomelo", 7 | "flatbuffer", 8 | "pomelo flatbuffer", 9 | "protobuff" 10 | ], 11 | "license": "MIT", 12 | "dependencies": { 13 | }, 14 | "devDependencies": { 15 | "eslint": "5.3.0" 16 | }, 17 | "scripts": { 18 | "lint": "eslint .", 19 | "test": "node ./test/PomeloFlatBuffer.js" 20 | }, 21 | "main": "./index.js", 22 | "engines": { 23 | "node": ">=4.0.0" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git://github.com/frank198/pomelo-flatbuffer.git" 28 | }, 29 | "eslintConfig": { 30 | "extends": [ 31 | "eslint:recommended" 32 | ], 33 | "parserOptions": { 34 | "ecmaVersion": 2015 35 | }, 36 | "env": { 37 | "node": true, 38 | "mocha": true, 39 | "es6": true 40 | }, 41 | "rules": { 42 | "comma-style": "error", 43 | "consistent-this": [ 44 | "error", 45 | "_this" 46 | ], 47 | "indent": [ 48 | "error", 49 | 2, 50 | { 51 | "SwitchCase": 1, 52 | "VariableDeclarator": 2 53 | } 54 | ], 55 | "keyword-spacing": "error", 56 | "no-buffer-constructor": "warn", 57 | "no-console": "off", 58 | "no-multi-spaces": "error", 59 | "func-call-spacing": "error", 60 | "no-trailing-spaces": "error", 61 | "quotes": [ 62 | "error", 63 | "single" 64 | ], 65 | "semi": "error", 66 | "space-before-blocks": "error", 67 | "space-before-function-paren": [ 68 | "error", 69 | "never" 70 | ], 71 | "space-infix-ops": "error", 72 | "space-unary-ops": "error", 73 | "no-var": "warn", 74 | "prefer-const": "warn", 75 | "strict": [ 76 | "error", 77 | "global" 78 | ] 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /tests/FlatBufferTest.js: -------------------------------------------------------------------------------- 1 | const FlatBuffer = require('../lib/index'); 2 | const exampleData = require('./exampleData'); 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | 6 | const data = fs.readFileSync(path.join(__dirname, '/serverBFBS/MessageBoxInfo.bfbs')); 7 | const flatBuild = FlatBuffer.compileSchema(data); 8 | const bytes = flatBuild.generate(exampleData.MessageBoxInfo); 9 | console.log(bytes.toString()); 10 | const jsonData = flatBuild.parse(bytes); 11 | -------------------------------------------------------------------------------- /tests/PomeloFlatBuffer.js: -------------------------------------------------------------------------------- 1 | const FlatBuffer = require('../lib/components/flatbuffer'); 2 | const exampleData = require('./exampleData'); 3 | 4 | const app = { 5 | getBase : function() 6 | { 7 | return __dirname; 8 | }, 9 | get: function() 10 | { 11 | return 'development'; 12 | } 13 | }; 14 | 15 | const flatBufferInstance = FlatBuffer(app, { 16 | serverProtos : '/serverProtos.json', 17 | clientProtos : '/clientProtos.json', 18 | serverFBPath : '/serverBFBS/', 19 | clientFBPath : '/clientBFBS/' 20 | }); 21 | 22 | flatBufferInstance.start(() => 23 | { 24 | const data = flatBufferInstance.encode('LoginUserInfo', exampleData.LoginUserInfo); 25 | console.log(data.toString()); 26 | 27 | }); -------------------------------------------------------------------------------- /tests/clientBFBS/ConnectorGateServer.bfbs: -------------------------------------------------------------------------------- 1 | BFBS 0(  ConnectorGateServer$h passWord 2 |  3 |  userName 4 |  5 | -------------------------------------------------------------------------------- /tests/clientBFBS/clientFBCheck.json: -------------------------------------------------------------------------------- 1 | { 2 | "gate.gateHandler.getConnector": "ConnectorGateServer" 3 | } -------------------------------------------------------------------------------- /tests/clientProtos.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "gate.gateHandler.getConnector": 4 | { 5 | "required string userName":1, 6 | "required string passWord":2 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /tests/exampleData.js: -------------------------------------------------------------------------------- 1 | const tc = {}; 2 | tc.ItemDistances = { 3 | itemDistances : [ 4 | { 5 | linkId : 'playerRole_3a82c8d04b6111e7b14757060500f1e9口PropertyInfo', 6 | distance : '10' 7 | }, 8 | { 9 | linkId : 'playerRole_3a82c8d04b6111e7b14757060500f1e9口Watch', 10 | distance : '100' 11 | } 12 | ] 13 | }; 14 | 15 | tc.LoginUserInfo = { 16 | uuid:'this is uuid', 17 | playerRoleId:'playerRoleId_123ter', 18 | gameElement:{gameElementSettingKey:'default'}, 19 | alert:'' 20 | }; 21 | 22 | tc.MessageBoxInfo = { 23 | "moduleKey": "RoleInfoBox", 24 | viewOpenLinkId:"RoleInfoBox_test", 25 | "messageItemList": [ 26 | { 27 | "propertyValue": "『无名之辈』", 28 | "linkProperties": [], 29 | "key": "title" 30 | }, 31 | { 32 | "propertyValue": "", 33 | "linkProperties": [], 34 | "key": "relation" 35 | }, 36 | { 37 | "propertyValue": "", 38 | "linkProperties": [], 39 | "key": "name" 40 | }, 41 | { 42 | "propertyValue": "新进玩家#3568", 43 | "linkProperties": [], 44 | "key": "nameAndId" 45 | }, 46 | { 47 | "propertyValue": "等级 5", 48 | "linkProperties": [], 49 | "key": "level" 50 | }, 51 | { 52 | "propertyValue": "你查看自己,只见他身形纤长,略显瘦弱,满头银发,一口大金牙,脸上布满皱纹,拇指是金色的,头上左眼的瞳仁是红色,右臂上的胳膊上的右手不知被什么东西砍去了。身穿,看起来雌雄难辨,容貌可怖,难以直视。", 53 | "linkProperties": [], 54 | "key": "describe" 55 | }, 56 | { 57 | "propertyValue": "加血Buff{playerRole_3a82c8d04b6111e7b14757060500f1e9口delayLink}", 58 | "linkProperties": [ 59 | { 60 | "linkId":"playerRole_3a82c8d04b6111e7b14757060500f1e9口delayLink", 61 | "linkContent": "", 62 | "unitFormat": "[{2}{0}{1}]", 63 | "units": [ 64 | "秒剩余", 65 | "" 66 | ] 67 | } 68 | ], 69 | "key": "buffList" 70 | }, 71 | { 72 | "propertyValue": "状态", 73 | "linkProperties": [], 74 | "key": "buffTitle" 75 | } 76 | ], 77 | "buttonItemList": [ 78 | { 79 | "key": "property", 80 | "linkId": "playerRole_3a82c8d04b6111e7b14757060500f1e9口PropertyInfo", 81 | "buttonTitle": "属性详细", 82 | "isClose": false 83 | } 84 | ] 85 | }; 86 | 87 | module.exports = tc; -------------------------------------------------------------------------------- /tests/flatSchema/ConnectorGateServer.fbs: -------------------------------------------------------------------------------- 1 | 2 | table ConnectorGateServer { 3 | userName:string; 4 | passWord:string; 5 | } 6 | 7 | root_type ConnectorGateServer; 8 | -------------------------------------------------------------------------------- /tests/flatSchema/ItemDistances.fbs: -------------------------------------------------------------------------------- 1 | 2 | table ItemDistances { 3 | itemDataArr:[ItemDistance]; 4 | } 5 | 6 | 7 | table ItemDistance { 8 | linkId:string; 9 | distance:string; 10 | } 11 | 12 | 13 | 14 | root_type ItemDistances; 15 | -------------------------------------------------------------------------------- /tests/serverBFBS/ItemDistances.bfbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frank198/pomelo-flatbuffer/8382039ef7c22a57ed5d1f023651fdc627a55312/tests/serverBFBS/ItemDistances.bfbs -------------------------------------------------------------------------------- /tests/serverBFBS/MessageBoxInfo.bfbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frank198/pomelo-flatbuffer/8382039ef7c22a57ed5d1f023651fdc627a55312/tests/serverBFBS/MessageBoxInfo.bfbs -------------------------------------------------------------------------------- /tests/serverBFBS/serverFBCheck.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } -------------------------------------------------------------------------------- /tests/serverProtos.json: -------------------------------------------------------------------------------- 1 | { 2 | "ItemDistances": 3 | { 4 | "repeated ItemDistance itemDistances":1 5 | }, 6 | "message ItemDistance": 7 | { 8 | "required string linkId":1, 9 | "required string distance":2 10 | } 11 | } --------------------------------------------------------------------------------