diff --git a/CHANGELOG.md b/CHANGELOG.md index e0a710101da..43078b44d21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - Build: - FIXED: Reduce MSVC compiler warnings by suppressing informational warnings while preserving bug-indicating warnings [#7253](https://github.com/Project-OSRM/osrm-backend/issues/7253) - Misc: + - CHANGED: Upgrade FlatBuffers to v25.9.23 with TypeScript workflow [#7235](https://github.com/Project-OSRM/osrm-backend/issues/7235) - CHANGED: Add std::format compatibility layer with fallback to fmt::format [#7261](https://github.com/Project-OSRM/osrm-backend/pull/7261) - FIXED: Update node_osrm to C++20 to fix ABI mismatch with libosrm (was overlooked in #6877) [#7261](https://github.com/Project-OSRM/osrm-backend/pull/7261) - CHANGED: Update fmt library to version 11.2.0 [#7238](https://github.com/Project-OSRM/osrm-backend/issues/7238) diff --git a/eslint.config.js b/eslint.config.js index aae0bdf8020..2a84eb9798b 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -2,6 +2,9 @@ import { Linter } from 'eslint'; /** @type {Linter.Config} */ const config = [ + { + ignores: ['node_modules/', 'build/', 'dist/', 'coverage/', 'features/support/osrm/'], + }, { files: ["**/*.js"], languageOptions: { @@ -25,7 +28,6 @@ const config = [ 'prefer-template': 'error', 'prefer-arrow-callback': 'error', }, - ignores: ['node_modules/', 'build/', 'dist/', 'coverage/', 'features/support/fbresult_generated.js'], }, ]; diff --git a/features/step_definitions/distance_matrix.js b/features/step_definitions/distance_matrix.js index bd40ccc4674..348c9efb2b2 100644 --- a/features/step_definitions/distance_matrix.js +++ b/features/step_definitions/distance_matrix.js @@ -2,8 +2,7 @@ import util from 'util'; import flatbuffers from 'flatbuffers'; -import { osrm } from '../support/fbresult_generated.js'; -const FBResult = osrm.engine.api.fbresult.FBResult; +import { FBResult } from '../support/osrm/engine/api/fbresult/fbresult.js'; import { When } from '@cucumber/cucumber'; // Regular expressions for matching different matrix API test scenarios diff --git a/features/step_definitions/nearest.js b/features/step_definitions/nearest.js index 16fef436cc4..a4c0c1afe59 100644 --- a/features/step_definitions/nearest.js +++ b/features/step_definitions/nearest.js @@ -2,8 +2,7 @@ import util from 'util'; import flatbuffers from 'flatbuffers'; -import { osrm } from '../support/fbresult_generated.js'; -const FBResult = osrm.engine.api.fbresult.FBResult; +import { FBResult } from '../support/osrm/engine/api/fbresult/fbresult.js'; import { When } from '@cucumber/cucumber'; When(/^I request nearest I should get$/, function (table, callback) { diff --git a/features/support/env.js b/features/support/env.js index 6f27eeada9a..5d034167a6e 100644 --- a/features/support/env.js +++ b/features/support/env.js @@ -8,9 +8,11 @@ import tryConnect from '../lib/try_connect.js'; import { setDefaultTimeout } from '@cucumber/cucumber'; // Set global timeout for all steps and hooks +// Use higher timeout on macOS due to slower performance +const DEFAULT_TIMEOUT = process.platform === 'darwin' ? 10000 : 5000; setDefaultTimeout( (process.env.CUCUMBER_TIMEOUT && parseInt(process.env.CUCUMBER_TIMEOUT)) || - 5000, + DEFAULT_TIMEOUT, ); // Sets up all constants that are valid for all features @@ -21,7 +23,7 @@ export default class Env { // Initializes all environment constants and paths for test execution initializeEnv(callback) { - this.TIMEOUT = parseInt(process.env.CUCUMBER_TIMEOUT) || 5000; + this.TIMEOUT = parseInt(process.env.CUCUMBER_TIMEOUT) || DEFAULT_TIMEOUT; this.ROOT_PATH = process.cwd(); this.TEST_PATH = path.resolve(this.ROOT_PATH, 'test'); diff --git a/features/support/fbresult_generated.js b/features/support/fbresult_generated.js deleted file mode 100644 index 37ea76215a5..00000000000 --- a/features/support/fbresult_generated.js +++ /dev/null @@ -1,3971 +0,0 @@ -// automatically generated by the FlatBuffers compiler, do not modify - -/** - * @const - * @namespace - */ -var osrm = osrm || {}; - -/** - * @const - * @namespace - */ -osrm.engine = osrm.engine || {}; - -/** - * @const - * @namespace - */ -osrm.engine.api = osrm.engine.api || {}; - -/** - * @const - * @namespace - */ -osrm.engine.api.fbresult = osrm.engine.api.fbresult || {}; - -/** - * @enum {number} - */ -osrm.engine.api.fbresult.ManeuverType = { - Turn: 0, - NewName: 1, - Depart: 2, - Arrive: 3, - Merge: 4, - OnRamp: 5, - OffRamp: 6, - Fork: 7, - EndOfRoad: 8, - Continue: 9, - Roundabout: 10, - Rotary: 11, - RoundaboutTurn: 12, - Notification: 13, - ExitRoundabout: 14, - ExitRotary: 15, -}; - -/** - * @enum {string} - */ -osrm.engine.api.fbresult.ManeuverTypeName = { - 0: 'Turn', - 1: 'NewName', - 2: 'Depart', - 3: 'Arrive', - 4: 'Merge', - 5: 'OnRamp', - 6: 'OffRamp', - 7: 'Fork', - 8: 'EndOfRoad', - 9: 'Continue', - 10: 'Roundabout', - 11: 'Rotary', - 12: 'RoundaboutTurn', - 13: 'Notification', - 14: 'ExitRoundabout', - 15: 'ExitRotary', -}; - -/** - * @enum {number} - */ -osrm.engine.api.fbresult.Turn = { - None: 0, - UTurn: 1, - SharpRight: 2, - Right: 3, - SlightRight: 4, - Straight: 5, - SlightLeft: 6, - Left: 7, - SharpLeft: 8, -}; - -/** - * @enum {string} - */ -osrm.engine.api.fbresult.TurnName = { - 0: 'None', - 1: 'UTurn', - 2: 'SharpRight', - 3: 'Right', - 4: 'SlightRight', - 5: 'Straight', - 6: 'SlightLeft', - 7: 'Left', - 8: 'SharpLeft', -}; - -/** - * @constructor - */ -osrm.engine.api.fbresult.Position = function () { - /** - * @type {flatbuffers.ByteBuffer} - */ - this.bb = null; - - /** - * @type {number} - */ - this.bb_pos = 0; -}; - -/** - * @param {number} i - * @param {flatbuffers.ByteBuffer} bb - * @returns {osrm.engine.api.fbresult.Position} - */ -osrm.engine.api.fbresult.Position.prototype.__init = function (i, bb) { - this.bb_pos = i; - this.bb = bb; - return this; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Position.prototype.longitude = function () { - return this.bb.readFloat32(this.bb_pos); -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Position.prototype.latitude = function () { - return this.bb.readFloat32(this.bb_pos + 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} longitude - * @param {number} latitude - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Position.createPosition = function ( - builder, - longitude, - latitude, -) { - builder.prep(4, 8); - builder.writeFloat32(latitude); - builder.writeFloat32(longitude); - return builder.offset(); -}; - -/** - * @constructor - */ -osrm.engine.api.fbresult.Uint64Pair = function () { - /** - * @type {flatbuffers.ByteBuffer} - */ - this.bb = null; - - /** - * @type {number} - */ - this.bb_pos = 0; -}; - -/** - * @param {number} i - * @param {flatbuffers.ByteBuffer} bb - * @returns {osrm.engine.api.fbresult.Uint64Pair} - */ -osrm.engine.api.fbresult.Uint64Pair.prototype.__init = function (i, bb) { - this.bb_pos = i; - this.bb = bb; - return this; -}; - -/** - * @returns {flatbuffers.Long} - */ -osrm.engine.api.fbresult.Uint64Pair.prototype.first = function () { - return this.bb.readUint64(this.bb_pos); -}; - -/** - * @returns {flatbuffers.Long} - */ -osrm.engine.api.fbresult.Uint64Pair.prototype.second = function () { - return this.bb.readUint64(this.bb_pos + 8); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Long} first - * @param {flatbuffers.Long} second - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Uint64Pair.createUint64Pair = function ( - builder, - first, - second, -) { - builder.prep(8, 16); - builder.writeInt64(second); - builder.writeInt64(first); - return builder.offset(); -}; - -/** - * @constructor - */ -osrm.engine.api.fbresult.Waypoint = function () { - /** - * @type {flatbuffers.ByteBuffer} - */ - this.bb = null; - - /** - * @type {number} - */ - this.bb_pos = 0; -}; - -/** - * @param {number} i - * @param {flatbuffers.ByteBuffer} bb - * @returns {osrm.engine.api.fbresult.Waypoint} - */ -osrm.engine.api.fbresult.Waypoint.prototype.__init = function (i, bb) { - this.bb_pos = i; - this.bb = bb; - return this; -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Waypoint=} obj - * @returns {osrm.engine.api.fbresult.Waypoint} - */ -osrm.engine.api.fbresult.Waypoint.getRootAsWaypoint = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.Waypoint()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Waypoint=} obj - * @returns {osrm.engine.api.fbresult.Waypoint} - */ -osrm.engine.api.fbresult.Waypoint.getSizePrefixedRootAsWaypoint = function ( - bb, - obj, -) { - return (obj || new osrm.engine.api.fbresult.Waypoint()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.Waypoint.prototype.hint = function (optionalEncoding) { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Waypoint.prototype.distance = function () { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.Waypoint.prototype.name = function (optionalEncoding) { - const offset = this.bb.__offset(this.bb_pos, 8); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @param {osrm.engine.api.fbresult.Position=} obj - * @returns {osrm.engine.api.fbresult.Position|null} - */ -osrm.engine.api.fbresult.Waypoint.prototype.location = function (obj) { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset - ? (obj || new osrm.engine.api.fbresult.Position()).__init( - this.bb_pos + offset, - this.bb, - ) - : null; -}; - -/** - * @param {osrm.engine.api.fbresult.Uint64Pair=} obj - * @returns {osrm.engine.api.fbresult.Uint64Pair|null} - */ -osrm.engine.api.fbresult.Waypoint.prototype.nodes = function (obj) { - const offset = this.bb.__offset(this.bb_pos, 12); - return offset - ? (obj || new osrm.engine.api.fbresult.Uint64Pair()).__init( - this.bb_pos + offset, - this.bb, - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Waypoint.prototype.matchingsIndex = function () { - const offset = this.bb.__offset(this.bb_pos, 14); - return offset ? this.bb.readUint32(this.bb_pos + offset) : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Waypoint.prototype.waypointIndex = function () { - const offset = this.bb.__offset(this.bb_pos, 16); - return offset ? this.bb.readUint32(this.bb_pos + offset) : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Waypoint.prototype.alternativesCount = function () { - const offset = this.bb.__offset(this.bb_pos, 18); - return offset ? this.bb.readUint32(this.bb_pos + offset) : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Waypoint.prototype.tripsIndex = function () { - const offset = this.bb.__offset(this.bb_pos, 20); - return offset ? this.bb.readUint32(this.bb_pos + offset) : 0; -}; - -/** - * @param {flatbuffers.Builder} builder - */ -osrm.engine.api.fbresult.Waypoint.startWaypoint = function (builder) { - builder.startObject(9); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} hintOffset - */ -osrm.engine.api.fbresult.Waypoint.addHint = function (builder, hintOffset) { - builder.addFieldOffset(0, hintOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} distance - */ -osrm.engine.api.fbresult.Waypoint.addDistance = function (builder, distance) { - builder.addFieldFloat32(1, distance, 0.0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} nameOffset - */ -osrm.engine.api.fbresult.Waypoint.addName = function (builder, nameOffset) { - builder.addFieldOffset(2, nameOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} locationOffset - */ -osrm.engine.api.fbresult.Waypoint.addLocation = function ( - builder, - locationOffset, -) { - builder.addFieldStruct(3, locationOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} nodesOffset - */ -osrm.engine.api.fbresult.Waypoint.addNodes = function (builder, nodesOffset) { - builder.addFieldStruct(4, nodesOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} matchingsIndex - */ -osrm.engine.api.fbresult.Waypoint.addMatchingsIndex = function ( - builder, - matchingsIndex, -) { - builder.addFieldInt32(5, matchingsIndex, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} waypointIndex - */ -osrm.engine.api.fbresult.Waypoint.addWaypointIndex = function ( - builder, - waypointIndex, -) { - builder.addFieldInt32(6, waypointIndex, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} alternativesCount - */ -osrm.engine.api.fbresult.Waypoint.addAlternativesCount = function ( - builder, - alternativesCount, -) { - builder.addFieldInt32(7, alternativesCount, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} tripsIndex - */ -osrm.engine.api.fbresult.Waypoint.addTripsIndex = function ( - builder, - tripsIndex, -) { - builder.addFieldInt32(8, tripsIndex, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Waypoint.endWaypoint = function (builder) { - const offset = builder.endObject(); - return offset; -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} hintOffset - * @param {number} distance - * @param {flatbuffers.Offset} nameOffset - * @param {flatbuffers.Offset} locationOffset - * @param {flatbuffers.Offset} nodesOffset - * @param {number} matchingsIndex - * @param {number} waypointIndex - * @param {number} alternativesCount - * @param {number} tripsIndex - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Waypoint.createWaypoint = function ( - builder, - hintOffset, - distance, - nameOffset, - locationOffset, - nodesOffset, - matchingsIndex, - waypointIndex, - alternativesCount, - tripsIndex, -) { - osrm.engine.api.fbresult.Waypoint.startWaypoint(builder); - osrm.engine.api.fbresult.Waypoint.addHint(builder, hintOffset); - osrm.engine.api.fbresult.Waypoint.addDistance(builder, distance); - osrm.engine.api.fbresult.Waypoint.addName(builder, nameOffset); - osrm.engine.api.fbresult.Waypoint.addLocation(builder, locationOffset); - osrm.engine.api.fbresult.Waypoint.addNodes(builder, nodesOffset); - osrm.engine.api.fbresult.Waypoint.addMatchingsIndex(builder, matchingsIndex); - osrm.engine.api.fbresult.Waypoint.addWaypointIndex(builder, waypointIndex); - osrm.engine.api.fbresult.Waypoint.addAlternativesCount( - builder, - alternativesCount, - ); - osrm.engine.api.fbresult.Waypoint.addTripsIndex(builder, tripsIndex); - return osrm.engine.api.fbresult.Waypoint.endWaypoint(builder); -}; - -/** - * @constructor - */ -osrm.engine.api.fbresult.Metadata = function () { - /** - * @type {flatbuffers.ByteBuffer} - */ - this.bb = null; - - /** - * @type {number} - */ - this.bb_pos = 0; -}; - -/** - * @param {number} i - * @param {flatbuffers.ByteBuffer} bb - * @returns {osrm.engine.api.fbresult.Metadata} - */ -osrm.engine.api.fbresult.Metadata.prototype.__init = function (i, bb) { - this.bb_pos = i; - this.bb = bb; - return this; -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Metadata=} obj - * @returns {osrm.engine.api.fbresult.Metadata} - */ -osrm.engine.api.fbresult.Metadata.getRootAsMetadata = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.Metadata()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Metadata=} obj - * @returns {osrm.engine.api.fbresult.Metadata} - */ -osrm.engine.api.fbresult.Metadata.getSizePrefixedRootAsMetadata = function ( - bb, - obj, -) { - return (obj || new osrm.engine.api.fbresult.Metadata()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {number} index - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array} - */ -osrm.engine.api.fbresult.Metadata.prototype.datasourceNames = function ( - index, - optionalEncoding, -) { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset - ? this.bb.__string( - this.bb.__vector(this.bb_pos + offset) + index * 4, - optionalEncoding, - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Metadata.prototype.datasourceNamesLength = - function () { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; - }; - -/** - * @param {flatbuffers.Builder} builder - */ -osrm.engine.api.fbresult.Metadata.startMetadata = function (builder) { - builder.startObject(1); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} datasourceNamesOffset - */ -osrm.engine.api.fbresult.Metadata.addDatasourceNames = function ( - builder, - datasourceNamesOffset, -) { - builder.addFieldOffset(0, datasourceNamesOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Metadata.createDatasourceNamesVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addOffset(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Metadata.startDatasourceNamesVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Metadata.endMetadata = function (builder) { - const offset = builder.endObject(); - return offset; -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} datasourceNamesOffset - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Metadata.createMetadata = function ( - builder, - datasourceNamesOffset, -) { - osrm.engine.api.fbresult.Metadata.startMetadata(builder); - osrm.engine.api.fbresult.Metadata.addDatasourceNames( - builder, - datasourceNamesOffset, - ); - return osrm.engine.api.fbresult.Metadata.endMetadata(builder); -}; - -/** - * @constructor - */ -osrm.engine.api.fbresult.Annotation = function () { - /** - * @type {flatbuffers.ByteBuffer} - */ - this.bb = null; - - /** - * @type {number} - */ - this.bb_pos = 0; -}; - -/** - * @param {number} i - * @param {flatbuffers.ByteBuffer} bb - * @returns {osrm.engine.api.fbresult.Annotation} - */ -osrm.engine.api.fbresult.Annotation.prototype.__init = function (i, bb) { - this.bb_pos = i; - this.bb = bb; - return this; -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Annotation=} obj - * @returns {osrm.engine.api.fbresult.Annotation} - */ -osrm.engine.api.fbresult.Annotation.getRootAsAnnotation = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.Annotation()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Annotation=} obj - * @returns {osrm.engine.api.fbresult.Annotation} - */ -osrm.engine.api.fbresult.Annotation.getSizePrefixedRootAsAnnotation = function ( - bb, - obj, -) { - return (obj || new osrm.engine.api.fbresult.Annotation()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {number} index - * @returns {number} - */ -osrm.engine.api.fbresult.Annotation.prototype.distance = function (index) { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset - ? this.bb.readUint32(this.bb.__vector(this.bb_pos + offset) + index * 4) - : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Annotation.prototype.distanceLength = function () { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @returns {Uint32Array} - */ -osrm.engine.api.fbresult.Annotation.prototype.distanceArray = function () { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset - ? new Uint32Array( - this.bb.bytes().buffer, - this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), - this.bb.__vector_len(this.bb_pos + offset), - ) - : null; -}; - -/** - * @param {number} index - * @returns {number} - */ -osrm.engine.api.fbresult.Annotation.prototype.duration = function (index) { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset - ? this.bb.readUint32(this.bb.__vector(this.bb_pos + offset) + index * 4) - : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Annotation.prototype.durationLength = function () { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @returns {Uint32Array} - */ -osrm.engine.api.fbresult.Annotation.prototype.durationArray = function () { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset - ? new Uint32Array( - this.bb.bytes().buffer, - this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), - this.bb.__vector_len(this.bb_pos + offset), - ) - : null; -}; - -/** - * @param {number} index - * @returns {number} - */ -osrm.engine.api.fbresult.Annotation.prototype.datasources = function (index) { - const offset = this.bb.__offset(this.bb_pos, 8); - return offset - ? this.bb.readUint32(this.bb.__vector(this.bb_pos + offset) + index * 4) - : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Annotation.prototype.datasourcesLength = function () { - const offset = this.bb.__offset(this.bb_pos, 8); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @returns {Uint32Array} - */ -osrm.engine.api.fbresult.Annotation.prototype.datasourcesArray = function () { - const offset = this.bb.__offset(this.bb_pos, 8); - return offset - ? new Uint32Array( - this.bb.bytes().buffer, - this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), - this.bb.__vector_len(this.bb_pos + offset), - ) - : null; -}; - -/** - * @param {number} index - * @returns {number} - */ -osrm.engine.api.fbresult.Annotation.prototype.nodes = function (index) { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset - ? this.bb.readUint32(this.bb.__vector(this.bb_pos + offset) + index * 4) - : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Annotation.prototype.nodesLength = function () { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @returns {Uint32Array} - */ -osrm.engine.api.fbresult.Annotation.prototype.nodesArray = function () { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset - ? new Uint32Array( - this.bb.bytes().buffer, - this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), - this.bb.__vector_len(this.bb_pos + offset), - ) - : null; -}; - -/** - * @param {number} index - * @returns {number} - */ -osrm.engine.api.fbresult.Annotation.prototype.weight = function (index) { - const offset = this.bb.__offset(this.bb_pos, 12); - return offset - ? this.bb.readUint32(this.bb.__vector(this.bb_pos + offset) + index * 4) - : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Annotation.prototype.weightLength = function () { - const offset = this.bb.__offset(this.bb_pos, 12); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @returns {Uint32Array} - */ -osrm.engine.api.fbresult.Annotation.prototype.weightArray = function () { - const offset = this.bb.__offset(this.bb_pos, 12); - return offset - ? new Uint32Array( - this.bb.bytes().buffer, - this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), - this.bb.__vector_len(this.bb_pos + offset), - ) - : null; -}; - -/** - * @param {number} index - * @returns {number} - */ -osrm.engine.api.fbresult.Annotation.prototype.speed = function (index) { - const offset = this.bb.__offset(this.bb_pos, 14); - return offset - ? this.bb.readFloat32(this.bb.__vector(this.bb_pos + offset) + index * 4) - : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Annotation.prototype.speedLength = function () { - const offset = this.bb.__offset(this.bb_pos, 14); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @returns {Float32Array} - */ -osrm.engine.api.fbresult.Annotation.prototype.speedArray = function () { - const offset = this.bb.__offset(this.bb_pos, 14); - return offset - ? new Float32Array( - this.bb.bytes().buffer, - this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), - this.bb.__vector_len(this.bb_pos + offset), - ) - : null; -}; - -/** - * @param {osrm.engine.api.fbresult.Metadata=} obj - * @returns {osrm.engine.api.fbresult.Metadata|null} - */ -osrm.engine.api.fbresult.Annotation.prototype.metadata = function (obj) { - const offset = this.bb.__offset(this.bb_pos, 16); - return offset - ? (obj || new osrm.engine.api.fbresult.Metadata()).__init( - this.bb.__indirect(this.bb_pos + offset), - this.bb, - ) - : null; -}; - -/** - * @param {flatbuffers.Builder} builder - */ -osrm.engine.api.fbresult.Annotation.startAnnotation = function (builder) { - builder.startObject(7); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} distanceOffset - */ -osrm.engine.api.fbresult.Annotation.addDistance = function ( - builder, - distanceOffset, -) { - builder.addFieldOffset(0, distanceOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Annotation.createDistanceVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addInt32(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Annotation.startDistanceVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} durationOffset - */ -osrm.engine.api.fbresult.Annotation.addDuration = function ( - builder, - durationOffset, -) { - builder.addFieldOffset(1, durationOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Annotation.createDurationVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addInt32(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Annotation.startDurationVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} datasourcesOffset - */ -osrm.engine.api.fbresult.Annotation.addDatasources = function ( - builder, - datasourcesOffset, -) { - builder.addFieldOffset(2, datasourcesOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Annotation.createDatasourcesVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addInt32(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Annotation.startDatasourcesVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} nodesOffset - */ -osrm.engine.api.fbresult.Annotation.addNodes = function (builder, nodesOffset) { - builder.addFieldOffset(3, nodesOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Annotation.createNodesVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addInt32(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Annotation.startNodesVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} weightOffset - */ -osrm.engine.api.fbresult.Annotation.addWeight = function ( - builder, - weightOffset, -) { - builder.addFieldOffset(4, weightOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Annotation.createWeightVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addInt32(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Annotation.startWeightVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} speedOffset - */ -osrm.engine.api.fbresult.Annotation.addSpeed = function (builder, speedOffset) { - builder.addFieldOffset(5, speedOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Annotation.createSpeedVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addFloat32(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Annotation.startSpeedVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} metadataOffset - */ -osrm.engine.api.fbresult.Annotation.addMetadata = function ( - builder, - metadataOffset, -) { - builder.addFieldOffset(6, metadataOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Annotation.endAnnotation = function (builder) { - const offset = builder.endObject(); - return offset; -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} distanceOffset - * @param {flatbuffers.Offset} durationOffset - * @param {flatbuffers.Offset} datasourcesOffset - * @param {flatbuffers.Offset} nodesOffset - * @param {flatbuffers.Offset} weightOffset - * @param {flatbuffers.Offset} speedOffset - * @param {flatbuffers.Offset} metadataOffset - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Annotation.createAnnotation = function ( - builder, - distanceOffset, - durationOffset, - datasourcesOffset, - nodesOffset, - weightOffset, - speedOffset, - metadataOffset, -) { - osrm.engine.api.fbresult.Annotation.startAnnotation(builder); - osrm.engine.api.fbresult.Annotation.addDistance(builder, distanceOffset); - osrm.engine.api.fbresult.Annotation.addDuration(builder, durationOffset); - osrm.engine.api.fbresult.Annotation.addDatasources( - builder, - datasourcesOffset, - ); - osrm.engine.api.fbresult.Annotation.addNodes(builder, nodesOffset); - osrm.engine.api.fbresult.Annotation.addWeight(builder, weightOffset); - osrm.engine.api.fbresult.Annotation.addSpeed(builder, speedOffset); - osrm.engine.api.fbresult.Annotation.addMetadata(builder, metadataOffset); - return osrm.engine.api.fbresult.Annotation.endAnnotation(builder); -}; - -/** - * @constructor - */ -osrm.engine.api.fbresult.StepManeuver = function () { - /** - * @type {flatbuffers.ByteBuffer} - */ - this.bb = null; - - /** - * @type {number} - */ - this.bb_pos = 0; -}; - -/** - * @param {number} i - * @param {flatbuffers.ByteBuffer} bb - * @returns {osrm.engine.api.fbresult.StepManeuver} - */ -osrm.engine.api.fbresult.StepManeuver.prototype.__init = function (i, bb) { - this.bb_pos = i; - this.bb = bb; - return this; -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.StepManeuver=} obj - * @returns {osrm.engine.api.fbresult.StepManeuver} - */ -osrm.engine.api.fbresult.StepManeuver.getRootAsStepManeuver = function ( - bb, - obj, -) { - return (obj || new osrm.engine.api.fbresult.StepManeuver()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.StepManeuver=} obj - * @returns {osrm.engine.api.fbresult.StepManeuver} - */ -osrm.engine.api.fbresult.StepManeuver.getSizePrefixedRootAsStepManeuver = - function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.StepManeuver()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); - }; - -/** - * @param {osrm.engine.api.fbresult.Position=} obj - * @returns {osrm.engine.api.fbresult.Position|null} - */ -osrm.engine.api.fbresult.StepManeuver.prototype.location = function (obj) { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset - ? (obj || new osrm.engine.api.fbresult.Position()).__init( - this.bb_pos + offset, - this.bb, - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.StepManeuver.prototype.bearingBefore = function () { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset ? this.bb.readUint16(this.bb_pos + offset) : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.StepManeuver.prototype.bearingAfter = function () { - const offset = this.bb.__offset(this.bb_pos, 8); - return offset ? this.bb.readUint16(this.bb_pos + offset) : 0; -}; - -/** - * @returns {osrm.engine.api.fbresult.ManeuverType} - */ -osrm.engine.api.fbresult.StepManeuver.prototype.type = function () { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset - ? /** @type {osrm.engine.api.fbresult.ManeuverType} */ ( - this.bb.readInt8(this.bb_pos + offset) - ) - : osrm.engine.api.fbresult.ManeuverType.Turn; -}; - -/** - * @returns {osrm.engine.api.fbresult.Turn} - */ -osrm.engine.api.fbresult.StepManeuver.prototype.modifier = function () { - const offset = this.bb.__offset(this.bb_pos, 12); - return offset - ? /** @type {osrm.engine.api.fbresult.Turn} */ ( - this.bb.readInt8(this.bb_pos + offset) - ) - : osrm.engine.api.fbresult.Turn.None; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.StepManeuver.prototype.exit = function () { - const offset = this.bb.__offset(this.bb_pos, 14); - return offset ? this.bb.readUint8(this.bb_pos + offset) : 0; -}; - -/** - * @param {flatbuffers.Builder} builder - */ -osrm.engine.api.fbresult.StepManeuver.startStepManeuver = function (builder) { - builder.startObject(6); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} locationOffset - */ -osrm.engine.api.fbresult.StepManeuver.addLocation = function ( - builder, - locationOffset, -) { - builder.addFieldStruct(0, locationOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} bearingBefore - */ -osrm.engine.api.fbresult.StepManeuver.addBearingBefore = function ( - builder, - bearingBefore, -) { - builder.addFieldInt16(1, bearingBefore, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} bearingAfter - */ -osrm.engine.api.fbresult.StepManeuver.addBearingAfter = function ( - builder, - bearingAfter, -) { - builder.addFieldInt16(2, bearingAfter, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {osrm.engine.api.fbresult.ManeuverType} type - */ -osrm.engine.api.fbresult.StepManeuver.addType = function (builder, type) { - builder.addFieldInt8(3, type, osrm.engine.api.fbresult.ManeuverType.Turn); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {osrm.engine.api.fbresult.Turn} modifier - */ -osrm.engine.api.fbresult.StepManeuver.addModifier = function ( - builder, - modifier, -) { - builder.addFieldInt8(4, modifier, osrm.engine.api.fbresult.Turn.None); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} exit - */ -osrm.engine.api.fbresult.StepManeuver.addExit = function (builder, exit) { - builder.addFieldInt8(5, exit, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.StepManeuver.endStepManeuver = function (builder) { - const offset = builder.endObject(); - return offset; -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} locationOffset - * @param {number} bearingBefore - * @param {number} bearingAfter - * @param {osrm.engine.api.fbresult.ManeuverType} type - * @param {osrm.engine.api.fbresult.Turn} modifier - * @param {number} exit - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.StepManeuver.createStepManeuver = function ( - builder, - locationOffset, - bearingBefore, - bearingAfter, - type, - modifier, - exit, -) { - osrm.engine.api.fbresult.StepManeuver.startStepManeuver(builder); - osrm.engine.api.fbresult.StepManeuver.addLocation(builder, locationOffset); - osrm.engine.api.fbresult.StepManeuver.addBearingBefore( - builder, - bearingBefore, - ); - osrm.engine.api.fbresult.StepManeuver.addBearingAfter(builder, bearingAfter); - osrm.engine.api.fbresult.StepManeuver.addType(builder, type); - osrm.engine.api.fbresult.StepManeuver.addModifier(builder, modifier); - osrm.engine.api.fbresult.StepManeuver.addExit(builder, exit); - return osrm.engine.api.fbresult.StepManeuver.endStepManeuver(builder); -}; - -/** - * @constructor - */ -osrm.engine.api.fbresult.Lane = function () { - /** - * @type {flatbuffers.ByteBuffer} - */ - this.bb = null; - - /** - * @type {number} - */ - this.bb_pos = 0; -}; - -/** - * @param {number} i - * @param {flatbuffers.ByteBuffer} bb - * @returns {osrm.engine.api.fbresult.Lane} - */ -osrm.engine.api.fbresult.Lane.prototype.__init = function (i, bb) { - this.bb_pos = i; - this.bb = bb; - return this; -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Lane=} obj - * @returns {osrm.engine.api.fbresult.Lane} - */ -osrm.engine.api.fbresult.Lane.getRootAsLane = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.Lane()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Lane=} obj - * @returns {osrm.engine.api.fbresult.Lane} - */ -osrm.engine.api.fbresult.Lane.getSizePrefixedRootAsLane = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.Lane()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {number} index - * @returns {osrm.engine.api.fbresult.Turn} - */ -osrm.engine.api.fbresult.Lane.prototype.indications = function (index) { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset - ? /** @type {osrm.engine.api.fbresult.Turn} */ ( - this.bb.readInt8(this.bb.__vector(this.bb_pos + offset) + index) - ) - : /** @type {osrm.engine.api.fbresult.Turn} */ (0); -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Lane.prototype.indicationsLength = function () { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @returns {Int8Array} - */ -osrm.engine.api.fbresult.Lane.prototype.indicationsArray = function () { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset - ? new Int8Array( - this.bb.bytes().buffer, - this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), - this.bb.__vector_len(this.bb_pos + offset), - ) - : null; -}; - -/** - * @returns {boolean} - */ -osrm.engine.api.fbresult.Lane.prototype.valid = function () { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false; -}; - -/** - * @param {flatbuffers.Builder} builder - */ -osrm.engine.api.fbresult.Lane.startLane = function (builder) { - builder.startObject(2); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} indicationsOffset - */ -osrm.engine.api.fbresult.Lane.addIndications = function ( - builder, - indicationsOffset, -) { - builder.addFieldOffset(0, indicationsOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Lane.createIndicationsVector = function ( - builder, - data, -) { - builder.startVector(1, data.length, 1); - for (let i = data.length - 1; i >= 0; i--) { - builder.addInt8(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Lane.startIndicationsVector = function ( - builder, - numElems, -) { - builder.startVector(1, numElems, 1); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {boolean} valid - */ -osrm.engine.api.fbresult.Lane.addValid = function (builder, valid) { - builder.addFieldInt8(1, +valid, +false); -}; - -/** - * @param {flatbuffers.Builder} builder - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Lane.endLane = function (builder) { - const offset = builder.endObject(); - return offset; -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} indicationsOffset - * @param {boolean} valid - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Lane.createLane = function ( - builder, - indicationsOffset, - valid, -) { - osrm.engine.api.fbresult.Lane.startLane(builder); - osrm.engine.api.fbresult.Lane.addIndications(builder, indicationsOffset); - osrm.engine.api.fbresult.Lane.addValid(builder, valid); - return osrm.engine.api.fbresult.Lane.endLane(builder); -}; - -/** - * @constructor - */ -osrm.engine.api.fbresult.Intersection = function () { - /** - * @type {flatbuffers.ByteBuffer} - */ - this.bb = null; - - /** - * @type {number} - */ - this.bb_pos = 0; -}; - -/** - * @param {number} i - * @param {flatbuffers.ByteBuffer} bb - * @returns {osrm.engine.api.fbresult.Intersection} - */ -osrm.engine.api.fbresult.Intersection.prototype.__init = function (i, bb) { - this.bb_pos = i; - this.bb = bb; - return this; -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Intersection=} obj - * @returns {osrm.engine.api.fbresult.Intersection} - */ -osrm.engine.api.fbresult.Intersection.getRootAsIntersection = function ( - bb, - obj, -) { - return (obj || new osrm.engine.api.fbresult.Intersection()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Intersection=} obj - * @returns {osrm.engine.api.fbresult.Intersection} - */ -osrm.engine.api.fbresult.Intersection.getSizePrefixedRootAsIntersection = - function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.Intersection()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); - }; - -/** - * @param {osrm.engine.api.fbresult.Position=} obj - * @returns {osrm.engine.api.fbresult.Position|null} - */ -osrm.engine.api.fbresult.Intersection.prototype.location = function (obj) { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset - ? (obj || new osrm.engine.api.fbresult.Position()).__init( - this.bb_pos + offset, - this.bb, - ) - : null; -}; - -/** - * @param {number} index - * @returns {number} - */ -osrm.engine.api.fbresult.Intersection.prototype.bearings = function (index) { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset - ? this.bb.readInt16(this.bb.__vector(this.bb_pos + offset) + index * 2) - : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Intersection.prototype.bearingsLength = function () { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @returns {Int16Array} - */ -osrm.engine.api.fbresult.Intersection.prototype.bearingsArray = function () { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset - ? new Int16Array( - this.bb.bytes().buffer, - this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), - this.bb.__vector_len(this.bb_pos + offset), - ) - : null; -}; - -/** - * @param {number} index - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array} - */ -osrm.engine.api.fbresult.Intersection.prototype.classes = function ( - index, - optionalEncoding, -) { - const offset = this.bb.__offset(this.bb_pos, 8); - return offset - ? this.bb.__string( - this.bb.__vector(this.bb_pos + offset) + index * 4, - optionalEncoding, - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Intersection.prototype.classesLength = function () { - const offset = this.bb.__offset(this.bb_pos, 8); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @param {number} index - * @returns {boolean} - */ -osrm.engine.api.fbresult.Intersection.prototype.entry = function (index) { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset - ? !!this.bb.readInt8(this.bb.__vector(this.bb_pos + offset) + index) - : false; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Intersection.prototype.entryLength = function () { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @returns {Int8Array} - */ -osrm.engine.api.fbresult.Intersection.prototype.entryArray = function () { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset - ? new Int8Array( - this.bb.bytes().buffer, - this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), - this.bb.__vector_len(this.bb_pos + offset), - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Intersection.prototype.inBearing = function () { - const offset = this.bb.__offset(this.bb_pos, 12); - return offset ? this.bb.readUint32(this.bb_pos + offset) : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Intersection.prototype.outBearing = function () { - const offset = this.bb.__offset(this.bb_pos, 14); - return offset ? this.bb.readUint32(this.bb_pos + offset) : 0; -}; - -/** - * @param {number} index - * @param {osrm.engine.api.fbresult.Lane=} obj - * @returns {osrm.engine.api.fbresult.Lane} - */ -osrm.engine.api.fbresult.Intersection.prototype.lanes = function (index, obj) { - const offset = this.bb.__offset(this.bb_pos, 16); - return offset - ? (obj || new osrm.engine.api.fbresult.Lane()).__init( - this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), - this.bb, - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Intersection.prototype.lanesLength = function () { - const offset = this.bb.__offset(this.bb_pos, 16); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @param {flatbuffers.Builder} builder - */ -osrm.engine.api.fbresult.Intersection.startIntersection = function (builder) { - builder.startObject(7); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} locationOffset - */ -osrm.engine.api.fbresult.Intersection.addLocation = function ( - builder, - locationOffset, -) { - builder.addFieldStruct(0, locationOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} bearingsOffset - */ -osrm.engine.api.fbresult.Intersection.addBearings = function ( - builder, - bearingsOffset, -) { - builder.addFieldOffset(1, bearingsOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Intersection.createBearingsVector = function ( - builder, - data, -) { - builder.startVector(2, data.length, 2); - for (let i = data.length - 1; i >= 0; i--) { - builder.addInt16(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Intersection.startBearingsVector = function ( - builder, - numElems, -) { - builder.startVector(2, numElems, 2); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} classesOffset - */ -osrm.engine.api.fbresult.Intersection.addClasses = function ( - builder, - classesOffset, -) { - builder.addFieldOffset(2, classesOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Intersection.createClassesVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addOffset(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Intersection.startClassesVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} entryOffset - */ -osrm.engine.api.fbresult.Intersection.addEntry = function ( - builder, - entryOffset, -) { - builder.addFieldOffset(3, entryOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Intersection.createEntryVector = function ( - builder, - data, -) { - builder.startVector(1, data.length, 1); - for (let i = data.length - 1; i >= 0; i--) { - builder.addInt8(+data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Intersection.startEntryVector = function ( - builder, - numElems, -) { - builder.startVector(1, numElems, 1); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} inBearing - */ -osrm.engine.api.fbresult.Intersection.addInBearing = function ( - builder, - inBearing, -) { - builder.addFieldInt32(4, inBearing, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} outBearing - */ -osrm.engine.api.fbresult.Intersection.addOutBearing = function ( - builder, - outBearing, -) { - builder.addFieldInt32(5, outBearing, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} lanesOffset - */ -osrm.engine.api.fbresult.Intersection.addLanes = function ( - builder, - lanesOffset, -) { - builder.addFieldOffset(6, lanesOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Intersection.createLanesVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addOffset(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Intersection.startLanesVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Intersection.endIntersection = function (builder) { - const offset = builder.endObject(); - return offset; -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} locationOffset - * @param {flatbuffers.Offset} bearingsOffset - * @param {flatbuffers.Offset} classesOffset - * @param {flatbuffers.Offset} entryOffset - * @param {number} inBearing - * @param {number} outBearing - * @param {flatbuffers.Offset} lanesOffset - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Intersection.createIntersection = function ( - builder, - locationOffset, - bearingsOffset, - classesOffset, - entryOffset, - inBearing, - outBearing, - lanesOffset, -) { - osrm.engine.api.fbresult.Intersection.startIntersection(builder); - osrm.engine.api.fbresult.Intersection.addLocation(builder, locationOffset); - osrm.engine.api.fbresult.Intersection.addBearings(builder, bearingsOffset); - osrm.engine.api.fbresult.Intersection.addClasses(builder, classesOffset); - osrm.engine.api.fbresult.Intersection.addEntry(builder, entryOffset); - osrm.engine.api.fbresult.Intersection.addInBearing(builder, inBearing); - osrm.engine.api.fbresult.Intersection.addOutBearing(builder, outBearing); - osrm.engine.api.fbresult.Intersection.addLanes(builder, lanesOffset); - return osrm.engine.api.fbresult.Intersection.endIntersection(builder); -}; - -/** - * @constructor - */ -osrm.engine.api.fbresult.Step = function () { - /** - * @type {flatbuffers.ByteBuffer} - */ - this.bb = null; - - /** - * @type {number} - */ - this.bb_pos = 0; -}; - -/** - * @param {number} i - * @param {flatbuffers.ByteBuffer} bb - * @returns {osrm.engine.api.fbresult.Step} - */ -osrm.engine.api.fbresult.Step.prototype.__init = function (i, bb) { - this.bb_pos = i; - this.bb = bb; - return this; -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Step=} obj - * @returns {osrm.engine.api.fbresult.Step} - */ -osrm.engine.api.fbresult.Step.getRootAsStep = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.Step()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Step=} obj - * @returns {osrm.engine.api.fbresult.Step} - */ -osrm.engine.api.fbresult.Step.getSizePrefixedRootAsStep = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.Step()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Step.prototype.distance = function () { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Step.prototype.duration = function () { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.Step.prototype.polyline = function (optionalEncoding) { - const offset = this.bb.__offset(this.bb_pos, 8); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @param {number} index - * @param {osrm.engine.api.fbresult.Position=} obj - * @returns {osrm.engine.api.fbresult.Position} - */ -osrm.engine.api.fbresult.Step.prototype.coordinates = function (index, obj) { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset - ? (obj || new osrm.engine.api.fbresult.Position()).__init( - this.bb.__vector(this.bb_pos + offset) + index * 8, - this.bb, - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Step.prototype.coordinatesLength = function () { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Step.prototype.weight = function () { - const offset = this.bb.__offset(this.bb_pos, 12); - return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.Step.prototype.name = function (optionalEncoding) { - const offset = this.bb.__offset(this.bb_pos, 14); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.Step.prototype.ref = function (optionalEncoding) { - const offset = this.bb.__offset(this.bb_pos, 16); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.Step.prototype.pronunciation = function ( - optionalEncoding, -) { - const offset = this.bb.__offset(this.bb_pos, 18); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.Step.prototype.destinations = function ( - optionalEncoding, -) { - const offset = this.bb.__offset(this.bb_pos, 20); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.Step.prototype.exits = function (optionalEncoding) { - const offset = this.bb.__offset(this.bb_pos, 22); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.Step.prototype.mode = function (optionalEncoding) { - const offset = this.bb.__offset(this.bb_pos, 24); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @param {osrm.engine.api.fbresult.StepManeuver=} obj - * @returns {osrm.engine.api.fbresult.StepManeuver|null} - */ -osrm.engine.api.fbresult.Step.prototype.maneuver = function (obj) { - const offset = this.bb.__offset(this.bb_pos, 26); - return offset - ? (obj || new osrm.engine.api.fbresult.StepManeuver()).__init( - this.bb.__indirect(this.bb_pos + offset), - this.bb, - ) - : null; -}; - -/** - * @param {number} index - * @param {osrm.engine.api.fbresult.Intersection=} obj - * @returns {osrm.engine.api.fbresult.Intersection} - */ -osrm.engine.api.fbresult.Step.prototype.intersections = function (index, obj) { - const offset = this.bb.__offset(this.bb_pos, 28); - return offset - ? (obj || new osrm.engine.api.fbresult.Intersection()).__init( - this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), - this.bb, - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Step.prototype.intersectionsLength = function () { - const offset = this.bb.__offset(this.bb_pos, 28); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.Step.prototype.rotaryName = function ( - optionalEncoding, -) { - const offset = this.bb.__offset(this.bb_pos, 30); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.Step.prototype.rotaryPronunciation = function ( - optionalEncoding, -) { - const offset = this.bb.__offset(this.bb_pos, 32); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @returns {boolean} - */ -osrm.engine.api.fbresult.Step.prototype.drivingSide = function () { - const offset = this.bb.__offset(this.bb_pos, 34); - return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false; -}; - -/** - * @param {flatbuffers.Builder} builder - */ -osrm.engine.api.fbresult.Step.startStep = function (builder) { - builder.startObject(16); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} distance - */ -osrm.engine.api.fbresult.Step.addDistance = function (builder, distance) { - builder.addFieldFloat32(0, distance, 0.0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} duration - */ -osrm.engine.api.fbresult.Step.addDuration = function (builder, duration) { - builder.addFieldFloat32(1, duration, 0.0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} polylineOffset - */ -osrm.engine.api.fbresult.Step.addPolyline = function (builder, polylineOffset) { - builder.addFieldOffset(2, polylineOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} coordinatesOffset - */ -osrm.engine.api.fbresult.Step.addCoordinates = function ( - builder, - coordinatesOffset, -) { - builder.addFieldOffset(3, coordinatesOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Step.startCoordinatesVector = function ( - builder, - numElems, -) { - builder.startVector(8, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} weight - */ -osrm.engine.api.fbresult.Step.addWeight = function (builder, weight) { - builder.addFieldFloat32(4, weight, 0.0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} nameOffset - */ -osrm.engine.api.fbresult.Step.addName = function (builder, nameOffset) { - builder.addFieldOffset(5, nameOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} refOffset - */ -osrm.engine.api.fbresult.Step.addRef = function (builder, refOffset) { - builder.addFieldOffset(6, refOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} pronunciationOffset - */ -osrm.engine.api.fbresult.Step.addPronunciation = function ( - builder, - pronunciationOffset, -) { - builder.addFieldOffset(7, pronunciationOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} destinationsOffset - */ -osrm.engine.api.fbresult.Step.addDestinations = function ( - builder, - destinationsOffset, -) { - builder.addFieldOffset(8, destinationsOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} exitsOffset - */ -osrm.engine.api.fbresult.Step.addExits = function (builder, exitsOffset) { - builder.addFieldOffset(9, exitsOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} modeOffset - */ -osrm.engine.api.fbresult.Step.addMode = function (builder, modeOffset) { - builder.addFieldOffset(10, modeOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} maneuverOffset - */ -osrm.engine.api.fbresult.Step.addManeuver = function (builder, maneuverOffset) { - builder.addFieldOffset(11, maneuverOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} intersectionsOffset - */ -osrm.engine.api.fbresult.Step.addIntersections = function ( - builder, - intersectionsOffset, -) { - builder.addFieldOffset(12, intersectionsOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Step.createIntersectionsVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addOffset(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Step.startIntersectionsVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} rotaryNameOffset - */ -osrm.engine.api.fbresult.Step.addRotaryName = function ( - builder, - rotaryNameOffset, -) { - builder.addFieldOffset(13, rotaryNameOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} rotaryPronunciationOffset - */ -osrm.engine.api.fbresult.Step.addRotaryPronunciation = function ( - builder, - rotaryPronunciationOffset, -) { - builder.addFieldOffset(14, rotaryPronunciationOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {boolean} drivingSide - */ -osrm.engine.api.fbresult.Step.addDrivingSide = function (builder, drivingSide) { - builder.addFieldInt8(15, +drivingSide, +false); -}; - -/** - * @param {flatbuffers.Builder} builder - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Step.endStep = function (builder) { - const offset = builder.endObject(); - return offset; -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} distance - * @param {number} duration - * @param {flatbuffers.Offset} polylineOffset - * @param {flatbuffers.Offset} coordinatesOffset - * @param {number} weight - * @param {flatbuffers.Offset} nameOffset - * @param {flatbuffers.Offset} refOffset - * @param {flatbuffers.Offset} pronunciationOffset - * @param {flatbuffers.Offset} destinationsOffset - * @param {flatbuffers.Offset} exitsOffset - * @param {flatbuffers.Offset} modeOffset - * @param {flatbuffers.Offset} maneuverOffset - * @param {flatbuffers.Offset} intersectionsOffset - * @param {flatbuffers.Offset} rotaryNameOffset - * @param {flatbuffers.Offset} rotaryPronunciationOffset - * @param {boolean} drivingSide - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Step.createStep = function ( - builder, - distance, - duration, - polylineOffset, - coordinatesOffset, - weight, - nameOffset, - refOffset, - pronunciationOffset, - destinationsOffset, - exitsOffset, - modeOffset, - maneuverOffset, - intersectionsOffset, - rotaryNameOffset, - rotaryPronunciationOffset, - drivingSide, -) { - osrm.engine.api.fbresult.Step.startStep(builder); - osrm.engine.api.fbresult.Step.addDistance(builder, distance); - osrm.engine.api.fbresult.Step.addDuration(builder, duration); - osrm.engine.api.fbresult.Step.addPolyline(builder, polylineOffset); - osrm.engine.api.fbresult.Step.addCoordinates(builder, coordinatesOffset); - osrm.engine.api.fbresult.Step.addWeight(builder, weight); - osrm.engine.api.fbresult.Step.addName(builder, nameOffset); - osrm.engine.api.fbresult.Step.addRef(builder, refOffset); - osrm.engine.api.fbresult.Step.addPronunciation(builder, pronunciationOffset); - osrm.engine.api.fbresult.Step.addDestinations(builder, destinationsOffset); - osrm.engine.api.fbresult.Step.addExits(builder, exitsOffset); - osrm.engine.api.fbresult.Step.addMode(builder, modeOffset); - osrm.engine.api.fbresult.Step.addManeuver(builder, maneuverOffset); - osrm.engine.api.fbresult.Step.addIntersections(builder, intersectionsOffset); - osrm.engine.api.fbresult.Step.addRotaryName(builder, rotaryNameOffset); - osrm.engine.api.fbresult.Step.addRotaryPronunciation( - builder, - rotaryPronunciationOffset, - ); - osrm.engine.api.fbresult.Step.addDrivingSide(builder, drivingSide); - return osrm.engine.api.fbresult.Step.endStep(builder); -}; - -/** - * @constructor - */ -osrm.engine.api.fbresult.Leg = function () { - /** - * @type {flatbuffers.ByteBuffer} - */ - this.bb = null; - - /** - * @type {number} - */ - this.bb_pos = 0; -}; - -/** - * @param {number} i - * @param {flatbuffers.ByteBuffer} bb - * @returns {osrm.engine.api.fbresult.Leg} - */ -osrm.engine.api.fbresult.Leg.prototype.__init = function (i, bb) { - this.bb_pos = i; - this.bb = bb; - return this; -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Leg=} obj - * @returns {osrm.engine.api.fbresult.Leg} - */ -osrm.engine.api.fbresult.Leg.getRootAsLeg = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.Leg()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Leg=} obj - * @returns {osrm.engine.api.fbresult.Leg} - */ -osrm.engine.api.fbresult.Leg.getSizePrefixedRootAsLeg = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.Leg()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Leg.prototype.distance = function () { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset ? this.bb.readFloat64(this.bb_pos + offset) : 0.0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Leg.prototype.duration = function () { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset ? this.bb.readFloat64(this.bb_pos + offset) : 0.0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Leg.prototype.weight = function () { - const offset = this.bb.__offset(this.bb_pos, 8); - return offset ? this.bb.readFloat64(this.bb_pos + offset) : 0.0; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.Leg.prototype.summary = function (optionalEncoding) { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @param {osrm.engine.api.fbresult.Annotation=} obj - * @returns {osrm.engine.api.fbresult.Annotation|null} - */ -osrm.engine.api.fbresult.Leg.prototype.annotations = function (obj) { - const offset = this.bb.__offset(this.bb_pos, 12); - return offset - ? (obj || new osrm.engine.api.fbresult.Annotation()).__init( - this.bb.__indirect(this.bb_pos + offset), - this.bb, - ) - : null; -}; - -/** - * @param {number} index - * @param {osrm.engine.api.fbresult.Step=} obj - * @returns {osrm.engine.api.fbresult.Step} - */ -osrm.engine.api.fbresult.Leg.prototype.steps = function (index, obj) { - const offset = this.bb.__offset(this.bb_pos, 14); - return offset - ? (obj || new osrm.engine.api.fbresult.Step()).__init( - this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), - this.bb, - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Leg.prototype.stepsLength = function () { - const offset = this.bb.__offset(this.bb_pos, 14); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @param {flatbuffers.Builder} builder - */ -osrm.engine.api.fbresult.Leg.startLeg = function (builder) { - builder.startObject(6); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} distance - */ -osrm.engine.api.fbresult.Leg.addDistance = function (builder, distance) { - builder.addFieldFloat64(0, distance, 0.0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} duration - */ -osrm.engine.api.fbresult.Leg.addDuration = function (builder, duration) { - builder.addFieldFloat64(1, duration, 0.0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} weight - */ -osrm.engine.api.fbresult.Leg.addWeight = function (builder, weight) { - builder.addFieldFloat64(2, weight, 0.0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} summaryOffset - */ -osrm.engine.api.fbresult.Leg.addSummary = function (builder, summaryOffset) { - builder.addFieldOffset(3, summaryOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} annotationsOffset - */ -osrm.engine.api.fbresult.Leg.addAnnotations = function ( - builder, - annotationsOffset, -) { - builder.addFieldOffset(4, annotationsOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} stepsOffset - */ -osrm.engine.api.fbresult.Leg.addSteps = function (builder, stepsOffset) { - builder.addFieldOffset(5, stepsOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Leg.createStepsVector = function (builder, data) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addOffset(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Leg.startStepsVector = function (builder, numElems) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Leg.endLeg = function (builder) { - const offset = builder.endObject(); - return offset; -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} distance - * @param {number} duration - * @param {number} weight - * @param {flatbuffers.Offset} summaryOffset - * @param {flatbuffers.Offset} annotationsOffset - * @param {flatbuffers.Offset} stepsOffset - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Leg.createLeg = function ( - builder, - distance, - duration, - weight, - summaryOffset, - annotationsOffset, - stepsOffset, -) { - osrm.engine.api.fbresult.Leg.startLeg(builder); - osrm.engine.api.fbresult.Leg.addDistance(builder, distance); - osrm.engine.api.fbresult.Leg.addDuration(builder, duration); - osrm.engine.api.fbresult.Leg.addWeight(builder, weight); - osrm.engine.api.fbresult.Leg.addSummary(builder, summaryOffset); - osrm.engine.api.fbresult.Leg.addAnnotations(builder, annotationsOffset); - osrm.engine.api.fbresult.Leg.addSteps(builder, stepsOffset); - return osrm.engine.api.fbresult.Leg.endLeg(builder); -}; - -/** - * @constructor - */ -osrm.engine.api.fbresult.RouteObject = function () { - /** - * @type {flatbuffers.ByteBuffer} - */ - this.bb = null; - - /** - * @type {number} - */ - this.bb_pos = 0; -}; - -/** - * @param {number} i - * @param {flatbuffers.ByteBuffer} bb - * @returns {osrm.engine.api.fbresult.RouteObject} - */ -osrm.engine.api.fbresult.RouteObject.prototype.__init = function (i, bb) { - this.bb_pos = i; - this.bb = bb; - return this; -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.RouteObject=} obj - * @returns {osrm.engine.api.fbresult.RouteObject} - */ -osrm.engine.api.fbresult.RouteObject.getRootAsRouteObject = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.RouteObject()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.RouteObject=} obj - * @returns {osrm.engine.api.fbresult.RouteObject} - */ -osrm.engine.api.fbresult.RouteObject.getSizePrefixedRootAsRouteObject = - function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.RouteObject()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); - }; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.RouteObject.prototype.distance = function () { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.RouteObject.prototype.duration = function () { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.RouteObject.prototype.weight = function () { - const offset = this.bb.__offset(this.bb_pos, 8); - return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.RouteObject.prototype.weightName = function ( - optionalEncoding, -) { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.RouteObject.prototype.confidence = function () { - const offset = this.bb.__offset(this.bb_pos, 12); - return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.RouteObject.prototype.polyline = function ( - optionalEncoding, -) { - const offset = this.bb.__offset(this.bb_pos, 14); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @param {number} index - * @param {osrm.engine.api.fbresult.Position=} obj - * @returns {osrm.engine.api.fbresult.Position} - */ -osrm.engine.api.fbresult.RouteObject.prototype.coordinates = function ( - index, - obj, -) { - const offset = this.bb.__offset(this.bb_pos, 16); - return offset - ? (obj || new osrm.engine.api.fbresult.Position()).__init( - this.bb.__vector(this.bb_pos + offset) + index * 8, - this.bb, - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.RouteObject.prototype.coordinatesLength = function () { - const offset = this.bb.__offset(this.bb_pos, 16); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @param {number} index - * @param {osrm.engine.api.fbresult.Leg=} obj - * @returns {osrm.engine.api.fbresult.Leg} - */ -osrm.engine.api.fbresult.RouteObject.prototype.legs = function (index, obj) { - const offset = this.bb.__offset(this.bb_pos, 18); - return offset - ? (obj || new osrm.engine.api.fbresult.Leg()).__init( - this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), - this.bb, - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.RouteObject.prototype.legsLength = function () { - const offset = this.bb.__offset(this.bb_pos, 18); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @param {flatbuffers.Builder} builder - */ -osrm.engine.api.fbresult.RouteObject.startRouteObject = function (builder) { - builder.startObject(8); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} distance - */ -osrm.engine.api.fbresult.RouteObject.addDistance = function ( - builder, - distance, -) { - builder.addFieldFloat32(0, distance, 0.0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} duration - */ -osrm.engine.api.fbresult.RouteObject.addDuration = function ( - builder, - duration, -) { - builder.addFieldFloat32(1, duration, 0.0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} weight - */ -osrm.engine.api.fbresult.RouteObject.addWeight = function (builder, weight) { - builder.addFieldFloat32(2, weight, 0.0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} weightNameOffset - */ -osrm.engine.api.fbresult.RouteObject.addWeightName = function ( - builder, - weightNameOffset, -) { - builder.addFieldOffset(3, weightNameOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} confidence - */ -osrm.engine.api.fbresult.RouteObject.addConfidence = function ( - builder, - confidence, -) { - builder.addFieldFloat32(4, confidence, 0.0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} polylineOffset - */ -osrm.engine.api.fbresult.RouteObject.addPolyline = function ( - builder, - polylineOffset, -) { - builder.addFieldOffset(5, polylineOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} coordinatesOffset - */ -osrm.engine.api.fbresult.RouteObject.addCoordinates = function ( - builder, - coordinatesOffset, -) { - builder.addFieldOffset(6, coordinatesOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.RouteObject.startCoordinatesVector = function ( - builder, - numElems, -) { - builder.startVector(8, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} legsOffset - */ -osrm.engine.api.fbresult.RouteObject.addLegs = function (builder, legsOffset) { - builder.addFieldOffset(7, legsOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.RouteObject.createLegsVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addOffset(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.RouteObject.startLegsVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.RouteObject.endRouteObject = function (builder) { - const offset = builder.endObject(); - return offset; -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} distance - * @param {number} duration - * @param {number} weight - * @param {flatbuffers.Offset} weightNameOffset - * @param {number} confidence - * @param {flatbuffers.Offset} polylineOffset - * @param {flatbuffers.Offset} coordinatesOffset - * @param {flatbuffers.Offset} legsOffset - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.RouteObject.createRouteObject = function ( - builder, - distance, - duration, - weight, - weightNameOffset, - confidence, - polylineOffset, - coordinatesOffset, - legsOffset, -) { - osrm.engine.api.fbresult.RouteObject.startRouteObject(builder); - osrm.engine.api.fbresult.RouteObject.addDistance(builder, distance); - osrm.engine.api.fbresult.RouteObject.addDuration(builder, duration); - osrm.engine.api.fbresult.RouteObject.addWeight(builder, weight); - osrm.engine.api.fbresult.RouteObject.addWeightName(builder, weightNameOffset); - osrm.engine.api.fbresult.RouteObject.addConfidence(builder, confidence); - osrm.engine.api.fbresult.RouteObject.addPolyline(builder, polylineOffset); - osrm.engine.api.fbresult.RouteObject.addCoordinates( - builder, - coordinatesOffset, - ); - osrm.engine.api.fbresult.RouteObject.addLegs(builder, legsOffset); - return osrm.engine.api.fbresult.RouteObject.endRouteObject(builder); -}; - -/** - * @constructor - */ -osrm.engine.api.fbresult.Table = function () { - /** - * @type {flatbuffers.ByteBuffer} - */ - this.bb = null; - - /** - * @type {number} - */ - this.bb_pos = 0; -}; - -/** - * @param {number} i - * @param {flatbuffers.ByteBuffer} bb - * @returns {osrm.engine.api.fbresult.Table} - */ -osrm.engine.api.fbresult.Table.prototype.__init = function (i, bb) { - this.bb_pos = i; - this.bb = bb; - return this; -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Table=} obj - * @returns {osrm.engine.api.fbresult.Table} - */ -osrm.engine.api.fbresult.Table.getRootAsTable = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.Table()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Table=} obj - * @returns {osrm.engine.api.fbresult.Table} - */ -osrm.engine.api.fbresult.Table.getSizePrefixedRootAsTable = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.Table()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {number} index - * @returns {number} - */ -osrm.engine.api.fbresult.Table.prototype.durations = function (index) { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset - ? this.bb.readFloat32(this.bb.__vector(this.bb_pos + offset) + index * 4) - : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Table.prototype.durationsLength = function () { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @returns {Float32Array} - */ -osrm.engine.api.fbresult.Table.prototype.durationsArray = function () { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset - ? new Float32Array( - this.bb.bytes().buffer, - this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), - this.bb.__vector_len(this.bb_pos + offset), - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Table.prototype.rows = function () { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset ? this.bb.readUint16(this.bb_pos + offset) : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Table.prototype.cols = function () { - const offset = this.bb.__offset(this.bb_pos, 8); - return offset ? this.bb.readUint16(this.bb_pos + offset) : 0; -}; - -/** - * @param {number} index - * @returns {number} - */ -osrm.engine.api.fbresult.Table.prototype.distances = function (index) { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset - ? this.bb.readFloat32(this.bb.__vector(this.bb_pos + offset) + index * 4) - : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Table.prototype.distancesLength = function () { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @returns {Float32Array} - */ -osrm.engine.api.fbresult.Table.prototype.distancesArray = function () { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset - ? new Float32Array( - this.bb.bytes().buffer, - this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), - this.bb.__vector_len(this.bb_pos + offset), - ) - : null; -}; - -/** - * @param {number} index - * @param {osrm.engine.api.fbresult.Waypoint=} obj - * @returns {osrm.engine.api.fbresult.Waypoint} - */ -osrm.engine.api.fbresult.Table.prototype.destinations = function (index, obj) { - const offset = this.bb.__offset(this.bb_pos, 12); - return offset - ? (obj || new osrm.engine.api.fbresult.Waypoint()).__init( - this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), - this.bb, - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Table.prototype.destinationsLength = function () { - const offset = this.bb.__offset(this.bb_pos, 12); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @param {number} index - * @returns {number} - */ -osrm.engine.api.fbresult.Table.prototype.fallbackSpeedCells = function (index) { - const offset = this.bb.__offset(this.bb_pos, 14); - return offset - ? this.bb.readUint32(this.bb.__vector(this.bb_pos + offset) + index * 4) - : 0; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.Table.prototype.fallbackSpeedCellsLength = - function () { - const offset = this.bb.__offset(this.bb_pos, 14); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; - }; - -/** - * @returns {Uint32Array} - */ -osrm.engine.api.fbresult.Table.prototype.fallbackSpeedCellsArray = function () { - const offset = this.bb.__offset(this.bb_pos, 14); - return offset - ? new Uint32Array( - this.bb.bytes().buffer, - this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), - this.bb.__vector_len(this.bb_pos + offset), - ) - : null; -}; - -/** - * @param {flatbuffers.Builder} builder - */ -osrm.engine.api.fbresult.Table.startTable = function (builder) { - builder.startObject(6); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} durationsOffset - */ -osrm.engine.api.fbresult.Table.addDurations = function ( - builder, - durationsOffset, -) { - builder.addFieldOffset(0, durationsOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Table.createDurationsVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addFloat32(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Table.startDurationsVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} rows - */ -osrm.engine.api.fbresult.Table.addRows = function (builder, rows) { - builder.addFieldInt16(1, rows, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} cols - */ -osrm.engine.api.fbresult.Table.addCols = function (builder, cols) { - builder.addFieldInt16(2, cols, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} distancesOffset - */ -osrm.engine.api.fbresult.Table.addDistances = function ( - builder, - distancesOffset, -) { - builder.addFieldOffset(3, distancesOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Table.createDistancesVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addFloat32(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Table.startDistancesVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} destinationsOffset - */ -osrm.engine.api.fbresult.Table.addDestinations = function ( - builder, - destinationsOffset, -) { - builder.addFieldOffset(4, destinationsOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Table.createDestinationsVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addOffset(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Table.startDestinationsVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} fallbackSpeedCellsOffset - */ -osrm.engine.api.fbresult.Table.addFallbackSpeedCells = function ( - builder, - fallbackSpeedCellsOffset, -) { - builder.addFieldOffset(5, fallbackSpeedCellsOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Table.createFallbackSpeedCellsVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addInt32(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.Table.startFallbackSpeedCellsVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Table.endTable = function (builder) { - const offset = builder.endObject(); - return offset; -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} durationsOffset - * @param {number} rows - * @param {number} cols - * @param {flatbuffers.Offset} distancesOffset - * @param {flatbuffers.Offset} destinationsOffset - * @param {flatbuffers.Offset} fallbackSpeedCellsOffset - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Table.createTable = function ( - builder, - durationsOffset, - rows, - cols, - distancesOffset, - destinationsOffset, - fallbackSpeedCellsOffset, -) { - osrm.engine.api.fbresult.Table.startTable(builder); - osrm.engine.api.fbresult.Table.addDurations(builder, durationsOffset); - osrm.engine.api.fbresult.Table.addRows(builder, rows); - osrm.engine.api.fbresult.Table.addCols(builder, cols); - osrm.engine.api.fbresult.Table.addDistances(builder, distancesOffset); - osrm.engine.api.fbresult.Table.addDestinations(builder, destinationsOffset); - osrm.engine.api.fbresult.Table.addFallbackSpeedCells( - builder, - fallbackSpeedCellsOffset, - ); - return osrm.engine.api.fbresult.Table.endTable(builder); -}; - -/** - * @constructor - */ -osrm.engine.api.fbresult.Error = function () { - /** - * @type {flatbuffers.ByteBuffer} - */ - this.bb = null; - - /** - * @type {number} - */ - this.bb_pos = 0; -}; - -/** - * @param {number} i - * @param {flatbuffers.ByteBuffer} bb - * @returns {osrm.engine.api.fbresult.Error} - */ -osrm.engine.api.fbresult.Error.prototype.__init = function (i, bb) { - this.bb_pos = i; - this.bb = bb; - return this; -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Error=} obj - * @returns {osrm.engine.api.fbresult.Error} - */ -osrm.engine.api.fbresult.Error.getRootAsError = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.Error()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.Error=} obj - * @returns {osrm.engine.api.fbresult.Error} - */ -osrm.engine.api.fbresult.Error.getSizePrefixedRootAsError = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.Error()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.Error.prototype.code = function (optionalEncoding) { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.Error.prototype.message = function (optionalEncoding) { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @param {flatbuffers.Builder} builder - */ -osrm.engine.api.fbresult.Error.startError = function (builder) { - builder.startObject(2); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} codeOffset - */ -osrm.engine.api.fbresult.Error.addCode = function (builder, codeOffset) { - builder.addFieldOffset(0, codeOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} messageOffset - */ -osrm.engine.api.fbresult.Error.addMessage = function (builder, messageOffset) { - builder.addFieldOffset(1, messageOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Error.endError = function (builder) { - const offset = builder.endObject(); - return offset; -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} codeOffset - * @param {flatbuffers.Offset} messageOffset - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.Error.createError = function ( - builder, - codeOffset, - messageOffset, -) { - osrm.engine.api.fbresult.Error.startError(builder); - osrm.engine.api.fbresult.Error.addCode(builder, codeOffset); - osrm.engine.api.fbresult.Error.addMessage(builder, messageOffset); - return osrm.engine.api.fbresult.Error.endError(builder); -}; - -/** - * @constructor - */ -osrm.engine.api.fbresult.FBResult = function () { - /** - * @type {flatbuffers.ByteBuffer} - */ - this.bb = null; - - /** - * @type {number} - */ - this.bb_pos = 0; -}; - -/** - * @param {number} i - * @param {flatbuffers.ByteBuffer} bb - * @returns {osrm.engine.api.fbresult.FBResult} - */ -osrm.engine.api.fbresult.FBResult.prototype.__init = function (i, bb) { - this.bb_pos = i; - this.bb = bb; - return this; -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.FBResult=} obj - * @returns {osrm.engine.api.fbresult.FBResult} - */ -osrm.engine.api.fbresult.FBResult.getRootAsFBResult = function (bb, obj) { - return (obj || new osrm.engine.api.fbresult.FBResult()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @param {flatbuffers.ByteBuffer} bb - * @param {osrm.engine.api.fbresult.FBResult=} obj - * @returns {osrm.engine.api.fbresult.FBResult} - */ -osrm.engine.api.fbresult.FBResult.getSizePrefixedRootAsFBResult = function ( - bb, - obj, -) { - return (obj || new osrm.engine.api.fbresult.FBResult()).__init( - bb.readInt32(bb.position()) + bb.position(), - bb, - ); -}; - -/** - * @returns {boolean} - */ -osrm.engine.api.fbresult.FBResult.prototype.error = function () { - const offset = this.bb.__offset(this.bb_pos, 4); - return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false; -}; - -/** - * @param {osrm.engine.api.fbresult.Error=} obj - * @returns {osrm.engine.api.fbresult.Error|null} - */ -osrm.engine.api.fbresult.FBResult.prototype.code = function (obj) { - const offset = this.bb.__offset(this.bb_pos, 6); - return offset - ? (obj || new osrm.engine.api.fbresult.Error()).__init( - this.bb.__indirect(this.bb_pos + offset), - this.bb, - ) - : null; -}; - -/** - * @param {flatbuffers.Encoding=} optionalEncoding - * @returns {string|Uint8Array|null} - */ -osrm.engine.api.fbresult.FBResult.prototype.dataVersion = function ( - optionalEncoding, -) { - const offset = this.bb.__offset(this.bb_pos, 8); - return offset - ? this.bb.__string(this.bb_pos + offset, optionalEncoding) - : null; -}; - -/** - * @param {number} index - * @param {osrm.engine.api.fbresult.Waypoint=} obj - * @returns {osrm.engine.api.fbresult.Waypoint} - */ -osrm.engine.api.fbresult.FBResult.prototype.waypoints = function (index, obj) { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset - ? (obj || new osrm.engine.api.fbresult.Waypoint()).__init( - this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), - this.bb, - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.FBResult.prototype.waypointsLength = function () { - const offset = this.bb.__offset(this.bb_pos, 10); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @param {number} index - * @param {osrm.engine.api.fbresult.RouteObject=} obj - * @returns {osrm.engine.api.fbresult.RouteObject} - */ -osrm.engine.api.fbresult.FBResult.prototype.routes = function (index, obj) { - const offset = this.bb.__offset(this.bb_pos, 12); - return offset - ? (obj || new osrm.engine.api.fbresult.RouteObject()).__init( - this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), - this.bb, - ) - : null; -}; - -/** - * @returns {number} - */ -osrm.engine.api.fbresult.FBResult.prototype.routesLength = function () { - const offset = this.bb.__offset(this.bb_pos, 12); - return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @param {osrm.engine.api.fbresult.Table=} obj - * @returns {osrm.engine.api.fbresult.Table|null} - */ -osrm.engine.api.fbresult.FBResult.prototype.table = function (obj) { - const offset = this.bb.__offset(this.bb_pos, 14); - return offset - ? (obj || new osrm.engine.api.fbresult.Table()).__init( - this.bb.__indirect(this.bb_pos + offset), - this.bb, - ) - : null; -}; - -/** - * @param {flatbuffers.Builder} builder - */ -osrm.engine.api.fbresult.FBResult.startFBResult = function (builder) { - builder.startObject(6); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {boolean} error - */ -osrm.engine.api.fbresult.FBResult.addError = function (builder, error) { - builder.addFieldInt8(0, +error, +false); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} codeOffset - */ -osrm.engine.api.fbresult.FBResult.addCode = function (builder, codeOffset) { - builder.addFieldOffset(1, codeOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} dataVersionOffset - */ -osrm.engine.api.fbresult.FBResult.addDataVersion = function ( - builder, - dataVersionOffset, -) { - builder.addFieldOffset(2, dataVersionOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} waypointsOffset - */ -osrm.engine.api.fbresult.FBResult.addWaypoints = function ( - builder, - waypointsOffset, -) { - builder.addFieldOffset(3, waypointsOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.FBResult.createWaypointsVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addOffset(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.FBResult.startWaypointsVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} routesOffset - */ -osrm.engine.api.fbresult.FBResult.addRoutes = function (builder, routesOffset) { - builder.addFieldOffset(4, routesOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {Array.} data - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.FBResult.createRoutesVector = function ( - builder, - data, -) { - builder.startVector(4, data.length, 4); - for (let i = data.length - 1; i >= 0; i--) { - builder.addOffset(data[i]); - } - return builder.endVector(); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {number} numElems - */ -osrm.engine.api.fbresult.FBResult.startRoutesVector = function ( - builder, - numElems, -) { - builder.startVector(4, numElems, 4); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} tableOffset - */ -osrm.engine.api.fbresult.FBResult.addTable = function (builder, tableOffset) { - builder.addFieldOffset(5, tableOffset, 0); -}; - -/** - * @param {flatbuffers.Builder} builder - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.FBResult.endFBResult = function (builder) { - const offset = builder.endObject(); - return offset; -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} offset - */ -osrm.engine.api.fbresult.FBResult.finishFBResultBuffer = function ( - builder, - offset, -) { - builder.finish(offset); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {flatbuffers.Offset} offset - */ -osrm.engine.api.fbresult.FBResult.finishSizePrefixedFBResultBuffer = function ( - builder, - offset, -) { - builder.finish(offset, undefined, true); -}; - -/** - * @param {flatbuffers.Builder} builder - * @param {boolean} error - * @param {flatbuffers.Offset} codeOffset - * @param {flatbuffers.Offset} dataVersionOffset - * @param {flatbuffers.Offset} waypointsOffset - * @param {flatbuffers.Offset} routesOffset - * @param {flatbuffers.Offset} tableOffset - * @returns {flatbuffers.Offset} - */ -osrm.engine.api.fbresult.FBResult.createFBResult = function ( - builder, - error, - codeOffset, - dataVersionOffset, - waypointsOffset, - routesOffset, - tableOffset, -) { - osrm.engine.api.fbresult.FBResult.startFBResult(builder); - osrm.engine.api.fbresult.FBResult.addError(builder, error); - osrm.engine.api.fbresult.FBResult.addCode(builder, codeOffset); - osrm.engine.api.fbresult.FBResult.addDataVersion(builder, dataVersionOffset); - osrm.engine.api.fbresult.FBResult.addWaypoints(builder, waypointsOffset); - osrm.engine.api.fbresult.FBResult.addRoutes(builder, routesOffset); - osrm.engine.api.fbresult.FBResult.addTable(builder, tableOffset); - return osrm.engine.api.fbresult.FBResult.endFBResult(builder); -}; - -// Exports for Node.js, RequireJS, and ES modules -if (typeof module !== 'undefined' && module.exports) { - module.exports = { osrm }; -} else if (typeof this !== 'undefined') { - this.osrm = osrm; -} else if (typeof globalThis !== 'undefined') { - globalThis.osrm = osrm; -} - -// ES module export for compatibility -export { osrm }; diff --git a/features/support/osrm/engine/api/fbresult.js b/features/support/osrm/engine/api/fbresult.js new file mode 100644 index 00000000000..f9eea2dce17 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult.js @@ -0,0 +1,5 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +export { Position } from './fbresult/position.js'; +export { Uint64Pair } from './fbresult/uint64-pair.js'; +export { Waypoint } from './fbresult/waypoint.js'; diff --git a/features/support/osrm/engine/api/fbresult.ts b/features/support/osrm/engine/api/fbresult.ts new file mode 100644 index 00000000000..c9446fdb8aa --- /dev/null +++ b/features/support/osrm/engine/api/fbresult.ts @@ -0,0 +1,7 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +export { Position } from './fbresult/position.js'; +export { Uint64Pair } from './fbresult/uint64-pair.js'; +export { Waypoint } from './fbresult/waypoint.js'; diff --git a/features/support/osrm/engine/api/fbresult/annotation.js b/features/support/osrm/engine/api/fbresult/annotation.js new file mode 100644 index 00000000000..541e2005567 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/annotation.js @@ -0,0 +1,184 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +import * as flatbuffers from 'flatbuffers'; +import { Metadata } from '../../../../osrm/engine/api/fbresult/metadata.js'; +export class Annotation { + bb = null; + bb_pos = 0; + __init(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; + } + static getRootAsAnnotation(bb, obj) { + return (obj || new Annotation()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + static getSizePrefixedRootAsAnnotation(bb, obj) { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Annotation()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + distance(index) { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? this.bb.readUint32(this.bb.__vector(this.bb_pos + offset) + index * 4) : 0; + } + distanceLength() { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + distanceArray() { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? new Uint32Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null; + } + duration(index) { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? this.bb.readUint32(this.bb.__vector(this.bb_pos + offset) + index * 4) : 0; + } + durationLength() { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + durationArray() { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? new Uint32Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null; + } + datasources(index) { + const offset = this.bb.__offset(this.bb_pos, 8); + return offset ? this.bb.readUint32(this.bb.__vector(this.bb_pos + offset) + index * 4) : 0; + } + datasourcesLength() { + const offset = this.bb.__offset(this.bb_pos, 8); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + datasourcesArray() { + const offset = this.bb.__offset(this.bb_pos, 8); + return offset ? new Uint32Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null; + } + nodes(index) { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? this.bb.readUint32(this.bb.__vector(this.bb_pos + offset) + index * 4) : 0; + } + nodesLength() { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + nodesArray() { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? new Uint32Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null; + } + weight(index) { + const offset = this.bb.__offset(this.bb_pos, 12); + return offset ? this.bb.readUint32(this.bb.__vector(this.bb_pos + offset) + index * 4) : 0; + } + weightLength() { + const offset = this.bb.__offset(this.bb_pos, 12); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + weightArray() { + const offset = this.bb.__offset(this.bb_pos, 12); + return offset ? new Uint32Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null; + } + speed(index) { + const offset = this.bb.__offset(this.bb_pos, 14); + return offset ? this.bb.readFloat32(this.bb.__vector(this.bb_pos + offset) + index * 4) : 0; + } + speedLength() { + const offset = this.bb.__offset(this.bb_pos, 14); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + speedArray() { + const offset = this.bb.__offset(this.bb_pos, 14); + return offset ? new Float32Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null; + } + metadata(obj) { + const offset = this.bb.__offset(this.bb_pos, 16); + return offset ? (obj || new Metadata()).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null; + } + static startAnnotation(builder) { + builder.startObject(7); + } + static addDistance(builder, distanceOffset) { + builder.addFieldOffset(0, distanceOffset, 0); + } + static createDistanceVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt32(data[i]); + } + return builder.endVector(); + } + static startDistanceVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static addDuration(builder, durationOffset) { + builder.addFieldOffset(1, durationOffset, 0); + } + static createDurationVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt32(data[i]); + } + return builder.endVector(); + } + static startDurationVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static addDatasources(builder, datasourcesOffset) { + builder.addFieldOffset(2, datasourcesOffset, 0); + } + static createDatasourcesVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt32(data[i]); + } + return builder.endVector(); + } + static startDatasourcesVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static addNodes(builder, nodesOffset) { + builder.addFieldOffset(3, nodesOffset, 0); + } + static createNodesVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt32(data[i]); + } + return builder.endVector(); + } + static startNodesVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static addWeight(builder, weightOffset) { + builder.addFieldOffset(4, weightOffset, 0); + } + static createWeightVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt32(data[i]); + } + return builder.endVector(); + } + static startWeightVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static addSpeed(builder, speedOffset) { + builder.addFieldOffset(5, speedOffset, 0); + } + static createSpeedVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addFloat32(data[i]); + } + return builder.endVector(); + } + static startSpeedVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static addMetadata(builder, metadataOffset) { + builder.addFieldOffset(6, metadataOffset, 0); + } + static endAnnotation(builder) { + const offset = builder.endObject(); + return offset; + } +} diff --git a/features/support/osrm/engine/api/fbresult/annotation.ts b/features/support/osrm/engine/api/fbresult/annotation.ts new file mode 100644 index 00000000000..1b6a385edb3 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/annotation.ts @@ -0,0 +1,262 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +import { Metadata } from '../../../../osrm/engine/api/fbresult/metadata.js'; + + +export class Annotation { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):Annotation { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsAnnotation(bb:flatbuffers.ByteBuffer, obj?:Annotation):Annotation { + return (obj || new Annotation()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsAnnotation(bb:flatbuffers.ByteBuffer, obj?:Annotation):Annotation { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Annotation()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +distance(index: number):number|null { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readUint32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; +} + +distanceLength():number { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +distanceArray():Uint32Array|null { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? new Uint32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +duration(index: number):number|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readUint32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; +} + +durationLength():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +durationArray():Uint32Array|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? new Uint32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +datasources(index: number):number|null { + const offset = this.bb!.__offset(this.bb_pos, 8); + return offset ? this.bb!.readUint32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; +} + +datasourcesLength():number { + const offset = this.bb!.__offset(this.bb_pos, 8); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +datasourcesArray():Uint32Array|null { + const offset = this.bb!.__offset(this.bb_pos, 8); + return offset ? new Uint32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +nodes(index: number):number|null { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? this.bb!.readUint32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; +} + +nodesLength():number { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +nodesArray():Uint32Array|null { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? new Uint32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +weight(index: number):number|null { + const offset = this.bb!.__offset(this.bb_pos, 12); + return offset ? this.bb!.readUint32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; +} + +weightLength():number { + const offset = this.bb!.__offset(this.bb_pos, 12); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +weightArray():Uint32Array|null { + const offset = this.bb!.__offset(this.bb_pos, 12); + return offset ? new Uint32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +speed(index: number):number|null { + const offset = this.bb!.__offset(this.bb_pos, 14); + return offset ? this.bb!.readFloat32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; +} + +speedLength():number { + const offset = this.bb!.__offset(this.bb_pos, 14); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +speedArray():Float32Array|null { + const offset = this.bb!.__offset(this.bb_pos, 14); + return offset ? new Float32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +metadata(obj?:Metadata):Metadata|null { + const offset = this.bb!.__offset(this.bb_pos, 16); + return offset ? (obj || new Metadata()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null; +} + +static startAnnotation(builder:flatbuffers.Builder) { + builder.startObject(7); +} + +static addDistance(builder:flatbuffers.Builder, distanceOffset:flatbuffers.Offset) { + builder.addFieldOffset(0, distanceOffset, 0); +} + +static createDistanceVector(builder:flatbuffers.Builder, data:number[]|Uint32Array):flatbuffers.Offset; +/** + * @deprecated This Uint8Array overload will be removed in the future. + */ +static createDistanceVector(builder:flatbuffers.Builder, data:number[]|Uint8Array):flatbuffers.Offset; +static createDistanceVector(builder:flatbuffers.Builder, data:number[]|Uint32Array|Uint8Array):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt32(data[i]!); + } + return builder.endVector(); +} + +static startDistanceVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static addDuration(builder:flatbuffers.Builder, durationOffset:flatbuffers.Offset) { + builder.addFieldOffset(1, durationOffset, 0); +} + +static createDurationVector(builder:flatbuffers.Builder, data:number[]|Uint32Array):flatbuffers.Offset; +/** + * @deprecated This Uint8Array overload will be removed in the future. + */ +static createDurationVector(builder:flatbuffers.Builder, data:number[]|Uint8Array):flatbuffers.Offset; +static createDurationVector(builder:flatbuffers.Builder, data:number[]|Uint32Array|Uint8Array):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt32(data[i]!); + } + return builder.endVector(); +} + +static startDurationVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static addDatasources(builder:flatbuffers.Builder, datasourcesOffset:flatbuffers.Offset) { + builder.addFieldOffset(2, datasourcesOffset, 0); +} + +static createDatasourcesVector(builder:flatbuffers.Builder, data:number[]|Uint32Array):flatbuffers.Offset; +/** + * @deprecated This Uint8Array overload will be removed in the future. + */ +static createDatasourcesVector(builder:flatbuffers.Builder, data:number[]|Uint8Array):flatbuffers.Offset; +static createDatasourcesVector(builder:flatbuffers.Builder, data:number[]|Uint32Array|Uint8Array):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt32(data[i]!); + } + return builder.endVector(); +} + +static startDatasourcesVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static addNodes(builder:flatbuffers.Builder, nodesOffset:flatbuffers.Offset) { + builder.addFieldOffset(3, nodesOffset, 0); +} + +static createNodesVector(builder:flatbuffers.Builder, data:number[]|Uint32Array):flatbuffers.Offset; +/** + * @deprecated This Uint8Array overload will be removed in the future. + */ +static createNodesVector(builder:flatbuffers.Builder, data:number[]|Uint8Array):flatbuffers.Offset; +static createNodesVector(builder:flatbuffers.Builder, data:number[]|Uint32Array|Uint8Array):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt32(data[i]!); + } + return builder.endVector(); +} + +static startNodesVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static addWeight(builder:flatbuffers.Builder, weightOffset:flatbuffers.Offset) { + builder.addFieldOffset(4, weightOffset, 0); +} + +static createWeightVector(builder:flatbuffers.Builder, data:number[]|Uint32Array):flatbuffers.Offset; +/** + * @deprecated This Uint8Array overload will be removed in the future. + */ +static createWeightVector(builder:flatbuffers.Builder, data:number[]|Uint8Array):flatbuffers.Offset; +static createWeightVector(builder:flatbuffers.Builder, data:number[]|Uint32Array|Uint8Array):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt32(data[i]!); + } + return builder.endVector(); +} + +static startWeightVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static addSpeed(builder:flatbuffers.Builder, speedOffset:flatbuffers.Offset) { + builder.addFieldOffset(5, speedOffset, 0); +} + +static createSpeedVector(builder:flatbuffers.Builder, data:number[]|Float32Array):flatbuffers.Offset; +/** + * @deprecated This Uint8Array overload will be removed in the future. + */ +static createSpeedVector(builder:flatbuffers.Builder, data:number[]|Uint8Array):flatbuffers.Offset; +static createSpeedVector(builder:flatbuffers.Builder, data:number[]|Float32Array|Uint8Array):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addFloat32(data[i]!); + } + return builder.endVector(); +} + +static startSpeedVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static addMetadata(builder:flatbuffers.Builder, metadataOffset:flatbuffers.Offset) { + builder.addFieldOffset(6, metadataOffset, 0); +} + +static endAnnotation(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +} diff --git a/features/support/osrm/engine/api/fbresult/error.js b/features/support/osrm/engine/api/fbresult/error.js new file mode 100644 index 00000000000..0ee14c0b88a --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/error.js @@ -0,0 +1,46 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +import * as flatbuffers from 'flatbuffers'; +export class Error { + bb = null; + bb_pos = 0; + __init(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; + } + static getRootAsError(bb, obj) { + return (obj || new Error()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + static getSizePrefixedRootAsError(bb, obj) { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Error()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + code(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + message(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + static startError(builder) { + builder.startObject(2); + } + static addCode(builder, codeOffset) { + builder.addFieldOffset(0, codeOffset, 0); + } + static addMessage(builder, messageOffset) { + builder.addFieldOffset(1, messageOffset, 0); + } + static endError(builder) { + const offset = builder.endObject(); + return offset; + } + static createError(builder, codeOffset, messageOffset) { + Error.startError(builder); + Error.addCode(builder, codeOffset); + Error.addMessage(builder, messageOffset); + return Error.endError(builder); + } +} diff --git a/features/support/osrm/engine/api/fbresult/error.ts b/features/support/osrm/engine/api/fbresult/error.ts new file mode 100644 index 00000000000..b92253cdd8d --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/error.ts @@ -0,0 +1,62 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +export class Error { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):Error { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsError(bb:flatbuffers.ByteBuffer, obj?:Error):Error { + return (obj || new Error()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsError(bb:flatbuffers.ByteBuffer, obj?:Error):Error { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Error()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +code():string|null +code(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +code(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +message():string|null +message(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +message(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +static startError(builder:flatbuffers.Builder) { + builder.startObject(2); +} + +static addCode(builder:flatbuffers.Builder, codeOffset:flatbuffers.Offset) { + builder.addFieldOffset(0, codeOffset, 0); +} + +static addMessage(builder:flatbuffers.Builder, messageOffset:flatbuffers.Offset) { + builder.addFieldOffset(1, messageOffset, 0); +} + +static endError(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createError(builder:flatbuffers.Builder, codeOffset:flatbuffers.Offset, messageOffset:flatbuffers.Offset):flatbuffers.Offset { + Error.startError(builder); + Error.addCode(builder, codeOffset); + Error.addMessage(builder, messageOffset); + return Error.endError(builder); +} +} diff --git a/features/support/osrm/engine/api/fbresult/fbresult.js b/features/support/osrm/engine/api/fbresult/fbresult.js new file mode 100644 index 00000000000..4446b554b3b --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/fbresult.js @@ -0,0 +1,106 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +import * as flatbuffers from 'flatbuffers'; +import { Error } from '../../../../osrm/engine/api/fbresult/error.js'; +import { RouteObject } from '../../../../osrm/engine/api/fbresult/route-object.js'; +import { TableResult } from '../../../../osrm/engine/api/fbresult/table-result.js'; +import { Waypoint } from '../../../../osrm/engine/api/fbresult/waypoint.js'; +export class FBResult { + bb = null; + bb_pos = 0; + __init(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; + } + static getRootAsFBResult(bb, obj) { + return (obj || new FBResult()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + static getSizePrefixedRootAsFBResult(bb, obj) { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new FBResult()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + error() { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false; + } + code(obj) { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? (obj || new Error()).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null; + } + dataVersion(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 8); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + waypoints(index, obj) { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? (obj || new Waypoint()).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; + } + waypointsLength() { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + routes(index, obj) { + const offset = this.bb.__offset(this.bb_pos, 12); + return offset ? (obj || new RouteObject()).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; + } + routesLength() { + const offset = this.bb.__offset(this.bb_pos, 12); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + table(obj) { + const offset = this.bb.__offset(this.bb_pos, 14); + return offset ? (obj || new TableResult()).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null; + } + static startFBResult(builder) { + builder.startObject(6); + } + static addError(builder, error) { + builder.addFieldInt8(0, +error, +false); + } + static addCode(builder, codeOffset) { + builder.addFieldOffset(1, codeOffset, 0); + } + static addDataVersion(builder, dataVersionOffset) { + builder.addFieldOffset(2, dataVersionOffset, 0); + } + static addWaypoints(builder, waypointsOffset) { + builder.addFieldOffset(3, waypointsOffset, 0); + } + static createWaypointsVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]); + } + return builder.endVector(); + } + static startWaypointsVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static addRoutes(builder, routesOffset) { + builder.addFieldOffset(4, routesOffset, 0); + } + static createRoutesVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]); + } + return builder.endVector(); + } + static startRoutesVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static addTable(builder, tableOffset) { + builder.addFieldOffset(5, tableOffset, 0); + } + static endFBResult(builder) { + const offset = builder.endObject(); + return offset; + } + static finishFBResultBuffer(builder, offset) { + builder.finish(offset); + } + static finishSizePrefixedFBResultBuffer(builder, offset) { + builder.finish(offset, undefined, true); + } +} diff --git a/features/support/osrm/engine/api/fbresult/fbresult.ts b/features/support/osrm/engine/api/fbresult/fbresult.ts new file mode 100644 index 00000000000..e5f8f803c58 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/fbresult.ts @@ -0,0 +1,138 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +import { Error } from '../../../../osrm/engine/api/fbresult/error.js'; +import { RouteObject } from '../../../../osrm/engine/api/fbresult/route-object.js'; +import { TableResult } from '../../../../osrm/engine/api/fbresult/table-result.js'; +import { Waypoint } from '../../../../osrm/engine/api/fbresult/waypoint.js'; + + +export class FBResult { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):FBResult { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsFBResult(bb:flatbuffers.ByteBuffer, obj?:FBResult):FBResult { + return (obj || new FBResult()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsFBResult(bb:flatbuffers.ByteBuffer, obj?:FBResult):FBResult { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new FBResult()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +error():boolean { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? !!this.bb!.readInt8(this.bb_pos + offset) : false; +} + +code(obj?:Error):Error|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? (obj || new Error()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null; +} + +dataVersion():string|null +dataVersion(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +dataVersion(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 8); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +waypoints(index: number, obj?:Waypoint):Waypoint|null { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? (obj || new Waypoint()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null; +} + +waypointsLength():number { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +routes(index: number, obj?:RouteObject):RouteObject|null { + const offset = this.bb!.__offset(this.bb_pos, 12); + return offset ? (obj || new RouteObject()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null; +} + +routesLength():number { + const offset = this.bb!.__offset(this.bb_pos, 12); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +table(obj?:TableResult):TableResult|null { + const offset = this.bb!.__offset(this.bb_pos, 14); + return offset ? (obj || new TableResult()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null; +} + +static startFBResult(builder:flatbuffers.Builder) { + builder.startObject(6); +} + +static addError(builder:flatbuffers.Builder, error:boolean) { + builder.addFieldInt8(0, +error, +false); +} + +static addCode(builder:flatbuffers.Builder, codeOffset:flatbuffers.Offset) { + builder.addFieldOffset(1, codeOffset, 0); +} + +static addDataVersion(builder:flatbuffers.Builder, dataVersionOffset:flatbuffers.Offset) { + builder.addFieldOffset(2, dataVersionOffset, 0); +} + +static addWaypoints(builder:flatbuffers.Builder, waypointsOffset:flatbuffers.Offset) { + builder.addFieldOffset(3, waypointsOffset, 0); +} + +static createWaypointsVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]!); + } + return builder.endVector(); +} + +static startWaypointsVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static addRoutes(builder:flatbuffers.Builder, routesOffset:flatbuffers.Offset) { + builder.addFieldOffset(4, routesOffset, 0); +} + +static createRoutesVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]!); + } + return builder.endVector(); +} + +static startRoutesVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static addTable(builder:flatbuffers.Builder, tableOffset:flatbuffers.Offset) { + builder.addFieldOffset(5, tableOffset, 0); +} + +static endFBResult(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static finishFBResultBuffer(builder:flatbuffers.Builder, offset:flatbuffers.Offset) { + builder.finish(offset); +} + +static finishSizePrefixedFBResultBuffer(builder:flatbuffers.Builder, offset:flatbuffers.Offset) { + builder.finish(offset, undefined, true); +} + +} diff --git a/features/support/osrm/engine/api/fbresult/intersection.js b/features/support/osrm/engine/api/fbresult/intersection.js new file mode 100644 index 00000000000..5e0a636d031 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/intersection.js @@ -0,0 +1,152 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +import * as flatbuffers from 'flatbuffers'; +import { Lane } from '../../../../osrm/engine/api/fbresult/lane.js'; +import { Position } from '../../../../osrm/engine/api/fbresult/position.js'; +export class Intersection { + bb = null; + bb_pos = 0; + __init(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; + } + static getRootAsIntersection(bb, obj) { + return (obj || new Intersection()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + static getSizePrefixedRootAsIntersection(bb, obj) { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Intersection()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + location(obj) { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? (obj || new Position()).__init(this.bb_pos + offset, this.bb) : null; + } + bearings(index) { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? this.bb.readInt16(this.bb.__vector(this.bb_pos + offset) + index * 2) : 0; + } + bearingsLength() { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + bearingsArray() { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? new Int16Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null; + } + classes(index, optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 8); + return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; + } + classesLength() { + const offset = this.bb.__offset(this.bb_pos, 8); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + entry(index) { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? !!this.bb.readInt8(this.bb.__vector(this.bb_pos + offset) + index) : false; + } + entryLength() { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + entryArray() { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? new Int8Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null; + } + inBearing() { + const offset = this.bb.__offset(this.bb_pos, 12); + return offset ? this.bb.readUint32(this.bb_pos + offset) : 0; + } + outBearing() { + const offset = this.bb.__offset(this.bb_pos, 14); + return offset ? this.bb.readUint32(this.bb_pos + offset) : 0; + } + lanes(index, obj) { + const offset = this.bb.__offset(this.bb_pos, 16); + return offset ? (obj || new Lane()).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; + } + lanesLength() { + const offset = this.bb.__offset(this.bb_pos, 16); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + static startIntersection(builder) { + builder.startObject(7); + } + static addLocation(builder, locationOffset) { + builder.addFieldStruct(0, locationOffset, 0); + } + static addBearings(builder, bearingsOffset) { + builder.addFieldOffset(1, bearingsOffset, 0); + } + static createBearingsVector(builder, data) { + builder.startVector(2, data.length, 2); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt16(data[i]); + } + return builder.endVector(); + } + static startBearingsVector(builder, numElems) { + builder.startVector(2, numElems, 2); + } + static addClasses(builder, classesOffset) { + builder.addFieldOffset(2, classesOffset, 0); + } + static createClassesVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]); + } + return builder.endVector(); + } + static startClassesVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static addEntry(builder, entryOffset) { + builder.addFieldOffset(3, entryOffset, 0); + } + static createEntryVector(builder, data) { + builder.startVector(1, data.length, 1); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt8(+data[i]); + } + return builder.endVector(); + } + static startEntryVector(builder, numElems) { + builder.startVector(1, numElems, 1); + } + static addInBearing(builder, inBearing) { + builder.addFieldInt32(4, inBearing, 0); + } + static addOutBearing(builder, outBearing) { + builder.addFieldInt32(5, outBearing, 0); + } + static addLanes(builder, lanesOffset) { + builder.addFieldOffset(6, lanesOffset, 0); + } + static createLanesVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]); + } + return builder.endVector(); + } + static startLanesVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static endIntersection(builder) { + const offset = builder.endObject(); + return offset; + } + static createIntersection(builder, locationOffset, bearingsOffset, classesOffset, entryOffset, inBearing, outBearing, lanesOffset) { + Intersection.startIntersection(builder); + Intersection.addLocation(builder, locationOffset); + Intersection.addBearings(builder, bearingsOffset); + Intersection.addClasses(builder, classesOffset); + Intersection.addEntry(builder, entryOffset); + Intersection.addInBearing(builder, inBearing); + Intersection.addOutBearing(builder, outBearing); + Intersection.addLanes(builder, lanesOffset); + return Intersection.endIntersection(builder); + } +} diff --git a/features/support/osrm/engine/api/fbresult/intersection.ts b/features/support/osrm/engine/api/fbresult/intersection.ts new file mode 100644 index 00000000000..e3b298a7dda --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/intersection.ts @@ -0,0 +1,197 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +import { Lane } from '../../../../osrm/engine/api/fbresult/lane.js'; +import { Position } from '../../../../osrm/engine/api/fbresult/position.js'; + + +export class Intersection { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):Intersection { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsIntersection(bb:flatbuffers.ByteBuffer, obj?:Intersection):Intersection { + return (obj || new Intersection()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsIntersection(bb:flatbuffers.ByteBuffer, obj?:Intersection):Intersection { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Intersection()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +location(obj?:Position):Position|null { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? (obj || new Position()).__init(this.bb_pos + offset, this.bb!) : null; +} + +bearings(index: number):number|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readInt16(this.bb!.__vector(this.bb_pos + offset) + index * 2) : 0; +} + +bearingsLength():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +bearingsArray():Int16Array|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? new Int16Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +classes(index: number):string +classes(index: number,optionalEncoding:flatbuffers.Encoding):string|Uint8Array +classes(index: number,optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 8); + return offset ? this.bb!.__string(this.bb!.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; +} + +classesLength():number { + const offset = this.bb!.__offset(this.bb_pos, 8); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +entry(index: number):boolean|null { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? !!this.bb!.readInt8(this.bb!.__vector(this.bb_pos + offset) + index) : false; +} + +entryLength():number { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +entryArray():Int8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? new Int8Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +inBearing():number { + const offset = this.bb!.__offset(this.bb_pos, 12); + return offset ? this.bb!.readUint32(this.bb_pos + offset) : 0; +} + +outBearing():number { + const offset = this.bb!.__offset(this.bb_pos, 14); + return offset ? this.bb!.readUint32(this.bb_pos + offset) : 0; +} + +lanes(index: number, obj?:Lane):Lane|null { + const offset = this.bb!.__offset(this.bb_pos, 16); + return offset ? (obj || new Lane()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null; +} + +lanesLength():number { + const offset = this.bb!.__offset(this.bb_pos, 16); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +static startIntersection(builder:flatbuffers.Builder) { + builder.startObject(7); +} + +static addLocation(builder:flatbuffers.Builder, locationOffset:flatbuffers.Offset) { + builder.addFieldStruct(0, locationOffset, 0); +} + +static addBearings(builder:flatbuffers.Builder, bearingsOffset:flatbuffers.Offset) { + builder.addFieldOffset(1, bearingsOffset, 0); +} + +static createBearingsVector(builder:flatbuffers.Builder, data:number[]|Int16Array):flatbuffers.Offset; +/** + * @deprecated This Uint8Array overload will be removed in the future. + */ +static createBearingsVector(builder:flatbuffers.Builder, data:number[]|Uint8Array):flatbuffers.Offset; +static createBearingsVector(builder:flatbuffers.Builder, data:number[]|Int16Array|Uint8Array):flatbuffers.Offset { + builder.startVector(2, data.length, 2); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt16(data[i]!); + } + return builder.endVector(); +} + +static startBearingsVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(2, numElems, 2); +} + +static addClasses(builder:flatbuffers.Builder, classesOffset:flatbuffers.Offset) { + builder.addFieldOffset(2, classesOffset, 0); +} + +static createClassesVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]!); + } + return builder.endVector(); +} + +static startClassesVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static addEntry(builder:flatbuffers.Builder, entryOffset:flatbuffers.Offset) { + builder.addFieldOffset(3, entryOffset, 0); +} + +static createEntryVector(builder:flatbuffers.Builder, data:boolean[]):flatbuffers.Offset { + builder.startVector(1, data.length, 1); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt8(+data[i]!); + } + return builder.endVector(); +} + +static startEntryVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(1, numElems, 1); +} + +static addInBearing(builder:flatbuffers.Builder, inBearing:number) { + builder.addFieldInt32(4, inBearing, 0); +} + +static addOutBearing(builder:flatbuffers.Builder, outBearing:number) { + builder.addFieldInt32(5, outBearing, 0); +} + +static addLanes(builder:flatbuffers.Builder, lanesOffset:flatbuffers.Offset) { + builder.addFieldOffset(6, lanesOffset, 0); +} + +static createLanesVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]!); + } + return builder.endVector(); +} + +static startLanesVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static endIntersection(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createIntersection(builder:flatbuffers.Builder, locationOffset:flatbuffers.Offset, bearingsOffset:flatbuffers.Offset, classesOffset:flatbuffers.Offset, entryOffset:flatbuffers.Offset, inBearing:number, outBearing:number, lanesOffset:flatbuffers.Offset):flatbuffers.Offset { + Intersection.startIntersection(builder); + Intersection.addLocation(builder, locationOffset); + Intersection.addBearings(builder, bearingsOffset); + Intersection.addClasses(builder, classesOffset); + Intersection.addEntry(builder, entryOffset); + Intersection.addInBearing(builder, inBearing); + Intersection.addOutBearing(builder, outBearing); + Intersection.addLanes(builder, lanesOffset); + return Intersection.endIntersection(builder); +} +} diff --git a/features/support/osrm/engine/api/fbresult/lane.js b/features/support/osrm/engine/api/fbresult/lane.js new file mode 100644 index 00000000000..806bed7fe82 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/lane.js @@ -0,0 +1,64 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +import * as flatbuffers from 'flatbuffers'; +export class Lane { + bb = null; + bb_pos = 0; + __init(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; + } + static getRootAsLane(bb, obj) { + return (obj || new Lane()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + static getSizePrefixedRootAsLane(bb, obj) { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Lane()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + indications(index) { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? this.bb.readInt8(this.bb.__vector(this.bb_pos + offset) + index) : null; + } + indicationsLength() { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + indicationsArray() { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? new Int8Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null; + } + valid() { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false; + } + static startLane(builder) { + builder.startObject(2); + } + static addIndications(builder, indicationsOffset) { + builder.addFieldOffset(0, indicationsOffset, 0); + } + static createIndicationsVector(builder, data) { + builder.startVector(1, data.length, 1); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt8(data[i]); + } + return builder.endVector(); + } + static startIndicationsVector(builder, numElems) { + builder.startVector(1, numElems, 1); + } + static addValid(builder, valid) { + builder.addFieldInt8(1, +valid, +false); + } + static endLane(builder) { + const offset = builder.endObject(); + return offset; + } + static createLane(builder, indicationsOffset, valid) { + Lane.startLane(builder); + Lane.addIndications(builder, indicationsOffset); + Lane.addValid(builder, valid); + return Lane.endLane(builder); + } +} diff --git a/features/support/osrm/engine/api/fbresult/lane.ts b/features/support/osrm/engine/api/fbresult/lane.ts new file mode 100644 index 00000000000..27530f510d1 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/lane.ts @@ -0,0 +1,83 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +import { Turn } from '../../../../osrm/engine/api/fbresult/turn.js'; + + +export class Lane { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):Lane { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsLane(bb:flatbuffers.ByteBuffer, obj?:Lane):Lane { + return (obj || new Lane()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsLane(bb:flatbuffers.ByteBuffer, obj?:Lane):Lane { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Lane()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +indications(index: number):Turn|null { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readInt8(this.bb!.__vector(this.bb_pos + offset) + index) : null; +} + +indicationsLength():number { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +indicationsArray():Int8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? new Int8Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +valid():boolean { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? !!this.bb!.readInt8(this.bb_pos + offset) : false; +} + +static startLane(builder:flatbuffers.Builder) { + builder.startObject(2); +} + +static addIndications(builder:flatbuffers.Builder, indicationsOffset:flatbuffers.Offset) { + builder.addFieldOffset(0, indicationsOffset, 0); +} + +static createIndicationsVector(builder:flatbuffers.Builder, data:Turn[]):flatbuffers.Offset { + builder.startVector(1, data.length, 1); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt8(data[i]!); + } + return builder.endVector(); +} + +static startIndicationsVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(1, numElems, 1); +} + +static addValid(builder:flatbuffers.Builder, valid:boolean) { + builder.addFieldInt8(1, +valid, +false); +} + +static endLane(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createLane(builder:flatbuffers.Builder, indicationsOffset:flatbuffers.Offset, valid:boolean):flatbuffers.Offset { + Lane.startLane(builder); + Lane.addIndications(builder, indicationsOffset); + Lane.addValid(builder, valid); + return Lane.endLane(builder); +} +} diff --git a/features/support/osrm/engine/api/fbresult/leg.js b/features/support/osrm/engine/api/fbresult/leg.js new file mode 100644 index 00000000000..1c7c81935a4 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/leg.js @@ -0,0 +1,84 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +import * as flatbuffers from 'flatbuffers'; +import { Annotation } from '../../../../osrm/engine/api/fbresult/annotation.js'; +import { Step } from '../../../../osrm/engine/api/fbresult/step.js'; +export class Leg { + bb = null; + bb_pos = 0; + __init(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; + } + static getRootAsLeg(bb, obj) { + return (obj || new Leg()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + static getSizePrefixedRootAsLeg(bb, obj) { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Leg()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + distance() { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? this.bb.readFloat64(this.bb_pos + offset) : 0.0; + } + duration() { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? this.bb.readFloat64(this.bb_pos + offset) : 0.0; + } + weight() { + const offset = this.bb.__offset(this.bb_pos, 8); + return offset ? this.bb.readFloat64(this.bb_pos + offset) : 0.0; + } + summary(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + annotations(obj) { + const offset = this.bb.__offset(this.bb_pos, 12); + return offset ? (obj || new Annotation()).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null; + } + steps(index, obj) { + const offset = this.bb.__offset(this.bb_pos, 14); + return offset ? (obj || new Step()).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; + } + stepsLength() { + const offset = this.bb.__offset(this.bb_pos, 14); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + static startLeg(builder) { + builder.startObject(6); + } + static addDistance(builder, distance) { + builder.addFieldFloat64(0, distance, 0.0); + } + static addDuration(builder, duration) { + builder.addFieldFloat64(1, duration, 0.0); + } + static addWeight(builder, weight) { + builder.addFieldFloat64(2, weight, 0.0); + } + static addSummary(builder, summaryOffset) { + builder.addFieldOffset(3, summaryOffset, 0); + } + static addAnnotations(builder, annotationsOffset) { + builder.addFieldOffset(4, annotationsOffset, 0); + } + static addSteps(builder, stepsOffset) { + builder.addFieldOffset(5, stepsOffset, 0); + } + static createStepsVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]); + } + return builder.endVector(); + } + static startStepsVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static endLeg(builder) { + const offset = builder.endObject(); + return offset; + } +} diff --git a/features/support/osrm/engine/api/fbresult/leg.ts b/features/support/osrm/engine/api/fbresult/leg.ts new file mode 100644 index 00000000000..4885b77257e --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/leg.ts @@ -0,0 +1,111 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +import { Annotation } from '../../../../osrm/engine/api/fbresult/annotation.js'; +import { Step } from '../../../../osrm/engine/api/fbresult/step.js'; + + +export class Leg { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):Leg { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsLeg(bb:flatbuffers.ByteBuffer, obj?:Leg):Leg { + return (obj || new Leg()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsLeg(bb:flatbuffers.ByteBuffer, obj?:Leg):Leg { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Leg()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +distance():number { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readFloat64(this.bb_pos + offset) : 0.0; +} + +duration():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readFloat64(this.bb_pos + offset) : 0.0; +} + +weight():number { + const offset = this.bb!.__offset(this.bb_pos, 8); + return offset ? this.bb!.readFloat64(this.bb_pos + offset) : 0.0; +} + +summary():string|null +summary(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +summary(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +annotations(obj?:Annotation):Annotation|null { + const offset = this.bb!.__offset(this.bb_pos, 12); + return offset ? (obj || new Annotation()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null; +} + +steps(index: number, obj?:Step):Step|null { + const offset = this.bb!.__offset(this.bb_pos, 14); + return offset ? (obj || new Step()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null; +} + +stepsLength():number { + const offset = this.bb!.__offset(this.bb_pos, 14); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +static startLeg(builder:flatbuffers.Builder) { + builder.startObject(6); +} + +static addDistance(builder:flatbuffers.Builder, distance:number) { + builder.addFieldFloat64(0, distance, 0.0); +} + +static addDuration(builder:flatbuffers.Builder, duration:number) { + builder.addFieldFloat64(1, duration, 0.0); +} + +static addWeight(builder:flatbuffers.Builder, weight:number) { + builder.addFieldFloat64(2, weight, 0.0); +} + +static addSummary(builder:flatbuffers.Builder, summaryOffset:flatbuffers.Offset) { + builder.addFieldOffset(3, summaryOffset, 0); +} + +static addAnnotations(builder:flatbuffers.Builder, annotationsOffset:flatbuffers.Offset) { + builder.addFieldOffset(4, annotationsOffset, 0); +} + +static addSteps(builder:flatbuffers.Builder, stepsOffset:flatbuffers.Offset) { + builder.addFieldOffset(5, stepsOffset, 0); +} + +static createStepsVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]!); + } + return builder.endVector(); +} + +static startStepsVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static endLeg(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +} diff --git a/features/support/osrm/engine/api/fbresult/maneuver-type.js b/features/support/osrm/engine/api/fbresult/maneuver-type.js new file mode 100644 index 00000000000..c377456ba16 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/maneuver-type.js @@ -0,0 +1,21 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +export var ManeuverType; +(function (ManeuverType) { + ManeuverType[ManeuverType["Turn"] = 0] = "Turn"; + ManeuverType[ManeuverType["NewName"] = 1] = "NewName"; + ManeuverType[ManeuverType["Depart"] = 2] = "Depart"; + ManeuverType[ManeuverType["Arrive"] = 3] = "Arrive"; + ManeuverType[ManeuverType["Merge"] = 4] = "Merge"; + ManeuverType[ManeuverType["OnRamp"] = 5] = "OnRamp"; + ManeuverType[ManeuverType["OffRamp"] = 6] = "OffRamp"; + ManeuverType[ManeuverType["Fork"] = 7] = "Fork"; + ManeuverType[ManeuverType["EndOfRoad"] = 8] = "EndOfRoad"; + ManeuverType[ManeuverType["Continue"] = 9] = "Continue"; + ManeuverType[ManeuverType["Roundabout"] = 10] = "Roundabout"; + ManeuverType[ManeuverType["Rotary"] = 11] = "Rotary"; + ManeuverType[ManeuverType["RoundaboutTurn"] = 12] = "RoundaboutTurn"; + ManeuverType[ManeuverType["Notification"] = 13] = "Notification"; + ManeuverType[ManeuverType["ExitRoundabout"] = 14] = "ExitRoundabout"; + ManeuverType[ManeuverType["ExitRotary"] = 15] = "ExitRotary"; +})(ManeuverType || (ManeuverType = {})); diff --git a/features/support/osrm/engine/api/fbresult/maneuver-type.ts b/features/support/osrm/engine/api/fbresult/maneuver-type.ts new file mode 100644 index 00000000000..39d70f8127d --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/maneuver-type.ts @@ -0,0 +1,22 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +export enum ManeuverType { + Turn = 0, + NewName = 1, + Depart = 2, + Arrive = 3, + Merge = 4, + OnRamp = 5, + OffRamp = 6, + Fork = 7, + EndOfRoad = 8, + Continue = 9, + Roundabout = 10, + Rotary = 11, + RoundaboutTurn = 12, + Notification = 13, + ExitRoundabout = 14, + ExitRotary = 15 +} diff --git a/features/support/osrm/engine/api/fbresult/metadata.js b/features/support/osrm/engine/api/fbresult/metadata.js new file mode 100644 index 00000000000..7b86d25e2db --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/metadata.js @@ -0,0 +1,52 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +import * as flatbuffers from 'flatbuffers'; +export class Metadata { + bb = null; + bb_pos = 0; + __init(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; + } + static getRootAsMetadata(bb, obj) { + return (obj || new Metadata()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + static getSizePrefixedRootAsMetadata(bb, obj) { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Metadata()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + datasourceNames(index, optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; + } + datasourceNamesLength() { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + static startMetadata(builder) { + builder.startObject(1); + } + static addDatasourceNames(builder, datasourceNamesOffset) { + builder.addFieldOffset(0, datasourceNamesOffset, 0); + } + static createDatasourceNamesVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]); + } + return builder.endVector(); + } + static startDatasourceNamesVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static endMetadata(builder) { + const offset = builder.endObject(); + return offset; + } + static createMetadata(builder, datasourceNamesOffset) { + Metadata.startMetadata(builder); + Metadata.addDatasourceNames(builder, datasourceNamesOffset); + return Metadata.endMetadata(builder); + } +} diff --git a/features/support/osrm/engine/api/fbresult/metadata.ts b/features/support/osrm/engine/api/fbresult/metadata.ts new file mode 100644 index 00000000000..8820da0c14c --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/metadata.ts @@ -0,0 +1,67 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +export class Metadata { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):Metadata { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsMetadata(bb:flatbuffers.ByteBuffer, obj?:Metadata):Metadata { + return (obj || new Metadata()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsMetadata(bb:flatbuffers.ByteBuffer, obj?:Metadata):Metadata { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Metadata()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +datasourceNames(index: number):string +datasourceNames(index: number,optionalEncoding:flatbuffers.Encoding):string|Uint8Array +datasourceNames(index: number,optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.__string(this.bb!.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; +} + +datasourceNamesLength():number { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +static startMetadata(builder:flatbuffers.Builder) { + builder.startObject(1); +} + +static addDatasourceNames(builder:flatbuffers.Builder, datasourceNamesOffset:flatbuffers.Offset) { + builder.addFieldOffset(0, datasourceNamesOffset, 0); +} + +static createDatasourceNamesVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]!); + } + return builder.endVector(); +} + +static startDatasourceNamesVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static endMetadata(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createMetadata(builder:flatbuffers.Builder, datasourceNamesOffset:flatbuffers.Offset):flatbuffers.Offset { + Metadata.startMetadata(builder); + Metadata.addDatasourceNames(builder, datasourceNamesOffset); + return Metadata.endMetadata(builder); +} +} diff --git a/features/support/osrm/engine/api/fbresult/position.js b/features/support/osrm/engine/api/fbresult/position.js new file mode 100644 index 00000000000..ccb4e8b5a59 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/position.js @@ -0,0 +1,25 @@ +// automatically generated by the FlatBuffers compiler, do not modify +export class Position { + bb = null; + bb_pos = 0; + __init(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; + } + longitude() { + return this.bb.readFloat32(this.bb_pos); + } + latitude() { + return this.bb.readFloat32(this.bb_pos + 4); + } + static sizeOf() { + return 8; + } + static createPosition(builder, longitude, latitude) { + builder.prep(4, 8); + builder.writeFloat32(latitude); + builder.writeFloat32(longitude); + return builder.offset(); + } +} diff --git a/features/support/osrm/engine/api/fbresult/position.ts b/features/support/osrm/engine/api/fbresult/position.ts new file mode 100644 index 00000000000..fb02b335af5 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/position.ts @@ -0,0 +1,35 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +export class Position { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):Position { + this.bb_pos = i; + this.bb = bb; + return this; +} + +longitude():number { + return this.bb!.readFloat32(this.bb_pos); +} + +latitude():number { + return this.bb!.readFloat32(this.bb_pos + 4); +} + +static sizeOf():number { + return 8; +} + +static createPosition(builder:flatbuffers.Builder, longitude: number, latitude: number):flatbuffers.Offset { + builder.prep(4, 8); + builder.writeFloat32(latitude); + builder.writeFloat32(longitude); + return builder.offset(); +} + +} diff --git a/features/support/osrm/engine/api/fbresult/route-object.js b/features/support/osrm/engine/api/fbresult/route-object.js new file mode 100644 index 00000000000..9aec4c0c145 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/route-object.js @@ -0,0 +1,117 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +import * as flatbuffers from 'flatbuffers'; +import { Leg } from '../../../../osrm/engine/api/fbresult/leg.js'; +import { Position } from '../../../../osrm/engine/api/fbresult/position.js'; +export class RouteObject { + bb = null; + bb_pos = 0; + __init(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; + } + static getRootAsRouteObject(bb, obj) { + return (obj || new RouteObject()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + static getSizePrefixedRootAsRouteObject(bb, obj) { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new RouteObject()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + distance() { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; + } + duration() { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; + } + weight() { + const offset = this.bb.__offset(this.bb_pos, 8); + return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; + } + weightName(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + confidence() { + const offset = this.bb.__offset(this.bb_pos, 12); + return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; + } + polyline(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 14); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + coordinates(index, obj) { + const offset = this.bb.__offset(this.bb_pos, 16); + return offset ? (obj || new Position()).__init(this.bb.__vector(this.bb_pos + offset) + index * 8, this.bb) : null; + } + coordinatesLength() { + const offset = this.bb.__offset(this.bb_pos, 16); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + legs(index, obj) { + const offset = this.bb.__offset(this.bb_pos, 18); + return offset ? (obj || new Leg()).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; + } + legsLength() { + const offset = this.bb.__offset(this.bb_pos, 18); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + static startRouteObject(builder) { + builder.startObject(8); + } + static addDistance(builder, distance) { + builder.addFieldFloat32(0, distance, 0.0); + } + static addDuration(builder, duration) { + builder.addFieldFloat32(1, duration, 0.0); + } + static addWeight(builder, weight) { + builder.addFieldFloat32(2, weight, 0.0); + } + static addWeightName(builder, weightNameOffset) { + builder.addFieldOffset(3, weightNameOffset, 0); + } + static addConfidence(builder, confidence) { + builder.addFieldFloat32(4, confidence, 0.0); + } + static addPolyline(builder, polylineOffset) { + builder.addFieldOffset(5, polylineOffset, 0); + } + static addCoordinates(builder, coordinatesOffset) { + builder.addFieldOffset(6, coordinatesOffset, 0); + } + static startCoordinatesVector(builder, numElems) { + builder.startVector(8, numElems, 4); + } + static addLegs(builder, legsOffset) { + builder.addFieldOffset(7, legsOffset, 0); + } + static createLegsVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]); + } + return builder.endVector(); + } + static startLegsVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static endRouteObject(builder) { + const offset = builder.endObject(); + return offset; + } + static createRouteObject(builder, distance, duration, weight, weightNameOffset, confidence, polylineOffset, coordinatesOffset, legsOffset) { + RouteObject.startRouteObject(builder); + RouteObject.addDistance(builder, distance); + RouteObject.addDuration(builder, duration); + RouteObject.addWeight(builder, weight); + RouteObject.addWeightName(builder, weightNameOffset); + RouteObject.addConfidence(builder, confidence); + RouteObject.addPolyline(builder, polylineOffset); + RouteObject.addCoordinates(builder, coordinatesOffset); + RouteObject.addLegs(builder, legsOffset); + return RouteObject.endRouteObject(builder); + } +} diff --git a/features/support/osrm/engine/api/fbresult/route-object.ts b/features/support/osrm/engine/api/fbresult/route-object.ts new file mode 100644 index 00000000000..4acf02978f0 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/route-object.ts @@ -0,0 +1,152 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +import { Leg } from '../../../../osrm/engine/api/fbresult/leg.js'; +import { Position } from '../../../../osrm/engine/api/fbresult/position.js'; + + +export class RouteObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):RouteObject { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsRouteObject(bb:flatbuffers.ByteBuffer, obj?:RouteObject):RouteObject { + return (obj || new RouteObject()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsRouteObject(bb:flatbuffers.ByteBuffer, obj?:RouteObject):RouteObject { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new RouteObject()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +distance():number { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readFloat32(this.bb_pos + offset) : 0.0; +} + +duration():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readFloat32(this.bb_pos + offset) : 0.0; +} + +weight():number { + const offset = this.bb!.__offset(this.bb_pos, 8); + return offset ? this.bb!.readFloat32(this.bb_pos + offset) : 0.0; +} + +weightName():string|null +weightName(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +weightName(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +confidence():number { + const offset = this.bb!.__offset(this.bb_pos, 12); + return offset ? this.bb!.readFloat32(this.bb_pos + offset) : 0.0; +} + +polyline():string|null +polyline(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +polyline(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 14); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +coordinates(index: number, obj?:Position):Position|null { + const offset = this.bb!.__offset(this.bb_pos, 16); + return offset ? (obj || new Position()).__init(this.bb!.__vector(this.bb_pos + offset) + index * 8, this.bb!) : null; +} + +coordinatesLength():number { + const offset = this.bb!.__offset(this.bb_pos, 16); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +legs(index: number, obj?:Leg):Leg|null { + const offset = this.bb!.__offset(this.bb_pos, 18); + return offset ? (obj || new Leg()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null; +} + +legsLength():number { + const offset = this.bb!.__offset(this.bb_pos, 18); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +static startRouteObject(builder:flatbuffers.Builder) { + builder.startObject(8); +} + +static addDistance(builder:flatbuffers.Builder, distance:number) { + builder.addFieldFloat32(0, distance, 0.0); +} + +static addDuration(builder:flatbuffers.Builder, duration:number) { + builder.addFieldFloat32(1, duration, 0.0); +} + +static addWeight(builder:flatbuffers.Builder, weight:number) { + builder.addFieldFloat32(2, weight, 0.0); +} + +static addWeightName(builder:flatbuffers.Builder, weightNameOffset:flatbuffers.Offset) { + builder.addFieldOffset(3, weightNameOffset, 0); +} + +static addConfidence(builder:flatbuffers.Builder, confidence:number) { + builder.addFieldFloat32(4, confidence, 0.0); +} + +static addPolyline(builder:flatbuffers.Builder, polylineOffset:flatbuffers.Offset) { + builder.addFieldOffset(5, polylineOffset, 0); +} + +static addCoordinates(builder:flatbuffers.Builder, coordinatesOffset:flatbuffers.Offset) { + builder.addFieldOffset(6, coordinatesOffset, 0); +} + +static startCoordinatesVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(8, numElems, 4); +} + +static addLegs(builder:flatbuffers.Builder, legsOffset:flatbuffers.Offset) { + builder.addFieldOffset(7, legsOffset, 0); +} + +static createLegsVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]!); + } + return builder.endVector(); +} + +static startLegsVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static endRouteObject(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createRouteObject(builder:flatbuffers.Builder, distance:number, duration:number, weight:number, weightNameOffset:flatbuffers.Offset, confidence:number, polylineOffset:flatbuffers.Offset, coordinatesOffset:flatbuffers.Offset, legsOffset:flatbuffers.Offset):flatbuffers.Offset { + RouteObject.startRouteObject(builder); + RouteObject.addDistance(builder, distance); + RouteObject.addDuration(builder, duration); + RouteObject.addWeight(builder, weight); + RouteObject.addWeightName(builder, weightNameOffset); + RouteObject.addConfidence(builder, confidence); + RouteObject.addPolyline(builder, polylineOffset); + RouteObject.addCoordinates(builder, coordinatesOffset); + RouteObject.addLegs(builder, legsOffset); + return RouteObject.endRouteObject(builder); +} +} diff --git a/features/support/osrm/engine/api/fbresult/step-maneuver.js b/features/support/osrm/engine/api/fbresult/step-maneuver.js new file mode 100644 index 00000000000..ec5e0d3dfec --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/step-maneuver.js @@ -0,0 +1,81 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +import * as flatbuffers from 'flatbuffers'; +import { ManeuverType } from '../../../../osrm/engine/api/fbresult/maneuver-type.js'; +import { Position } from '../../../../osrm/engine/api/fbresult/position.js'; +import { Turn } from '../../../../osrm/engine/api/fbresult/turn.js'; +export class StepManeuver { + bb = null; + bb_pos = 0; + __init(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; + } + static getRootAsStepManeuver(bb, obj) { + return (obj || new StepManeuver()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + static getSizePrefixedRootAsStepManeuver(bb, obj) { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new StepManeuver()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + location(obj) { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? (obj || new Position()).__init(this.bb_pos + offset, this.bb) : null; + } + bearingBefore() { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? this.bb.readUint16(this.bb_pos + offset) : 0; + } + bearingAfter() { + const offset = this.bb.__offset(this.bb_pos, 8); + return offset ? this.bb.readUint16(this.bb_pos + offset) : 0; + } + type() { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? this.bb.readInt8(this.bb_pos + offset) : ManeuverType.Turn; + } + modifier() { + const offset = this.bb.__offset(this.bb_pos, 12); + return offset ? this.bb.readInt8(this.bb_pos + offset) : Turn.None; + } + exit() { + const offset = this.bb.__offset(this.bb_pos, 14); + return offset ? this.bb.readUint8(this.bb_pos + offset) : 0; + } + static startStepManeuver(builder) { + builder.startObject(6); + } + static addLocation(builder, locationOffset) { + builder.addFieldStruct(0, locationOffset, 0); + } + static addBearingBefore(builder, bearingBefore) { + builder.addFieldInt16(1, bearingBefore, 0); + } + static addBearingAfter(builder, bearingAfter) { + builder.addFieldInt16(2, bearingAfter, 0); + } + static addType(builder, type) { + builder.addFieldInt8(3, type, ManeuverType.Turn); + } + static addModifier(builder, modifier) { + builder.addFieldInt8(4, modifier, Turn.None); + } + static addExit(builder, exit) { + builder.addFieldInt8(5, exit, 0); + } + static endStepManeuver(builder) { + const offset = builder.endObject(); + return offset; + } + static createStepManeuver(builder, locationOffset, bearingBefore, bearingAfter, type, modifier, exit) { + StepManeuver.startStepManeuver(builder); + StepManeuver.addLocation(builder, locationOffset); + StepManeuver.addBearingBefore(builder, bearingBefore); + StepManeuver.addBearingAfter(builder, bearingAfter); + StepManeuver.addType(builder, type); + StepManeuver.addModifier(builder, modifier); + StepManeuver.addExit(builder, exit); + return StepManeuver.endStepManeuver(builder); + } +} diff --git a/features/support/osrm/engine/api/fbresult/step-maneuver.ts b/features/support/osrm/engine/api/fbresult/step-maneuver.ts new file mode 100644 index 00000000000..464a0d357bd --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/step-maneuver.ts @@ -0,0 +1,103 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +import { ManeuverType } from '../../../../osrm/engine/api/fbresult/maneuver-type.js'; +import { Position } from '../../../../osrm/engine/api/fbresult/position.js'; +import { Turn } from '../../../../osrm/engine/api/fbresult/turn.js'; + + +export class StepManeuver { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):StepManeuver { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsStepManeuver(bb:flatbuffers.ByteBuffer, obj?:StepManeuver):StepManeuver { + return (obj || new StepManeuver()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsStepManeuver(bb:flatbuffers.ByteBuffer, obj?:StepManeuver):StepManeuver { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new StepManeuver()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +location(obj?:Position):Position|null { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? (obj || new Position()).__init(this.bb_pos + offset, this.bb!) : null; +} + +bearingBefore():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readUint16(this.bb_pos + offset) : 0; +} + +bearingAfter():number { + const offset = this.bb!.__offset(this.bb_pos, 8); + return offset ? this.bb!.readUint16(this.bb_pos + offset) : 0; +} + +type():ManeuverType { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? this.bb!.readInt8(this.bb_pos + offset) : ManeuverType.Turn; +} + +modifier():Turn { + const offset = this.bb!.__offset(this.bb_pos, 12); + return offset ? this.bb!.readInt8(this.bb_pos + offset) : Turn.None; +} + +exit():number { + const offset = this.bb!.__offset(this.bb_pos, 14); + return offset ? this.bb!.readUint8(this.bb_pos + offset) : 0; +} + +static startStepManeuver(builder:flatbuffers.Builder) { + builder.startObject(6); +} + +static addLocation(builder:flatbuffers.Builder, locationOffset:flatbuffers.Offset) { + builder.addFieldStruct(0, locationOffset, 0); +} + +static addBearingBefore(builder:flatbuffers.Builder, bearingBefore:number) { + builder.addFieldInt16(1, bearingBefore, 0); +} + +static addBearingAfter(builder:flatbuffers.Builder, bearingAfter:number) { + builder.addFieldInt16(2, bearingAfter, 0); +} + +static addType(builder:flatbuffers.Builder, type:ManeuverType) { + builder.addFieldInt8(3, type, ManeuverType.Turn); +} + +static addModifier(builder:flatbuffers.Builder, modifier:Turn) { + builder.addFieldInt8(4, modifier, Turn.None); +} + +static addExit(builder:flatbuffers.Builder, exit:number) { + builder.addFieldInt8(5, exit, 0); +} + +static endStepManeuver(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createStepManeuver(builder:flatbuffers.Builder, locationOffset:flatbuffers.Offset, bearingBefore:number, bearingAfter:number, type:ManeuverType, modifier:Turn, exit:number):flatbuffers.Offset { + StepManeuver.startStepManeuver(builder); + StepManeuver.addLocation(builder, locationOffset); + StepManeuver.addBearingBefore(builder, bearingBefore); + StepManeuver.addBearingAfter(builder, bearingAfter); + StepManeuver.addType(builder, type); + StepManeuver.addModifier(builder, modifier); + StepManeuver.addExit(builder, exit); + return StepManeuver.endStepManeuver(builder); +} +} diff --git a/features/support/osrm/engine/api/fbresult/step.js b/features/support/osrm/engine/api/fbresult/step.js new file mode 100644 index 00000000000..f9895271f82 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/step.js @@ -0,0 +1,162 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +import * as flatbuffers from 'flatbuffers'; +import { Intersection } from '../../../../osrm/engine/api/fbresult/intersection.js'; +import { Position } from '../../../../osrm/engine/api/fbresult/position.js'; +import { StepManeuver } from '../../../../osrm/engine/api/fbresult/step-maneuver.js'; +export class Step { + bb = null; + bb_pos = 0; + __init(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; + } + static getRootAsStep(bb, obj) { + return (obj || new Step()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + static getSizePrefixedRootAsStep(bb, obj) { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Step()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + distance() { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; + } + duration() { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; + } + polyline(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 8); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + coordinates(index, obj) { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? (obj || new Position()).__init(this.bb.__vector(this.bb_pos + offset) + index * 8, this.bb) : null; + } + coordinatesLength() { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + weight() { + const offset = this.bb.__offset(this.bb_pos, 12); + return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; + } + name(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 14); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + ref(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 16); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + pronunciation(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 18); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + destinations(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 20); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + exits(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 22); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + mode(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 24); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + maneuver(obj) { + const offset = this.bb.__offset(this.bb_pos, 26); + return offset ? (obj || new StepManeuver()).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null; + } + intersections(index, obj) { + const offset = this.bb.__offset(this.bb_pos, 28); + return offset ? (obj || new Intersection()).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; + } + intersectionsLength() { + const offset = this.bb.__offset(this.bb_pos, 28); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + rotaryName(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 30); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + rotaryPronunciation(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 32); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + drivingSide() { + const offset = this.bb.__offset(this.bb_pos, 34); + return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false; + } + static startStep(builder) { + builder.startObject(16); + } + static addDistance(builder, distance) { + builder.addFieldFloat32(0, distance, 0.0); + } + static addDuration(builder, duration) { + builder.addFieldFloat32(1, duration, 0.0); + } + static addPolyline(builder, polylineOffset) { + builder.addFieldOffset(2, polylineOffset, 0); + } + static addCoordinates(builder, coordinatesOffset) { + builder.addFieldOffset(3, coordinatesOffset, 0); + } + static startCoordinatesVector(builder, numElems) { + builder.startVector(8, numElems, 4); + } + static addWeight(builder, weight) { + builder.addFieldFloat32(4, weight, 0.0); + } + static addName(builder, nameOffset) { + builder.addFieldOffset(5, nameOffset, 0); + } + static addRef(builder, refOffset) { + builder.addFieldOffset(6, refOffset, 0); + } + static addPronunciation(builder, pronunciationOffset) { + builder.addFieldOffset(7, pronunciationOffset, 0); + } + static addDestinations(builder, destinationsOffset) { + builder.addFieldOffset(8, destinationsOffset, 0); + } + static addExits(builder, exitsOffset) { + builder.addFieldOffset(9, exitsOffset, 0); + } + static addMode(builder, modeOffset) { + builder.addFieldOffset(10, modeOffset, 0); + } + static addManeuver(builder, maneuverOffset) { + builder.addFieldOffset(11, maneuverOffset, 0); + } + static addIntersections(builder, intersectionsOffset) { + builder.addFieldOffset(12, intersectionsOffset, 0); + } + static createIntersectionsVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]); + } + return builder.endVector(); + } + static startIntersectionsVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static addRotaryName(builder, rotaryNameOffset) { + builder.addFieldOffset(13, rotaryNameOffset, 0); + } + static addRotaryPronunciation(builder, rotaryPronunciationOffset) { + builder.addFieldOffset(14, rotaryPronunciationOffset, 0); + } + static addDrivingSide(builder, drivingSide) { + builder.addFieldInt8(15, +drivingSide, +false); + } + static endStep(builder) { + const offset = builder.endObject(); + return offset; + } +} diff --git a/features/support/osrm/engine/api/fbresult/step.ts b/features/support/osrm/engine/api/fbresult/step.ts new file mode 100644 index 00000000000..3fe970bd84b --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/step.ts @@ -0,0 +1,227 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +import { Intersection } from '../../../../osrm/engine/api/fbresult/intersection.js'; +import { Position } from '../../../../osrm/engine/api/fbresult/position.js'; +import { StepManeuver } from '../../../../osrm/engine/api/fbresult/step-maneuver.js'; + + +export class Step { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):Step { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsStep(bb:flatbuffers.ByteBuffer, obj?:Step):Step { + return (obj || new Step()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsStep(bb:flatbuffers.ByteBuffer, obj?:Step):Step { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Step()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +distance():number { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readFloat32(this.bb_pos + offset) : 0.0; +} + +duration():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readFloat32(this.bb_pos + offset) : 0.0; +} + +polyline():string|null +polyline(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +polyline(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 8); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +coordinates(index: number, obj?:Position):Position|null { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? (obj || new Position()).__init(this.bb!.__vector(this.bb_pos + offset) + index * 8, this.bb!) : null; +} + +coordinatesLength():number { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +weight():number { + const offset = this.bb!.__offset(this.bb_pos, 12); + return offset ? this.bb!.readFloat32(this.bb_pos + offset) : 0.0; +} + +name():string|null +name(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +name(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 14); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +ref():string|null +ref(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +ref(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 16); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +pronunciation():string|null +pronunciation(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +pronunciation(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 18); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +destinations():string|null +destinations(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +destinations(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 20); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +exits():string|null +exits(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +exits(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 22); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +mode():string|null +mode(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +mode(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 24); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +maneuver(obj?:StepManeuver):StepManeuver|null { + const offset = this.bb!.__offset(this.bb_pos, 26); + return offset ? (obj || new StepManeuver()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null; +} + +intersections(index: number, obj?:Intersection):Intersection|null { + const offset = this.bb!.__offset(this.bb_pos, 28); + return offset ? (obj || new Intersection()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null; +} + +intersectionsLength():number { + const offset = this.bb!.__offset(this.bb_pos, 28); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +rotaryName():string|null +rotaryName(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +rotaryName(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 30); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +rotaryPronunciation():string|null +rotaryPronunciation(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +rotaryPronunciation(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 32); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +drivingSide():boolean { + const offset = this.bb!.__offset(this.bb_pos, 34); + return offset ? !!this.bb!.readInt8(this.bb_pos + offset) : false; +} + +static startStep(builder:flatbuffers.Builder) { + builder.startObject(16); +} + +static addDistance(builder:flatbuffers.Builder, distance:number) { + builder.addFieldFloat32(0, distance, 0.0); +} + +static addDuration(builder:flatbuffers.Builder, duration:number) { + builder.addFieldFloat32(1, duration, 0.0); +} + +static addPolyline(builder:flatbuffers.Builder, polylineOffset:flatbuffers.Offset) { + builder.addFieldOffset(2, polylineOffset, 0); +} + +static addCoordinates(builder:flatbuffers.Builder, coordinatesOffset:flatbuffers.Offset) { + builder.addFieldOffset(3, coordinatesOffset, 0); +} + +static startCoordinatesVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(8, numElems, 4); +} + +static addWeight(builder:flatbuffers.Builder, weight:number) { + builder.addFieldFloat32(4, weight, 0.0); +} + +static addName(builder:flatbuffers.Builder, nameOffset:flatbuffers.Offset) { + builder.addFieldOffset(5, nameOffset, 0); +} + +static addRef(builder:flatbuffers.Builder, refOffset:flatbuffers.Offset) { + builder.addFieldOffset(6, refOffset, 0); +} + +static addPronunciation(builder:flatbuffers.Builder, pronunciationOffset:flatbuffers.Offset) { + builder.addFieldOffset(7, pronunciationOffset, 0); +} + +static addDestinations(builder:flatbuffers.Builder, destinationsOffset:flatbuffers.Offset) { + builder.addFieldOffset(8, destinationsOffset, 0); +} + +static addExits(builder:flatbuffers.Builder, exitsOffset:flatbuffers.Offset) { + builder.addFieldOffset(9, exitsOffset, 0); +} + +static addMode(builder:flatbuffers.Builder, modeOffset:flatbuffers.Offset) { + builder.addFieldOffset(10, modeOffset, 0); +} + +static addManeuver(builder:flatbuffers.Builder, maneuverOffset:flatbuffers.Offset) { + builder.addFieldOffset(11, maneuverOffset, 0); +} + +static addIntersections(builder:flatbuffers.Builder, intersectionsOffset:flatbuffers.Offset) { + builder.addFieldOffset(12, intersectionsOffset, 0); +} + +static createIntersectionsVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]!); + } + return builder.endVector(); +} + +static startIntersectionsVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static addRotaryName(builder:flatbuffers.Builder, rotaryNameOffset:flatbuffers.Offset) { + builder.addFieldOffset(13, rotaryNameOffset, 0); +} + +static addRotaryPronunciation(builder:flatbuffers.Builder, rotaryPronunciationOffset:flatbuffers.Offset) { + builder.addFieldOffset(14, rotaryPronunciationOffset, 0); +} + +static addDrivingSide(builder:flatbuffers.Builder, drivingSide:boolean) { + builder.addFieldInt8(15, +drivingSide, +false); +} + +static endStep(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +} diff --git a/features/support/osrm/engine/api/fbresult/table-result.js b/features/support/osrm/engine/api/fbresult/table-result.js new file mode 100644 index 00000000000..47c9478695b --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/table-result.js @@ -0,0 +1,147 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +import * as flatbuffers from 'flatbuffers'; +import { Waypoint } from '../../../../osrm/engine/api/fbresult/waypoint.js'; +export class TableResult { + bb = null; + bb_pos = 0; + __init(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; + } + static getRootAsTableResult(bb, obj) { + return (obj || new TableResult()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + static getSizePrefixedRootAsTableResult(bb, obj) { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new TableResult()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + durations(index) { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? this.bb.readFloat32(this.bb.__vector(this.bb_pos + offset) + index * 4) : 0; + } + durationsLength() { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + durationsArray() { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? new Float32Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null; + } + rows() { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? this.bb.readUint16(this.bb_pos + offset) : 0; + } + cols() { + const offset = this.bb.__offset(this.bb_pos, 8); + return offset ? this.bb.readUint16(this.bb_pos + offset) : 0; + } + distances(index) { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? this.bb.readFloat32(this.bb.__vector(this.bb_pos + offset) + index * 4) : 0; + } + distancesLength() { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + distancesArray() { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? new Float32Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null; + } + destinations(index, obj) { + const offset = this.bb.__offset(this.bb_pos, 12); + return offset ? (obj || new Waypoint()).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; + } + destinationsLength() { + const offset = this.bb.__offset(this.bb_pos, 12); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + fallbackSpeedCells(index) { + const offset = this.bb.__offset(this.bb_pos, 14); + return offset ? this.bb.readUint32(this.bb.__vector(this.bb_pos + offset) + index * 4) : 0; + } + fallbackSpeedCellsLength() { + const offset = this.bb.__offset(this.bb_pos, 14); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; + } + fallbackSpeedCellsArray() { + const offset = this.bb.__offset(this.bb_pos, 14); + return offset ? new Uint32Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null; + } + static startTableResult(builder) { + builder.startObject(6); + } + static addDurations(builder, durationsOffset) { + builder.addFieldOffset(0, durationsOffset, 0); + } + static createDurationsVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addFloat32(data[i]); + } + return builder.endVector(); + } + static startDurationsVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static addRows(builder, rows) { + builder.addFieldInt16(1, rows, 0); + } + static addCols(builder, cols) { + builder.addFieldInt16(2, cols, 0); + } + static addDistances(builder, distancesOffset) { + builder.addFieldOffset(3, distancesOffset, 0); + } + static createDistancesVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addFloat32(data[i]); + } + return builder.endVector(); + } + static startDistancesVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static addDestinations(builder, destinationsOffset) { + builder.addFieldOffset(4, destinationsOffset, 0); + } + static createDestinationsVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]); + } + return builder.endVector(); + } + static startDestinationsVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static addFallbackSpeedCells(builder, fallbackSpeedCellsOffset) { + builder.addFieldOffset(5, fallbackSpeedCellsOffset, 0); + } + static createFallbackSpeedCellsVector(builder, data) { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt32(data[i]); + } + return builder.endVector(); + } + static startFallbackSpeedCellsVector(builder, numElems) { + builder.startVector(4, numElems, 4); + } + static endTableResult(builder) { + const offset = builder.endObject(); + return offset; + } + static createTableResult(builder, durationsOffset, rows, cols, distancesOffset, destinationsOffset, fallbackSpeedCellsOffset) { + TableResult.startTableResult(builder); + TableResult.addDurations(builder, durationsOffset); + TableResult.addRows(builder, rows); + TableResult.addCols(builder, cols); + TableResult.addDistances(builder, distancesOffset); + TableResult.addDestinations(builder, destinationsOffset); + TableResult.addFallbackSpeedCells(builder, fallbackSpeedCellsOffset); + return TableResult.endTableResult(builder); + } +} diff --git a/features/support/osrm/engine/api/fbresult/table-result.ts b/features/support/osrm/engine/api/fbresult/table-result.ts new file mode 100644 index 00000000000..b6ed7f12d0e --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/table-result.ts @@ -0,0 +1,199 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +import { Waypoint } from '../../../../osrm/engine/api/fbresult/waypoint.js'; + + +export class TableResult { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):TableResult { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsTableResult(bb:flatbuffers.ByteBuffer, obj?:TableResult):TableResult { + return (obj || new TableResult()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsTableResult(bb:flatbuffers.ByteBuffer, obj?:TableResult):TableResult { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new TableResult()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +durations(index: number):number|null { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readFloat32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; +} + +durationsLength():number { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +durationsArray():Float32Array|null { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? new Float32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +rows():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readUint16(this.bb_pos + offset) : 0; +} + +cols():number { + const offset = this.bb!.__offset(this.bb_pos, 8); + return offset ? this.bb!.readUint16(this.bb_pos + offset) : 0; +} + +distances(index: number):number|null { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? this.bb!.readFloat32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; +} + +distancesLength():number { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +distancesArray():Float32Array|null { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? new Float32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +destinations(index: number, obj?:Waypoint):Waypoint|null { + const offset = this.bb!.__offset(this.bb_pos, 12); + return offset ? (obj || new Waypoint()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null; +} + +destinationsLength():number { + const offset = this.bb!.__offset(this.bb_pos, 12); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +fallbackSpeedCells(index: number):number|null { + const offset = this.bb!.__offset(this.bb_pos, 14); + return offset ? this.bb!.readUint32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; +} + +fallbackSpeedCellsLength():number { + const offset = this.bb!.__offset(this.bb_pos, 14); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +fallbackSpeedCellsArray():Uint32Array|null { + const offset = this.bb!.__offset(this.bb_pos, 14); + return offset ? new Uint32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +static startTableResult(builder:flatbuffers.Builder) { + builder.startObject(6); +} + +static addDurations(builder:flatbuffers.Builder, durationsOffset:flatbuffers.Offset) { + builder.addFieldOffset(0, durationsOffset, 0); +} + +static createDurationsVector(builder:flatbuffers.Builder, data:number[]|Float32Array):flatbuffers.Offset; +/** + * @deprecated This Uint8Array overload will be removed in the future. + */ +static createDurationsVector(builder:flatbuffers.Builder, data:number[]|Uint8Array):flatbuffers.Offset; +static createDurationsVector(builder:flatbuffers.Builder, data:number[]|Float32Array|Uint8Array):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addFloat32(data[i]!); + } + return builder.endVector(); +} + +static startDurationsVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static addRows(builder:flatbuffers.Builder, rows:number) { + builder.addFieldInt16(1, rows, 0); +} + +static addCols(builder:flatbuffers.Builder, cols:number) { + builder.addFieldInt16(2, cols, 0); +} + +static addDistances(builder:flatbuffers.Builder, distancesOffset:flatbuffers.Offset) { + builder.addFieldOffset(3, distancesOffset, 0); +} + +static createDistancesVector(builder:flatbuffers.Builder, data:number[]|Float32Array):flatbuffers.Offset; +/** + * @deprecated This Uint8Array overload will be removed in the future. + */ +static createDistancesVector(builder:flatbuffers.Builder, data:number[]|Uint8Array):flatbuffers.Offset; +static createDistancesVector(builder:flatbuffers.Builder, data:number[]|Float32Array|Uint8Array):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addFloat32(data[i]!); + } + return builder.endVector(); +} + +static startDistancesVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static addDestinations(builder:flatbuffers.Builder, destinationsOffset:flatbuffers.Offset) { + builder.addFieldOffset(4, destinationsOffset, 0); +} + +static createDestinationsVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]!); + } + return builder.endVector(); +} + +static startDestinationsVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static addFallbackSpeedCells(builder:flatbuffers.Builder, fallbackSpeedCellsOffset:flatbuffers.Offset) { + builder.addFieldOffset(5, fallbackSpeedCellsOffset, 0); +} + +static createFallbackSpeedCellsVector(builder:flatbuffers.Builder, data:number[]|Uint32Array):flatbuffers.Offset; +/** + * @deprecated This Uint8Array overload will be removed in the future. + */ +static createFallbackSpeedCellsVector(builder:flatbuffers.Builder, data:number[]|Uint8Array):flatbuffers.Offset; +static createFallbackSpeedCellsVector(builder:flatbuffers.Builder, data:number[]|Uint32Array|Uint8Array):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt32(data[i]!); + } + return builder.endVector(); +} + +static startFallbackSpeedCellsVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static endTableResult(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createTableResult(builder:flatbuffers.Builder, durationsOffset:flatbuffers.Offset, rows:number, cols:number, distancesOffset:flatbuffers.Offset, destinationsOffset:flatbuffers.Offset, fallbackSpeedCellsOffset:flatbuffers.Offset):flatbuffers.Offset { + TableResult.startTableResult(builder); + TableResult.addDurations(builder, durationsOffset); + TableResult.addRows(builder, rows); + TableResult.addCols(builder, cols); + TableResult.addDistances(builder, distancesOffset); + TableResult.addDestinations(builder, destinationsOffset); + TableResult.addFallbackSpeedCells(builder, fallbackSpeedCellsOffset); + return TableResult.endTableResult(builder); +} +} diff --git a/features/support/osrm/engine/api/fbresult/turn.js b/features/support/osrm/engine/api/fbresult/turn.js new file mode 100644 index 00000000000..e68fd3857b9 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/turn.js @@ -0,0 +1,14 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +export var Turn; +(function (Turn) { + Turn[Turn["None"] = 0] = "None"; + Turn[Turn["UTurn"] = 1] = "UTurn"; + Turn[Turn["SharpRight"] = 2] = "SharpRight"; + Turn[Turn["Right"] = 3] = "Right"; + Turn[Turn["SlightRight"] = 4] = "SlightRight"; + Turn[Turn["Straight"] = 5] = "Straight"; + Turn[Turn["SlightLeft"] = 6] = "SlightLeft"; + Turn[Turn["Left"] = 7] = "Left"; + Turn[Turn["SharpLeft"] = 8] = "SharpLeft"; +})(Turn || (Turn = {})); diff --git a/features/support/osrm/engine/api/fbresult/turn.ts b/features/support/osrm/engine/api/fbresult/turn.ts new file mode 100644 index 00000000000..6fa0e17b07c --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/turn.ts @@ -0,0 +1,15 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +export enum Turn { + None = 0, + UTurn = 1, + SharpRight = 2, + Right = 3, + SlightRight = 4, + Straight = 5, + SlightLeft = 6, + Left = 7, + SharpLeft = 8 +} diff --git a/features/support/osrm/engine/api/fbresult/uint64-pair.js b/features/support/osrm/engine/api/fbresult/uint64-pair.js new file mode 100644 index 00000000000..0db2a9a45c5 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/uint64-pair.js @@ -0,0 +1,25 @@ +// automatically generated by the FlatBuffers compiler, do not modify +export class Uint64Pair { + bb = null; + bb_pos = 0; + __init(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; + } + first() { + return this.bb.readUint64(this.bb_pos); + } + second() { + return this.bb.readUint64(this.bb_pos + 8); + } + static sizeOf() { + return 16; + } + static createUint64Pair(builder, first, second) { + builder.prep(8, 16); + builder.writeInt64(BigInt(second ?? 0)); + builder.writeInt64(BigInt(first ?? 0)); + return builder.offset(); + } +} diff --git a/features/support/osrm/engine/api/fbresult/uint64-pair.ts b/features/support/osrm/engine/api/fbresult/uint64-pair.ts new file mode 100644 index 00000000000..8502b3b396e --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/uint64-pair.ts @@ -0,0 +1,35 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +export class Uint64Pair { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):Uint64Pair { + this.bb_pos = i; + this.bb = bb; + return this; +} + +first():bigint { + return this.bb!.readUint64(this.bb_pos); +} + +second():bigint { + return this.bb!.readUint64(this.bb_pos + 8); +} + +static sizeOf():number { + return 16; +} + +static createUint64Pair(builder:flatbuffers.Builder, first: bigint, second: bigint):flatbuffers.Offset { + builder.prep(8, 16); + builder.writeInt64(BigInt(second ?? 0)); + builder.writeInt64(BigInt(first ?? 0)); + return builder.offset(); +} + +} diff --git a/features/support/osrm/engine/api/fbresult/waypoint.js b/features/support/osrm/engine/api/fbresult/waypoint.js new file mode 100644 index 00000000000..51628e01608 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/waypoint.js @@ -0,0 +1,91 @@ +// automatically generated by the FlatBuffers compiler, do not modify +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ +import * as flatbuffers from 'flatbuffers'; +import { Position } from '../../../../osrm/engine/api/fbresult/position.js'; +import { Uint64Pair } from '../../../../osrm/engine/api/fbresult/uint64-pair.js'; +export class Waypoint { + bb = null; + bb_pos = 0; + __init(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; + } + static getRootAsWaypoint(bb, obj) { + return (obj || new Waypoint()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + static getSizePrefixedRootAsWaypoint(bb, obj) { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Waypoint()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + } + hint(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 4); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + distance() { + const offset = this.bb.__offset(this.bb_pos, 6); + return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; + } + name(optionalEncoding) { + const offset = this.bb.__offset(this.bb_pos, 8); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; + } + location(obj) { + const offset = this.bb.__offset(this.bb_pos, 10); + return offset ? (obj || new Position()).__init(this.bb_pos + offset, this.bb) : null; + } + nodes(obj) { + const offset = this.bb.__offset(this.bb_pos, 12); + return offset ? (obj || new Uint64Pair()).__init(this.bb_pos + offset, this.bb) : null; + } + matchingsIndex() { + const offset = this.bb.__offset(this.bb_pos, 14); + return offset ? this.bb.readUint32(this.bb_pos + offset) : 0; + } + waypointIndex() { + const offset = this.bb.__offset(this.bb_pos, 16); + return offset ? this.bb.readUint32(this.bb_pos + offset) : 0; + } + alternativesCount() { + const offset = this.bb.__offset(this.bb_pos, 18); + return offset ? this.bb.readUint32(this.bb_pos + offset) : 0; + } + tripsIndex() { + const offset = this.bb.__offset(this.bb_pos, 20); + return offset ? this.bb.readUint32(this.bb_pos + offset) : 0; + } + static startWaypoint(builder) { + builder.startObject(9); + } + static addHint(builder, hintOffset) { + builder.addFieldOffset(0, hintOffset, 0); + } + static addDistance(builder, distance) { + builder.addFieldFloat32(1, distance, 0.0); + } + static addName(builder, nameOffset) { + builder.addFieldOffset(2, nameOffset, 0); + } + static addLocation(builder, locationOffset) { + builder.addFieldStruct(3, locationOffset, 0); + } + static addNodes(builder, nodesOffset) { + builder.addFieldStruct(4, nodesOffset, 0); + } + static addMatchingsIndex(builder, matchingsIndex) { + builder.addFieldInt32(5, matchingsIndex, 0); + } + static addWaypointIndex(builder, waypointIndex) { + builder.addFieldInt32(6, waypointIndex, 0); + } + static addAlternativesCount(builder, alternativesCount) { + builder.addFieldInt32(7, alternativesCount, 0); + } + static addTripsIndex(builder, tripsIndex) { + builder.addFieldInt32(8, tripsIndex, 0); + } + static endWaypoint(builder) { + const offset = builder.endObject(); + return offset; + } +} diff --git a/features/support/osrm/engine/api/fbresult/waypoint.ts b/features/support/osrm/engine/api/fbresult/waypoint.ts new file mode 100644 index 00000000000..4d258943418 --- /dev/null +++ b/features/support/osrm/engine/api/fbresult/waypoint.ts @@ -0,0 +1,123 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +import { Position } from '../../../../osrm/engine/api/fbresult/position.js'; +import { Uint64Pair } from '../../../../osrm/engine/api/fbresult/uint64-pair.js'; + + +export class Waypoint { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):Waypoint { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsWaypoint(bb:flatbuffers.ByteBuffer, obj?:Waypoint):Waypoint { + return (obj || new Waypoint()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsWaypoint(bb:flatbuffers.ByteBuffer, obj?:Waypoint):Waypoint { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Waypoint()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +hint():string|null +hint(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +hint(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +distance():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readFloat32(this.bb_pos + offset) : 0.0; +} + +name():string|null +name(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null +name(optionalEncoding?:any):string|Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 8); + return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; +} + +location(obj?:Position):Position|null { + const offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? (obj || new Position()).__init(this.bb_pos + offset, this.bb!) : null; +} + +nodes(obj?:Uint64Pair):Uint64Pair|null { + const offset = this.bb!.__offset(this.bb_pos, 12); + return offset ? (obj || new Uint64Pair()).__init(this.bb_pos + offset, this.bb!) : null; +} + +matchingsIndex():number { + const offset = this.bb!.__offset(this.bb_pos, 14); + return offset ? this.bb!.readUint32(this.bb_pos + offset) : 0; +} + +waypointIndex():number { + const offset = this.bb!.__offset(this.bb_pos, 16); + return offset ? this.bb!.readUint32(this.bb_pos + offset) : 0; +} + +alternativesCount():number { + const offset = this.bb!.__offset(this.bb_pos, 18); + return offset ? this.bb!.readUint32(this.bb_pos + offset) : 0; +} + +tripsIndex():number { + const offset = this.bb!.__offset(this.bb_pos, 20); + return offset ? this.bb!.readUint32(this.bb_pos + offset) : 0; +} + +static startWaypoint(builder:flatbuffers.Builder) { + builder.startObject(9); +} + +static addHint(builder:flatbuffers.Builder, hintOffset:flatbuffers.Offset) { + builder.addFieldOffset(0, hintOffset, 0); +} + +static addDistance(builder:flatbuffers.Builder, distance:number) { + builder.addFieldFloat32(1, distance, 0.0); +} + +static addName(builder:flatbuffers.Builder, nameOffset:flatbuffers.Offset) { + builder.addFieldOffset(2, nameOffset, 0); +} + +static addLocation(builder:flatbuffers.Builder, locationOffset:flatbuffers.Offset) { + builder.addFieldStruct(3, locationOffset, 0); +} + +static addNodes(builder:flatbuffers.Builder, nodesOffset:flatbuffers.Offset) { + builder.addFieldStruct(4, nodesOffset, 0); +} + +static addMatchingsIndex(builder:flatbuffers.Builder, matchingsIndex:number) { + builder.addFieldInt32(5, matchingsIndex, 0); +} + +static addWaypointIndex(builder:flatbuffers.Builder, waypointIndex:number) { + builder.addFieldInt32(6, waypointIndex, 0); +} + +static addAlternativesCount(builder:flatbuffers.Builder, alternativesCount:number) { + builder.addFieldInt32(7, alternativesCount, 0); +} + +static addTripsIndex(builder:flatbuffers.Builder, tripsIndex:number) { + builder.addFieldInt32(8, tripsIndex, 0); +} + +static endWaypoint(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +} diff --git a/generated/include/engine/api/flatbuffers/fbresult_generated.h b/generated/include/engine/api/flatbuffers/fbresult_generated.h index 0f01298198f..0c81c04e57c 100644 --- a/generated/include/engine/api/flatbuffers/fbresult_generated.h +++ b/generated/include/engine/api/flatbuffers/fbresult_generated.h @@ -8,9 +8,9 @@ // Ensure the included flatbuffers.h is the same version as when this file was // generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && - FLATBUFFERS_VERSION_MINOR == 3 && - FLATBUFFERS_VERSION_REVISION == 25, +static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && + FLATBUFFERS_VERSION_MINOR == 9 && + FLATBUFFERS_VERSION_REVISION == 23, "Non-compatible flatbuffers version included"); #include "route_generated.h" diff --git a/generated/include/engine/api/flatbuffers/position_generated.h b/generated/include/engine/api/flatbuffers/position_generated.h index aa3ea2d8b21..84cf39edc01 100644 --- a/generated/include/engine/api/flatbuffers/position_generated.h +++ b/generated/include/engine/api/flatbuffers/position_generated.h @@ -8,9 +8,9 @@ // Ensure the included flatbuffers.h is the same version as when this file was // generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && - FLATBUFFERS_VERSION_MINOR == 3 && - FLATBUFFERS_VERSION_REVISION == 25, +static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && + FLATBUFFERS_VERSION_MINOR == 9 && + FLATBUFFERS_VERSION_REVISION == 23, "Non-compatible flatbuffers version included"); namespace osrm { diff --git a/generated/include/engine/api/flatbuffers/route_generated.h b/generated/include/engine/api/flatbuffers/route_generated.h index 6ae492bd429..4c28ed5fbd8 100644 --- a/generated/include/engine/api/flatbuffers/route_generated.h +++ b/generated/include/engine/api/flatbuffers/route_generated.h @@ -8,9 +8,9 @@ // Ensure the included flatbuffers.h is the same version as when this file was // generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && - FLATBUFFERS_VERSION_MINOR == 3 && - FLATBUFFERS_VERSION_REVISION == 25, +static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && + FLATBUFFERS_VERSION_MINOR == 9 && + FLATBUFFERS_VERSION_REVISION == 23, "Non-compatible flatbuffers version included"); #include "waypoint_generated.h" diff --git a/generated/include/engine/api/flatbuffers/table_generated.h b/generated/include/engine/api/flatbuffers/table_generated.h index 30c6bd81ca8..5076028b8a8 100644 --- a/generated/include/engine/api/flatbuffers/table_generated.h +++ b/generated/include/engine/api/flatbuffers/table_generated.h @@ -8,9 +8,9 @@ // Ensure the included flatbuffers.h is the same version as when this file was // generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && - FLATBUFFERS_VERSION_MINOR == 3 && - FLATBUFFERS_VERSION_REVISION == 25, +static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && + FLATBUFFERS_VERSION_MINOR == 9 && + FLATBUFFERS_VERSION_REVISION == 23, "Non-compatible flatbuffers version included"); #include "waypoint_generated.h" diff --git a/generated/include/engine/api/flatbuffers/waypoint_generated.h b/generated/include/engine/api/flatbuffers/waypoint_generated.h index 3fae94975d7..edfb9f8186f 100644 --- a/generated/include/engine/api/flatbuffers/waypoint_generated.h +++ b/generated/include/engine/api/flatbuffers/waypoint_generated.h @@ -8,9 +8,9 @@ // Ensure the included flatbuffers.h is the same version as when this file was // generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && - FLATBUFFERS_VERSION_MINOR == 3 && - FLATBUFFERS_VERSION_REVISION == 25, +static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && + FLATBUFFERS_VERSION_MINOR == 9 && + FLATBUFFERS_VERSION_REVISION == 23, "Non-compatible flatbuffers version included"); #include "position_generated.h" diff --git a/package-lock.json b/package-lock.json index 02b4c3fe3f9..caebaabd5cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,13 +36,14 @@ "documentation": "^14.0.2", "eslint": "9.26.0", "faucet": "^0.0.4", - "flatbuffers": "24.3.25", + "flatbuffers": "25.9.23", "husky": "^9.1.7", "jsonpath": "^1.1.1", "lint-staged": "^16.1.6", "node-addon-api": "8.3.1", "node-cmake": "^2.5.1", "tape": "5.9.0", + "typescript": "^5.0.0", "uglify-js": "^3.17.0", "xmlbuilder": "15.1.1" }, @@ -133,6 +134,7 @@ "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -2291,6 +2293,7 @@ "integrity": "sha512-659CCFsrsyvuBi/Eix1fnhSheMnojSfnBcqJ3IMPNawx7JlrNJDcXYSSdxcUw3n/nG05P+ptCjmiZY3i14p+tA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@cucumber/messages": ">=19.1.4 <29" } @@ -2462,6 +2465,7 @@ "integrity": "sha512-Kxap9uP5jD8tHUZVjTWgzxemi/0uOsbGjd4LBOSxcJoOCRbESFwemUzilJuzNTB8pcTQUh8D5oudUyxfkJOKmA==", "dev": true, "license": "MIT", + "peer": true, "peerDependencies": { "@cucumber/messages": ">=17.1.1" } @@ -2472,6 +2476,7 @@ "integrity": "sha512-f2o/HqKHgsqzFLdq6fAhfG1FNOQPdBdyMGpKwhb7hZqg0yZtx9BVqkTyuoNk83Fcvk3wjMVfouFXXHNEk4nddA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/uuid": "10.0.0", "class-transformer": "0.5.1", @@ -5979,6 +5984,7 @@ "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6038,6 +6044,7 @@ "version": "5.5.2", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "co": "^4.6.0", "fast-deep-equal": "^1.0.0", @@ -8472,6 +8479,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001737", "electron-to-chromium": "^1.5.211", @@ -11271,6 +11279,7 @@ "version": "0.1.13", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "iconv-lite": "^0.6.2" } @@ -11621,6 +11630,7 @@ "integrity": "sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", @@ -13120,9 +13130,9 @@ } }, "node_modules/flatbuffers": { - "version": "24.3.25", - "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-24.3.25.tgz", - "integrity": "sha512-3HDgPbgiwWMI9zVB7VYBHaMrbOO7Gm0v+yD2FV/sCKj+9NDeVL7BOBYUuhWAQGKWOzBo8S9WdMvV0eixO233XQ==", + "version": "25.9.23", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz", + "integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==", "dev": true, "license": "Apache-2.0" }, @@ -19859,6 +19869,7 @@ "version": "15.7.0", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "create-react-class": "^15.6.0", "fbjs": "^0.8.9", @@ -23153,6 +23164,20 @@ "dev": true, "license": "MIT" }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/typical": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/typical/-/typical-7.3.0.tgz", @@ -24483,6 +24508,7 @@ "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", "dev": true, "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index 51893bc223e..46bd7ef4341 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,11 @@ "docs": "./scripts/build_api_docs.sh", "install": "node-pre-gyp install --fallback-to-build=false || ./scripts/node_install.sh", "nodejs-tests": "make -C test/data && ./lib/binding/osrm-datastore test/data/ch/monaco.osrm && node test/nodejs/index.js | faucet", - "prepare": "husky" + "prepare": "husky", + "generate:flatbuffers:ts": "flatc --ts -o features/support include/engine/api/flatbuffers/fbresult.fbs include/engine/api/flatbuffers/position.fbs include/engine/api/flatbuffers/route.fbs include/engine/api/flatbuffers/table.fbs include/engine/api/flatbuffers/waypoint.fbs", + "generate:flatbuffers:js": "tsc --project tsconfig.flatbuffers.json", + "generate:flatbuffers:cpp": "flatc --cpp -o generated/include/engine/api/flatbuffers include/engine/api/flatbuffers/fbresult.fbs include/engine/api/flatbuffers/position.fbs include/engine/api/flatbuffers/route.fbs include/engine/api/flatbuffers/table.fbs include/engine/api/flatbuffers/waypoint.fbs", + "generate:flatbuffers": "npm run generate:flatbuffers:ts && npm run generate:flatbuffers:js && npm run generate:flatbuffers:cpp" }, "repository": { "type": "git", @@ -59,8 +63,9 @@ "documentation": "^14.0.2", "eslint": "9.26.0", "faucet": "^0.0.4", - "flatbuffers": "24.3.25", + "flatbuffers": "25.9.23", "husky": "^9.1.7", + "typescript": "^5.0.0", "jsonpath": "^1.1.1", "lint-staged": "^16.1.6", "node-addon-api": "8.3.1", diff --git a/scripts/update_dependencies.sh b/scripts/update_dependencies.sh index 0ef21ce8f50..870f39b8984 100755 --- a/scripts/update_dependencies.sh +++ b/scripts/update_dependencies.sh @@ -33,7 +33,7 @@ FMT_PATH="fmtlib/fmt" FMT_TAG=11.2.0 FLATBUFFERS_PATH="google/flatbuffers" -FLATBUFFERS_TAG=v24.3.25 +FLATBUFFERS_TAG=v25.9.23 function update_subtree () { name=$(echo "$1" | tr '[:lower:]' '[:upper:]') diff --git a/test/nodejs/match.js b/test/nodejs/match.js index fc82ea8b452..5548e852f91 100644 --- a/test/nodejs/match.js +++ b/test/nodejs/match.js @@ -3,9 +3,8 @@ import OSRM from '../../lib/index.js'; import test from 'tape'; import { data_path, mld_data_path, three_test_coordinates, two_test_coordinates } from './constants.js'; import flatbuffers from 'flatbuffers'; -import { osrm } from '../../features/support/fbresult_generated.js'; +import { FBResult } from '../../features/support/osrm/engine/api/fbresult/fbresult.js'; -const FBResult = osrm.engine.api.fbresult.FBResult; test('match: match in Monaco with flatbuffers format', function(assert) { diff --git a/test/nodejs/nearest.js b/test/nodejs/nearest.js index 81b7702949d..f8c269839bb 100644 --- a/test/nodejs/nearest.js +++ b/test/nodejs/nearest.js @@ -3,9 +3,8 @@ import OSRM from '../../lib/index.js'; import test from 'tape'; import { data_path, mld_data_path, three_test_coordinates, two_test_coordinates } from './constants.js'; import flatbuffers from 'flatbuffers'; -import { osrm } from '../../features/support/fbresult_generated.js'; +import { FBResult } from '../../features/support/osrm/engine/api/fbresult/fbresult.js'; -const FBResult = osrm.engine.api.fbresult.FBResult; test('nearest with flatbuffers format', function(assert) { diff --git a/test/nodejs/route.js b/test/nodejs/route.js index 17d4de23a73..4f26cb70b2c 100644 --- a/test/nodejs/route.js +++ b/test/nodejs/route.js @@ -3,9 +3,8 @@ import OSRM from '../../lib/index.js'; import test from 'tape'; import { data_path as monaco_path, mld_data_path as monaco_mld_path, three_test_coordinates, two_test_coordinates } from './constants.js'; import flatbuffers from 'flatbuffers'; -import { osrm } from '../../features/support/fbresult_generated.js'; +import { FBResult } from '../../features/support/osrm/engine/api/fbresult/fbresult.js'; -const FBResult = osrm.engine.api.fbresult.FBResult; test('route: routes Monaco and can return result in flatbuffers', function(assert) { assert.plan(5); diff --git a/test/nodejs/table.js b/test/nodejs/table.js index be4a53b8ba1..f4b4c182df3 100644 --- a/test/nodejs/table.js +++ b/test/nodejs/table.js @@ -3,9 +3,8 @@ import OSRM from '../../lib/index.js'; import test from 'tape'; import { data_path, mld_data_path, three_test_coordinates, two_test_coordinates } from './constants.js'; import flatbuffers from 'flatbuffers'; -import { osrm } from '../../features/support/fbresult_generated.js'; +import { FBResult } from '../../features/support/osrm/engine/api/fbresult/fbresult.js'; -const FBResult = osrm.engine.api.fbresult.FBResult; test('table: flatbuffer format', function(assert) { assert.plan(3); diff --git a/test/nodejs/trip.js b/test/nodejs/trip.js index 0363607bf0c..6d9b8677cb4 100644 --- a/test/nodejs/trip.js +++ b/test/nodejs/trip.js @@ -3,9 +3,8 @@ import OSRM from '../../lib/index.js'; import test from 'tape'; import { data_path, mld_data_path, three_test_coordinates, two_test_coordinates } from './constants.js'; import flatbuffers from 'flatbuffers'; -import { osrm } from '../../features/support/fbresult_generated.js'; +import { FBResult } from '../../features/support/osrm/engine/api/fbresult/fbresult.js'; -const FBResult = osrm.engine.api.fbresult.FBResult; test('trip: trip in Monaco with flatbuffers format', function(assert) { assert.plan(2); diff --git a/third_party/flatbuffers/.bazelci/presubmit.yml b/third_party/flatbuffers/.bazelci/presubmit.yml index bcab65430d6..aa88684f153 100644 --- a/third_party/flatbuffers/.bazelci/presubmit.yml +++ b/third_party/flatbuffers/.bazelci/presubmit.yml @@ -1,38 +1,60 @@ --- buildifier: latest -bazel: 6.4.0 -platforms: - ubuntu1804: +matrix: + bazel: + - 7.x + - 8.x +tasks: + verify_ubuntu2004: + platform: ubuntu2004 + bazel: ${{ bazel }} environment: CC: clang - SWIFT_VERSION: "5.5.3" + SWIFT_VERSION: "5.9" SWIFT_HOME: "$HOME/swift-$SWIFT_VERSION" PATH: "$PATH:$SWIFT_HOME/usr/bin" shell_commands: - "echo --- Downloading and extracting Swift $SWIFT_VERSION to $SWIFT_HOME" - "mkdir $SWIFT_HOME" - - "curl https://download.swift.org/swift-${SWIFT_VERSION}-release/ubuntu1804/swift-${SWIFT_VERSION}-RELEASE/swift-${SWIFT_VERSION}-RELEASE-ubuntu18.04.tar.gz | tar xvz --strip-components=1 -C $SWIFT_HOME" + - "curl https://download.swift.org/swift-${SWIFT_VERSION}-release/ubuntu2004/swift-${SWIFT_VERSION}-RELEASE/swift-${SWIFT_VERSION}-RELEASE-ubuntu20.04.tar.gz | tar xvz --strip-components=1 -C $SWIFT_HOME" build_targets: - "//..." test_targets: - "//..." - ubuntu2004: + verify_ubuntu2204: + platform: ubuntu2204 + bazel: ${{ bazel }} environment: CC: clang - SWIFT_VERSION: "5.5.3" + SWIFT_VERSION: "5.9" SWIFT_HOME: "$HOME/swift-$SWIFT_VERSION" PATH: "$PATH:$SWIFT_HOME/usr/bin" shell_commands: - "echo --- Downloading and extracting Swift $SWIFT_VERSION to $SWIFT_HOME" - "mkdir $SWIFT_HOME" - - "curl https://download.swift.org/swift-${SWIFT_VERSION}-release/ubuntu2004/swift-${SWIFT_VERSION}-RELEASE/swift-${SWIFT_VERSION}-RELEASE-ubuntu20.04.tar.gz | tar xvz --strip-components=1 -C $SWIFT_HOME" + - "curl https://download.swift.org/swift-${SWIFT_VERSION}-release/ubuntu2204/swift-${SWIFT_VERSION}-RELEASE/swift-${SWIFT_VERSION}-RELEASE-ubuntu22.04.tar.gz | tar xvz --strip-components=1 -C $SWIFT_HOME" build_targets: - "//..." test_targets: - "//..." - macos: - xcode_version: "14.2" + test_module_cpp: + platform: ubuntu2204 + bazel: ${{ bazel }} + working_directory: tests/bazel_repository_test_dir build_targets: - "//..." + test_module_ts: + platform: ubuntu2204 + bazel: ${{ bazel }} + working_directory: tests/ts/bazel_repository_test_dir test_targets: - "//..." + verify_macos: + platform: macos + bazel: ${{ bazel }} + xcode_version: "15.2" + build_targets: + - "//:flatbuffers" + - "//:flatc" + test_targets: + - "//tests:flatbuffers_test" diff --git a/third_party/flatbuffers/.bazelignore b/third_party/flatbuffers/.bazelignore index 3c3629e647f..874adf91565 100644 --- a/third_party/flatbuffers/.bazelignore +++ b/third_party/flatbuffers/.bazelignore @@ -1 +1,5 @@ -node_modules +ts/node_modules + +# Test workspaces +tests/bazel_repository_test_dir +tests/ts/bazel_repository_test_dir diff --git a/third_party/flatbuffers/.bazelrc b/third_party/flatbuffers/.bazelrc index f9f47a74237..a02667e1821 100644 --- a/third_party/flatbuffers/.bazelrc +++ b/third_party/flatbuffers/.bazelrc @@ -1,4 +1,18 @@ # We cannot use "common" here because the "version" command doesn't support # --deleted_packages. We need to specify it for both build and query instead. -build --deleted_packages=tests/ts/bazel_repository_test_dir -query --deleted_packages=tests/ts/bazel_repository_test_dir +build --deleted_packages=tests/bazel_repository_test_dir,tests/ts/bazel_repository_test_dir +query --deleted_packages=tests/bazel_repository_test_dir,tests/ts/bazel_repository_test_dir +# Point tools such as coursier (used in rules_jvm_external) to Bazel's internal JDK +# suggested in https://github.com/bazelbuild/rules_jvm_external/issues/445 +common --repo_env=JAVA_HOME=../bazel_tools/jdk +common --action_env=JAVA_HOME=../bazel_tools/jdk +# Workaround "Error: need --enable_runfiles on Windows for to support rules_js" +common:windows --enable_runfiles +# Swift is not required on Windows +common:windows --deleted_packages=swift +# Ignore warnings in external dependencies +build --per_file_copt=external/.*@-Wno-everything --host_per_file_copt=external/.*@-Wno-everything +# Honor the setting of `skipLibCheck` in the tsconfig.json file. +common --@aspect_rules_ts//ts:skipLibCheck=honor_tsconfig +# Use "tsc" as the transpiler when ts_project has no `transpiler` set. +common --@aspect_rules_ts//ts:default_to_tsc_transpiler diff --git a/third_party/flatbuffers/.clang-format b/third_party/flatbuffers/.clang-format index 7da2b4389e5..bb2e3440d42 100644 --- a/third_party/flatbuffers/.clang-format +++ b/third_party/flatbuffers/.clang-format @@ -1,13 +1,5 @@ --- Language: Cpp BasedOnStyle: Google -DerivePointerAlignment: false -PointerAlignment: Right -IndentPPDirectives: AfterHash -Cpp11BracedListStyle: false -AlwaysBreakTemplateDeclarations: false -AllowShortCaseLabelsOnASingleLine: true -SpaceAfterTemplateKeyword: false -AllowShortBlocksOnASingleLine: true ... diff --git a/third_party/flatbuffers/.eslintrc.js b/third_party/flatbuffers/.eslintrc.js deleted file mode 100644 index 321169b07c0..00000000000 --- a/third_party/flatbuffers/.eslintrc.js +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint-env node */ - -module.exports = { - root: true, - parser: '@typescript-eslint/parser', - plugins: [ - '@typescript-eslint', - ], - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - ] -}; \ No newline at end of file diff --git a/third_party/flatbuffers/.github/ISSUE_TEMPLATE.md b/third_party/flatbuffers/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000000..a053fe4406a --- /dev/null +++ b/third_party/flatbuffers/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,12 @@ +Thank you for submitting an issue! + +Please make sure you include the names of the affected language(s), compiler version(s), operating system version(s), and FlatBuffers version(s) in your issue title. + +This helps us get the correct maintainers to look at your issue. Here are examples of good titles: + +- Crash when accessing FlatBuffer [C++, gcc 4.8, OS X, master] +- Flatc converts a protobuf 'bytes' field to 'string' in fbs schema file [all languages, FlatBuffers 1.4] + +Include other details as appropriate. + +Thanks! diff --git a/third_party/flatbuffers/.github/ISSUE_TEMPLATE/404-doc.md b/third_party/flatbuffers/.github/ISSUE_TEMPLATE/404-doc.md new file mode 100644 index 00000000000..c394d384541 --- /dev/null +++ b/third_party/flatbuffers/.github/ISSUE_TEMPLATE/404-doc.md @@ -0,0 +1,11 @@ +--- +name: 404 Doc +about: To fix broken documentation links +title: "[Doc 404]" +labels: documentation +assignees: dbaileychess + +--- + +Target URL: +[Optional] Source Site: diff --git a/third_party/flatbuffers/.github/PULL_REQUEST_TEMPLATE.md b/third_party/flatbuffers/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000000..b8cc0ce1db5 --- /dev/null +++ b/third_party/flatbuffers/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,19 @@ +Thank you for submitting a PR! + +Please delete this standard text once you've created your own description. + +If you make changes to any of the code generators (`src/idl_gen*`) be sure to +[build](https://google.github.io/flatbuffers/flatbuffers_guide_building.html) your project, as it will generate code based on the changes. If necessary +the code generation script can be directly run (`scripts/generate_code.py`), +requires Python3. This allows us to better see the effect of the PR. + +If your PR includes C++ code, please adhere to the +[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html), +and don't forget we try to support older compilers (e.g. VS2010, GCC 4.6.3), +so only some C++11 support is available. + +For any C++ changes, please make sure to run `sh scripts/clang-format-git.sh` + +Include other details as appropriate. + +Thanks! diff --git a/third_party/flatbuffers/.github/labeler.yml b/third_party/flatbuffers/.github/labeler.yml new file mode 100644 index 00000000000..e3da18c1eda --- /dev/null +++ b/third_party/flatbuffers/.github/labeler.yml @@ -0,0 +1,97 @@ +# Configuration for Auto Labeler during pull request +# +# See https://github.com/actions/labeler for file format +# and https://github.com/google/flatbuffers/labels for a list of valid labels +# +# See .github/workflows/label.yml for Github Action workflow script + +c#: + - '**/*.cs' + - net/**/* + - tests/FlatBuffers.Test/**/* + - tests/FlatBuffers.Benchmarks/**/* + - src/idl_gen_csharp.cpp + +swift: + - '**/*.swift' + - swift/**/* + - tests/swift/** + - src/idl_gen_swift.cpp + +nim: + - '**/*.nim' + - nim/**/* + - src/idl_gen_nim.cpp + - src/bfbs_gen_nim.cpp + +javascript: + - '**/*.js' + - src/idl_gen_ts.cpp + +typescript: + - '**/*.ts' + - src/idl_gen_ts.cpp + - grpc/flatbuffers-js-grpc/**/*.ts + +golang: + - '**/*.go' + - src/idl_gen_go.cpp + +python: + - '**/*.py' + - src/idl_gen_python.cpp + +java: + - '**/*.java' + - src/idl_gen_java.cpp + +kotlin: + - '**/*.kt' + - src/idl_gen_kotlin.cpp + - src/idl_gen_kotlin_kmp.cpp + +lua: + - '**/*.lua' + - lua/**/* + - src/bfbs_gen_lua.cpp + +lobster: + - '**/*.lobster' + - src/idl_gen_lobster.cpp + +php: + - '**/*.php' + - src/idl_gen_php.cpp + +rust: + - '**/*.rs' + - rust/**/* + - src/idl_gen_rust.cpp + +dart: + - '**/*.dart' + - src/idl_gen_dart.cpp + +c++: + - '**/*.cc' + - '**/*.cpp' + - '**/*.h' + +json: + - '**/*.json' + - src/idl_gen_json_schema.cpp + +codegen: + - src/**/* + +documentation: + - docs/**/* + - '**/*.md' + +CI: + - '.github/**/*' + - '.bazelci/**/*' + +grpc: + - grpc/**/* + - src/idl_gen_grpc.cpp diff --git a/third_party/flatbuffers/.github/workflows/build.yml b/third_party/flatbuffers/.github/workflows/build.yml new file mode 100644 index 00000000000..0d6e6e614a4 --- /dev/null +++ b/third_party/flatbuffers/.github/workflows/build.yml @@ -0,0 +1,647 @@ +name: CI +permissions: read-all + +on: + # For manual tests. + workflow_dispatch: + push: + tags: + - "*" # new tag version, like `0.8.4` or else + branches: + - master + pull_request: + branches: + - master + schedule: + # Run daily at 4:45 A.M. to catch dependencies that break us. + - cron: '45 4 * * *' + +jobs: + build-linux: + permissions: + contents: write + outputs: + digests-gcc: ${{ steps.hash-gcc.outputs.hashes }} + digests-clang: ${{ steps.hash-clang.outputs.hashes }} + name: Build Linux + runs-on: ubuntu-24.04 + strategy: + matrix: + cxx: [g++-13, clang++-18] + fail-fast: false + steps: + - uses: actions/checkout@v3 + - name: cmake + run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON -DFLATBUFFERS_STATIC_FLATC=ON . + - name: build + run: make -j + - name: test + run: ./flattests + - name: make flatc executable + run: | + chmod +x flatc + ./flatc --version + - name: upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: Linux flatc binary ${{ matrix.cxx }} + path: flatc + # Below if only for release. + - name: Zip file + if: startsWith(github.ref, 'refs/tags/') + run: zip Linux.flatc.binary.${{ matrix.cxx }}.zip flatc + - name: Release zip file + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: Linux.flatc.binary.${{ matrix.cxx }}.zip + - name: Generate SLSA subjects - clang + if: matrix.cxx == 'clang++-18' && startsWith(github.ref, 'refs/tags/') + id: hash-clang + run: echo "hashes=$(sha256sum Linux.flatc.binary.${{ matrix.cxx }}.zip | base64 -w0)" >> $GITHUB_OUTPUT + - name: Generate SLSA subjects - gcc + if: matrix.cxx == 'g++-13' && startsWith(github.ref, 'refs/tags/') + id: hash-gcc + run: echo "hashes=$(sha256sum Linux.flatc.binary.${{ matrix.cxx }}.zip | base64 -w0)" >> $GITHUB_OUTPUT + + build-linux-no-file-tests: + name: Build Linux with -DFLATBUFFERS_NO_FILE_TESTS + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - name: cmake + run: CXX=clang++-18 cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON -DFLATBUFFERS_CXX_FLAGS="-DFLATBUFFERS_NO_FILE_TESTS" . + - name: build + run: make -j + - name: test + run: ./flattests + + build-linux-out-of-source: + name: Build Linux with out-of-source build location + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - name: make build directory + run: mkdir build + - name: cmake + working-directory: build + run: > + CXX=clang++-18 cmake .. -G "Unix Makefiles" -DFLATBUFFERS_STRICT_MODE=ON + -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_CPP_STD=17 + - name: build + working-directory: build + run: make -j + - name: test + working-directory: build + run: pwd && ./flattests + - name: test C++17 + working-directory: build + run: ./flattests_cpp17 + + build-linux-cpp-std: + name: Build Linux C++ + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + std: [11, 14, 17, 20, 23] + cxx: [g++-13, clang++-18] + exclude: + # Clang++15 10.3.0 stdlibc++ doesn't fully support std 23 + - cxx: clang++-18 + std: 23 + + steps: + - uses: actions/checkout@v3 + - name: cmake + run: > + CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" + -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON + -DFLATBUFFERS_CPP_STD=${{ matrix.std }} + -DFLATBUFFERS_BUILD_CPP17=${{ matrix.std >= 17 && 'On' || 'Off'}} + - name: build + run: make -j + - name: test + run: ./flattests + - name: test C++17 + if: matrix.std >= 17 + run: ./flattests_cpp17 + + build-cpp-std: + name: Build Windows C++ + runs-on: windows-2022 + strategy: + matrix: + std: [11, 14, 17, 20, 23] + fail-fast: false + steps: + - uses: actions/checkout@v3 + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v1.1 + - name: cmake + run: > + cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release + -DFLATBUFFERS_STRICT_MODE=ON + -DFLATBUFFERS_CPP_STD=${{ matrix.std }} + -DFLATBUFFERS_BUILD_CPP17=${{ matrix.std >= 17 && 'On' || 'Off'}} + - name: build + run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64 + - name: test + run: Release\flattests.exe + - name: test C++17 + if: matrix.std >= 17 + run: Release\flattests_cpp17.exe + + build-windows: + permissions: + contents: write + outputs: + digests: ${{ steps.hash.outputs.hashes }} + name: Build Windows 2022 + runs-on: windows-2022 + steps: + - uses: actions/checkout@v3 + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v1.1 + - name: cmake + run: cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON . + - name: build + run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64 + - name: test + run: Release\flattests.exe + - name: upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: Windows flatc binary + path: Release\flatc.exe + # Below if only for release. + - name: Zip file + if: startsWith(github.ref, 'refs/tags/') + run: move Release/flatc.exe . && Compress-Archive flatc.exe Windows.flatc.binary.zip + - name: Release binary + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: Windows.flatc.binary.zip + - name: Generate SLSA subjects + if: startsWith(github.ref, 'refs/tags/') + id: hash + shell: bash + run: echo "hashes=$(sha256sum Windows.flatc.binary.zip | base64 -w0)" >> $GITHUB_OUTPUT + + build-dotnet-windows: + name: Build .NET Windows + runs-on: windows-2022-64core + strategy: + matrix: + configuration: [ + '', + '-p:UnsafeByteBuffer=true', + # Fails two tests currently. + #'-p:EnableSpanT=true,UnsafeByteBuffer=true' + ] + steps: + - uses: actions/checkout@v3 + - name: Setup .NET Core SDK + uses: actions/setup-dotnet@v4.2.0 + with: + dotnet-version: '8.0.x' + - name: Build + run: | + cd tests\FlatBuffers.Test + dotnet new sln --force --name FlatBuffers.Test + dotnet sln FlatBuffers.Test.sln add FlatBuffers.Test.csproj + dotnet build -c Release ${{matrix.configuration}} FlatBuffers.Test.sln + - name: Run net6.0 + run: | + cd tests\FlatBuffers.Test\bin\Release\net6.0 + dir + .\FlatBuffers.Test.exe + - name: Run net8.0 + run: | + cd tests\FlatBuffers.Test\bin\Release\net8.0 + .\FlatBuffers.Test.exe + + build-mac-intel: + permissions: + contents: write + outputs: + digests: ${{ steps.hash.outputs.hashes }} + name: Build Mac (for Intel) + runs-on: macos-latest-large + steps: + - uses: actions/checkout@v3 + - name: cmake + run: cmake -G "Xcode" -DCMAKE_OSX_ARCHITECTURES="x86_64" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . + - name: build + run: xcodebuild -toolchain clang -configuration Release -target flattests + - name: check that the binary is x86_64 + run: | + info=$(file Release/flatc) + echo $info + echo $info | grep "Mach-O 64-bit executable x86_64" + - name: test + run: Release/flattests + - name: make flatc executable + run: | + chmod +x Release/flatc + Release/flatc --version + - name: upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: Mac flatc binary Intel + path: Release/flatc + # Below if only for release. + - name: Zip file + if: startsWith(github.ref, 'refs/tags/') + run: mv Release/flatc . && zip MacIntel.flatc.binary.zip flatc + - name: Release binary + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: MacIntel.flatc.binary.zip + - name: Generate SLSA subjects + if: startsWith(github.ref, 'refs/tags/') + id: hash + run: echo "hashes=$(shasum -a 256 MacIntel.flatc.binary.zip | base64)" >> $GITHUB_OUTPUT + + build-mac-universal: + permissions: + contents: write + outputs: + digests: ${{ steps.hash.outputs.hashes }} + name: Build Mac (universal build) + runs-on: macos-latest + steps: + - uses: actions/checkout@v3 + - name: cmake + run: cmake -G "Xcode" -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . + - name: build + run: xcodebuild -toolchain clang -configuration Release -target flattests + - name: check that the binary is "universal" + run: | + info=$(file Release/flatc) + echo $info + echo $info | grep "Mach-O universal binary with 2 architectures" + - name: test + run: Release/flattests + - name: make flatc executable + run: | + chmod +x Release/flatc + Release/flatc --version + - name: upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: Mac flatc binary Universal + path: Release/flatc + # Below if only for release. + - name: Zip file + if: startsWith(github.ref, 'refs/tags/') + run: mv Release/flatc . && zip Mac.flatc.binary.zip flatc + - name: Release binary + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: Mac.flatc.binary.zip + - name: Generate SLSA subjects + if: startsWith(github.ref, 'refs/tags/') + id: hash + run: echo "hashes=$(shasum -a 256 Mac.flatc.binary.zip | base64)" >> $GITHUB_OUTPUT + + build-android: + name: Build Android (on Linux) + if: false #disabled due to continual failure + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - name: set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + - name: set up Gradle + uses: gradle/actions/setup-gradle@v4 + - name: set up flatc + run: | + cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . + make -j + echo "${PWD}" >> $GITHUB_PATH + - name: build + working-directory: android + run: gradle clean build + + build-generator: + name: Check Generated Code + runs-on: ubuntu-24.04 + strategy: + matrix: + cxx: [g++-13, clang++-18] + steps: + - uses: actions/checkout@v3 + - name: cmake + run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DFLATBUFFERS_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . && make -j + - name: Generate + run: scripts/check_generate_code.py + - name: Generate gRPC + run: scripts/check-grpc-generated-code.py + + build-generator-windows: + name: Check Generated Code on Windows + runs-on: windows-2022 + steps: + - uses: actions/checkout@v3 + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v1.1 + - name: cmake + run: cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON -DFLATBUFFERS_STRICT_MODE=ON . + - name: build + run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64 + - name: Generate + run: python3 scripts/check_generate_code.py --flatc Release\flatc.exe + - name: Generate gRPC + run: python3 scripts/check-grpc-generated-code.py --flatc Release\flatc.exe + + build-benchmarks: + name: Build Benchmarks (on Linux) + runs-on: ubuntu-24.04 + strategy: + matrix: + cxx: [g++-13] + steps: + - uses: actions/checkout@v3 + - name: cmake + run: CXX=${{ matrix.cxx }} cmake -G "Unix Makefiles" -DFLATBUFFERS_CXX_FLAGS="-Wno-unused-parameter -fno-aligned-new" -DFLATBUFFERS_BUILD_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_STRICT_MODE=ON . && make -j + - name: Run benchmarks + run: ./flatbenchmark --benchmark_repetitions=5 --benchmark_display_aggregates_only=true --benchmark_out_format=console --benchmark_out=benchmarks/results_${{matrix.cxx}} + - name: Upload benchmarks results + uses: actions/upload-artifact@v4 + with: + name: Linux flatbenchmark results ${{matrix.cxx}} + path: benchmarks/results_${{matrix.cxx}} + + build-java: + name: Build Java + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - name: test + working-directory: java + run: mvn test + + build-kotlin-macos: + name: Build Kotlin MacOS + runs-on: macos-13 + steps: + - name: Checkout + uses: actions/checkout@v3 + # Force Xcode 14.3 since Xcode 15 doesnt support older versions of + # kotlin. For Xcode 15, kotlin should be bumpped to 1.9.10 + # https://stackoverflow.com/a/77150623 + # For now, run with macos-13 which has this 14.3 installed: + # https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#xcode + - name: Set up Xcode version + run: sudo xcode-select -s /Applications/Xcode_14.3.app/Contents/Developer + - name: set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + - name: set up Gradle + uses: gradle/actions/setup-gradle@v4 + - name: Build flatc + run: | + cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . + make -j + echo "${PWD}" >> $GITHUB_PATH + - name: Build + working-directory: kotlin + run: ./gradlew clean iosSimulatorArm64Test macosX64Test macosArm64Test + + build-kotlin-linux: + name: Build Kotlin Linux + if: false #disabled due to continual failure + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + - name: set up Gradle + uses: gradle/actions/setup-gradle@v4 + - name: Build flatc + run: | + cmake -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . + make -j + echo "${PWD}" >> $GITHUB_PATH + - name: Build + working-directory: kotlin + # we are using docker's version of gradle + # so no need for wrapper validation or user + # gradlew + run: gradle jvmMainClasses jvmTest jsTest jsBrowserTest + + build-rust-linux: + name: Build Rust Linux + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - name: test + working-directory: tests + run: bash RustTest.sh + + build-rust-windows: + name: Build Rust Windows + runs-on: windows-2022-64core + steps: + - uses: actions/checkout@v3 + - name: test + working-directory: tests + run: ./RustTest.bat + + build-python: + name: Build Python + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - name: flatc + # FIXME: make test script not rely on flatc + run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j + - name: test + working-directory: tests + run: bash PythonTest.sh + + build-go: + name: Build Go + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - name: flatc + # FIXME: make test script not rely on flatc + run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j + - name: test + working-directory: tests + run: bash GoTest.sh + + build-php: + name: Build PHP + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - name: flatc + # FIXME: make test script not rely on flatc + run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j + - name: test + working-directory: tests + run: | + php phpTest.php + sh phpUnionVectorTest.sh + + build-swift: + name: Test Swift + strategy: + matrix: + swift: ["5.9", "5.10", "6.1"] + # Only 22.04 has swift at the moment https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md?plain=1#L30 + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - uses: vapor/swiftly-action@v0.2 + with: + toolchain: ${{ matrix.swift }} + - name: Get swift version + run: swift --version + - name: test + run: | + swift build --build-tests + swift test + + build-swift-windows: + name: Test swift windows + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + - uses: SwiftyLab/setup-swift@latest + with: + swift-version: '6.1' + - run: swift build + - run: swift test + + build-swift-wasm: + name: Test Swift Wasm + runs-on: ubuntu-24.04 + container: + image: ghcr.io/swiftwasm/carton:0.20.1 + steps: + - uses: actions/checkout@v3 + - uses: bytecodealliance/actions/wasmtime/setup@v1 + - uses: swiftwasm/setup-swiftwasm@v1 + with: + swift-version: "wasm-6.0.2-RELEASE" + - name: Test + working-directory: tests/swift/Wasm.tests + run: swift run carton test + + build-ts: + name: Build TS + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - name: flatc + # FIXME: make test script not rely on flatc + run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j + - name: pnpm + run: npm install -g pnpm esbuild + - name: deps + run: pnpm i + - name: compile + run: pnpm compile + - name: test + working-directory: tests/ts + run: | + python3 TypeScriptTest.py + + build-dart: + name: Build Dart + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - uses: dart-lang/setup-dart@v1 + with: + sdk: stable + - name: flatc + # FIXME: make test script not rely on flatc + run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF -DFLATBUFFERS_STRICT_MODE=ON . && make -j + - name: test + working-directory: tests + run: bash DartTest.sh + + build-nim: + name: Build Nim + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - name: flatc + # FIXME: make test script not rely on flatc + run: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF . && make -j + - uses: jiro4989/setup-nim-action@v1 + - name: install library + working-directory: nim + run: nimble -y develop && nimble install + - name: test + working-directory: tests/nim + run: python3 testnim.py + + bazel: + name: Bazel + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - name: bazel build + run: > + bazel build + //:flatc + //:flatbuffers + - name: bazel test + run: > + bazel test + //tests:flatbuffers_test + + release-digests: + if: startsWith(github.ref, 'refs/tags/') + needs: [build-linux, build-windows, build-mac-intel, build-mac-universal] + outputs: + digests: ${{ steps.hash.outputs.digests }} + runs-on: ubuntu-24.04 + steps: + - name: Merge results + id: hash + env: + LINUXGCC_DIGESTS: "${{ needs.build-linux.outputs.digests-gcc }}" + LINUXCLANG_DIGESTS: "${{ needs.build-linux.outputs.digests-clang }}" + MAC_DIGESTS: "${{ needs.build-mac-universal.outputs.digests }}" + MACINTEL_DIGESTS: "${{ needs.build-mac-intel.outputs.digests }}" + WINDOWS_DIGESTS: "${{ needs.build-windows.outputs.digests }}" + run: | + set -euo pipefail + echo "$LINUXGCC_DIGESTS" | base64 -d > checksums.txt + echo "$LINUXCLANG_DIGESTS" | base64 -d >> checksums.txt + echo "$MAC_DIGESTS" | base64 -d >> checksums.txt + echo "$MACINTEL_DIGESTS" | base64 -d >> checksums.txt + echo "$WINDOWS_DIGESTS" | base64 -d >> checksums.txt + echo "digests=$(cat checksums.txt | base64 -w0)" >> $GITHUB_OUTPUT + + provenance: + if: startsWith(github.ref, 'refs/tags/') + needs: [release-digests] + permissions: + actions: read # To read the workflow path. + id-token: write # To sign the provenance. + contents: write # To add assets to a release. + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.2.1 + with: + base64-subjects: "${{ needs.release-digests.outputs.digests }}" + upload-assets: true # Optional: Upload to a new release + compile-generator: true # Workaround for https://github.com/slsa-framework/slsa-github-generator/issues/1163 diff --git a/third_party/flatbuffers/.github/workflows/docs.yml b/third_party/flatbuffers/.github/workflows/docs.yml new file mode 100644 index 00000000000..cac8561828b --- /dev/null +++ b/third_party/flatbuffers/.github/workflows/docs.yml @@ -0,0 +1,36 @@ +name: docs +on: + # For manual pushes. + workflow_dispatch: + + # Pushes to main that touch the documentation directory. + push: + branches: + - master + paths: + - 'docs/**' + +permissions: + contents: write +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Configure Git Credentials + run: | + git config user.name github-actions[bot] + git config user.email 41898282+github-actions[bot]@users.noreply.github.com + - uses: actions/setup-python@v5 + with: + python-version: 3.x + - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV + - uses: actions/cache@v4 + with: + key: mkdocs-material-${{ env.cache_id }} + path: .cache + restore-keys: | + mkdocs-material- + - run: pip install mkdocs-material + - run: pip install mkdocs-redirects + - run: mkdocs gh-deploy --force -f docs/mkdocs.yml diff --git a/third_party/flatbuffers/.github/workflows/label.yml b/third_party/flatbuffers/.github/workflows/label.yml new file mode 100644 index 00000000000..8749a9f5d6f --- /dev/null +++ b/third_party/flatbuffers/.github/workflows/label.yml @@ -0,0 +1,24 @@ +# This workflow will triage pull requests and apply a label based on the +# paths that are modified in the pull request. +# +# To use this workflow, you will need to set up a .github/labeler.yml +# file with configuration. For more information, see: +# https://github.com/actions/labeler + +name: Labeler +permissions: read-all + +on: [pull_request_target] + +jobs: + label: + permissions: + contents: read + pull-requests: write + + runs-on: ubuntu-latest + + steps: + - uses: actions/labeler@ee18d5d34efd9b4f7dafdb0e363cb688eb438044 # 4.1.0 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/third_party/flatbuffers/.github/workflows/main.yml b/third_party/flatbuffers/.github/workflows/main.yml new file mode 100644 index 00000000000..9a900953924 --- /dev/null +++ b/third_party/flatbuffers/.github/workflows/main.yml @@ -0,0 +1,34 @@ +name: OSS-Fuzz +permissions: read-all + +on: + pull_request: + branches: + - master + paths: + - include/** + - src/** + - tests/**.cpp + - tests/**.h +jobs: + Fuzzing: + runs-on: ubuntu-latest + steps: + - name: Build Fuzzers + id: build + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + with: + oss-fuzz-project-name: 'flatbuffers' + language: c++ + - name: Run Fuzzers + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + with: + oss-fuzz-project-name: 'flatbuffers' + language: c++ + fuzz-seconds: 60 + - name: Upload Crash + uses: actions/upload-artifact@v4 + if: failure() && steps.build.outcome == 'success' + with: + name: artifacts + path: ./out/artifacts diff --git a/third_party/flatbuffers/.github/workflows/release.yml b/third_party/flatbuffers/.github/workflows/release.yml new file mode 100644 index 00000000000..b39b04c5ffa --- /dev/null +++ b/third_party/flatbuffers/.github/workflows/release.yml @@ -0,0 +1,152 @@ +name: Release +permissions: read-all + +on: + # For manual tests. + workflow_dispatch: + release: + types: [published] + +jobs: + publish-npm: + name: Publish NPM + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '20.x' + registry-url: 'https://registry.npmjs.org' + + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + publish-pypi: + name: Publish PyPi + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./python + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - name: Install Dependencies + run: | + python3 -m pip install --upgrade pip + python3 -m pip install setuptools wheel twine + + - name: Build + run: | + python3 setup.py sdist bdist_wheel + + - name: Upload to PyPi + run: | + python3 -m twine upload dist/* + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.TWINE_TOKEN }} + + publish-nuget: + name: Publish NuGet + runs-on: windows-latest + defaults: + run: + working-directory: ./net/flatbuffers + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.0.x' + - name: Build + run: | + dotnet build Google.FlatBuffers.csproj -c Release + + - name: Pack + run: | + dotnet pack Google.FlatBuffers.csproj -c Release + + - name: Upload to NuGet + run: | + dotnet nuget push .\bin\Release\Google.FlatBuffers.*.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json + + publish-maven: + name: Publish Maven + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./java + steps: + - uses: actions/checkout@v3 + + - name: Set up Maven Central Repository + uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'adopt' + cache: 'maven' + server-id: ossrh + server-username: OSSRH_USERNAME + server-password: OSSRH_PASSWORD + gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE # this needs to be an env var + + - name: Publish Maven + run: mvn --batch-mode clean deploy + env: + OSSRH_USERNAME: ${{ secrets.OSSRH_USER_V2 }} + OSSRH_PASSWORD: ${{ secrets.OSSRH_TOKEN_V2 }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} + + publish-maven-kotlin: + name: Publish Maven - Kotlin + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./kotlin + steps: + - uses: actions/checkout@v3 + - name: Set up Maven Central Repository + uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'adopt' + cache: 'maven' + server-id: ossrh + server-username: OSSRH_USERNAME + server-password: OSSRH_PASSWORD + gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE # this needs to be an env var + + - name: Publish Kotlin Library on Maven + run: ./gradlew publishAllPublicationsToSonatypeRepository + env: + OSSRH_USERNAME: ${{ secrets.OSSRH_USER_V2 }} + OSSRH_PASSWORD: ${{ secrets.OSSRH_TOKEN_V2 }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} + + + publish-crates: + name: Publish crates.io + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + - name: Publish Flatbuffers + uses: katyo/publish-crates@v2 + with: + path: ./rust/flatbuffers + registry-token: ${{ secrets.CARGO_TOKEN }} + + - name: Publish Flexbuffers + uses: katyo/publish-crates@v2 + with: + path: ./rust/flexbuffers + registry-token: ${{ secrets.CARGO_TOKEN }} diff --git a/third_party/flatbuffers/.github/workflows/stale.yml b/third_party/flatbuffers/.github/workflows/stale.yml new file mode 100644 index 00000000000..6f9bac59654 --- /dev/null +++ b/third_party/flatbuffers/.github/workflows/stale.yml @@ -0,0 +1,37 @@ +name: Mark stale issues and pull requests +permissions: + issues: write + pull-requests: write + +on: + # For manual tests. + workflow_dispatch: + schedule: + - cron: "30 20 * * *" + +jobs: + stale: + + runs-on: ubuntu-latest + + steps: + - uses: actions/stale@v7.0.0 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + operations-per-run: 500 + exempt-all-milestones: true + remove-stale-when-updated: true + + stale-issue-message: 'This issue is stale because it has been open 6 months with no activity. Please comment or label `not-stale`, or this will be closed in 14 days.' + close-issue-message: 'This issue was automatically closed due to no activity for 6 months plus the 14 day notice period.' + days-before-issue-stale: 182 # 6 months + days-before-issue-close: 14 # 2 weeks + exempt-issue-labels: not-stale + + stale-pr-message: 'This pull request is stale because it has been open 6 months with no activity. Please comment or label `not-stale`, or this will be closed in 14 days.' + close-pr-message: 'This pull request was automatically closed due to no activity for 6 months plus the 14 day notice period.' + days-before-pr-stale: 182 # 6 months + days-before-pr-close: 14 # 2 week + exempt-pr-labels: not-stale + exempt-draft-pr: false + diff --git a/third_party/flatbuffers/.gitignore b/third_party/flatbuffers/.gitignore index 828ca1d618e..0296f8fac36 100644 --- a/third_party/flatbuffers/.gitignore +++ b/third_party/flatbuffers/.gitignore @@ -153,3 +153,7 @@ cmake-build-debug/ _deps/ **/.gradle/** kotlin/**/generated +MODULE.bazel.lock + +# Ignore the generated docs +docs/site \ No newline at end of file diff --git a/third_party/flatbuffers/BUILD.bazel b/third_party/flatbuffers/BUILD.bazel index b4f015a0e29..20a4fd60a4d 100644 --- a/third_party/flatbuffers/BUILD.bazel +++ b/third_party/flatbuffers/BUILD.bazel @@ -1,5 +1,3 @@ -load("@aspect_rules_js//npm:defs.bzl", "npm_link_package") -load("@npm//:defs.bzl", "npm_link_all_packages") load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") licenses(["notice"]) @@ -8,13 +6,6 @@ package( default_visibility = ["//visibility:public"], ) -npm_link_all_packages(name = "node_modules") - -npm_link_package( - name = "node_modules/flatbuffers", - src = "//ts:flatbuffers", -) - exports_files([ "LICENSE", "tsconfig.json", @@ -37,11 +28,16 @@ config_setting( filegroup( name = "distribution", srcs = [ + ".bazelignore", + ".npmrc", "BUILD.bazel", - "WORKSPACE", + "MODULE.bazel", "build_defs.bzl", + "package.json", + "pnpm-lock.yaml", "typescript.bzl", "//grpc/src/compiler:distribution", + "//include/codegen:distribution", "//reflection:distribution", "//src:distribution", "//ts:distribution", @@ -125,15 +121,7 @@ filegroup( # Library used by flatbuffer_cc_library rules. cc_library( name = "runtime_cc", - hdrs = [ - "include/flatbuffers/base.h", - "include/flatbuffers/flatbuffers.h", - "include/flatbuffers/flexbuffers.h", - "include/flatbuffers/stl_emulation.h", - "include/flatbuffers/util.h", - "include/flatbuffers/vector.h", - "include/flatbuffers/verifier.h", - ], + hdrs = ["//:public_headers"], linkstatic = 1, strip_include_prefix = "/include", ) diff --git a/third_party/flatbuffers/CHANGELOG.md b/third_party/flatbuffers/CHANGELOG.md index 2b0380df6c5..e38b0835a03 100644 --- a/third_party/flatbuffers/CHANGELOG.md +++ b/third_party/flatbuffers/CHANGELOG.md @@ -4,6 +4,29 @@ All major or breaking changes will be documented in this file, as well as any new features that should be highlighted. Minor fixes or improvements are not necessarily listed. +## [25.9.23] (September 23 2025)(https://github.com/google/flatbuffers/releases/tag/v25.9.23) + +* flatc: `--grpc-callback-api` flag generates C++ gRPC Callback API server `CallbackService` skeletons AND client native callback/async stubs (unary + all streaming reactor forms) (opt-in, non-breaking, issue #8596). +* Swift - Adds new API to reduce memory copying within swift (#8484) +* Rust - Support Rust edition 2024 (#8638) +# [:C++] - Use the Google Style for clang-format without exceptions (#8706) + +## [25.2.10] (February 10 2025)(https://github.com/google/flatbuffers/releases/tag/v25.2.10) + +* Removed the old documentation pages. The new one is live at https://flatbuffers.dev +* Swift version 6.0 support (#8414) + +## [25.1.24] (January 24 2025)(https://github.com/google/flatbuffers/releases/tag/v25.1.24) + +* Mostly related to bazel build support. +* Min bazel supported is now 7 or higher, as WORKSPACE files are removed (#8509) +* Minor C++ codegen fix removing extra semicolon (#8488) + +## [25.1.21] (January 21 2025)(https://github.com/google/flatbuffers/releases/tag/v25.1.21) + +* Rust Full Reflection (#8102) +* Mostly documentation updates hosted at https://flatbuffers.dev + ## [24.3.25] (March 25 2024)(https://github.com/google/flatbuffers/releases/tag/v24.3.25) * Fixed license metadata parsing (#8253) diff --git a/third_party/flatbuffers/CMake/Version.cmake b/third_party/flatbuffers/CMake/Version.cmake index df18fe47a08..ba784265a28 100644 --- a/third_party/flatbuffers/CMake/Version.cmake +++ b/third_party/flatbuffers/CMake/Version.cmake @@ -1,6 +1,6 @@ -set(VERSION_MAJOR 24) -set(VERSION_MINOR 3) -set(VERSION_PATCH 25) +set(VERSION_MAJOR 25) +set(VERSION_MINOR 9) +set(VERSION_PATCH 23) set(VERSION_COMMIT 0) if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git") diff --git a/third_party/flatbuffers/CMakeLists.txt b/third_party/flatbuffers/CMakeLists.txt index c03688533a7..f7f388f83ec 100644 --- a/third_party/flatbuffers/CMakeLists.txt +++ b/third_party/flatbuffers/CMakeLists.txt @@ -112,6 +112,7 @@ endif() add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$) if(NOT WIN32) + include(CheckSymbolExists) check_symbol_exists(realpath "stdlib.h" HAVE_REALPATH) if(NOT HAVE_REALPATH) add_definitions(-DFLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION) @@ -183,6 +184,10 @@ set(FlatBuffers_Compiler_SRCS src/bfbs_gen_lua.h src/bfbs_gen_nim.h src/bfbs_namer.h + include/codegen/idl_namer.h + include/codegen/namer.h + include/codegen/python.h + include/codegen/python.cc include/flatbuffers/code_generators.h src/binary_annotator.h src/binary_annotator.cpp @@ -274,6 +279,8 @@ set(FlatBuffers_GRPCTest_SRCS tests/test_builder.cpp grpc/tests/grpctest.cpp grpc/tests/message_builder_test.cpp + grpc/tests/grpctest_callback_compile.cpp + grpc/tests/grpctest_callback_client_compile.cpp ) # TODO(dbaileychess): Figure out how this would now work. I posted a question on diff --git a/third_party/flatbuffers/CONTRIBUTING.md b/third_party/flatbuffers/CONTRIBUTING.md index 17428add545..df4eee55eb6 100644 --- a/third_party/flatbuffers/CONTRIBUTING.md +++ b/third_party/flatbuffers/CONTRIBUTING.md @@ -40,3 +40,26 @@ Some tips for good pull requests: # The small print Contributions made by corporations are covered by a different agreement than the one above, the Software Grant and Corporate Contributor License Agreement. + +# Code + +TL/DR + +See [how to build flatc](https://flatbuffers.dev/building/). + +When making changes, build `flatc` and then re-generate the goldens files to see the effect of your changes: + +``` +$ cp build/flatc . +$ goldens/generate_goldens.py +``` + +Re-generate other code files to see the effects of the changes: + +``` +$ scripts/generate_code.py +``` + +Run tests with [TestAll.sh](tests/TestAll.sh) in [tests](tests), or directly any of the sub-scripts run by it. + +[Format the code](Formatters.md) before submitting a PR. diff --git a/third_party/flatbuffers/FlatBuffers.podspec b/third_party/flatbuffers/FlatBuffers.podspec index 2aa69e2a027..95e04b8aa59 100644 --- a/third_party/flatbuffers/FlatBuffers.podspec +++ b/third_party/flatbuffers/FlatBuffers.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FlatBuffers' - s.version = '24.3.25' + s.version = '25.9.23' s.summary = 'FlatBuffers: Memory Efficient Serialization Library' s.description = "FlatBuffers is a cross platform serialization library architected for @@ -10,12 +10,15 @@ Pod::Spec.new do |s| s.homepage = 'https://github.com/google/flatbuffers' s.license = { :type => 'Apache2.0', :file => 'LICENSE' } - s.author = { 'mustii' => 'mustii@mmk.one' } - s.source = { :git => 'https://github.com/google/flatbuffers.git', :tag => s.version.to_s, :submodules => true } + s.author = { 'mustii' => 'me@mustiikhalil.se' } + s.source = { :git => 'https://github.com/google/flatbuffers.git', :tag => "v" + s.version.to_s, :submodules => true } s.ios.deployment_target = '11.0' s.osx.deployment_target = '10.14' s.swift_version = '5.0' s.source_files = 'swift/Sources/Flatbuffers/*.swift' + s.pod_target_xcconfig = { + 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' + } end diff --git a/third_party/flatbuffers/MODULE.bazel b/third_party/flatbuffers/MODULE.bazel new file mode 100644 index 00000000000..a2f0d2d6d7a --- /dev/null +++ b/third_party/flatbuffers/MODULE.bazel @@ -0,0 +1,77 @@ +module( + name = "flatbuffers", + version = "25.9.23", + compatibility_level = 1, + repo_name = "com_github_google_flatbuffers", +) + +bazel_dep( + name = "aspect_bazel_lib", + version = "2.11.0", +) +bazel_dep( + name = "aspect_rules_esbuild", + version = "0.21.0", +) +bazel_dep( + name = "aspect_rules_js", + version = "2.3.8", +) +bazel_dep( + name = "aspect_rules_ts", + version = "3.6.0", +) +bazel_dep( + name = "grpc", + version = "1.70.1", + repo_name = "com_github_grpc_grpc", +) +bazel_dep( + name = "platforms", + version = "0.0.10", +) +bazel_dep( + name = "rules_cc", + version = "0.0.16", +) +bazel_dep( + name = "rules_go", + version = "0.50.1", + repo_name = "io_bazel_rules_go", +) +bazel_dep( + name = "rules_nodejs", + version = "6.3.3", +) +bazel_dep( + name = "rules_shell", + version = "0.3.0", +) +bazel_dep( + name = "rules_swift", + version = "2.1.1", + repo_name = "build_bazel_rules_swift", +) +bazel_dep( + name = "bazel_skylib", + version = "1.7.1", +) + +npm = use_extension("@aspect_rules_js//npm:extensions.bzl", "npm") +npm.npm_translate_lock( + name = "flatbuffers_npm", + npmrc = "//:.npmrc", + pnpm_lock = "//ts:pnpm-lock.yaml", + # Override the Bazel package where pnpm-lock.yaml is located and link + # to the specified package instead. + root_package = "ts", + verify_node_modules_ignored = "//:.bazelignore", +) +use_repo(npm, "flatbuffers_npm") + +node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node") +use_repo(node, "nodejs_linux_amd64") + +rules_ts_ext = use_extension("@aspect_rules_ts//ts:extensions.bzl", "ext") +rules_ts_ext.deps() +use_repo(rules_ts_ext, "npm_typescript") diff --git a/third_party/flatbuffers/Package.swift b/third_party/flatbuffers/Package.swift index 0fc26da7601..57ce61e6b1c 100644 --- a/third_party/flatbuffers/Package.swift +++ b/third_party/flatbuffers/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.6 +// swift-tools-version:5.9 /* * Copyright 2020 Google Inc. All rights reserved. * @@ -20,17 +20,61 @@ import PackageDescription let package = Package( name: "FlatBuffers", platforms: [ - .iOS(.v11), + .iOS(.v12), .macOS(.v10_14), ], products: [ .library( name: "FlatBuffers", targets: ["FlatBuffers"]), + .library( + name: "FlexBuffers", + targets: ["FlexBuffers"]), ], + dependencies: .dependencies, targets: [ .target( name: "FlatBuffers", - dependencies: [], - path: "swift/Sources"), + dependencies: ["Common"], + path: "swift/Sources/FlatBuffers"), + .target( + name: "FlexBuffers", + dependencies: ["Common"], + path: "swift/Sources/FlexBuffers"), + .target( + name: "Common", + path: "swift/Sources/Common"), + .testTarget( + name: "FlatbuffersTests", + dependencies: .dependencies, + path: "tests/swift/Tests/Flatbuffers"), + .testTarget( + name: "FlexbuffersTests", + dependencies: ["FlexBuffers"], + path: "tests/swift/Tests/Flexbuffers"), ]) + +extension Array where Element == Package.Dependency { + static var dependencies: [Package.Dependency] { + #if os(Windows) + [] + #else + // Test only Dependency + [.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.4.1")] + #endif + } +} + +extension Array where Element == PackageDescription.Target.Dependency { + static var dependencies: [PackageDescription.Target.Dependency] { + #if os(Windows) + ["FlatBuffers"] + #else + // Test only Dependency + [ + .product(name: "GRPC", package: "grpc-swift"), + "FlatBuffers", + ] + #endif + } +} diff --git a/third_party/flatbuffers/README.md b/third_party/flatbuffers/README.md index 47d506720e1..ed3637afb75 100644 --- a/third_party/flatbuffers/README.md +++ b/third_party/flatbuffers/README.md @@ -1,11 +1,9 @@ -![logo](http://google.github.io/flatbuffers/fpl_logo_small.png) FlatBuffers +![logo](https://flatbuffers.dev/assets/flatbuffers_logo.svg) FlatBuffers =========== ![Build status](https://github.com/google/flatbuffers/actions/workflows/build.yml/badge.svg?branch=master) [![BuildKite status](https://badge.buildkite.com/7979d93bc6279aa539971f271253c65d5e8fe2fe43c90bbb25.svg)](https://buildkite.com/bazel/flatbuffers) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/flatbuffers.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:flatbuffers) -[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/google/flatbuffers/badge)](https://api.securityscorecards.dev/projects/github.com/google/flatbuffers) -[![Join the chat at https://gitter.im/google/flatbuffers](https://badges.gitter.im/google/flatbuffers.svg)](https://gitter.im/google/flatbuffers?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Discord Chat](https://img.shields.io/discord/656202785926152206.svg)](https:///discord.gg/6qgKs3R) [![Twitter Follow](https://img.shields.io/twitter/follow/wvo.svg?style=social)](https://twitter.com/wvo) [![Twitter Follow](https://img.shields.io/twitter/follow/dbaileychess.svg?style=social)](https://twitter.com/dbaileychess) @@ -18,7 +16,7 @@ maximum memory efficiency. It allows you to directly access serialized data with 1. Build the compiler for flatbuffers (`flatc`) - Use `cmake` to create the build files for your platform and then perform the compliation (Linux example). + Use `cmake` to create the build files for your platform and then perform the compilation (Linux example). ``` cmake -G "Unix Makefiles" diff --git a/third_party/flatbuffers/WORKSPACE b/third_party/flatbuffers/WORKSPACE deleted file mode 100644 index e56d4ce364b..00000000000 --- a/third_party/flatbuffers/WORKSPACE +++ /dev/null @@ -1,169 +0,0 @@ -workspace(name = "com_github_google_flatbuffers") - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file") - -http_archive( - name = "platforms", - sha256 = "3a561c99e7bdbe9173aa653fd579fe849f1d8d67395780ab4770b1f381431d51", - urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.7/platforms-0.0.7.tar.gz", - "https://github.com/bazelbuild/platforms/releases/download/0.0.7/platforms-0.0.7.tar.gz", - ], -) - -http_archive( - name = "build_bazel_rules_apple", - sha256 = "34c41bfb59cdaea29ac2df5a2fa79e5add609c71bb303b2ebb10985f93fa20e7", - url = "https://github.com/bazelbuild/rules_apple/releases/download/3.1.1/rules_apple.3.1.1.tar.gz", -) - -load( - "@build_bazel_rules_apple//apple:repositories.bzl", - "apple_rules_dependencies", -) - -apple_rules_dependencies() - -http_archive( - name = "build_bazel_rules_swift", - sha256 = "a2fd565e527f83fb3f9eb07eb9737240e668c9242d3bc318712efa54a7deda97", - url = "https://github.com/bazelbuild/rules_swift/releases/download/0.27.0/rules_swift.0.27.0.tar.gz", -) - -load( - "@build_bazel_rules_swift//swift:repositories.bzl", - "swift_rules_dependencies", -) - -swift_rules_dependencies() - -load( - "@build_bazel_rules_swift//swift:extras.bzl", - "swift_rules_extra_dependencies", -) - -swift_rules_extra_dependencies() - -http_archive( - name = "io_bazel_rules_go", - sha256 = "278b7ff5a826f3dc10f04feaf0b70d48b68748ccd512d7f98bf442077f043fe3", - urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.41.0/rules_go-v0.41.0.zip", - "https://github.com/bazelbuild/rules_go/releases/download/v0.41.0/rules_go-v0.41.0.zip", - ], -) - -load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies") - -go_rules_dependencies() - -##### Protobuf -_PROTOBUF_VERSION = "3.15.2" - -http_archive( - name = "com_google_protobuf", - strip_prefix = "protobuf-" + _PROTOBUF_VERSION, - urls = [ - "https://github.com/protocolbuffers/protobuf/archive/v" + _PROTOBUF_VERSION + ".tar.gz", - ], -) - -##### GRPC -_GRPC_VERSION = "1.49.0" # https://github.com/grpc/grpc/releases/tag/v1.48.0 - -http_archive( - name = "com_github_grpc_grpc", - patch_args = ["-p1"], - patches = ["//grpc:build_grpc_with_cxx14.patch"], - sha256 = "15715e1847cc9e42014f02c727dbcb48e39dbdb90f79ad3d66fe4361709ff935", - strip_prefix = "grpc-" + _GRPC_VERSION, - urls = ["https://github.com/grpc/grpc/archive/refs/tags/v" + _GRPC_VERSION + ".tar.gz"], -) - -load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") - -grpc_deps() - -load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps") - -grpc_extra_deps() - -# rules_go from https://github.com/bazelbuild/rules_go/releases/tag/v0.34.0 - -http_archive( - name = "aspect_rules_js", - sha256 = "76a04ef2120ee00231d85d1ff012ede23963733339ad8db81f590791a031f643", - strip_prefix = "rules_js-1.34.1", - url = "https://github.com/aspect-build/rules_js/releases/download/v1.34.1/rules_js-v1.34.1.tar.gz", -) - -load("@aspect_rules_js//js:repositories.bzl", "rules_js_dependencies") - -rules_js_dependencies() - -load("@aspect_rules_js//npm:npm_import.bzl", "npm_translate_lock", "pnpm_repository") - -pnpm_repository(name = "pnpm") - -http_archive( - name = "aspect_rules_ts", - sha256 = "4c3f34fff9f96ffc9c26635d8235a32a23a6797324486c7d23c1dfa477e8b451", - strip_prefix = "rules_ts-1.4.5", - url = "https://github.com/aspect-build/rules_ts/releases/download/v1.4.5/rules_ts-v1.4.5.tar.gz", -) - -load("@aspect_rules_ts//ts:repositories.bzl", "rules_ts_dependencies") - -rules_ts_dependencies( - # Since rules_ts doesn't always have the newest integrity hashes, we - # compute it manually here. - # $ curl --silent https://registry.npmjs.org/typescript/5.3.3 | jq ._integrity - ts_integrity = "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - ts_version_from = "//:package.json", -) - -load("@rules_nodejs//nodejs:repositories.bzl", "DEFAULT_NODE_VERSION", "nodejs_register_toolchains") - -nodejs_register_toolchains( - name = "nodejs", - node_version = DEFAULT_NODE_VERSION, -) - -npm_translate_lock( - name = "npm", - npmrc = "//:.npmrc", - pnpm_lock = "//:pnpm-lock.yaml", - # Set this to True when the lock file needs to be updated, commit the - # changes, then set to False again. - update_pnpm_lock = False, - verify_node_modules_ignored = "//:.bazelignore", -) - -load("@npm//:repositories.bzl", "npm_repositories") - -npm_repositories() - -http_archive( - name = "aspect_rules_esbuild", - sha256 = "098e38e5ee868c14a6484ba263b79e57d48afacfc361ba30137c757a9c4716d6", - strip_prefix = "rules_esbuild-0.15.0", - url = "https://github.com/aspect-build/rules_esbuild/releases/download/v0.15.0/rules_esbuild-v0.15.0.tar.gz", -) - -# Register a toolchain containing esbuild npm package and native bindings -load("@aspect_rules_esbuild//esbuild:repositories.bzl", "LATEST_ESBUILD_VERSION", "esbuild_register_toolchains") - -esbuild_register_toolchains( - name = "esbuild", - esbuild_version = LATEST_ESBUILD_VERSION, -) - -http_file( - name = "bazel_linux_x86_64", - downloaded_file_path = "bazel", - executable = True, - sha256 = "e78fc3394deae5408d6f49a15c7b1e615901969ecf6e50d55ef899996b0b8458", - urls = [ - "https://github.com/bazelbuild/bazel/releases/download/6.3.2/bazel-6.3.2-linux-x86_64", - ], -) diff --git a/third_party/flatbuffers/android/.project b/third_party/flatbuffers/android/.project new file mode 100644 index 00000000000..17f0659d4a1 --- /dev/null +++ b/third_party/flatbuffers/android/.project @@ -0,0 +1,22 @@ + + + FlatBufferTest + + + + + + + + + + 1672434305228 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + diff --git a/third_party/flatbuffers/android/AndroidManifest.xml b/third_party/flatbuffers/android/AndroidManifest.xml new file mode 100644 index 00000000000..a6c97492b17 --- /dev/null +++ b/third_party/flatbuffers/android/AndroidManifest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/flatbuffers/android/app/.gitignore b/third_party/flatbuffers/android/app/.gitignore new file mode 100644 index 00000000000..796b96d1c40 --- /dev/null +++ b/third_party/flatbuffers/android/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/third_party/flatbuffers/android/app/build.gradle b/third_party/flatbuffers/android/app/build.gradle new file mode 100644 index 00000000000..99417830993 --- /dev/null +++ b/third_party/flatbuffers/android/app/build.gradle @@ -0,0 +1,125 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' + +android { + compileSdk 33 + + defaultConfig { + applicationId "com.flatbuffers.app" + minSdkVersion 26 + targetSdkVersion 33 + versionCode 1 + versionName "1.0" + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + sourceSets { + main { + java { + srcDir '../../java/src/main/java/' + } + } + } + + ndk { + abiFilters 'arm64-v8a', 'armeabi-v7a' + } + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + externalNativeBuild { + cmake { + arguments "-DFLATBUFFERS_SRC=${rootProject.projectDir}/.." + } + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + externalNativeBuild { + cmake { + path "src/main/cpp/CMakeLists.txt" + } + } + + task generateFbsCpp(type: Exec) { + def inputDir = file("$projectDir/src/main/fbs") + def outputCppDir = file("$projectDir/src/main/cpp/generated/") + def fbsFiles = layout.files { file(inputDir).listFiles() }.filter { File f -> f.name.endsWith(".fbs") }.toList() + ignoreExitValue(true) + + standardOutput = new ByteArrayOutputStream() + errorOutput = new ByteArrayOutputStream() + def commandLineArgs = ['flatc', '-o', outputCppDir, '--cpp'] + fbsFiles.forEach{ + commandLineArgs.add(it.path) + } + + commandLine commandLineArgs + + doFirst { + delete "$outputCppDir/" + mkdir "$outputCppDir/" + } + + doLast { + if (executionResult.get().exitValue != 0) { + throw new GradleException("flatc failed with: ${executionResult.get().toString()}") + } + } + } + + task generateFbsKotlin(type: Exec) { + def inputDir = file("$projectDir/src/main/fbs") + def outputKotlinDir = file("$projectDir/src/main/java/generated/") + def fbsFiles = layout.files { file(inputDir).listFiles() }.filter { File f -> f.name.endsWith(".fbs") }.toList() + ignoreExitValue(true) + + standardOutput = new ByteArrayOutputStream() + errorOutput = new ByteArrayOutputStream() + + setErrorOutput(errorOutput) + setStandardOutput(standardOutput) + + def commandLineArgs = ['flatc', '-o', outputKotlinDir, '--kotlin'] + fbsFiles.forEach{ + commandLineArgs.add(it.path) + } + commandLine commandLineArgs + + doFirst { + delete "$outputKotlinDir/" + mkdir "$outputKotlinDir/" + } + doLast { + if (executionResult.get().exitValue != 0) { + throw new GradleException("flatc failed with: ${executionResult.get().toString()}") + } + } + } + + afterEvaluate { + tasks.named("preBuild") { + dependsOn(generateFbsKotlin) + dependsOn(generateFbsCpp) + } + } + namespace 'com.flatbuffers.app' +} + +dependencies { + implementation fileTree(dir: "libs", include: ["*.jar"]) + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'androidx.appcompat:appcompat:1.6.1' + + // If you using java runtime you can add its dependency as the example below + // implementation 'com.google.flatbuffers:flatbuffers-java:$latest_version' + +} diff --git a/third_party/flatbuffers/android/app/proguard-rules.pro b/third_party/flatbuffers/android/app/proguard-rules.pro new file mode 100644 index 00000000000..f1b424510da --- /dev/null +++ b/third_party/flatbuffers/android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/third_party/flatbuffers/android/app/src/main/AndroidManifest.xml b/third_party/flatbuffers/android/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..53caca65bcf --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + diff --git a/third_party/flatbuffers/android/app/src/main/cpp/CMakeLists.txt b/third_party/flatbuffers/android/app/src/main/cpp/CMakeLists.txt new file mode 100644 index 00000000000..abb8250bda0 --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/cpp/CMakeLists.txt @@ -0,0 +1,53 @@ +# For more information about using CMake with Android Studio, read the +# documentation: https://d.android.com/studio/projects/add-native-code.html + +# Sets the minimum version of CMake required to build the native library. + +cmake_minimum_required(VERSION 3.4.1) + +# Creates and names a library, sets it as either STATIC +# or SHARED, and provides the relative paths to its source code. +# You can define multiple libraries, and CMake builds them for you. +# Gradle automatically packages shared libraries with your APK. + +include_directories(${FLATBUFFERS_SRC}/include) + +add_subdirectory(flatbuffers) + +FILE(GLOB Generated_SRCS generated/*.h) + +add_library( # Sets the name of the library. + native-lib + + # Sets the library as a shared library. + SHARED + + # Provides a relative path to your source file(s). + animals.cpp + ${Generated_SRCS} + +) + +# Searches for a specified prebuilt library and stores the path as a +# variable. Because CMake includes system libraries in the search path by +# default, you only need to specify the name of the public NDK library +# you want to add. CMake verifies that the library exists before +# completing its build. + +find_library( # Sets the name of the path variable. + log-lib + + # Specifies the name of the NDK library that + # you want CMake to locate. + log ) + +# Specifies libraries CMake should link to your target library. You +# can link multiple libraries, such as libraries you define in this +# build script, prebuilt third-party libraries, or system libraries. + +target_link_libraries( # Specifies the target library. + native-lib + flatbuffers + # Links the target library to the log library + # included in the NDK. + ${log-lib} ) diff --git a/third_party/flatbuffers/android/app/src/main/cpp/animals.cpp b/third_party/flatbuffers/android/app/src/main/cpp/animals.cpp new file mode 100644 index 00000000000..bf87b875c63 --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/cpp/animals.cpp @@ -0,0 +1,39 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "generated/animal_generated.h" + +using namespace com::fbs::app; +using namespace flatbuffers; + +extern "C" JNIEXPORT jbyteArray JNICALL Java_com_flatbuffers_app_MainActivity_createAnimalFromJNI( + JNIEnv* env, + jobject /* this */) { + // create a new animal flatbuffers + auto fb = FlatBufferBuilder(1024); + auto tiger = CreateAnimalDirect(fb, "Tiger", "Roar", 300); + fb.Finish(tiger); + + // copies it to a Java byte array. + auto buf = reinterpret_cast(fb.GetBufferPointer()); + int size = fb.GetSize(); + auto ret = env->NewByteArray(size); + env->SetByteArrayRegion (ret, 0, fb.GetSize(), buf); + return ret; +} diff --git a/third_party/flatbuffers/android/app/src/main/cpp/flatbuffers/CMakeLists.txt b/third_party/flatbuffers/android/app/src/main/cpp/flatbuffers/CMakeLists.txt new file mode 100644 index 00000000000..144523ee85a --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/cpp/flatbuffers/CMakeLists.txt @@ -0,0 +1,56 @@ +# For more information about using CMake with Android Studio, read the +# documentation: https://d.android.com/studio/projects/add-native-code.html + +# Sets the minimum version of CMake required to build the native library. + +cmake_minimum_required(VERSION 3.4.1) + +include_directories(${FLATBUFFERS_SRC}/include) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -fexceptions -Wall -DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE") + +# Certain platforms such as ARM do not use signed chars by default +# which causes issues with certain bounds checks. +set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -fsigned-char") + +set(FlatBuffers_Library_SRCS + ${FLATBUFFERS_SRC}/include/flatbuffers/allocator.h + ${FLATBUFFERS_SRC}/include/flatbuffers/array.h + ${FLATBUFFERS_SRC}/include/flatbuffers/base.h + ${FLATBUFFERS_SRC}/include/flatbuffers/buffer.h + ${FLATBUFFERS_SRC}/include/flatbuffers/buffer_ref.h + ${FLATBUFFERS_SRC}/include/flatbuffers/default_allocator.h + ${FLATBUFFERS_SRC}/include/flatbuffers/detached_buffer.h + ${FLATBUFFERS_SRC}/include/flatbuffers/flatbuffer_builder.h + ${FLATBUFFERS_SRC}/include/flatbuffers/flatbuffers.h + ${FLATBUFFERS_SRC}/include/flatbuffers/flexbuffers.h + ${FLATBUFFERS_SRC}/include/flatbuffers/flex_flat_util.h + ${FLATBUFFERS_SRC}/include/flatbuffers/hash.h + ${FLATBUFFERS_SRC}/include/flatbuffers/idl.h + ${FLATBUFFERS_SRC}/include/flatbuffers/minireflect.h + ${FLATBUFFERS_SRC}/include/flatbuffers/reflection.h + ${FLATBUFFERS_SRC}/include/flatbuffers/reflection_generated.h + ${FLATBUFFERS_SRC}/include/flatbuffers/registry.h + ${FLATBUFFERS_SRC}/include/flatbuffers/stl_emulation.h + ${FLATBUFFERS_SRC}/include/flatbuffers/string.h + ${FLATBUFFERS_SRC}/include/flatbuffers/struct.h + ${FLATBUFFERS_SRC}/include/flatbuffers/table.h + ${FLATBUFFERS_SRC}/include/flatbuffers/util.h + ${FLATBUFFERS_SRC}/include/flatbuffers/vector.h + ${FLATBUFFERS_SRC}/include/flatbuffers/vector_downward.h + ${FLATBUFFERS_SRC}/include/flatbuffers/verifier.h + ${FLATBUFFERS_SRC}/src/idl_parser.cpp + ${FLATBUFFERS_SRC}/src/idl_gen_text.cpp + ${FLATBUFFERS_SRC}/src/reflection.cpp + ${FLATBUFFERS_SRC}/src/util.cpp + ${FLATBUFFERS_SRC}/src/idl_gen_fbs.cpp + ${FLATBUFFERS_SRC}/src/code_generators.cpp + ) + +add_library( # Sets the name of the library. + flatbuffers + + ${FlatBuffers_Library_SRCS} + ${Generated_SRCS} +) diff --git a/third_party/flatbuffers/android/app/src/main/cpp/generated/animal_generated.h b/third_party/flatbuffers/android/app/src/main/cpp/generated/animal_generated.h new file mode 100644 index 00000000000..a34bce4f85a --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/cpp/generated/animal_generated.h @@ -0,0 +1,119 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +#ifndef FLATBUFFERS_GENERATED_ANIMAL_COM_FBS_APP_H_ +#define FLATBUFFERS_GENERATED_ANIMAL_COM_FBS_APP_H_ + +#include "flatbuffers/flatbuffers.h" + +// Ensure the included flatbuffers.h is the same version as when this file was +// generated, otherwise it may not be compatible. +static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && + FLATBUFFERS_VERSION_MINOR == 12 && + FLATBUFFERS_VERSION_REVISION == 23, + "Non-compatible flatbuffers version included"); + +namespace com { +namespace fbs { +namespace app { + +struct Animal; +struct AnimalBuilder; + +struct Animal FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef AnimalBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NAME = 4, + VT_SOUND = 6, + VT_WEIGHT = 8 + }; + const ::flatbuffers::String* name() const { + return GetPointer(VT_NAME); + } + const ::flatbuffers::String* sound() const { + return GetPointer(VT_SOUND); + } + uint16_t weight() const { return GetField(VT_WEIGHT, 0); } + bool Verify(::flatbuffers::Verifier& verifier) const { + return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_NAME) && + verifier.VerifyString(name()) && VerifyOffset(verifier, VT_SOUND) && + verifier.VerifyString(sound()) && + VerifyField(verifier, VT_WEIGHT, 2) && verifier.EndTable(); + } +}; + +struct AnimalBuilder { + typedef Animal Table; + ::flatbuffers::FlatBufferBuilder& fbb_; + ::flatbuffers::uoffset_t start_; + void add_name(::flatbuffers::Offset<::flatbuffers::String> name) { + fbb_.AddOffset(Animal::VT_NAME, name); + } + void add_sound(::flatbuffers::Offset<::flatbuffers::String> sound) { + fbb_.AddOffset(Animal::VT_SOUND, sound); + } + void add_weight(uint16_t weight) { + fbb_.AddElement(Animal::VT_WEIGHT, weight, 0); + } + explicit AnimalBuilder(::flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateAnimal( + ::flatbuffers::FlatBufferBuilder& _fbb, + ::flatbuffers::Offset<::flatbuffers::String> name = 0, + ::flatbuffers::Offset<::flatbuffers::String> sound = 0, + uint16_t weight = 0) { + AnimalBuilder builder_(_fbb); + builder_.add_sound(sound); + builder_.add_name(name); + builder_.add_weight(weight); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateAnimalDirect( + ::flatbuffers::FlatBufferBuilder& _fbb, const char* name = nullptr, + const char* sound = nullptr, uint16_t weight = 0) { + auto name__ = name ? _fbb.CreateString(name) : 0; + auto sound__ = sound ? _fbb.CreateString(sound) : 0; + return com::fbs::app::CreateAnimal(_fbb, name__, sound__, weight); +} + +inline const com::fbs::app::Animal* GetAnimal(const void* buf) { + return ::flatbuffers::GetRoot(buf); +} + +inline const com::fbs::app::Animal* GetSizePrefixedAnimal(const void* buf) { + return ::flatbuffers::GetSizePrefixedRoot(buf); +} + +inline bool VerifyAnimalBuffer(::flatbuffers::Verifier& verifier) { + return verifier.VerifyBuffer(nullptr); +} + +inline bool VerifySizePrefixedAnimalBuffer(::flatbuffers::Verifier& verifier) { + return verifier.VerifySizePrefixedBuffer(nullptr); +} + +inline void FinishAnimalBuffer( + ::flatbuffers::FlatBufferBuilder& fbb, + ::flatbuffers::Offset root) { + fbb.Finish(root); +} + +inline void FinishSizePrefixedAnimalBuffer( + ::flatbuffers::FlatBufferBuilder& fbb, + ::flatbuffers::Offset root) { + fbb.FinishSizePrefixed(root); +} + +} // namespace app +} // namespace fbs +} // namespace com + +#endif // FLATBUFFERS_GENERATED_ANIMAL_COM_FBS_APP_H_ diff --git a/third_party/flatbuffers/android/app/src/main/fbs/animal.fbs b/third_party/flatbuffers/android/app/src/main/fbs/animal.fbs new file mode 100644 index 00000000000..479e22b2940 --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/fbs/animal.fbs @@ -0,0 +1,23 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace com.fbs.app; + +table Animal { + name:string; + sound:string; + weight: uint16; +} + +root_type Animal; diff --git a/third_party/flatbuffers/android/app/src/main/java/com/flatbuffers/app/MainActivity.kt b/third_party/flatbuffers/android/app/src/main/java/com/flatbuffers/app/MainActivity.kt new file mode 100644 index 00000000000..8bf7a1c9a8a --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/java/com/flatbuffers/app/MainActivity.kt @@ -0,0 +1,52 @@ +package com.flatbuffers.app + +import android.annotation.SuppressLint +import android.os.Bundle +import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity +import com.fbs.app.Animal +import com.google.flatbuffers.FlatBufferBuilder +import java.nio.ByteBuffer + +@ExperimentalUnsignedTypes +class MainActivity : AppCompatActivity() { + + @SuppressLint("SetTextI18n") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + val tiger = Animal.getRootAsAnimal(ByteBuffer.wrap(createAnimalFromJNI())) + findViewById(R.id.tv_animal_one).text = animalInfo(tiger) + + findViewById(R.id.tv_animal_two).text = animalInfo(createAnimalFromKotlin()) + } + + // This function is a sample of communicating FlatBuffers between JNI (native C++) and Java. + // Implementation can be found on animals.cpp file. + private external fun createAnimalFromJNI(): ByteArray + + // Create a "Cow" Animal flatbuffers from Kotlin + private fun createAnimalFromKotlin(): Animal { + val fb = FlatBufferBuilder(100) + val cowOffset = + Animal.createAnimal( + builder = fb, + nameOffset = fb.createString("Cow"), + soundOffset = fb.createString("Moo"), + weight = 720u, + ) + fb.finish(cowOffset) + return Animal.getRootAsAnimal(fb.dataBuffer()) + } + + private fun animalInfo(animal: Animal): String = + "The ${animal.name} sound is ${animal.sound} and it weights ${animal.weight}kg." + + companion object { + // Used to load the 'native-lib' library on application startup. + init { + System.loadLibrary("native-lib") + } + } +} diff --git a/third_party/flatbuffers/android/app/src/main/java/generated/com/fbs/app/Animal.kt b/third_party/flatbuffers/android/app/src/main/java/generated/com/fbs/app/Animal.kt new file mode 100644 index 00000000000..f9243cbd9d9 --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/java/generated/com/fbs/app/Animal.kt @@ -0,0 +1,102 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package com.fbs.app + +import com.google.flatbuffers.Constants +import com.google.flatbuffers.FlatBufferBuilder +import com.google.flatbuffers.Table +import java.nio.ByteBuffer +import java.nio.ByteOrder + +@Suppress("unused") +@kotlin.ExperimentalUnsignedTypes +class Animal : Table() { + + fun __init(_i: Int, _bb: ByteBuffer) { + __reset(_i, _bb) + } + + fun __assign(_i: Int, _bb: ByteBuffer): Animal { + __init(_i, _bb) + return this + } + + val name: String? + get() { + val o = __offset(4) + return if (o != 0) { + __string(o + bb_pos) + } else { + null + } + } + + val nameAsByteBuffer: ByteBuffer + get() = __vector_as_bytebuffer(4, 1) + + fun nameInByteBuffer(_bb: ByteBuffer): ByteBuffer = __vector_in_bytebuffer(_bb, 4, 1) + + val sound: String? + get() { + val o = __offset(6) + return if (o != 0) { + __string(o + bb_pos) + } else { + null + } + } + + val soundAsByteBuffer: ByteBuffer + get() = __vector_as_bytebuffer(6, 1) + + fun soundInByteBuffer(_bb: ByteBuffer): ByteBuffer = __vector_in_bytebuffer(_bb, 6, 1) + + val weight: UShort + get() { + val o = __offset(8) + return if (o != 0) bb.getShort(o + bb_pos).toUShort() else 0u + } + + companion object { + fun validateVersion() = Constants.FLATBUFFERS_25_9_23() + + fun getRootAsAnimal(_bb: ByteBuffer): Animal = getRootAsAnimal(_bb, Animal()) + + fun getRootAsAnimal(_bb: ByteBuffer, obj: Animal): Animal { + _bb.order(ByteOrder.LITTLE_ENDIAN) + return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)) + } + + fun createAnimal( + builder: FlatBufferBuilder, + nameOffset: Int, + soundOffset: Int, + weight: UShort, + ): Int { + builder.startTable(3) + addSound(builder, soundOffset) + addName(builder, nameOffset) + addWeight(builder, weight) + return endAnimal(builder) + } + + fun startAnimal(builder: FlatBufferBuilder) = builder.startTable(3) + + fun addName(builder: FlatBufferBuilder, name: Int) = builder.addOffset(0, name, 0) + + fun addSound(builder: FlatBufferBuilder, sound: Int) = builder.addOffset(1, sound, 0) + + fun addWeight(builder: FlatBufferBuilder, weight: UShort) = + builder.addShort(2, weight.toShort(), 0) + + fun endAnimal(builder: FlatBufferBuilder): Int { + val o = builder.endTable() + return o + } + + fun finishAnimalBuffer(builder: FlatBufferBuilder, offset: Int) = builder.finish(offset) + + fun finishSizePrefixedAnimalBuffer(builder: FlatBufferBuilder, offset: Int) = + builder.finishSizePrefixed(offset) + } +} diff --git a/third_party/flatbuffers/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/third_party/flatbuffers/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 00000000000..7706ab9e6d4 --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + diff --git a/third_party/flatbuffers/android/app/src/main/res/drawable/ic_launcher_background.xml b/third_party/flatbuffers/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000000..07d5da9cbf1 --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third_party/flatbuffers/android/app/src/main/res/layout/activity_main.xml b/third_party/flatbuffers/android/app/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000000..d339c224064 --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/third_party/flatbuffers/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/third_party/flatbuffers/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000000..6b78462d615 --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/third_party/flatbuffers/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/third_party/flatbuffers/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000000..6b78462d615 --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/third_party/flatbuffers/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/third_party/flatbuffers/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000000..a571e60098c Binary files /dev/null and b/third_party/flatbuffers/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/third_party/flatbuffers/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/third_party/flatbuffers/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 00000000000..61da551c559 Binary files /dev/null and b/third_party/flatbuffers/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/third_party/flatbuffers/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/third_party/flatbuffers/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000000..c41dd285319 Binary files /dev/null and b/third_party/flatbuffers/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/third_party/flatbuffers/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/third_party/flatbuffers/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 00000000000..db5080a7527 Binary files /dev/null and b/third_party/flatbuffers/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/third_party/flatbuffers/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/third_party/flatbuffers/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000000..6dba46dab19 Binary files /dev/null and b/third_party/flatbuffers/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/third_party/flatbuffers/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/third_party/flatbuffers/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 00000000000..da31a871c8d Binary files /dev/null and b/third_party/flatbuffers/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/third_party/flatbuffers/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/third_party/flatbuffers/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000000..15ac681720f Binary files /dev/null and b/third_party/flatbuffers/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/third_party/flatbuffers/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/third_party/flatbuffers/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 00000000000..b216f2d313c Binary files /dev/null and b/third_party/flatbuffers/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/third_party/flatbuffers/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/third_party/flatbuffers/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000000..f25a4197447 Binary files /dev/null and b/third_party/flatbuffers/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/third_party/flatbuffers/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/third_party/flatbuffers/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 00000000000..e96783ccce8 Binary files /dev/null and b/third_party/flatbuffers/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/third_party/flatbuffers/android/app/src/main/res/values/colors.xml b/third_party/flatbuffers/android/app/src/main/res/values/colors.xml new file mode 100644 index 00000000000..030098fe0f7 --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #6200EE + #3700B3 + #03DAC5 + diff --git a/third_party/flatbuffers/android/app/src/main/res/values/strings.xml b/third_party/flatbuffers/android/app/src/main/res/values/strings.xml new file mode 100644 index 00000000000..71d53e98a2c --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + FlatbuffersTestApp + diff --git a/third_party/flatbuffers/android/app/src/main/res/values/styles.xml b/third_party/flatbuffers/android/app/src/main/res/values/styles.xml new file mode 100644 index 00000000000..391ec9ae3b7 --- /dev/null +++ b/third_party/flatbuffers/android/app/src/main/res/values/styles.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/third_party/flatbuffers/android/build.gradle b/third_party/flatbuffers/android/build.gradle new file mode 100644 index 00000000000..7e9cdec5196 --- /dev/null +++ b/third_party/flatbuffers/android/build.gradle @@ -0,0 +1,35 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + ext.kotlin_version = "1.7.21" + repositories { + google() + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:7.4.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + + compileKotlin { + dependsOn flatbuffer + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/third_party/flatbuffers/android/gradle.properties b/third_party/flatbuffers/android/gradle.properties new file mode 100644 index 00000000000..bf3068ddd74 --- /dev/null +++ b/third_party/flatbuffers/android/gradle.properties @@ -0,0 +1,23 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Use parallel builds +org.gradle.parallel=true \ No newline at end of file diff --git a/third_party/flatbuffers/android/gradle/wrapper/gradle-wrapper.jar b/third_party/flatbuffers/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..41d9927a4d4 Binary files /dev/null and b/third_party/flatbuffers/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/third_party/flatbuffers/android/gradle/wrapper/gradle-wrapper.properties b/third_party/flatbuffers/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..f72df95a7e8 --- /dev/null +++ b/third_party/flatbuffers/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/third_party/flatbuffers/android/gradlew b/third_party/flatbuffers/android/gradlew new file mode 100755 index 00000000000..cccdd3d517f --- /dev/null +++ b/third_party/flatbuffers/android/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/third_party/flatbuffers/android/gradlew.bat b/third_party/flatbuffers/android/gradlew.bat new file mode 100644 index 00000000000..f9553162f12 --- /dev/null +++ b/third_party/flatbuffers/android/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/third_party/flatbuffers/android/settings.gradle b/third_party/flatbuffers/android/settings.gradle new file mode 100644 index 00000000000..c4c0afbc97d --- /dev/null +++ b/third_party/flatbuffers/android/settings.gradle @@ -0,0 +1,2 @@ +include ':app' +rootProject.name = "FlatbuffersTest" diff --git a/third_party/flatbuffers/bazel/BUILD.bazel b/third_party/flatbuffers/bazel/BUILD.bazel new file mode 100644 index 00000000000..e69de29bb2d diff --git a/third_party/flatbuffers/benchmarks/CMakeLists.txt b/third_party/flatbuffers/benchmarks/CMakeLists.txt new file mode 100644 index 00000000000..18f6ef9fd4e --- /dev/null +++ b/third_party/flatbuffers/benchmarks/CMakeLists.txt @@ -0,0 +1,88 @@ +# Setup for running Google Benchmarks (https://github.com/google/benchmark) on +# flatbuffers. This requires both that benchmark library and its dependency gtest +# to build. Instead of including them here or doing a submodule, this uses +# FetchContent (https://cmake.org/cmake/help/latest/module/FetchContent.html) to +# grab the dependencies at config time. This requires CMake 3.14 or higher. + +cmake_minimum_required(VERSION 3.14) +include(FetchContent) + +# No particular reason for the specific GIT_TAGs for the following repos, they +# were just the latest releases when this was added. +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG e2239ee6043f73722e7aa812a459f54a28552929 # release-1.11.0 +) +FetchContent_Declare( + googlebenchmark + GIT_REPOSITORY https://github.com/google/benchmark.git + GIT_TAG 0d98dba29d66e93259db7daa53a9327df767a415 # v1.6.1 +) + +# For Windows: Prevent overriding the parent project's compiler/linker +# settings. +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable( + googletest + googlebenchmark +) + +set(CPP_BENCH_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cpp) +set(CPP_FB_BENCH_DIR ${CPP_BENCH_DIR}/flatbuffers) +set(CPP_RAW_BENCH_DIR ${CPP_BENCH_DIR}/raw) +set(CPP_BENCH_FBS ${CPP_FB_BENCH_DIR}/bench.fbs) +set(CPP_BENCH_FB_GEN ${CPP_FB_BENCH_DIR}/bench_generated.h) + +set(FlatBenchmark_SRCS + ${CPP_BENCH_DIR}/benchmark_main.cpp + ${CPP_FB_BENCH_DIR}/fb_bench.cpp + ${CPP_RAW_BENCH_DIR}/raw_bench.cpp + ${CPP_BENCH_FB_GEN} +) + +# Generate the flatbuffers benchmark code from the flatbuffers schema using +# flatc itself, thus it depends on flatc. This also depends on the C++ runtime +# flatbuffers and the schema file itself, so it should auto-generated at the +# correct times. +add_custom_command( + OUTPUT ${CPP_BENCH_FB_GEN} + COMMAND + "${FLATBUFFERS_FLATC_EXECUTABLE}" + --cpp + -o ${CPP_FB_BENCH_DIR} + ${CPP_BENCH_FBS} + DEPENDS + flatc + flatbuffers + ${CPP_BENCH_FBS} + COMMENT "Run Flatbuffers Benchmark Codegen: ${CPP_BENCH_FB_GEN}" + VERBATIM) + +# The main flatbuffers benchmark executable +add_executable(flatbenchmark ${FlatBenchmark_SRCS}) + +# Benchmark requires C++11 +target_compile_features(flatbenchmark PRIVATE + cxx_std_11 # requires cmake 3.8 +) + +target_compile_options(flatbenchmark + PRIVATE + -fno-aligned-new + -Wno-deprecated-declarations +) + +# Set the output directory to the root binary directory +set_target_properties(flatbenchmark + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_BINARY_DIR}" +) + +# The includes of the benchmark files are fully qualified from flatbuffers root. +target_include_directories(flatbenchmark PUBLIC ${CMAKE_SOURCE_DIR}) + +target_link_libraries(flatbenchmark PRIVATE + benchmark::benchmark_main # _main to use their entry point + gtest # Link to gtest so we can also assert in the benchmarks +) \ No newline at end of file diff --git a/third_party/flatbuffers/benchmarks/cpp/bench.h b/third_party/flatbuffers/benchmarks/cpp/bench.h new file mode 100644 index 00000000000..f358d210d0c --- /dev/null +++ b/third_party/flatbuffers/benchmarks/cpp/bench.h @@ -0,0 +1,19 @@ +#ifndef BENCHMARKS_CPP_BENCH_H_ +#define BENCHMARKS_CPP_BENCH_H_ + +#include + +struct Bench { + virtual ~Bench() {} + + inline void Add(int64_t value) { sum += value; } + + virtual uint8_t* Encode(void* buf, int64_t& len) = 0; + virtual void* Decode(void* buf, int64_t len) = 0; + virtual int64_t Use(void* decoded) = 0; + virtual void Dealloc(void* decoded) = 0; + + int64_t sum = 0; +}; + +#endif // BENCHMARKS_CPP_BENCH_H_ \ No newline at end of file diff --git a/third_party/flatbuffers/benchmarks/cpp/benchmark_main.cpp b/third_party/flatbuffers/benchmarks/cpp/benchmark_main.cpp new file mode 100644 index 00000000000..63807a5dd53 --- /dev/null +++ b/third_party/flatbuffers/benchmarks/cpp/benchmark_main.cpp @@ -0,0 +1,96 @@ +#include +#include + +#include "benchmarks/cpp/bench.h" +#include "benchmarks/cpp/flatbuffers/fb_bench.h" +#include "benchmarks/cpp/raw/raw_bench.h" + +static inline void Encode(benchmark::State &state, + std::unique_ptr &bench, uint8_t *buffer) { + int64_t length; + for (auto _ : state) { + bench->Encode(buffer, length); + benchmark::DoNotOptimize(length); + } +} + +static inline void Decode(benchmark::State &state, + std::unique_ptr &bench, uint8_t *buffer) { + int64_t length; + uint8_t *encoded = bench->Encode(buffer, length); + + for (auto _ : state) { + void *decoded = bench->Decode(encoded, length); + benchmark::DoNotOptimize(decoded); + } +} + +static inline void Use(benchmark::State &state, std::unique_ptr &bench, + uint8_t *buffer, int64_t check_sum) { + int64_t length; + uint8_t *encoded = bench->Encode(buffer, length); + void *decoded = bench->Decode(encoded, length); + + int64_t sum = 0; + + for (auto _ : state) { sum = bench->Use(decoded); } + + EXPECT_EQ(sum, check_sum); +} + +static void BM_Flatbuffers_Encode(benchmark::State &state) { + const int64_t kBufferLength = 1024; + uint8_t buffer[kBufferLength]; + + StaticAllocator allocator(&buffer[0]); + std::unique_ptr bench = NewFlatBuffersBench(kBufferLength, &allocator); + Encode(state, bench, buffer); +} +BENCHMARK(BM_Flatbuffers_Encode); + +static void BM_Flatbuffers_Decode(benchmark::State &state) { + const int64_t kBufferLength = 1024; + uint8_t buffer[kBufferLength]; + + StaticAllocator allocator(&buffer[0]); + std::unique_ptr bench = NewFlatBuffersBench(kBufferLength, &allocator); + Decode(state, bench, buffer); +} +BENCHMARK(BM_Flatbuffers_Decode); + +static void BM_Flatbuffers_Use(benchmark::State &state) { + const int64_t kBufferLength = 1024; + uint8_t buffer[kBufferLength]; + + StaticAllocator allocator(&buffer[0]); + std::unique_ptr bench = NewFlatBuffersBench(kBufferLength, &allocator); + Use(state, bench, buffer, 218812692406581874); +} +BENCHMARK(BM_Flatbuffers_Use); + +static void BM_Raw_Encode(benchmark::State &state) { + const int64_t kBufferLength = 1024; + uint8_t buffer[kBufferLength]; + + std::unique_ptr bench = NewRawBench(); + Encode(state, bench, buffer); +} +BENCHMARK(BM_Raw_Encode); + +static void BM_Raw_Decode(benchmark::State &state) { + const int64_t kBufferLength = 1024; + uint8_t buffer[kBufferLength]; + + std::unique_ptr bench = NewRawBench(); + Decode(state, bench, buffer); +} +BENCHMARK(BM_Raw_Decode); + +static void BM_Raw_Use(benchmark::State &state) { + const int64_t kBufferLength = 1024; + uint8_t buffer[kBufferLength]; + + std::unique_ptr bench = NewRawBench(); + Use(state, bench, buffer, 218812692406581874); +} +BENCHMARK(BM_Raw_Use); diff --git a/third_party/flatbuffers/benchmarks/cpp/flatbuffers/bench.fbs b/third_party/flatbuffers/benchmarks/cpp/flatbuffers/bench.fbs new file mode 100644 index 00000000000..8e5f3ff7e1c --- /dev/null +++ b/third_party/flatbuffers/benchmarks/cpp/flatbuffers/bench.fbs @@ -0,0 +1,52 @@ +// Copyright 2021 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +// trying to represent a typical mix of datatypes: +// 1 array of 3 elements, each element: 1 string, 3 nested objects, 9 scalars +// root element has the array, additional string and an enum + +namespace benchmarks_flatbuffers; + +enum Enum : short { Apples, Pears, Bananas} + +struct Foo { + id:ulong; + count:short; + prefix:byte; + length:uint; +} + +struct Bar { + parent:Foo; + time:int; + ratio:float; + size:ushort; +} + +table FooBar { + sibling:Bar; + name:string; + rating:double; + postfix:ubyte; +} + +table FooBarContainer { + list:[FooBar]; // 3 copies of the above + initialized:bool; + fruit:Enum; + location:string; +} + +root_type FooBarContainer; diff --git a/third_party/flatbuffers/benchmarks/cpp/flatbuffers/bench_generated.h b/third_party/flatbuffers/benchmarks/cpp/flatbuffers/bench_generated.h new file mode 100644 index 00000000000..e53a868c656 --- /dev/null +++ b/third_party/flatbuffers/benchmarks/cpp/flatbuffers/bench_generated.h @@ -0,0 +1,317 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +#ifndef FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_ +#define FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_ + +#include "flatbuffers/flatbuffers.h" + +// Ensure the included flatbuffers.h is the same version as when this file was +// generated, otherwise it may not be compatible. +static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && + FLATBUFFERS_VERSION_MINOR == 12 && + FLATBUFFERS_VERSION_REVISION == 23, + "Non-compatible flatbuffers version included"); + +namespace benchmarks_flatbuffers { + +struct Foo; + +struct Bar; + +struct FooBar; +struct FooBarBuilder; + +struct FooBarContainer; +struct FooBarContainerBuilder; + +enum Enum : int16_t { + Enum_Apples = 0, + Enum_Pears = 1, + Enum_Bananas = 2, + Enum_MIN = Enum_Apples, + Enum_MAX = Enum_Bananas +}; + +inline const Enum (&EnumValuesEnum())[3] { + static const Enum values[] = {Enum_Apples, Enum_Pears, Enum_Bananas}; + return values; +} + +inline const char* const* EnumNamesEnum() { + static const char* const names[4] = {"Apples", "Pears", "Bananas", nullptr}; + return names; +} + +inline const char* EnumNameEnum(Enum e) { + if (flatbuffers::IsOutRange(e, Enum_Apples, Enum_Bananas)) return ""; + const size_t index = static_cast(e); + return EnumNamesEnum()[index]; +} + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Foo FLATBUFFERS_FINAL_CLASS { + private: + uint64_t id_; + int16_t count_; + int8_t prefix_; + int8_t padding0__; + uint32_t length_; + + public: + Foo() : id_(0), count_(0), prefix_(0), padding0__(0), length_(0) { + (void)padding0__; + } + Foo(uint64_t _id, int16_t _count, int8_t _prefix, uint32_t _length) + : id_(flatbuffers::EndianScalar(_id)), + count_(flatbuffers::EndianScalar(_count)), + prefix_(flatbuffers::EndianScalar(_prefix)), + padding0__(0), + length_(flatbuffers::EndianScalar(_length)) { + (void)padding0__; + } + uint64_t id() const { return flatbuffers::EndianScalar(id_); } + int16_t count() const { return flatbuffers::EndianScalar(count_); } + int8_t prefix() const { return flatbuffers::EndianScalar(prefix_); } + uint32_t length() const { return flatbuffers::EndianScalar(length_); } +}; +FLATBUFFERS_STRUCT_END(Foo, 16); + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Bar FLATBUFFERS_FINAL_CLASS { + private: + benchmarks_flatbuffers::Foo parent_; + int32_t time_; + float ratio_; + uint16_t size_; + int16_t padding0__; + int32_t padding1__; + + public: + Bar() + : parent_(), time_(0), ratio_(0), size_(0), padding0__(0), padding1__(0) { + (void)padding0__; + (void)padding1__; + } + Bar(const benchmarks_flatbuffers::Foo& _parent, int32_t _time, float _ratio, + uint16_t _size) + : parent_(_parent), + time_(flatbuffers::EndianScalar(_time)), + ratio_(flatbuffers::EndianScalar(_ratio)), + size_(flatbuffers::EndianScalar(_size)), + padding0__(0), + padding1__(0) { + (void)padding0__; + (void)padding1__; + } + const benchmarks_flatbuffers::Foo& parent() const { return parent_; } + int32_t time() const { return flatbuffers::EndianScalar(time_); } + float ratio() const { return flatbuffers::EndianScalar(ratio_); } + uint16_t size() const { return flatbuffers::EndianScalar(size_); } +}; +FLATBUFFERS_STRUCT_END(Bar, 32); + +struct FooBar FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef FooBarBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_SIBLING = 4, + VT_NAME = 6, + VT_RATING = 8, + VT_POSTFIX = 10 + }; + const benchmarks_flatbuffers::Bar* sibling() const { + return GetStruct(VT_SIBLING); + } + const flatbuffers::String* name() const { + return GetPointer(VT_NAME); + } + double rating() const { return GetField(VT_RATING, 0.0); } + uint8_t postfix() const { return GetField(VT_POSTFIX, 0); } + bool Verify(flatbuffers::Verifier& verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_SIBLING, 8) && + VerifyOffset(verifier, VT_NAME) && verifier.VerifyString(name()) && + VerifyField(verifier, VT_RATING, 8) && + VerifyField(verifier, VT_POSTFIX, 1) && verifier.EndTable(); + } +}; + +struct FooBarBuilder { + typedef FooBar Table; + flatbuffers::FlatBufferBuilder& fbb_; + flatbuffers::uoffset_t start_; + void add_sibling(const benchmarks_flatbuffers::Bar* sibling) { + fbb_.AddStruct(FooBar::VT_SIBLING, sibling); + } + void add_name(flatbuffers::Offset name) { + fbb_.AddOffset(FooBar::VT_NAME, name); + } + void add_rating(double rating) { + fbb_.AddElement(FooBar::VT_RATING, rating, 0.0); + } + void add_postfix(uint8_t postfix) { + fbb_.AddElement(FooBar::VT_POSTFIX, postfix, 0); + } + explicit FooBarBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateFooBar( + flatbuffers::FlatBufferBuilder& _fbb, + const benchmarks_flatbuffers::Bar* sibling = nullptr, + flatbuffers::Offset name = 0, double rating = 0.0, + uint8_t postfix = 0) { + FooBarBuilder builder_(_fbb); + builder_.add_rating(rating); + builder_.add_name(name); + builder_.add_sibling(sibling); + builder_.add_postfix(postfix); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateFooBarDirect( + flatbuffers::FlatBufferBuilder& _fbb, + const benchmarks_flatbuffers::Bar* sibling = nullptr, + const char* name = nullptr, double rating = 0.0, uint8_t postfix = 0) { + auto name__ = name ? _fbb.CreateString(name) : 0; + return benchmarks_flatbuffers::CreateFooBar(_fbb, sibling, name__, rating, + postfix); +} + +struct FooBarContainer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef FooBarContainerBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_LIST = 4, + VT_INITIALIZED = 6, + VT_FRUIT = 8, + VT_LOCATION = 10 + }; + const flatbuffers::Vector< + flatbuffers::Offset>* + list() const { + return GetPointer>*>(VT_LIST); + } + bool initialized() const { return GetField(VT_INITIALIZED, 0) != 0; } + benchmarks_flatbuffers::Enum fruit() const { + return static_cast( + GetField(VT_FRUIT, 0)); + } + const flatbuffers::String* location() const { + return GetPointer(VT_LOCATION); + } + bool Verify(flatbuffers::Verifier& verifier) const { + return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_LIST) && + verifier.VerifyVector(list()) && + verifier.VerifyVectorOfTables(list()) && + VerifyField(verifier, VT_INITIALIZED, 1) && + VerifyField(verifier, VT_FRUIT, 2) && + VerifyOffset(verifier, VT_LOCATION) && + verifier.VerifyString(location()) && verifier.EndTable(); + } +}; + +struct FooBarContainerBuilder { + typedef FooBarContainer Table; + flatbuffers::FlatBufferBuilder& fbb_; + flatbuffers::uoffset_t start_; + void add_list(flatbuffers::Offset>> + list) { + fbb_.AddOffset(FooBarContainer::VT_LIST, list); + } + void add_initialized(bool initialized) { + fbb_.AddElement(FooBarContainer::VT_INITIALIZED, + static_cast(initialized), 0); + } + void add_fruit(benchmarks_flatbuffers::Enum fruit) { + fbb_.AddElement(FooBarContainer::VT_FRUIT, + static_cast(fruit), 0); + } + void add_location(flatbuffers::Offset location) { + fbb_.AddOffset(FooBarContainer::VT_LOCATION, location); + } + explicit FooBarContainerBuilder(flatbuffers::FlatBufferBuilder& _fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateFooBarContainer( + flatbuffers::FlatBufferBuilder& _fbb, + flatbuffers::Offset>> + list = 0, + bool initialized = false, + benchmarks_flatbuffers::Enum fruit = benchmarks_flatbuffers::Enum_Apples, + flatbuffers::Offset location = 0) { + FooBarContainerBuilder builder_(_fbb); + builder_.add_location(location); + builder_.add_list(list); + builder_.add_fruit(fruit); + builder_.add_initialized(initialized); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateFooBarContainerDirect( + flatbuffers::FlatBufferBuilder& _fbb, + const std::vector>* + list = nullptr, + bool initialized = false, + benchmarks_flatbuffers::Enum fruit = benchmarks_flatbuffers::Enum_Apples, + const char* location = nullptr) { + auto list__ = + list ? _fbb.CreateVector< + flatbuffers::Offset>(*list) + : 0; + auto location__ = location ? _fbb.CreateString(location) : 0; + return benchmarks_flatbuffers::CreateFooBarContainer( + _fbb, list__, initialized, fruit, location__); +} + +inline const benchmarks_flatbuffers::FooBarContainer* GetFooBarContainer( + const void* buf) { + return flatbuffers::GetRoot(buf); +} + +inline const benchmarks_flatbuffers::FooBarContainer* +GetSizePrefixedFooBarContainer(const void* buf) { + return flatbuffers::GetSizePrefixedRoot< + benchmarks_flatbuffers::FooBarContainer>(buf); +} + +inline bool VerifyFooBarContainerBuffer(flatbuffers::Verifier& verifier) { + return verifier.VerifyBuffer( + nullptr); +} + +inline bool VerifySizePrefixedFooBarContainerBuffer( + flatbuffers::Verifier& verifier) { + return verifier + .VerifySizePrefixedBuffer( + nullptr); +} + +inline void FinishFooBarContainerBuffer( + flatbuffers::FlatBufferBuilder& fbb, + flatbuffers::Offset root) { + fbb.Finish(root); +} + +inline void FinishSizePrefixedFooBarContainerBuffer( + flatbuffers::FlatBufferBuilder& fbb, + flatbuffers::Offset root) { + fbb.FinishSizePrefixed(root); +} + +} // namespace benchmarks_flatbuffers + +#endif // FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_ diff --git a/third_party/flatbuffers/benchmarks/cpp/flatbuffers/fb_bench.cpp b/third_party/flatbuffers/benchmarks/cpp/flatbuffers/fb_bench.cpp new file mode 100644 index 00000000000..935166745aa --- /dev/null +++ b/third_party/flatbuffers/benchmarks/cpp/flatbuffers/fb_bench.cpp @@ -0,0 +1,80 @@ +#include "benchmarks/cpp/flatbuffers/fb_bench.h" + +#include +#include + +#include "benchmarks/cpp/bench.h" +#include "benchmarks/cpp/flatbuffers/bench_generated.h" +#include "flatbuffers/flatbuffers.h" + +using namespace flatbuffers; +using namespace benchmarks_flatbuffers; + +namespace { + +struct FlatBufferBench : Bench { + explicit FlatBufferBench(int64_t initial_size, Allocator *allocator) + : fbb(initial_size, allocator, false) {} + + uint8_t *Encode(void *, int64_t &len) override { + fbb.Clear(); + + const int kVectorLength = 3; + Offset vec[kVectorLength]; + + for (int i = 0; i < kVectorLength; ++i) { + Foo foo(0xABADCAFEABADCAFE + i, 10000 + i, '@' + i, 1000000 + i); + Bar bar(foo, 123456 + i, 3.14159f + i, 10000 + i); + auto name = fbb.CreateString("Hello, World!"); + auto foobar = + CreateFooBar(fbb, &bar, name, 3.1415432432445543543 + i, '!' + i); + vec[i] = foobar; + } + auto location = fbb.CreateString("http://google.com/flatbuffers/"); + auto foobarvec = fbb.CreateVector(vec, kVectorLength); + auto foobarcontainer = + CreateFooBarContainer(fbb, foobarvec, true, Enum_Bananas, location); + fbb.Finish(foobarcontainer); + + len = fbb.GetSize(); + return fbb.GetBufferPointer(); + } + + int64_t Use(void *decoded) override { + sum = 0; + auto foobarcontainer = GetFooBarContainer(decoded); + sum = 0; + Add(foobarcontainer->initialized()); + Add(foobarcontainer->location()->Length()); + Add(foobarcontainer->fruit()); + for (unsigned int i = 0; i < foobarcontainer->list()->Length(); i++) { + auto foobar = foobarcontainer->list()->Get(i); + Add(foobar->name()->Length()); + Add(foobar->postfix()); + Add(static_cast(foobar->rating())); + auto bar = foobar->sibling(); + Add(static_cast(bar->ratio())); + Add(bar->size()); + Add(bar->time()); + auto &foo = bar->parent(); + Add(foo.count()); + Add(foo.id()); + Add(foo.length()); + Add(foo.prefix()); + } + return sum; + } + + void *Decode(void *buffer, int64_t) override { return buffer; } + void Dealloc(void *) override {}; + + FlatBufferBuilder fbb; +}; + +} // namespace + +std::unique_ptr NewFlatBuffersBench(int64_t initial_size, + Allocator *allocator) { + return std::unique_ptr( + new FlatBufferBench(initial_size, allocator)); +} diff --git a/third_party/flatbuffers/benchmarks/cpp/flatbuffers/fb_bench.h b/third_party/flatbuffers/benchmarks/cpp/flatbuffers/fb_bench.h new file mode 100644 index 00000000000..09eb2bac706 --- /dev/null +++ b/third_party/flatbuffers/benchmarks/cpp/flatbuffers/fb_bench.h @@ -0,0 +1,23 @@ +#ifndef BENCHMARKS_CPP_FLATBUFFERS_FB_BENCH_H_ +#define BENCHMARKS_CPP_FLATBUFFERS_FB_BENCH_H_ + +#include +#include + +#include "benchmarks/cpp/bench.h" +#include "include/flatbuffers/flatbuffers.h" + +struct StaticAllocator : public flatbuffers::Allocator { + explicit StaticAllocator(uint8_t* buffer) : buffer_(buffer) {} + + uint8_t* allocate(size_t) override { return buffer_; } + + void deallocate(uint8_t*, size_t) override {} + + uint8_t* buffer_; +}; + +std::unique_ptr NewFlatBuffersBench( + int64_t initial_size = 1024, flatbuffers::Allocator* allocator = nullptr); + +#endif // BENCHMARKS_CPP_FLATBUFFERS_FB_BENCH_H_ \ No newline at end of file diff --git a/third_party/flatbuffers/benchmarks/cpp/raw/raw_bench.cpp b/third_party/flatbuffers/benchmarks/cpp/raw/raw_bench.cpp new file mode 100644 index 00000000000..c65bca7f71c --- /dev/null +++ b/third_party/flatbuffers/benchmarks/cpp/raw/raw_bench.cpp @@ -0,0 +1,109 @@ +#include "benchmarks/cpp/raw/raw_bench.h" + +#include +#include +#include + +#include "benchmarks/cpp/bench.h" + +namespace { +const int64_t kStringLength = 32; +const int64_t kVectorLength = 3; + +enum Enum { Apples, Pears, Bananas }; + +struct Foo { + int64_t id; + short count; + char prefix; + int length; +}; + +struct Bar { + Foo parent; + int time; + float ratio; + unsigned short size; +}; + +struct FooBar { + Bar sibling; + // We have to stick this in, otherwise strlen() will make it slower than + // FlatBuffers: + int name_len; + char name[kStringLength]; + double rating; + unsigned char postfix; +}; + +struct FooBarContainer { + FooBar list[kVectorLength]; // 3 copies of the above + bool initialized; + Enum fruit; + int location_len; + char location[kStringLength]; +}; + +struct RawBench : Bench { + uint8_t *Encode(void *buf, int64_t &len) override { + FooBarContainer *fbc = new (buf) FooBarContainer; + strcpy(fbc->location, "http://google.com/flatbuffers/"); // Unsafe eek! + fbc->location_len = (int)strlen(fbc->location); + fbc->fruit = Bananas; + fbc->initialized = true; + for (int i = 0; i < kVectorLength; i++) { + // We add + i to not make these identical copies for a more realistic + // compression test. + auto &foobar = fbc->list[i]; + foobar.rating = 3.1415432432445543543 + i; + foobar.postfix = '!' + i; + strcpy(foobar.name, "Hello, World!"); + foobar.name_len = (int)strlen(foobar.name); + auto &bar = foobar.sibling; + bar.ratio = 3.14159f + i; + bar.size = 10000 + i; + bar.time = 123456 + i; + auto &foo = bar.parent; + foo.id = 0xABADCAFEABADCAFE + i; + foo.count = 10000 + i; + foo.length = 1000000 + i; + foo.prefix = '@' + i; + } + + len = sizeof(FooBarContainer); + return reinterpret_cast(fbc); + }; + + int64_t Use(void *decoded) override { + auto foobarcontainer = reinterpret_cast(decoded); + sum = 0; + Add(foobarcontainer->initialized); + Add(foobarcontainer->location_len); + Add(foobarcontainer->fruit); + for (unsigned int i = 0; i < kVectorLength; i++) { + auto foobar = &foobarcontainer->list[i]; + Add(foobar->name_len); + Add(foobar->postfix); + Add(static_cast(foobar->rating)); + auto bar = &foobar->sibling; + Add(static_cast(bar->ratio)); + Add(bar->size); + Add(bar->time); + auto &foo = bar->parent; + Add(foo.count); + Add(foo.id); + Add(foo.length); + Add(foo.prefix); + } + return sum; + } + + void *Decode(void *buf, int64_t) override { return buf; } + void Dealloc(void *) override{}; +}; + +} // namespace + +std::unique_ptr NewRawBench() { + return std::unique_ptr(new RawBench()); +} diff --git a/third_party/flatbuffers/benchmarks/cpp/raw/raw_bench.h b/third_party/flatbuffers/benchmarks/cpp/raw/raw_bench.h new file mode 100644 index 00000000000..68bb278c26f --- /dev/null +++ b/third_party/flatbuffers/benchmarks/cpp/raw/raw_bench.h @@ -0,0 +1,10 @@ +#ifndef BENCHMARKS_CPP_RAW_RAW_BENCH_H_ +#define BENCHMARKS_CPP_RAW_RAW_BENCH_H_ + +#include + +#include "benchmarks/cpp/bench.h" + +std::unique_ptr NewRawBench(); + +#endif // BENCHMARKS_CPP_RAW_RAW_BENCH_H_ \ No newline at end of file diff --git a/third_party/flatbuffers/benchmarks/swift/Benchmarks/FlatbuffersBenchmarks/FlatbuffersBenchmarks.swift b/third_party/flatbuffers/benchmarks/swift/Benchmarks/FlatbuffersBenchmarks/FlatbuffersBenchmarks.swift new file mode 100644 index 00000000000..92eaf4afc96 --- /dev/null +++ b/third_party/flatbuffers/benchmarks/swift/Benchmarks/FlatbuffersBenchmarks/FlatbuffersBenchmarks.swift @@ -0,0 +1,250 @@ +/* + * Copyright 2024 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Benchmark +import FlatBuffers +import Foundation + +@usableFromInline +struct AA: NativeStruct { + public init(a: Double, b: Double) { + self.a = a + self.b = b + } + var a: Double + var b: Double +} + +let benchmarks = { + let oneGB: Int32 = 1_024_000_000 + let data = { + var array = [8888.88, 8888.88] + var data = Data() + array.withUnsafeBytes { ptr in + data.append(contentsOf: ptr) + } + return data + }() + let ints: [Int] = Array(repeating: 42, count: 100) + let bytes: [UInt8] = Array(repeating: 42, count: 100) + let str10 = (0...9).map { _ -> String in "x" }.joined() + let str100 = (0...99).map { _ -> String in "x" }.joined() + let array: [AA] = [ + AA(a: 2.4, b: 2.4), + AA(a: 2.4, b: 2.4), + AA(a: 2.4, b: 2.4), + AA(a: 2.4, b: 2.4), + AA(a: 2.4, b: 2.4), + ] + + let metrics: [BenchmarkMetric] = [ + .cpuTotal, + .wallClock, + .mallocCountTotal, + .releaseCount, + .peakMemoryResident, + ] + let maxIterations = 1_000_000 + let maxDuration: Duration = .seconds(3) + let singleConfiguration: Benchmark.Configuration = .init( + metrics: metrics, + warmupIterations: 1, + scalingFactor: .one, + maxDuration: maxDuration, + maxIterations: maxIterations) + let kiloConfiguration: Benchmark.Configuration = .init( + metrics: metrics, + warmupIterations: 1, + scalingFactor: .kilo, + maxDuration: maxDuration, + maxIterations: maxIterations) + let megaConfiguration: Benchmark.Configuration = .init( + metrics: metrics, + warmupIterations: 1, + scalingFactor: .mega, + maxDuration: maxDuration, + maxIterations: maxIterations) + + Benchmark.defaultConfiguration = megaConfiguration + + Benchmark("Allocating 1GB", configuration: singleConfiguration) { benchmark in + for _ in benchmark.scaledIterations { + blackHole(FlatBufferBuilder(initialSize: oneGB)) + } + } + + Benchmark( + "Allocating ByteBuffer 1GB", + configuration: singleConfiguration + ) { benchmark in + let memory = UnsafeMutableRawPointer.allocate( + byteCount: 1_024_000_000, + alignment: 1) + benchmark.startMeasurement() + for _ in benchmark.scaledIterations { + blackHole(ByteBuffer(assumingMemoryBound: memory, capacity: Int(oneGB))) + } + } + + Benchmark("Clearing 1GB", configuration: singleConfiguration) { benchmark in + var fb = FlatBufferBuilder(initialSize: oneGB) + benchmark.startMeasurement() + for _ in benchmark.scaledIterations { + blackHole(fb.clear()) + } + } + + Benchmark("Strings 10") { benchmark in + var fb = FlatBufferBuilder(initialSize: 1 << 20) + benchmark.startMeasurement() + for _ in benchmark.scaledIterations { + blackHole(fb.create(string: str10)) + } + } + + Benchmark("Strings 100") { benchmark in + var fb = FlatBufferBuilder(initialSize: 1 << 20) + benchmark.startMeasurement() + for _ in benchmark.scaledIterations { + blackHole(fb.create(string: str100)) + } + } + + Benchmark("Vector 1 Bytes") { benchmark in + var fb = FlatBufferBuilder(initialSize: 1 << 20) + benchmark.startMeasurement() + for _ in benchmark.scaledIterations { + blackHole(fb.createVector(bytes: bytes)) + } + } + + Benchmark("Vector 1 Ints") { benchmark in + var fb = FlatBufferBuilder(initialSize: 1 << 20) + benchmark.startMeasurement() + for _ in benchmark.scaledIterations { + blackHole(fb.createVector(ints)) + } + } + + Benchmark("Vector 100 Ints") { benchmark in + var fb = FlatBufferBuilder(initialSize: 1 << 20) + benchmark.startMeasurement() + for i in benchmark.scaledIterations { + blackHole(fb.createVector(ints)) + } + } + + Benchmark("Vector 100 Bytes") { benchmark in + var fb = FlatBufferBuilder(initialSize: 1 << 20) + benchmark.startMeasurement() + for i in benchmark.scaledIterations { + blackHole(fb.createVector(bytes)) + } + } + + Benchmark("Vector 100 ContiguousBytes") { benchmark in + var fb = FlatBufferBuilder(initialSize: 1 << 20) + benchmark.startMeasurement() + for i in benchmark.scaledIterations { + blackHole(fb.createVector(bytes: bytes)) + } + } + + Benchmark( + "FlatBufferBuilder Add", + configuration: kiloConfiguration + ) { benchmark in + var fb = FlatBufferBuilder(initialSize: 1024 * 1024 * 32) + benchmark.startMeasurement() + for _ in benchmark.scaledIterations { + let off = fb.create(string: "T") + let s = fb.startTable(with: 4) + fb.add(element: 3.2, def: 0, at: 2) + fb.add(element: 4.2, def: 0, at: 4) + fb.add(element: 5.2, def: 0, at: 6) + fb.add(offset: off, at: 8) + blackHole(fb.endTable(at: s)) + } + } + + Benchmark( + "FlatBufferBuilder Start table", + configuration: kiloConfiguration + ) { benchmark in + var fb = FlatBufferBuilder(initialSize: 1024 * 1024 * 32) + benchmark.startMeasurement() + for _ in benchmark.scaledIterations { + let s = fb.startTable(with: 4) + blackHole(fb.endTable(at: s)) + } + } + + Benchmark("Struct") { benchmark in + var fb = FlatBufferBuilder(initialSize: 1024 * 1024 * 32) + benchmark.startMeasurement() + for _ in benchmark.scaledIterations { + blackHole(fb.create(struct: array.first!)) + } + } + + Benchmark("Structs") { benchmark in + let rawSize = ((16 * 5) * benchmark.scaledIterations.count) / 1024 + var fb = FlatBufferBuilder(initialSize: Int32(rawSize * 1600)) + var offsets: [Offset] = [] + + benchmark.startMeasurement() + for _ in benchmark.scaledIterations { + let vector = fb.createVector( + ofStructs: array) + let start = fb.startTable(with: 1) + fb.add(offset: vector, at: 4) + offsets.append(Offset(offset: fb.endTable(at: start))) + } + + let vector = fb.createVector(ofOffsets: offsets) + let start = fb.startTable(with: 1) + fb.add(offset: vector, at: 4) + let root = Offset(offset: fb.endTable(at: start)) + blackHole(fb.finish(offset: root)) + } + + Benchmark("Vector of Offsets") { benchmark in + let rawSize = ((16 * 5) * benchmark.scaledIterations.count) / 1024 + var fb = FlatBufferBuilder(initialSize: Int32(rawSize * 1600)) + benchmark.startMeasurement() + for _ in benchmark.scaledIterations { + let offsets = [ + fb.create(string: "T"), + fb.create(string: "2"), + fb.create(string: "3"), + ] + let off = fb.createVector(ofOffsets: [ + fb.createVector(ofOffsets: offsets), + fb.createVector(ofOffsets: offsets), + ]) + let s = fb.startTable(with: 2) + fb.add(offset: off, at: 2) + blackHole(fb.endTable(at: s)) + } + } + + Benchmark("Reading Doubles") { benchmark in + let byteBuffer = ByteBuffer(data: data) + for _ in benchmark.scaledIterations { + blackHole(byteBuffer.read(def: Double.self, position: 0)) + } + } +} diff --git a/third_party/flatbuffers/benchmarks/swift/Package.swift b/third_party/flatbuffers/benchmarks/swift/Package.swift new file mode 100644 index 00000000000..da2da4fdbe7 --- /dev/null +++ b/third_party/flatbuffers/benchmarks/swift/Package.swift @@ -0,0 +1,42 @@ +// swift-tools-version:5.9 +/* + * Copyright 2020 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import PackageDescription + +let package = Package( + name: "benchmarks", + platforms: [ + .macOS(.v13) + ], + dependencies: [ + .package(path: "../.."), + .package( + url: "https://github.com/ordo-one/package-benchmark", + from: "1.27.0"), + ], + targets: [ + .executableTarget( + name: "FlatbuffersBenchmarks", + dependencies: [ + .product(name: "FlatBuffers", package: "flatbuffers"), + .product(name: "Benchmark", package: "package-benchmark"), + ], + path: "Benchmarks/FlatbuffersBenchmarks", + plugins: [ + .plugin(name: "BenchmarkPlugin", package: "package-benchmark") + ]) + ]) diff --git a/third_party/flatbuffers/benchmarks/swift/README.md b/third_party/flatbuffers/benchmarks/swift/README.md new file mode 100644 index 00000000000..4f95872d639 --- /dev/null +++ b/third_party/flatbuffers/benchmarks/swift/README.md @@ -0,0 +1,9 @@ +# Benchmarks + +To open the benchmarks in xcode use: + +`open --env BENCHMARK_DISABLE_JEMALLOC=true Package.swift` + +or running them directly within terminal using: + +`swift package benchmark` \ No newline at end of file diff --git a/third_party/flatbuffers/build_defs.bzl b/third_party/flatbuffers/build_defs.bzl index fff235448fd..51d3ce20fed 100644 --- a/third_party/flatbuffers/build_defs.bzl +++ b/third_party/flatbuffers/build_defs.bzl @@ -7,13 +7,13 @@ Rules for building C++ flatbuffers with Bazel. load("@rules_cc//cc:defs.bzl", "cc_library") -TRUE_FLATC_PATH = "@com_github_google_flatbuffers//:flatc" +TRUE_FLATC_PATH = Label("//:flatc") DEFAULT_INCLUDE_PATHS = [ "./", "$(GENDIR)", "$(BINDIR)", - "$(execpath @com_github_google_flatbuffers//:flatc).runfiles/com_github_google_flatbuffers", + "$(execpath %s).runfiles/%s" % (TRUE_FLATC_PATH, TRUE_FLATC_PATH.repo_name), ] def default_include_paths(flatc_path): @@ -21,7 +21,7 @@ def default_include_paths(flatc_path): "./", "$(GENDIR)", "$(BINDIR)", - "$(execpath %s).runfiles/com_github_google_flatbuffers" % (flatc_path), + "$(execpath %s).runfiles/%s" % (flatc_path, flatc_path.repo_name), ] DEFAULT_FLATC_ARGS = [ @@ -47,7 +47,7 @@ def flatbuffer_library_public( compatible_with = None, restricted_to = None, target_compatible_with = None, - flatc_path = "@com_github_google_flatbuffers//:flatc", + flatc_path = None, output_to_bindir = False, tools = None, extra_env = None, @@ -87,6 +87,11 @@ def flatbuffer_library_public( optionally a Fileset([reflection_name]) with all generated reflection binaries. """ + if flatc_path == None: + flatc_path = TRUE_FLATC_PATH + else: + flatc_path = native.package_relative_label(flatc_path) + reflection_include_paths = include_paths if include_paths == None: include_paths = default_include_paths(flatc_path) @@ -131,6 +136,8 @@ def flatbuffer_library_public( reflection_genrule_cmd = " ".join([ "SRCS=($(SRCS));", "for f in $${SRCS[@]:0:%s}; do" % len(srcs), + # Move the .fbs file into the current package if it is not there already + 'if [[ $$(dirname $$f) != "{0}" ]]; then s="$$f"; f="{0}/$$(basename "$$f")"; mkdir -p "{0}"; mv "$$s" "$$f"; fi;'.format(native.package_relative_label(":invalid").package), "$(location %s)" % (TRUE_FLATC_PATH), "-b --schema", " ".join(flatc_args), @@ -141,9 +148,10 @@ def flatbuffer_library_public( "done", ]) reflection_outs = [ - (out_prefix + "%s.bfbs") % (s.replace(".fbs", "").split("/")[-1]) + (out_prefix + "%s.bfbs") % (native.package_relative_label(s).name.removesuffix(".fbs")) for s in srcs ] + native.genrule( name = "%s_srcs" % reflection_name, srcs = srcs + includes, @@ -262,8 +270,8 @@ def flatbuffer_cc_library( "-parse_headers", ], deps = [ - "@com_github_google_flatbuffers//:runtime_cc", - "@com_github_google_flatbuffers//:flatbuffers", + Label("//:runtime_cc"), + Label("//:flatbuffers"), ] + deps, includes = cc_include_paths, compatible_with = compatible_with, diff --git a/third_party/flatbuffers/conan/build.py b/third_party/flatbuffers/conan/build.py index 62a37990794..104f9e0f832 100644 --- a/third_party/flatbuffers/conan/build.py +++ b/third_party/flatbuffers/conan/build.py @@ -6,45 +6,54 @@ from cpt.packager import ConanMultiPackager - def get_branch(): - try: - for line in subprocess.check_output("git branch", shell=True).decode().splitlines(): - line = line.strip() - if line.startswith("*") and " (HEAD detached" not in line: - return line.replace("*", "", 1).strip() - return "" - except Exception: - pass + try: + for line in ( + subprocess.check_output("git branch", shell=True).decode().splitlines() + ): + line = line.strip() + if line.startswith("*") and " (HEAD detached" not in line: + return line.replace("*", "", 1).strip() return "" + except Exception: + pass + return "" def get_version(): - version = get_branch() - match = re.search(r"v(\d+\.\d+\.\d+.*)", version) - if match: - return match.group(1) - return version + version = get_branch() + match = re.search(r"v(\d+\.\d+\.\d+.*)", version) + if match: + return match.group(1) + return version def get_reference(username): - return "flatbuffers/{}@google/stable".format(get_version()) + return "flatbuffers/{}@google/stable".format(get_version()) if __name__ == "__main__": - login_username = os.getenv("CONAN_LOGIN_USERNAME", "aardappel") - username = os.getenv("CONAN_USERNAME", "google") - upload = os.getenv("CONAN_UPLOAD", "https://api.bintray.com/conan/aardappel/flatbuffers") - stable_branch_pattern = os.getenv("CONAN_STABLE_BRANCH_PATTERN", r"v\d+\.\d+\.\d+.*") - test_folder = os.getenv("CPT_TEST_FOLDER", os.path.join("conan", "test_package")) - upload_only_when_stable = os.getenv("CONAN_UPLOAD_ONLY_WHEN_STABLE", True) - - builder = ConanMultiPackager(reference=get_reference(username), - username=username, - login_username=login_username, - upload=upload, - stable_branch_pattern=stable_branch_pattern, - upload_only_when_stable=upload_only_when_stable, - test_folder=test_folder) - builder.add_common_builds(pure_c=False) - builder.run() + login_username = os.getenv("CONAN_LOGIN_USERNAME", "aardappel") + username = os.getenv("CONAN_USERNAME", "google") + upload = os.getenv( + "CONAN_UPLOAD", "https://api.bintray.com/conan/aardappel/flatbuffers" + ) + stable_branch_pattern = os.getenv( + "CONAN_STABLE_BRANCH_PATTERN", r"v\d+\.\d+\.\d+.*" + ) + test_folder = os.getenv( + "CPT_TEST_FOLDER", os.path.join("conan", "test_package") + ) + upload_only_when_stable = os.getenv("CONAN_UPLOAD_ONLY_WHEN_STABLE", True) + + builder = ConanMultiPackager( + reference=get_reference(username), + username=username, + login_username=login_username, + upload=upload, + stable_branch_pattern=stable_branch_pattern, + upload_only_when_stable=upload_only_when_stable, + test_folder=test_folder, + ) + builder.add_common_builds(pure_c=False) + builder.run() diff --git a/third_party/flatbuffers/conan/test_package/conanfile.py b/third_party/flatbuffers/conan/test_package/conanfile.py index 735e31d27bf..afa78945c11 100644 --- a/third_party/flatbuffers/conan/test_package/conanfile.py +++ b/third_party/flatbuffers/conan/test_package/conanfile.py @@ -1,21 +1,21 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from conans import ConanFile, CMake import os +from conans import CMake, ConanFile class TestPackageConan(ConanFile): - settings = "os", "compiler", "build_type", "arch" - generators = "cmake" + settings = "os", "compiler", "build_type", "arch" + generators = "cmake" - def build(self): - cmake = CMake(self) - cmake.configure() - cmake.build() + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() - def test(self): - bin_path = os.path.join("bin", "test_package") - self.run(bin_path, run_environment=True) - self.run("flatc --version", run_environment=True) - self.run("flathash fnv1_16 conan", run_environment=True) + def test(self): + bin_path = os.path.join("bin", "test_package") + self.run(bin_path, run_environment=True) + self.run("flatc --version", run_environment=True) + self.run("flathash fnv1_16 conan", run_environment=True) diff --git a/third_party/flatbuffers/conanfile.py b/third_party/flatbuffers/conanfile.py index 9d622908acd..dc63d14e246 100644 --- a/third_party/flatbuffers/conanfile.py +++ b/third_party/flatbuffers/conanfile.py @@ -1,75 +1,83 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -"""Conan recipe package for Google FlatBuffers -""" +"""Conan recipe package for Google FlatBuffers""" import os import shutil -from conans import ConanFile, CMake, tools +from conans import CMake, ConanFile, tools class FlatbuffersConan(ConanFile): - name = "flatbuffers" - license = "Apache-2.0" - url = "https://github.com/google/flatbuffers" - homepage = "http://google.github.io/flatbuffers/" - author = "Wouter van Oortmerssen" - topics = ("conan", "flatbuffers", "serialization", "rpc", "json-parser") - description = "Memory Efficient Serialization Library" - settings = "os", "compiler", "build_type", "arch" - options = {"shared": [True, False], "fPIC": [True, False]} - default_options = {"shared": False, "fPIC": True} - generators = "cmake" - exports = "LICENSE" - exports_sources = ["CMake/*", "include/*", "src/*", "grpc/*", "CMakeLists.txt", "conan/CMakeLists.txt"] + name = "flatbuffers" + license = "Apache-2.0" + url = "https://github.com/google/flatbuffers" + homepage = "http://google.github.io/flatbuffers/" + author = "Wouter van Oortmerssen" + topics = ("conan", "flatbuffers", "serialization", "rpc", "json-parser") + description = "Memory Efficient Serialization Library" + settings = "os", "compiler", "build_type", "arch" + options = {"shared": [True, False], "fPIC": [True, False]} + default_options = {"shared": False, "fPIC": True} + generators = "cmake" + exports = "LICENSE" + exports_sources = [ + "CMake/*", + "include/*", + "src/*", + "grpc/*", + "CMakeLists.txt", + "conan/CMakeLists.txt", + ] - def source(self): - """Wrap the original CMake file to call conan_basic_setup - """ - shutil.move("CMakeLists.txt", "CMakeListsOriginal.txt") - shutil.move(os.path.join("conan", "CMakeLists.txt"), "CMakeLists.txt") + def source(self): + """Wrap the original CMake file to call conan_basic_setup""" + shutil.move("CMakeLists.txt", "CMakeListsOriginal.txt") + shutil.move(os.path.join("conan", "CMakeLists.txt"), "CMakeLists.txt") - def config_options(self): - """Remove fPIC option on Windows platform - """ - if self.settings.os == "Windows": - self.options.remove("fPIC") + def config_options(self): + """Remove fPIC option on Windows platform""" + if self.settings.os == "Windows": + self.options.remove("fPIC") - def configure_cmake(self): - """Create CMake instance and execute configure step - """ - cmake = CMake(self) - cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False - cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared - cmake.definitions["FLATBUFFERS_BUILD_FLATLIB"] = not self.options.shared - cmake.configure() - return cmake + def configure_cmake(self): + """Create CMake instance and execute configure step""" + cmake = CMake(self) + cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False + cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared + cmake.definitions["FLATBUFFERS_BUILD_FLATLIB"] = not self.options.shared + cmake.configure() + return cmake - def build(self): - """Configure, build and install FlatBuffers using CMake. - """ - cmake = self.configure_cmake() - cmake.build() + def build(self): + """Configure, build and install FlatBuffers using CMake.""" + cmake = self.configure_cmake() + cmake.build() - def package(self): - """Copy Flatbuffers' artifacts to package folder - """ - cmake = self.configure_cmake() - cmake.install() - self.copy(pattern="LICENSE", dst="licenses") - self.copy(pattern="FindFlatBuffers.cmake", dst=os.path.join("lib", "cmake", "flatbuffers"), src="CMake") - self.copy(pattern="flathash*", dst="bin", src="bin") - self.copy(pattern="flatc*", dst="bin", src="bin") - if self.settings.os == "Windows" and self.options.shared: - if self.settings.compiler == "Visual Studio": - shutil.move(os.path.join(self.package_folder, "lib", "%s.dll" % self.name), - os.path.join(self.package_folder, "bin", "%s.dll" % self.name)) - elif self.settings.compiler == "gcc": - shutil.move(os.path.join(self.package_folder, "lib", "lib%s.dll" % self.name), - os.path.join(self.package_folder, "bin", "lib%s.dll" % self.name)) + def package(self): + """Copy Flatbuffers' artifacts to package folder""" + cmake = self.configure_cmake() + cmake.install() + self.copy(pattern="LICENSE", dst="licenses") + self.copy( + pattern="FindFlatBuffers.cmake", + dst=os.path.join("lib", "cmake", "flatbuffers"), + src="CMake", + ) + self.copy(pattern="flathash*", dst="bin", src="bin") + self.copy(pattern="flatc*", dst="bin", src="bin") + if self.settings.os == "Windows" and self.options.shared: + if self.settings.compiler == "Visual Studio": + shutil.move( + os.path.join(self.package_folder, "lib", "%s.dll" % self.name), + os.path.join(self.package_folder, "bin", "%s.dll" % self.name), + ) + elif self.settings.compiler == "gcc": + shutil.move( + os.path.join(self.package_folder, "lib", "lib%s.dll" % self.name), + os.path.join(self.package_folder, "bin", "lib%s.dll" % self.name), + ) - def package_info(self): - """Collect built libraries names and solve flatc path. - """ - self.cpp_info.libs = tools.collect_libs(self) - self.user_info.flatc = os.path.join(self.package_folder, "bin", "flatc") + def package_info(self): + """Collect built libraries names and solve flatc path.""" + self.cpp_info.libs = tools.collect_libs(self) + self.user_info.flatc = os.path.join(self.package_folder, "bin", "flatc") diff --git a/third_party/flatbuffers/dart/CHANGELOG.md b/third_party/flatbuffers/dart/CHANGELOG.md new file mode 100644 index 00000000000..9562920965c --- /dev/null +++ b/third_party/flatbuffers/dart/CHANGELOG.md @@ -0,0 +1,46 @@ +# Changelog + +## 23.5.26 + +- omit type annotationes for local variables (#7067, #7069, #7070) +- remove BSD 3-clause license (#7073) +- correctly parse lists of enums (#7157) +- align naming conventions for generated code (#7187) +- add `putBool` to fix errors when serializing structs with booleans (#7359) +- fix handling of +/-inf defaults in codegen (#7588) +- fix import issues in generated code (#7621) +- Fix incorrect storage of floats as ints in some cases (#7703) +- add final modifiers to the library implementation (#7943) + +## 2.0.5 + +- switch to null safety (#6696) +- add Object APIs (pack/unpack) (#6682, #6723, #6846) +- add custom builder buffer allocator support (#6711) +- add `Builder.size()` - finished buffer size (#6403) +- make `writeString()` argument non-nullable (#6737) +- make tables fixed size (expect the number of fields when creating) (#6735) +- make table deduplication optional (param `deduplicateTables`) (#6734) +- change `Builder.reset()` to reuse an existing buffer (#6661) +- change table building to assert() instead of exceptions (#6754) +- optimize `writeString()` for ASCII (param `asciiOptimization`) (#6736) +- change `StringReader` to make ASCII optimization optional (param `asciiOptimization`) (#6758) +- change `[byte]` and `[ubyte]` representation to `dart:typed_data` `Int8List` and `Uint8List` (#6839) +- rename `lowFinish()` to `buffer` getter (#6712) +- fix `Builder._writeString()` - always write trailing zero byte (#6390) +- fix `Builder.reset()` - clear vTables (#6386) +- make sure added padding is zeroed, same as in C++ (#6716) +- many performance improvements (#6755) + +## 1.9.2 + +- Ensure `_writeString` adds enough padding to null terminate strings. + +## 1.9.1 + +- Changed constant identifiers to be compatible with Dart 2.x +- No longer supports Dart 1.x + +## 1.9.0 + +- Initial release, supports Dart 1.x and many dev versions of Dart 2.x diff --git a/third_party/flatbuffers/dart/LICENSE b/third_party/flatbuffers/dart/LICENSE new file mode 100644 index 00000000000..c02ca2f7a13 --- /dev/null +++ b/third_party/flatbuffers/dart/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2014 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/third_party/flatbuffers/dart/README.md b/third_party/flatbuffers/dart/README.md new file mode 100644 index 00000000000..a07bc258ff6 --- /dev/null +++ b/third_party/flatbuffers/dart/README.md @@ -0,0 +1,15 @@ +# FlatBuffers for Dart + +This package is used to read and write [FlatBuffers](https://google.github.io/flatbuffers/). + +Most consumers will want to use the [`flatc` - FlatBuffer compiler](https://github.com/google/flatbuffers) binary for your platform. +You can download the flatc version matching your dart package version from [GitHub releases](https://github.com/google/flatbuffers/releases). + +The FlatBuffer compiler `flatc` reads a FlatBuffers IDL schema and generates Dart code. +The generated classes can be used to read or write binary data/files that are interoperable with +other languages and platforms supported by FlatBuffers, as illustrated in the `example.dart` in the +examples folder. + +For more details and documentation, head over to the official site and read the +[Tutorial](https://google.github.io/flatbuffers/flatbuffers_guide_tutorial.html) and how to +[use FlatBuffers in Dart](https://google.github.io/flatbuffers/flatbuffers_guide_use_dart.html). diff --git a/third_party/flatbuffers/dart/analysis_options.yaml b/third_party/flatbuffers/dart/analysis_options.yaml new file mode 100644 index 00000000000..572dd239d09 --- /dev/null +++ b/third_party/flatbuffers/dart/analysis_options.yaml @@ -0,0 +1 @@ +include: package:lints/recommended.yaml diff --git a/third_party/flatbuffers/dart/example/example.dart b/third_party/flatbuffers/dart/example/example.dart new file mode 100644 index 00000000000..329981357f3 --- /dev/null +++ b/third_party/flatbuffers/dart/example/example.dart @@ -0,0 +1,159 @@ +/* + * Copyright 2018 Dan Field. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'package:flat_buffers/flat_buffers.dart' as fb; + +import './monster_my_game.sample_generated.dart' as my_game; + +// Example how to use FlatBuffers to create and read binary buffers. + +void main() { + builderTest(); + objectBuilderTest(); +} + +void builderTest() { + final builder = fb.Builder(initialSize: 1024); + final int? weaponOneName = builder.writeString("Sword"); + final int weaponOneDamage = 3; + + final int? weaponTwoName = builder.writeString("Axe"); + final int weaponTwoDamage = 5; + + final swordBuilder = my_game.WeaponBuilder(builder) + ..begin() + ..addNameOffset(weaponOneName) + ..addDamage(weaponOneDamage); + final int sword = swordBuilder.finish(); + + final axeBuilder = my_game.WeaponBuilder(builder) + ..begin() + ..addNameOffset(weaponTwoName) + ..addDamage(weaponTwoDamage); + final int axe = axeBuilder.finish(); + + // Serialize a name for our monster, called "Orc". + final int? name = builder.writeString('Orc'); + + // Create a list representing the inventory of the Orc. Each number + // could correspond to an item that can be claimed after he is slain. + final List treasure = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + final inventory = builder.writeListUint8(treasure); + final weapons = builder.writeList([sword, axe]); + + // Struct builders are very easy to reuse. + final vec3Builder = my_game.Vec3Builder(builder); + + vec3Builder.finish(4.0, 5.0, 6.0); + vec3Builder.finish(1.0, 2.0, 3.0); + // Set his hit points to 300 and his mana to 150. + final int hp = 300; + final int mana = 150; + + final monster = my_game.MonsterBuilder(builder) + ..begin() + ..addNameOffset(name) + ..addInventoryOffset(inventory) + ..addWeaponsOffset(weapons) + ..addEquippedType(my_game.EquipmentTypeId.Weapon) + ..addEquippedOffset(axe) + ..addHp(hp) + ..addMana(mana) + ..addPos(vec3Builder.finish(1.0, 2.0, 3.0)) + ..addColor(my_game.Color.Red); + + final int monsteroff = monster.finish(); + builder.finish(monsteroff); + if (verify(builder.buffer)) { + print( + "The FlatBuffer was successfully created with a builder and verified!", + ); + } +} + +void objectBuilderTest() { + // Create the builder here so we can use it for both weapons and equipped + // the actual data will only be written to the buffer once. + var axe = my_game.WeaponObjectBuilder(name: 'Axe', damage: 5); + + var monsterBuilder = my_game.MonsterObjectBuilder( + pos: my_game.Vec3ObjectBuilder(x: 1.0, y: 2.0, z: 3.0), + mana: 150, + hp: 300, + name: 'Orc', + inventory: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + color: my_game.Color.Red, + weapons: [ + my_game.WeaponObjectBuilder(name: 'Sword', damage: 3), + axe, + ], + equippedType: my_game.EquipmentTypeId.Weapon, + equipped: axe, + ); + + var buffer = monsterBuilder.toBytes(); + + // We now have a FlatBuffer we can store on disk or send over a network. + + // ** file/network code goes here :) ** + + // Instead, we're going to access it right away (as if we just received it). + if (verify(buffer)) { + print( + "The FlatBuffer was successfully created with an object builder and verified!", + ); + } +} + +bool verify(List buffer) { + // Get access to the root: + var monster = my_game.Monster(buffer); + + // Get and test some scalar types from the FlatBuffer. + assert(monster.hp == 80); + assert(monster.mana == 150); // default + assert(monster.name == "MyMonster"); + + // Get and test a field of the FlatBuffer's `struct`. + var pos = monster.pos!; + assert(pos.z == 3.0); + + // Get a test an element from the `inventory` FlatBuffer's `vector`. + var inv = monster.inventory!; + assert(inv.length == 10); + assert(inv[9] == 9); + + // Get and test the `weapons` FlatBuffers's `vector`. + var expectedWeaponNames = ["Sword", "Axe"]; + var expectedWeaponDamages = [3, 5]; + var weps = monster.weapons!; + for (int i = 0; i < weps.length; i++) { + assert(weps[i].name == expectedWeaponNames[i]); + assert(weps[i].damage == expectedWeaponDamages[i]); + } + + // Get and test the `Equipment` union (`equipped` field). + assert(monster.equippedType!.value == my_game.EquipmentTypeId.Weapon.value); + assert(monster.equippedType == my_game.EquipmentTypeId.Weapon); + + assert(monster.equipped is my_game.Weapon); + var equipped = monster.equipped as my_game.Weapon; + assert(equipped.name == "Axe"); + assert(equipped.damage == 5); + + print(monster); + return true; +} diff --git a/third_party/flatbuffers/dart/example/monster_my_game.sample_generated.dart b/third_party/flatbuffers/dart/example/monster_my_game.sample_generated.dart new file mode 100644 index 00000000000..612de336b03 --- /dev/null +++ b/third_party/flatbuffers/dart/example/monster_my_game.sample_generated.dart @@ -0,0 +1,441 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable + +library my_game.sample; + +import 'dart:typed_data' show Uint8List; + +import 'package:flat_buffers/flat_buffers.dart' as fb; + +class Color { + final int value; + const Color._(this.value); + + factory Color.fromValue(int value) { + final result = values[value]; + if (result == null) { + throw StateError('Invalid value $value for bit flag enum Color'); + } + return result; + } + + static Color? _createOrNull(int? value) => + value == null ? null : Color.fromValue(value); + + static const int minValue = 0; + static const int maxValue = 2; + static bool containsValue(int value) => values.containsKey(value); + + static const Color Red = Color._(0); + static const Color Green = Color._(1); + static const Color Blue = Color._(2); + static const Map values = {0: Red, 1: Green, 2: Blue}; + + static const fb.Reader reader = _ColorReader(); + + @override + String toString() { + return 'Color{value: $value}'; + } +} + +class _ColorReader extends fb.Reader { + const _ColorReader(); + + @override + int get size => 1; + + @override + Color read(fb.BufferContext bc, int offset) => + Color.fromValue(const fb.Int8Reader().read(bc, offset)); +} + +class EquipmentTypeId { + final int value; + const EquipmentTypeId._(this.value); + + factory EquipmentTypeId.fromValue(int value) { + final result = values[value]; + if (result == null) { + throw StateError( + 'Invalid value $value for bit flag enum EquipmentTypeId', + ); + } + return result; + } + + static EquipmentTypeId? _createOrNull(int? value) => + value == null ? null : EquipmentTypeId.fromValue(value); + + static const int minValue = 0; + static const int maxValue = 1; + static bool containsValue(int value) => values.containsKey(value); + + static const EquipmentTypeId NONE = EquipmentTypeId._(0); + static const EquipmentTypeId Weapon = EquipmentTypeId._(1); + static const Map values = {0: NONE, 1: Weapon}; + + static const fb.Reader reader = _EquipmentTypeIdReader(); + + @override + String toString() { + return 'EquipmentTypeId{value: $value}'; + } +} + +class _EquipmentTypeIdReader extends fb.Reader { + const _EquipmentTypeIdReader(); + + @override + int get size => 1; + + @override + EquipmentTypeId read(fb.BufferContext bc, int offset) => + EquipmentTypeId.fromValue(const fb.Uint8Reader().read(bc, offset)); +} + +class Vec3 { + Vec3._(this._bc, this._bcOffset); + + static const fb.Reader reader = _Vec3Reader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + double get x => const fb.Float32Reader().read(_bc, _bcOffset + 0); + double get y => const fb.Float32Reader().read(_bc, _bcOffset + 4); + double get z => const fb.Float32Reader().read(_bc, _bcOffset + 8); + + @override + String toString() { + return 'Vec3{x: $x, y: $y, z: $z}'; + } +} + +class _Vec3Reader extends fb.StructReader { + const _Vec3Reader(); + + @override + int get size => 12; + + @override + Vec3 createObject(fb.BufferContext bc, int offset) => Vec3._(bc, offset); +} + +class Vec3Builder { + Vec3Builder(this.fbBuilder); + + final fb.Builder fbBuilder; + + int finish(double x, double y, double z) { + fbBuilder.putFloat32(z); + fbBuilder.putFloat32(y); + fbBuilder.putFloat32(x); + return fbBuilder.offset; + } +} + +class Vec3ObjectBuilder extends fb.ObjectBuilder { + final double _x; + final double _y; + final double _z; + + Vec3ObjectBuilder({required double x, required double y, required double z}) + : _x = x, + _y = y, + _z = z; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + fbBuilder.putFloat32(_z); + fbBuilder.putFloat32(_y); + fbBuilder.putFloat32(_x); + return fbBuilder.offset; + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} + +class Monster { + Monster._(this._bc, this._bcOffset); + factory Monster(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _MonsterReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + Vec3? get pos => Vec3.reader.vTableGetNullable(_bc, _bcOffset, 4); + int get mana => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, 150); + int get hp => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 8, 100); + String? get name => + const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 10); + List? get inventory => + const fb.Uint8ListReader().vTableGetNullable(_bc, _bcOffset, 14); + Color get color => + Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 16, 2)); + List? get weapons => const fb.ListReader( + Weapon.reader, + ).vTableGetNullable(_bc, _bcOffset, 18); + EquipmentTypeId? get equippedType => EquipmentTypeId._createOrNull( + const fb.Uint8Reader().vTableGetNullable(_bc, _bcOffset, 20), + ); + dynamic get equipped { + switch (equippedType?.value) { + case 1: + return Weapon.reader.vTableGetNullable(_bc, _bcOffset, 22); + default: + return null; + } + } + + List? get path => const fb.ListReader( + Vec3.reader, + ).vTableGetNullable(_bc, _bcOffset, 24); + + @override + String toString() { + return 'Monster{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, weapons: $weapons, equippedType: $equippedType, equipped: $equipped, path: $path}'; + } +} + +class _MonsterReader extends fb.TableReader { + const _MonsterReader(); + + @override + Monster createObject(fb.BufferContext bc, int offset) => + Monster._(bc, offset); +} + +class MonsterBuilder { + MonsterBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(10); + } + + int addPos(int offset) { + fbBuilder.addStruct(0, offset); + return fbBuilder.offset; + } + + int addMana(int? mana) { + fbBuilder.addInt16(1, mana); + return fbBuilder.offset; + } + + int addHp(int? hp) { + fbBuilder.addInt16(2, hp); + return fbBuilder.offset; + } + + int addNameOffset(int? offset) { + fbBuilder.addOffset(3, offset); + return fbBuilder.offset; + } + + int addInventoryOffset(int? offset) { + fbBuilder.addOffset(5, offset); + return fbBuilder.offset; + } + + int addColor(Color? color) { + fbBuilder.addInt8(6, color?.value); + return fbBuilder.offset; + } + + int addWeaponsOffset(int? offset) { + fbBuilder.addOffset(7, offset); + return fbBuilder.offset; + } + + int addEquippedType(EquipmentTypeId? equippedType) { + fbBuilder.addUint8(8, equippedType?.value); + return fbBuilder.offset; + } + + int addEquippedOffset(int? offset) { + fbBuilder.addOffset(9, offset); + return fbBuilder.offset; + } + + int addPathOffset(int? offset) { + fbBuilder.addOffset(10, offset); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class MonsterObjectBuilder extends fb.ObjectBuilder { + final Vec3ObjectBuilder? _pos; + final int? _mana; + final int? _hp; + final String? _name; + final List? _inventory; + final Color? _color; + final List? _weapons; + final EquipmentTypeId? _equippedType; + final dynamic _equipped; + final List? _path; + + MonsterObjectBuilder({ + Vec3ObjectBuilder? pos, + int? mana, + int? hp, + String? name, + List? inventory, + Color? color, + List? weapons, + EquipmentTypeId? equippedType, + dynamic equipped, + List? path, + }) : _pos = pos, + _mana = mana, + _hp = hp, + _name = name, + _inventory = inventory, + _color = color, + _weapons = weapons, + _equippedType = equippedType, + _equipped = equipped, + _path = path; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? nameOffset = _name == null + ? null + : fbBuilder.writeString(_name!); + final int? inventoryOffset = _inventory == null + ? null + : fbBuilder.writeListUint8(_inventory!); + final int? weaponsOffset = _weapons == null + ? null + : fbBuilder.writeList( + _weapons!.map((b) => b.getOrCreateOffset(fbBuilder)).toList(), + ); + final int? equippedOffset = _equipped?.getOrCreateOffset(fbBuilder); + final int? pathOffset = _path == null + ? null + : fbBuilder.writeListOfStructs(_path!); + fbBuilder.startTable(10); + if (_pos != null) { + fbBuilder.addStruct(0, _pos!.finish(fbBuilder)); + } + fbBuilder.addInt16(1, _mana); + fbBuilder.addInt16(2, _hp); + fbBuilder.addOffset(3, nameOffset); + fbBuilder.addOffset(5, inventoryOffset); + fbBuilder.addInt8(6, _color?.value); + fbBuilder.addOffset(7, weaponsOffset); + fbBuilder.addUint8(8, _equippedType?.value); + fbBuilder.addOffset(9, equippedOffset); + fbBuilder.addOffset(10, pathOffset); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} + +class Weapon { + Weapon._(this._bc, this._bcOffset); + factory Weapon(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _WeaponReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + String? get name => + const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 4); + int get damage => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, 0); + + @override + String toString() { + return 'Weapon{name: $name, damage: $damage}'; + } +} + +class _WeaponReader extends fb.TableReader { + const _WeaponReader(); + + @override + Weapon createObject(fb.BufferContext bc, int offset) => Weapon._(bc, offset); +} + +class WeaponBuilder { + WeaponBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(2); + } + + int addNameOffset(int? offset) { + fbBuilder.addOffset(0, offset); + return fbBuilder.offset; + } + + int addDamage(int? damage) { + fbBuilder.addInt16(1, damage); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class WeaponObjectBuilder extends fb.ObjectBuilder { + final String? _name; + final int? _damage; + + WeaponObjectBuilder({String? name, int? damage}) + : _name = name, + _damage = damage; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? nameOffset = _name == null + ? null + : fbBuilder.writeString(_name!); + fbBuilder.startTable(2); + fbBuilder.addOffset(0, nameOffset); + fbBuilder.addInt16(1, _damage); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} diff --git a/third_party/flatbuffers/dart/lib/flat_buffers.dart b/third_party/flatbuffers/dart/lib/flat_buffers.dart new file mode 100644 index 00000000000..7590bdba690 --- /dev/null +++ b/third_party/flatbuffers/dart/lib/flat_buffers.dart @@ -0,0 +1,1517 @@ +import 'dart:collection'; +import 'dart:convert'; +import 'dart:math'; +import 'dart:typed_data'; + +const int _sizeofUint8 = 1; +const int _sizeofUint16 = 2; +const int _sizeofUint32 = 4; +const int _sizeofUint64 = 8; +const int _sizeofInt8 = 1; +const int _sizeofInt16 = 2; +const int _sizeofInt32 = 4; +const int _sizeofInt64 = 8; +const int _sizeofFloat32 = 4; +const int _sizeofFloat64 = 8; + +/// Callback used to invoke a struct builder's finish method. +/// +/// This callback is used by other struct's `finish` methods to write the nested +/// struct's fields inline. +typedef StructBuilder = void Function(); + +/// Buffer with data and some context about it. +class BufferContext { + final ByteData _buffer; + + ByteData get buffer => _buffer; + + /// Create from a FlatBuffer represented by a list of bytes (uint8). + factory BufferContext.fromBytes(List byteList) => BufferContext( + byteList is Uint8List + ? byteList.buffer.asByteData(byteList.offsetInBytes) + : ByteData.view(Uint8List.fromList(byteList).buffer), + ); + + /// Create from a FlatBuffer represented by ByteData. + BufferContext(this._buffer); + + @pragma('vm:prefer-inline') + int derefObject(int offset) => offset + _getUint32(offset); + + @pragma('vm:prefer-inline') + Uint8List _asUint8List(int offset, int length) => + _buffer.buffer.asUint8List(_buffer.offsetInBytes + offset, length); + + @pragma('vm:prefer-inline') + double _getFloat64(int offset) => _buffer.getFloat64(offset, Endian.little); + + @pragma('vm:prefer-inline') + double _getFloat32(int offset) => _buffer.getFloat32(offset, Endian.little); + + @pragma('vm:prefer-inline') + int _getInt64(int offset) => _buffer.getInt64(offset, Endian.little); + + @pragma('vm:prefer-inline') + int _getInt32(int offset) => _buffer.getInt32(offset, Endian.little); + + @pragma('vm:prefer-inline') + int _getInt16(int offset) => _buffer.getInt16(offset, Endian.little); + + @pragma('vm:prefer-inline') + int _getInt8(int offset) => _buffer.getInt8(offset); + + @pragma('vm:prefer-inline') + int _getUint64(int offset) => _buffer.getUint64(offset, Endian.little); + + @pragma('vm:prefer-inline') + int _getUint32(int offset) => _buffer.getUint32(offset, Endian.little); + + @pragma('vm:prefer-inline') + int _getUint16(int offset) => _buffer.getUint16(offset, Endian.little); + + @pragma('vm:prefer-inline') + int _getUint8(int offset) => _buffer.getUint8(offset); +} + +/// Interface implemented by the "object-api" classes (ending with "T"). +abstract class Packable { + /// Serialize the object using the given builder, returning the offset. + int pack(Builder fbBuilder); +} + +/// Class implemented by typed builders generated by flatc. +abstract class ObjectBuilder { + int? _firstOffset; + + /// Can be used to write the data represented by this builder to the [Builder] + /// and reuse the offset created in multiple tables. + /// + /// Note that this method assumes you call it using the same [Builder] instance + /// every time. The returned offset is only good for the [Builder] used in the + /// first call to this method. + int getOrCreateOffset(Builder fbBuilder) { + _firstOffset ??= finish(fbBuilder); + return _firstOffset!; + } + + /// Writes the data in this helper to the [Builder]. + int finish(Builder fbBuilder); + + /// Convenience method that will create a new [Builder], [finish]es the data, + /// and returns the buffer as a [Uint8List] of bytes. + Uint8List toBytes(); +} + +/// Class that helps building flat buffers. +class Builder { + bool _finished = false; + + final int initialSize; + + /// The list of existing VTable(s). + final List _vTables; + + final bool deduplicateTables; + + ByteData _buf; + + final Allocator _allocator; + + /// The maximum alignment that has been seen so far. If [_buf] has to be + /// reallocated in the future (to insert room at its start for more bytes) the + /// reallocation will need to be a multiple of this many bytes. + int _maxAlign = 1; + + /// The number of bytes that have been written to the buffer so far. The + /// most recently written byte is this many bytes from the end of [_buf]. + int _tail = 0; + + /// The location of the end of the current table, measured in bytes from the + /// end of [_buf]. + int _currentTableEndTail = 0; + + _VTable? _currentVTable; + + /// Map containing all strings that have been written so far. This allows us + /// to avoid duplicating strings. + /// + /// Allocated only if `internStrings` is set to true on the constructor. + Map? _strings; + + /// Creates a new FlatBuffers Builder. + /// + /// `initialSize` is the initial array size in bytes. The [Builder] will + /// automatically grow the array if/as needed. `internStrings`, if set to + /// true, will cause [writeString] to pool strings in the buffer so that + /// identical strings will always use the same offset in tables. + Builder({ + this.initialSize = 1024, + bool internStrings = false, + Allocator allocator = const DefaultAllocator(), + this.deduplicateTables = true, + }) : _allocator = allocator, + _buf = allocator.allocate(initialSize), + _vTables = deduplicateTables ? [] : const [] { + if (internStrings) { + _strings = {}; + } + } + + /// Calculate the finished buffer size (aligned). + @pragma('vm:prefer-inline') + int size() => _tail + ((-_tail) & (_maxAlign - 1)); + + /// Add the [field] with the given boolean [value]. The field is not added if + /// the [value] is equal to [def]. Booleans are stored as 8-bit fields with + /// `0` for `false` and `1` for `true`. + void addBool(int field, bool? value, [bool? def]) { + assert(_inVTable); + if (value != null && value != def) { + _prepare(_sizeofUint8, 1); + _trackField(field); + _buf.setInt8(_buf.lengthInBytes - _tail, value ? 1 : 0); + } + } + + /// Add the [field] with the given 32-bit signed integer [value]. The field is + /// not added if the [value] is equal to [def]. + void addInt32(int field, int? value, [int? def]) { + assert(_inVTable); + if (value != null && value != def) { + _prepare(_sizeofInt32, 1); + _trackField(field); + _setInt32AtTail(_tail, value); + } + } + + /// Add the [field] with the given 32-bit signed integer [value]. The field is + /// not added if the [value] is equal to [def]. + void addInt16(int field, int? value, [int? def]) { + assert(_inVTable); + if (value != null && value != def) { + _prepare(_sizeofInt16, 1); + _trackField(field); + _setInt16AtTail(_tail, value); + } + } + + /// Add the [field] with the given 8-bit signed integer [value]. The field is + /// not added if the [value] is equal to [def]. + void addInt8(int field, int? value, [int? def]) { + assert(_inVTable); + if (value != null && value != def) { + _prepare(_sizeofInt8, 1); + _trackField(field); + _setInt8AtTail(_tail, value); + } + } + + void addStruct(int field, int offset) { + assert(_inVTable); + _trackField(field); + _currentVTable!.addField(field, offset); + } + + /// Add the [field] referencing an object with the given [offset]. + void addOffset(int field, int? offset) { + assert(_inVTable); + if (offset != null) { + _prepare(_sizeofUint32, 1); + _trackField(field); + _setUint32AtTail(_tail, _tail - offset); + } + } + + /// Add the [field] with the given 32-bit unsigned integer [value]. The field + /// is not added if the [value] is equal to [def]. + void addUint32(int field, int? value, [int? def]) { + assert(_inVTable); + if (value != null && value != def) { + _prepare(_sizeofUint32, 1); + _trackField(field); + _setUint32AtTail(_tail, value); + } + } + + /// Add the [field] with the given 32-bit unsigned integer [value]. The field + /// is not added if the [value] is equal to [def]. + void addUint16(int field, int? value, [int? def]) { + assert(_inVTable); + if (value != null && value != def) { + _prepare(_sizeofUint16, 1); + _trackField(field); + _setUint16AtTail(_tail, value); + } + } + + /// Add the [field] with the given 8-bit unsigned integer [value]. The field + /// is not added if the [value] is equal to [def]. + void addUint8(int field, int? value, [int? def]) { + assert(_inVTable); + if (value != null && value != def) { + _prepare(_sizeofUint8, 1); + _trackField(field); + _setUint8AtTail(_tail, value); + } + } + + /// Add the [field] with the given 32-bit float [value]. The field + /// is not added if the [value] is equal to [def]. + void addFloat32(int field, double? value, [double? def]) { + assert(_inVTable); + if (value != null && value != def) { + _prepare(_sizeofFloat32, 1); + _trackField(field); + _setFloat32AtTail(_tail, value); + } + } + + /// Add the [field] with the given 64-bit double [value]. The field + /// is not added if the [value] is equal to [def]. + void addFloat64(int field, double? value, [double? def]) { + assert(_inVTable); + if (value != null && value != def) { + _prepare(_sizeofFloat64, 1); + _trackField(field); + _setFloat64AtTail(_tail, value); + } + } + + /// Add the [field] with the given 64-bit unsigned integer [value]. The field + /// is not added if the [value] is equal to [def]. + void addUint64(int field, int? value, [double? def]) { + assert(_inVTable); + if (value != null && value != def) { + _prepare(_sizeofUint64, 1); + _trackField(field); + _setUint64AtTail(_tail, value); + } + } + + /// Add the [field] with the given 64-bit unsigned integer [value]. The field + /// is not added if the [value] is equal to [def]. + void addInt64(int field, int? value, [double? def]) { + assert(_inVTable); + if (value != null && value != def) { + _prepare(_sizeofInt64, 1); + _trackField(field); + _setInt64AtTail(_tail, value); + } + } + + /// End the current table and return its offset. + int endTable() { + assert(_inVTable); + // Prepare for writing the VTable. + _prepare(_sizeofInt32, 1); + final tableTail = _tail; + // Prepare the size of the current table. + final currentVTable = _currentVTable!; + currentVTable.tableSize = tableTail - _currentTableEndTail; + // Prepare the VTable to use for the current table. + int? vTableTail; + { + currentVTable.computeFieldOffsets(tableTail); + + // Try to find an existing compatible VTable. + if (deduplicateTables) { + // Search backward - more likely to have recently used one + for (var i = _vTables.length - 1; i >= 0; i--) { + final vt2Offset = _vTables[i]; + final vt2Start = _buf.lengthInBytes - vt2Offset; + final vt2Size = _buf.getUint16(vt2Start, Endian.little); + + if (currentVTable._vTableSize == vt2Size && + currentVTable._offsetsMatch(vt2Start, _buf)) { + vTableTail = vt2Offset; + break; + } + } + } + + // Write a new VTable. + if (vTableTail == null) { + _prepare(_sizeofUint16, _currentVTable!.numOfUint16); + vTableTail = _tail; + currentVTable.tail = vTableTail; + currentVTable.output(_buf, _buf.lengthInBytes - _tail); + if (deduplicateTables) _vTables.add(currentVTable.tail); + } + } + // Set the VTable offset. + _setInt32AtTail(tableTail, vTableTail - tableTail); + // Done with this table. + _currentVTable = null; + return tableTail; + } + + /// Returns the finished buffer. You must call [finish] before accessing this. + @pragma('vm:prefer-inline') + Uint8List get buffer { + assert(_finished); + final finishedSize = size(); + return _buf.buffer.asUint8List( + _buf.lengthInBytes - finishedSize, + finishedSize, + ); + } + + /// Finish off the creation of the buffer. The given [offset] is used as the + /// root object offset, and usually references directly or indirectly every + /// written object. If [fileIdentifier] is specified (and not `null`), it is + /// interpreted as a 4-byte Latin-1 encoded string that should be placed at + /// bytes 4-7 of the file. + void finish(int offset, [String? fileIdentifier]) { + final sizeBeforePadding = size(); + final requiredBytes = _sizeofUint32 * (fileIdentifier == null ? 1 : 2); + _prepare(max(requiredBytes, _maxAlign), 1); + final finishedSize = size(); + _setUint32AtTail(finishedSize, finishedSize - offset); + if (fileIdentifier != null) { + for (var i = 0; i < 4; i++) { + _setUint8AtTail( + finishedSize - _sizeofUint32 - i, + fileIdentifier.codeUnitAt(i), + ); + } + } + + // zero out the added padding + for ( + var i = sizeBeforePadding + 1; + i <= finishedSize - requiredBytes; + i++ + ) { + _setUint8AtTail(i, 0); + } + _finished = true; + } + + /// Writes a Float64 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putFloat64(double value) { + _prepare(_sizeofFloat64, 1); + _setFloat64AtTail(_tail, value); + } + + /// Writes a Float32 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putFloat32(double value) { + _prepare(_sizeofFloat32, 1); + _setFloat32AtTail(_tail, value); + } + + /// Writes a bool to the tail of the buffer after preparing space for it. + /// Bools are represented as a Uint8, with the value set to '1' for true, and '0' for false + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putBool(bool value) { + _prepare(_sizeofUint8, 1); + _buf.setInt8(_buf.lengthInBytes - _tail, value ? 1 : 0); + } + + /// Writes a Int64 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putInt64(int value) { + _prepare(_sizeofInt64, 1); + _setInt64AtTail(_tail, value); + } + + /// Writes a Uint32 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putInt32(int value) { + _prepare(_sizeofInt32, 1); + _setInt32AtTail(_tail, value); + } + + /// Writes a Uint16 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putInt16(int value) { + _prepare(_sizeofInt16, 1); + _setInt16AtTail(_tail, value); + } + + /// Writes a Uint8 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putInt8(int value) { + _prepare(_sizeofInt8, 1); + _buf.setInt8(_buf.lengthInBytes - _tail, value); + } + + /// Writes a Uint64 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putUint64(int value) { + _prepare(_sizeofUint64, 1); + _setUint64AtTail(_tail, value); + } + + /// Writes a Uint32 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putUint32(int value) { + _prepare(_sizeofUint32, 1); + _setUint32AtTail(_tail, value); + } + + /// Writes a Uint16 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putUint16(int value) { + _prepare(_sizeofUint16, 1); + _setUint16AtTail(_tail, value); + } + + /// Writes a Uint8 to the tail of the buffer after preparing space for it. + /// + /// Updates the [offset] pointer. This method is intended for use when writing structs to the buffer. + void putUint8(int value) { + _prepare(_sizeofUint8, 1); + _buf.setUint8(_buf.lengthInBytes - _tail, value); + } + + /// Reset the builder and make it ready for filling a new buffer. + void reset() { + _finished = false; + _maxAlign = 1; + _tail = 0; + _currentVTable = null; + if (deduplicateTables) _vTables.clear(); + if (_strings != null) { + _strings = {}; + } + } + + /// Start a new table. Must be finished with [endTable] invocation. + void startTable(int numFields) { + assert(!_inVTable); // Inline tables are not supported. + _currentVTable = _VTable(numFields); + _currentTableEndTail = _tail; + } + + /// Finish a Struct vector. Most callers should preferto use [writeListOfStructs]. + /// + /// Most callers should prefer [writeListOfStructs]. + int endStructVector(int count) { + putUint32(count); + return _tail; + } + + /// Writes a list of Structs to the buffer, returning the offset + int writeListOfStructs(List structBuilders) { + assert(!_inVTable); + for (var i = structBuilders.length - 1; i >= 0; i--) { + structBuilders[i].finish(this); + } + return endStructVector(structBuilders.length); + } + + /// Write the given list of [values]. + int writeList(List values) { + assert(!_inVTable); + _prepare(_sizeofUint32, 1 + values.length); + final result = _tail; + var tail = _tail; + _setUint32AtTail(tail, values.length); + tail -= _sizeofUint32; + for (final value in values) { + _setUint32AtTail(tail, tail - value); + tail -= _sizeofUint32; + } + return result; + } + + /// Write the given list of 64-bit float [values]. + int writeListFloat64(List values) { + assert(!_inVTable); + _prepare(_sizeofFloat64, values.length, additionalBytes: _sizeofUint32); + final result = _tail; + var tail = _tail; + _setUint32AtTail(tail, values.length); + tail -= _sizeofUint32; + for (final value in values) { + _setFloat64AtTail(tail, value); + tail -= _sizeofFloat64; + } + return result; + } + + /// Write the given list of 32-bit float [values]. + int writeListFloat32(List values) { + assert(!_inVTable); + _prepare(_sizeofFloat32, 1 + values.length); + final result = _tail; + var tail = _tail; + _setUint32AtTail(tail, values.length); + tail -= _sizeofUint32; + for (final value in values) { + _setFloat32AtTail(tail, value); + tail -= _sizeofFloat32; + } + return result; + } + + /// Write the given list of signed 64-bit integer [values]. + int writeListInt64(List values) { + assert(!_inVTable); + _prepare(_sizeofInt64, values.length, additionalBytes: _sizeofUint32); + final result = _tail; + var tail = _tail; + _setUint32AtTail(tail, values.length); + tail -= _sizeofUint32; + for (final value in values) { + _setInt64AtTail(tail, value); + tail -= _sizeofInt64; + } + return result; + } + + /// Write the given list of signed 64-bit integer [values]. + int writeListUint64(List values) { + assert(!_inVTable); + _prepare(_sizeofUint64, values.length, additionalBytes: _sizeofUint32); + final result = _tail; + var tail = _tail; + _setUint32AtTail(tail, values.length); + tail -= _sizeofUint32; + for (final value in values) { + _setUint64AtTail(tail, value); + tail -= _sizeofUint64; + } + return result; + } + + /// Write the given list of signed 32-bit integer [values]. + int writeListInt32(List values) { + assert(!_inVTable); + _prepare(_sizeofUint32, 1 + values.length); + final result = _tail; + var tail = _tail; + _setUint32AtTail(tail, values.length); + tail -= _sizeofUint32; + for (final value in values) { + _setInt32AtTail(tail, value); + tail -= _sizeofInt32; + } + return result; + } + + /// Write the given list of unsigned 32-bit integer [values]. + int writeListUint32(List values) { + assert(!_inVTable); + _prepare(_sizeofUint32, 1 + values.length); + final result = _tail; + var tail = _tail; + _setUint32AtTail(tail, values.length); + tail -= _sizeofUint32; + for (final value in values) { + _setUint32AtTail(tail, value); + tail -= _sizeofUint32; + } + return result; + } + + /// Write the given list of signed 16-bit integer [values]. + int writeListInt16(List values) { + assert(!_inVTable); + _prepare(_sizeofUint32, 1, additionalBytes: 2 * values.length); + final result = _tail; + var tail = _tail; + _setUint32AtTail(tail, values.length); + tail -= _sizeofUint32; + for (final value in values) { + _setInt16AtTail(tail, value); + tail -= _sizeofInt16; + } + return result; + } + + /// Write the given list of unsigned 16-bit integer [values]. + int writeListUint16(List values) { + assert(!_inVTable); + _prepare(_sizeofUint32, 1, additionalBytes: 2 * values.length); + final result = _tail; + var tail = _tail; + _setUint32AtTail(tail, values.length); + tail -= _sizeofUint32; + for (final value in values) { + _setUint16AtTail(tail, value); + tail -= _sizeofUint16; + } + return result; + } + + /// Write the given list of bools as unsigend 8-bit integer [values]. + int writeListBool(List values) { + return writeListUint8(values.map((b) => b ? 1 : 0).toList()); + } + + /// Write the given list of signed 8-bit integer [values]. + int writeListInt8(List values) { + assert(!_inVTable); + _prepare(_sizeofUint32, 1, additionalBytes: values.length); + final result = _tail; + var tail = _tail; + _setUint32AtTail(tail, values.length); + tail -= _sizeofUint32; + for (final value in values) { + _setInt8AtTail(tail, value); + tail -= _sizeofUint8; + } + return result; + } + + /// Write the given list of unsigned 8-bit integer [values]. + int writeListUint8(List values) { + assert(!_inVTable); + _prepare(_sizeofUint32, 1, additionalBytes: values.length); + final result = _tail; + var tail = _tail; + _setUint32AtTail(tail, values.length); + tail -= _sizeofUint32; + for (final value in values) { + _setUint8AtTail(tail, value); + tail -= _sizeofUint8; + } + return result; + } + + /// Write the given string [value] and return its offset. + /// + /// Dart strings are UTF-16 but must be stored as UTF-8 in FlatBuffers. + /// If the given string consists only of ASCII characters, you can indicate + /// enable [asciiOptimization]. In this mode, [writeString()] first tries to + /// copy the ASCII string directly to the output buffer and if that fails + /// (because there are no-ASCII characters in the string) it falls back and to + /// the default UTF-16 -> UTF-8 conversion (with slight performance penalty). + int writeString(String value, {bool asciiOptimization = false}) { + assert(!_inVTable); + if (_strings != null) { + return _strings!.putIfAbsent( + value, + () => _writeString(value, asciiOptimization), + ); + } else { + return _writeString(value, asciiOptimization); + } + } + + int _writeString(String value, bool asciiOptimization) { + if (asciiOptimization) { + // [utf8.encode()] is slow (up to at least Dart SDK 2.13). If the given + // string is ASCII we can just write it directly, without any conversion. + final originalTail = _tail; + if (_tryWriteASCIIString(value)) return _tail; + // if non-ASCII: reset the output buffer position for [_writeUTFString()] + _tail = originalTail; + } + _writeUTFString(value); + return _tail; + } + + // Try to write the string as ASCII, return false if there's a non-ascii char. + @pragma('vm:prefer-inline') + bool _tryWriteASCIIString(String value) { + _prepare(4, 1, additionalBytes: value.length + 1); + final length = value.length; + var offset = _buf.lengthInBytes - _tail + 4; + for (var i = 0; i < length; i++) { + // utf16 code unit, e.g. for '†' it's [0x20 0x20], which is 8224 decimal. + // ASCII characters go from 0x00 to 0x7F (which is 0 to 127 decimal). + final char = value.codeUnitAt(i); + if ((char & ~0x7F) != 0) { + return false; + } + _buf.setUint8(offset++, char); + } + _buf.setUint8(offset, 0); // trailing zero + _setUint32AtTail(_tail, value.length); + return true; + } + + @pragma('vm:prefer-inline') + void _writeUTFString(String value) { + final bytes = utf8.encode(value) as Uint8List; + final length = bytes.length; + _prepare(4, 1, additionalBytes: length + 1); + _setUint32AtTail(_tail, length); + var offset = _buf.lengthInBytes - _tail + 4; + for (var i = 0; i < length; i++) { + _buf.setUint8(offset++, bytes[i]); + } + _buf.setUint8(offset, 0); // trailing zero + } + + /// Used to assert whether a "Table" is currently being built. + /// + /// If you hit `assert(!_inVTable())`, you're trying to add table fields + /// without starting a table with [Builder.startTable()]. + /// + /// If you hit `assert(_inVTable())`, you're trying to construct a + /// Table/Vector/String during the construction of its parent table, + /// between the MyTableBuilder and [Builder.endTable()]. + /// Move the creation of these sub-objects to before the MyTableBuilder to + /// not get this assert. + @pragma('vm:prefer-inline') + bool get _inVTable => _currentVTable != null; + + /// The number of bytes that have been written to the buffer so far. The + /// most recently written byte is this many bytes from the end of the buffer. + @pragma('vm:prefer-inline') + int get offset => _tail; + + /// Zero-pads the buffer, which may be required for some struct layouts. + @pragma('vm:prefer-inline') + void pad(int howManyBytes) { + for (var i = 0; i < howManyBytes; i++) { + putUint8(0); + } + } + + /// Prepare for writing the given `count` of scalars of the given `size`. + /// Additionally allocate the specified `additionalBytes`. Update the current + /// tail pointer to point at the allocated space. + @pragma('vm:prefer-inline') + void _prepare(int size, int count, {int additionalBytes = 0}) { + assert(!_finished); + // Update the alignment. + if (_maxAlign < size) { + _maxAlign = size; + } + // Prepare amount of required space. + final dataSize = size * count + additionalBytes; + final alignDelta = (-(_tail + dataSize)) & (size - 1); + final bufSize = alignDelta + dataSize; + // Ensure that we have the required amount of space. + { + final oldCapacity = _buf.lengthInBytes; + if (_tail + bufSize > oldCapacity) { + final desiredNewCapacity = (oldCapacity + bufSize) * 2; + var deltaCapacity = desiredNewCapacity - oldCapacity; + deltaCapacity += (-deltaCapacity) & (_maxAlign - 1); + final newCapacity = oldCapacity + deltaCapacity; + _buf = _allocator.resize(_buf, newCapacity, _tail, 0); + } + } + + // zero out the added padding + for (var i = _tail + 1; i <= _tail + alignDelta; i++) { + _setUint8AtTail(i, 0); + } + + // Update the tail pointer. + _tail += bufSize; + } + + /// Record the offset of the given [field]. + @pragma('vm:prefer-inline') + void _trackField(int field) => _currentVTable!.addField(field, _tail); + + @pragma('vm:prefer-inline') + void _setFloat64AtTail(int tail, double x) => + _buf.setFloat64(_buf.lengthInBytes - tail, x, Endian.little); + + @pragma('vm:prefer-inline') + void _setFloat32AtTail(int tail, double x) => + _buf.setFloat32(_buf.lengthInBytes - tail, x, Endian.little); + + @pragma('vm:prefer-inline') + void _setUint64AtTail(int tail, int x) => + _buf.setUint64(_buf.lengthInBytes - tail, x, Endian.little); + + @pragma('vm:prefer-inline') + void _setInt64AtTail(int tail, int x) => + _buf.setInt64(_buf.lengthInBytes - tail, x, Endian.little); + + @pragma('vm:prefer-inline') + void _setInt32AtTail(int tail, int x) => + _buf.setInt32(_buf.lengthInBytes - tail, x, Endian.little); + + @pragma('vm:prefer-inline') + void _setUint32AtTail(int tail, int x) => + _buf.setUint32(_buf.lengthInBytes - tail, x, Endian.little); + + @pragma('vm:prefer-inline') + void _setInt16AtTail(int tail, int x) => + _buf.setInt16(_buf.lengthInBytes - tail, x, Endian.little); + + @pragma('vm:prefer-inline') + void _setUint16AtTail(int tail, int x) => + _buf.setUint16(_buf.lengthInBytes - tail, x, Endian.little); + + @pragma('vm:prefer-inline') + void _setInt8AtTail(int tail, int x) => + _buf.setInt8(_buf.lengthInBytes - tail, x); + + @pragma('vm:prefer-inline') + void _setUint8AtTail(int tail, int x) => + _buf.setUint8(_buf.lengthInBytes - tail, x); +} + +/// Reader of lists of boolean values. +/// +/// The returned unmodifiable lists lazily read values on access. +class BoolListReader extends Reader> { + const BoolListReader(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofUint32; + + @override + @pragma('vm:prefer-inline') + List read(BufferContext bc, int offset) => + _FbBoolList(bc, bc.derefObject(offset)); +} + +/// The reader of booleans. +class BoolReader extends Reader { + const BoolReader() : super(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofUint8; + + @override + @pragma('vm:prefer-inline') + bool read(BufferContext bc, int offset) => bc._getInt8(offset) != 0; +} + +/// The reader of lists of 64-bit float values. +/// +/// The returned unmodifiable lists lazily read values on access. +class Float64ListReader extends Reader> { + const Float64ListReader(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofFloat64; + + @override + @pragma('vm:prefer-inline') + List read(BufferContext bc, int offset) => + _FbFloat64List(bc, bc.derefObject(offset)); +} + +class Float32ListReader extends Reader> { + const Float32ListReader(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofFloat32; + + @override + @pragma('vm:prefer-inline') + List read(BufferContext bc, int offset) => + _FbFloat32List(bc, bc.derefObject(offset)); +} + +class Float64Reader extends Reader { + const Float64Reader(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofFloat64; + + @override + @pragma('vm:prefer-inline') + double read(BufferContext bc, int offset) => bc._getFloat64(offset); +} + +class Float32Reader extends Reader { + const Float32Reader(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofFloat32; + + @override + @pragma('vm:prefer-inline') + double read(BufferContext bc, int offset) => bc._getFloat32(offset); +} + +class Int64Reader extends Reader { + const Int64Reader() : super(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofInt64; + + @override + @pragma('vm:prefer-inline') + int read(BufferContext bc, int offset) => bc._getInt64(offset); +} + +/// The reader of signed 32-bit integers. +class Int32Reader extends Reader { + const Int32Reader() : super(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofInt32; + + @override + @pragma('vm:prefer-inline') + int read(BufferContext bc, int offset) => bc._getInt32(offset); +} + +/// The reader of signed 32-bit integers. +class Int16Reader extends Reader { + const Int16Reader() : super(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofInt16; + + @override + @pragma('vm:prefer-inline') + int read(BufferContext bc, int offset) => bc._getInt16(offset); +} + +/// The reader of 8-bit signed integers. +class Int8Reader extends Reader { + const Int8Reader() : super(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofInt8; + + @override + @pragma('vm:prefer-inline') + int read(BufferContext bc, int offset) => bc._getInt8(offset); +} + +/// The reader of lists of objects. Lazy by default - see [lazy]. +class ListReader extends Reader> { + final Reader _elementReader; + + /// Enables lazy reading of the list + /// + /// If true, the returned unmodifiable list lazily reads objects on access. + /// Therefore, the underlying buffer must not change while accessing the list. + /// + /// If false, reads the whole list immediately on access. + final bool lazy; + + const ListReader(this._elementReader, {this.lazy = true}); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofUint32; + + @override + List read(BufferContext bc, int offset) { + final listOffset = bc.derefObject(offset); + return lazy + ? _FbGenericList(_elementReader, bc, listOffset) + : List.generate( + bc.buffer.getUint32(listOffset, Endian.little), + (int index) => _elementReader.read( + bc, + listOffset + size + _elementReader.size * index, + ), + growable: true, + ); + } +} + +/// Object that can read a value at a [BufferContext]. +abstract class Reader { + const Reader(); + + /// The size of the value in bytes. + int get size; + + /// Read the value at the given [offset] in [bc]. + T read(BufferContext bc, int offset); + + /// Read the value of the given [field] in the given [object]. + @pragma('vm:prefer-inline') + T vTableGet(BufferContext object, int offset, int field, T defaultValue) { + final fieldOffset = _vTableFieldOffset(object, offset, field); + return fieldOffset == 0 ? defaultValue : read(object, offset + fieldOffset); + } + + /// Read the value of the given [field] in the given [object]. + @pragma('vm:prefer-inline') + T? vTableGetNullable(BufferContext object, int offset, int field) { + final fieldOffset = _vTableFieldOffset(object, offset, field); + return fieldOffset == 0 ? null : read(object, offset + fieldOffset); + } + + @pragma('vm:prefer-inline') + int _vTableFieldOffset(BufferContext object, int offset, int field) { + final vTableSOffset = object._getInt32(offset); + final vTableOffset = offset - vTableSOffset; + final vTableSize = object._getUint16(vTableOffset); + if (field >= vTableSize) return 0; + return object._getUint16(vTableOffset + field); + } +} + +/// The reader of string values. +class StringReader extends Reader { + final bool asciiOptimization; + + const StringReader({this.asciiOptimization = false}) : super(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofUint32; + + @override + @pragma('vm:prefer-inline') + String read(BufferContext bc, int offset) { + final strOffset = bc.derefObject(offset); + final length = bc._getUint32(strOffset); + final bytes = bc._asUint8List(strOffset + _sizeofUint32, length); + if (asciiOptimization && _isLatin(bytes)) { + return String.fromCharCodes(bytes); + } + return utf8.decode(bytes); + } + + @pragma('vm:prefer-inline') + static bool _isLatin(Uint8List bytes) { + final length = bytes.length; + for (var i = 0; i < length; i++) { + if (bytes[i] > 127) { + return false; + } + } + return true; + } +} + +/// An abstract reader for structs. +abstract class StructReader extends Reader { + const StructReader(); + + /// Return the object at `offset`. + T createObject(BufferContext bc, int offset); + + @override + T read(BufferContext bc, int offset) { + return createObject(bc, offset); + } +} + +/// An abstract reader for tables. +abstract class TableReader extends Reader { + const TableReader(); + + @override + @pragma('vm:prefer-inline') + int get size => 4; + + /// Return the object at [offset]. + T createObject(BufferContext bc, int offset); + + @override + T read(BufferContext bc, int offset) { + final objectOffset = bc.derefObject(offset); + return createObject(bc, objectOffset); + } +} + +/// Reader of lists of unsigned 32-bit integer values. +/// +/// The returned unmodifiable lists lazily read values on access. +class Uint32ListReader extends Reader> { + const Uint32ListReader(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofUint32; + + @override + @pragma('vm:prefer-inline') + List read(BufferContext bc, int offset) => + _FbUint32List(bc, bc.derefObject(offset)); +} + +/// The reader of unsigned 64-bit integers. +/// +/// WARNING: May have compatibility issues with JavaScript +class Uint64Reader extends Reader { + const Uint64Reader() : super(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofUint64; + + @override + @pragma('vm:prefer-inline') + int read(BufferContext bc, int offset) => bc._getUint64(offset); +} + +/// The reader of unsigned 32-bit integers. +class Uint32Reader extends Reader { + const Uint32Reader() : super(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofUint32; + + @override + @pragma('vm:prefer-inline') + int read(BufferContext bc, int offset) => bc._getUint32(offset); +} + +/// Reader of lists of unsigned 32-bit integer values. +/// +/// The returned unmodifiable lists lazily read values on access. +class Uint16ListReader extends Reader> { + const Uint16ListReader(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofUint32; + + @override + @pragma('vm:prefer-inline') + List read(BufferContext bc, int offset) => + _FbUint16List(bc, bc.derefObject(offset)); +} + +/// The reader of unsigned 32-bit integers. +class Uint16Reader extends Reader { + const Uint16Reader() : super(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofUint16; + + @override + @pragma('vm:prefer-inline') + int read(BufferContext bc, int offset) => bc._getUint16(offset); +} + +/// Reader of unmodifiable binary data (a list of unsigned 8-bit integers). +class Uint8ListReader extends Reader> { + /// Enables lazy reading of the list + /// + /// If true, the returned unmodifiable list lazily reads bytes on access. + /// Therefore, the underlying buffer must not change while accessing the list. + /// + /// If false, reads the whole list immediately as an Uint8List. + final bool lazy; + + const Uint8ListReader({this.lazy = true}); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofUint32; + + @override + @pragma('vm:prefer-inline') + List read(BufferContext bc, int offset) { + final listOffset = bc.derefObject(offset); + if (lazy) return _FbUint8List(bc, listOffset); + + final length = bc._getUint32(listOffset); + final result = Uint8List(length); + var pos = listOffset + _sizeofUint32; + for (var i = 0; i < length; i++, pos++) { + result[i] = bc._getUint8(pos); + } + return result; + } +} + +/// The reader of unsigned 8-bit integers. +class Uint8Reader extends Reader { + const Uint8Reader() : super(); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofUint8; + + @override + @pragma('vm:prefer-inline') + int read(BufferContext bc, int offset) => bc._getUint8(offset); +} + +/// Reader of unmodifiable binary data (a list of signed 8-bit integers). +class Int8ListReader extends Reader> { + /// Enables lazy reading of the list + /// + /// If true, the returned unmodifiable list lazily reads bytes on access. + /// Therefore, the underlying buffer must not change while accessing the list. + /// + /// If false, reads the whole list immediately as an Uint8List. + final bool lazy; + + const Int8ListReader({this.lazy = true}); + + @override + @pragma('vm:prefer-inline') + int get size => _sizeofUint32; + + @override + @pragma('vm:prefer-inline') + List read(BufferContext bc, int offset) { + final listOffset = bc.derefObject(offset); + if (lazy) return _FbUint8List(bc, listOffset); + + final length = bc._getUint32(listOffset); + final result = Int8List(length); + var pos = listOffset + _sizeofUint32; + for (var i = 0; i < length; i++, pos++) { + result[i] = bc._getInt8(pos); + } + return result; + } +} + +/// The list backed by 64-bit values - Uint64 length and Float64. +class _FbFloat64List extends _FbList { + _FbFloat64List(BufferContext bc, int offset) : super(bc, offset); + + @override + @pragma('vm:prefer-inline') + double operator [](int i) => bc._getFloat64(offset + 4 + 8 * i); +} + +/// The list backed by 32-bit values - Float32. +class _FbFloat32List extends _FbList { + _FbFloat32List(BufferContext bc, int offset) : super(bc, offset); + + @override + @pragma('vm:prefer-inline') + double operator [](int i) => bc._getFloat32(offset + 4 + 4 * i); +} + +/// List backed by a generic object which may have any size. +class _FbGenericList extends _FbList { + final Reader elementReader; + + List? _items; + + _FbGenericList(this.elementReader, BufferContext bp, int offset) + : super(bp, offset); + + @override + @pragma('vm:prefer-inline') + E operator [](int i) { + _items ??= List.filled(length, null); + var item = _items![i]; + if (item == null) { + item = elementReader.read(bc, offset + 4 + elementReader.size * i); + _items![i] = item; + } + return item!; + } +} + +/// The base class for immutable lists read from flat buffers. +abstract class _FbList extends Object with ListMixin implements List { + final BufferContext bc; + final int offset; + int? _length; + + _FbList(this.bc, this.offset); + + @override + @pragma('vm:prefer-inline') + int get length => _length ??= bc._getUint32(offset); + + @override + set length(int i) => throw StateError('Attempt to modify immutable list'); + + @override + void operator []=(int i, E e) => + throw StateError('Attempt to modify immutable list'); +} + +/// List backed by 32-bit unsigned integers. +class _FbUint32List extends _FbList { + _FbUint32List(BufferContext bc, int offset) : super(bc, offset); + + @override + @pragma('vm:prefer-inline') + int operator [](int i) => bc._getUint32(offset + 4 + 4 * i); +} + +/// List backed by 16-bit unsigned integers. +class _FbUint16List extends _FbList { + _FbUint16List(BufferContext bc, int offset) : super(bc, offset); + + @override + @pragma('vm:prefer-inline') + int operator [](int i) => bc._getUint16(offset + 4 + 2 * i); +} + +/// List backed by 8-bit unsigned integers. +class _FbUint8List extends _FbList { + _FbUint8List(BufferContext bc, int offset) : super(bc, offset); + + @override + @pragma('vm:prefer-inline') + int operator [](int i) => bc._getUint8(offset + 4 + i); +} + +/// List backed by 8-bit signed integers. +class _FbInt8List extends _FbList { + _FbInt8List(BufferContext bc, int offset) : super(bc, offset); + + @override + @pragma('vm:prefer-inline') + int operator [](int i) => bc._getInt8(offset + 4 + i); +} + +/// List backed by 8-bit unsigned integers. +class _FbBoolList extends _FbList { + _FbBoolList(BufferContext bc, int offset) : super(bc, offset); + + @override + @pragma('vm:prefer-inline') + bool operator [](int i) => bc._getUint8(offset + 4 + i) == 1 ? true : false; +} + +/// Class that describes the structure of a table. +class _VTable { + static const int _metadataLength = 4; + + final int numFields; + + // Note: fieldOffsets start as "tail offsets" and are then transformed by + // [computeFieldOffsets()] to actual offsets when a table is finished. + final Uint32List fieldOffsets; + bool offsetsComputed = false; + + _VTable(this.numFields) : fieldOffsets = Uint32List(numFields); + + /// The size of the table that uses this VTable. + int tableSize = 0; + + /// The tail of this VTable. It is used to share the same VTable between + /// multiple tables of identical structure. + int tail = 0; + + int get _vTableSize => numOfUint16 * _sizeofUint16; + + int get numOfUint16 => 1 + 1 + numFields; + + @pragma('vm:prefer-inline') + void addField(int field, int offset) { + assert(!offsetsComputed); + assert(offset > 0); // it's impossible for field to start at the buffer end + assert(offset <= 4294967295); // uint32 max + fieldOffsets[field] = offset; + } + + @pragma('vm:prefer-inline') + bool _offsetsMatch(int vt2Start, ByteData buf) { + assert(offsetsComputed); + for (var i = 0; i < numFields; i++) { + if (fieldOffsets[i] != + buf.getUint16(vt2Start + _metadataLength + (2 * i), Endian.little)) { + return false; + } + } + return true; + } + + /// Fill the [fieldOffsets] field. + @pragma('vm:prefer-inline') + void computeFieldOffsets(int tableTail) { + assert(!offsetsComputed); + offsetsComputed = true; + for (var i = 0; i < numFields; i++) { + if (fieldOffsets[i] != 0) { + fieldOffsets[i] = tableTail - fieldOffsets[i]; + } + } + } + + /// Outputs this VTable to [buf], which is is expected to be aligned to 16-bit + /// and have at least [numOfUint16] 16-bit words available. + @pragma('vm:prefer-inline') + void output(ByteData buf, int bufOffset) { + assert(offsetsComputed); + // VTable size. + buf.setUint16(bufOffset, numOfUint16 * 2, Endian.little); + bufOffset += 2; + // Table size. + buf.setUint16(bufOffset, tableSize, Endian.little); + bufOffset += 2; + // Field offsets. + for (var i = 0; i < numFields; i++) { + buf.setUint16(bufOffset, fieldOffsets[i], Endian.little); + bufOffset += 2; + } + } +} + +/// The interface that [Builder] uses to allocate buffers for encoding. +abstract class Allocator { + const Allocator(); + + /// Allocate a [ByteData] buffer of a given size. + ByteData allocate(int size); + + /// Free the given [ByteData] buffer previously allocated by [allocate]. + void deallocate(ByteData data); + + /// Reallocate [newSize] bytes of memory, replacing the old [oldData]. This + /// grows downwards, and is intended specifically for use with [Builder]. + /// Params [inUseBack] and [inUseFront] indicate how much of [oldData] is + /// actually in use at each end, and needs to be copied. + ByteData resize( + ByteData oldData, + int newSize, + int inUseBack, + int inUseFront, + ) { + final newData = allocate(newSize); + _copyDownward(oldData, newData, inUseBack, inUseFront); + deallocate(oldData); + return newData; + } + + /// Called by [resize] to copy memory from [oldData] to [newData]. Only + /// memory of size [inUseFront] and [inUseBack] will be copied from the front + /// and back of the old memory allocation. + void _copyDownward( + ByteData oldData, + ByteData newData, + int inUseBack, + int inUseFront, + ) { + if (inUseBack != 0) { + newData.buffer.asUint8List().setAll( + newData.lengthInBytes - inUseBack, + oldData.buffer.asUint8List().getRange( + oldData.lengthInBytes - inUseBack, + oldData.lengthInBytes, + ), + ); + } + if (inUseFront != 0) { + newData.buffer.asUint8List().setAll( + 0, + oldData.buffer.asUint8List().getRange(0, inUseFront), + ); + } + } +} + +class DefaultAllocator extends Allocator { + const DefaultAllocator(); + + @override + ByteData allocate(int size) => ByteData(size); + + @override + void deallocate(ByteData data) { + // nothing to do, it's garbage-collected + } +} diff --git a/third_party/flatbuffers/dart/lib/flex_buffers.dart b/third_party/flatbuffers/dart/lib/flex_buffers.dart new file mode 100644 index 00000000000..824affffcc5 --- /dev/null +++ b/third_party/flatbuffers/dart/lib/flex_buffers.dart @@ -0,0 +1,2 @@ +export 'src/builder.dart'; +export 'src/reference.dart'; diff --git a/third_party/flatbuffers/dart/lib/src/builder.dart b/third_party/flatbuffers/dart/lib/src/builder.dart new file mode 100644 index 00000000000..cdd0aec5323 --- /dev/null +++ b/third_party/flatbuffers/dart/lib/src/builder.dart @@ -0,0 +1,707 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'types.dart'; + +/// The main builder class for creation of a FlexBuffer. +class Builder { + final ByteData _buffer; + List<_StackValue> _stack = []; + List<_StackPointer> _stackPointers = []; + int _offset = 0; + bool _finished = false; + final Map _stringCache = {}; + final Map _keyCache = {}; + final Map<_KeysHash, _StackValue> _keyVectorCache = {}; + final Map _indirectIntCache = {}; + final Map _indirectDoubleCache = {}; + + /// Instantiate the builder if you intent to gradually build up the buffer by calling + /// add... methods and calling [finish] to receive the resulting byte array. + /// + /// The default size of internal buffer is set to 2048. Provide a different value in order to avoid buffer copies. + Builder({int size = 2048}) : _buffer = ByteData(size); + + /// Use this method in order to turn an object into a FlexBuffer directly. + /// + /// Use the manual instantiation of the [Builder] and gradual addition of values, if performance is more important than convenience. + static ByteBuffer buildFromObject(Object? value) { + final builder = Builder(); + builder._add(value); + final buffer = builder.finish(); + final byteData = ByteData(buffer.lengthInBytes); + byteData.buffer.asUint8List().setAll(0, buffer); + return byteData.buffer; + } + + void _add(Object? value) { + if (value == null) { + addNull(); + } else if (value is bool) { + addBool(value); + } else if (value is int) { + addInt(value); + } else if (value is double) { + addDouble(value); + } else if (value is ByteBuffer) { + addBlob(value); + } else if (value is String) { + addString(value); + } else if (value is List) { + startVector(); + for (var i = 0; i < value.length; i++) { + _add(value[i]); + } + end(); + } else if (value is Map) { + startMap(); + value.forEach((key, value) { + addKey(key); + _add(value); + }); + end(); + } else { + throw UnsupportedError('Value of unexpected type: $value'); + } + } + + /// Use this method if you want to store a null value. + /// + /// Specifically useful when building up a vector where values can be null. + void addNull() { + _integrityCheckOnValueAddition(); + _stack.add(_StackValue.withNull()); + } + + /// Adds a string value. + void addInt(int value) { + _integrityCheckOnValueAddition(); + _stack.add(_StackValue.withInt(value)); + } + + /// Adds a bool value. + void addBool(bool value) { + _integrityCheckOnValueAddition(); + _stack.add(_StackValue.withBool(value)); + } + + /// Adds a double value. + void addDouble(double value) { + _integrityCheckOnValueAddition(); + _stack.add(_StackValue.withDouble(value)); + } + + /// Adds a string value. + void addString(String value) { + _integrityCheckOnValueAddition(); + if (_stringCache.containsKey(value)) { + _stack.add(_stringCache[value]!); + return; + } + final utf8String = utf8.encode(value); + final length = utf8String.length; + final bitWidth = BitWidthUtil.uwidth(length); + final byteWidth = _align(bitWidth); + _writeUInt(length, byteWidth); + final stringOffset = _offset; + final newOffset = _newOffset(length + 1); + _pushBuffer(utf8String); + _offset = newOffset; + final stackValue = _StackValue.withOffset( + stringOffset, + ValueType.String, + bitWidth, + ); + _stack.add(stackValue); + _stringCache[value] = stackValue; + } + + /// This methods adds a key to a map and should be followed by an add... value call. + /// + /// It also implies that you call this method only after you called [startMap]. + void addKey(String value) { + _integrityCheckOnKeyAddition(); + if (_keyCache.containsKey(value)) { + _stack.add(_keyCache[value]!); + return; + } + final utf8String = utf8.encode(value); + final length = utf8String.length; + final keyOffset = _offset; + final newOffset = _newOffset(length + 1); + _pushBuffer(utf8String); + _offset = newOffset; + final stackValue = _StackValue.withOffset( + keyOffset, + ValueType.Key, + BitWidth.width8, + ); + _stack.add(stackValue); + _keyCache[value] = stackValue; + } + + /// Adds a byte array. + /// + /// This method can be used to store any generic BLOB. + void addBlob(ByteBuffer value) { + _integrityCheckOnValueAddition(); + final length = value.lengthInBytes; + final bitWidth = BitWidthUtil.uwidth(length); + final byteWidth = _align(bitWidth); + _writeUInt(length, byteWidth); + final blobOffset = _offset; + final newOffset = _newOffset(length); + _pushBuffer(value.asUint8List()); + _offset = newOffset; + final stackValue = _StackValue.withOffset( + blobOffset, + ValueType.Blob, + bitWidth, + ); + _stack.add(stackValue); + } + + /// Stores int value indirectly in the buffer. + /// + /// Adding large integer values indirectly might be beneficial if those values suppose to be store in a vector together with small integer values. + /// This is due to the fact that FlexBuffers will add padding to small integer values, if they are stored together with large integer values. + /// When we add integer indirectly the vector of ints will contain not the value itself, but only the relative offset to the value. + /// By setting the [cache] parameter to true, you make sure that the builder tracks added int value and performs deduplication. + void addIntIndirectly(int value, {bool cache = false}) { + _integrityCheckOnValueAddition(); + if (_indirectIntCache.containsKey(value)) { + _stack.add(_indirectIntCache[value]!); + return; + } + final stackValue = _StackValue.withInt(value); + final byteWidth = _align(stackValue.width); + final newOffset = _newOffset(byteWidth); + final valueOffset = _offset; + _pushBuffer(stackValue.asU8List(stackValue.width)); + final stackOffset = _StackValue.withOffset( + valueOffset, + ValueType.IndirectInt, + stackValue.width, + ); + _stack.add(stackOffset); + _offset = newOffset; + if (cache) { + _indirectIntCache[value] = stackOffset; + } + } + + /// Stores double value indirectly in the buffer. + /// + /// Double are stored as 8 or 4 byte values in FlexBuffers. If they are stored in a mixed vector, values which are smaller than 4 / 8 bytes will be padded. + /// When we add double indirectly, the vector will contain not the value itself, but only the relative offset to the value. Which could occupy only 1 or 2 bytes, reducing the odds for unnecessary padding. + /// By setting the [cache] parameter to true, you make sure that the builder tracks already added double value and performs deduplication. + void addDoubleIndirectly(double value, {bool cache = false}) { + _integrityCheckOnValueAddition(); + if (cache && _indirectDoubleCache.containsKey(value)) { + _stack.add(_indirectDoubleCache[value]!); + return; + } + final stackValue = _StackValue.withDouble(value); + final byteWidth = _align(stackValue.width); + final newOffset = _newOffset(byteWidth); + final valueOffset = _offset; + _pushBuffer(stackValue.asU8List(stackValue.width)); + final stackOffset = _StackValue.withOffset( + valueOffset, + ValueType.IndirectFloat, + stackValue.width, + ); + _stack.add(stackOffset); + _offset = newOffset; + if (cache) { + _indirectDoubleCache[value] = stackOffset; + } + } + + /// This method starts a vector definition and needs to be followed by 0 to n add... value calls. + /// + /// The vector definition needs to be finished with an [end] call. + /// It is also possible to add nested vector or map by calling [startVector] / [startMap]. + void startVector() { + _integrityCheckOnValueAddition(); + _stackPointers.add(_StackPointer(_stack.length, true)); + } + + /// This method starts a map definition. + /// + /// This method call needs to be followed by 0 to n [addKey] + add... value calls. + /// The map definition needs to be finished with an [end] call. + /// It is also possible to add nested vector or map by calling [startVector] / [startMap] after calling [addKey]. + void startMap() { + _integrityCheckOnValueAddition(); + _stackPointers.add(_StackPointer(_stack.length, false)); + } + + /// Marks that the addition of values to the last vector, or map have ended. + void end() { + final pointer = _stackPointers.removeLast(); + if (pointer.isVector) { + _endVector(pointer); + } else { + _sortKeysAndEndMap(pointer); + } + } + + /// Finish building the FlatBuffer and return array of bytes. + /// + /// Can be called multiple times, to get the array of bytes. + /// After the first call, adding values, or starting vectors / maps will result in an exception. + Uint8List finish() { + if (_finished == false) { + _finish(); + } + return _buffer.buffer.asUint8List(0, _offset); + } + + /// Builds a FlatBuffer with current state without finishing the builder. + /// + /// Creates an internal temporary copy of current builder and finishes the copy. + /// Use this method, when the state of a long lasting builder need to be persisted periodically. + ByteBuffer snapshot() { + final tmp = Builder(size: _offset + 200); + tmp._offset = _offset; + tmp._stack = List.from(_stack); + tmp._stackPointers = List.from(_stackPointers); + tmp._buffer.buffer.asUint8List().setAll( + 0, + _buffer.buffer.asUint8List(0, _offset), + ); + for (var i = 0; i < tmp._stackPointers.length; i++) { + tmp.end(); + } + final buffer = tmp.finish(); + final bd = ByteData(buffer.lengthInBytes); + bd.buffer.asUint8List().setAll(0, buffer); + return bd.buffer; + } + + void _integrityCheckOnValueAddition() { + if (_finished) { + throw StateError('Adding values after finish is prohibited'); + } + if (_stackPointers.isNotEmpty && _stackPointers.last.isVector == false) { + if (_stack.last.type != ValueType.Key) { + throw StateError( + 'Adding value to a map before adding a key is prohibited', + ); + } + } + } + + void _integrityCheckOnKeyAddition() { + if (_finished) { + throw StateError('Adding values after finish is prohibited'); + } + if (_stackPointers.isEmpty || _stackPointers.last.isVector) { + throw StateError('Adding key before staring a map is prohibited'); + } + } + + void _finish() { + if (_stack.length != 1) { + throw StateError( + 'Stack has to be exactly 1, but is ${_stack.length}. You have to end all started vectors and maps, before calling [finish]', + ); + } + final value = _stack[0]; + final byteWidth = _align(value.elementWidth(_offset, 0)); + _writeStackValue(value, byteWidth); + _writeUInt(value.storedPackedType(), 1); + _writeUInt(byteWidth, 1); + _finished = true; + } + + _StackValue _createVector( + int start, + int vecLength, + int step, [ + _StackValue? keys, + ]) { + var bitWidth = BitWidthUtil.uwidth(vecLength); + var prefixElements = 1; + if (keys != null) { + var elemWidth = keys.elementWidth(_offset, 0); + if (elemWidth.index > bitWidth.index) { + bitWidth = elemWidth; + } + prefixElements += 2; + } + var vectorType = ValueType.Key; + var typed = keys == null; + for (var i = start; i < _stack.length; i += step) { + final elemWidth = _stack[i].elementWidth(_offset, i + prefixElements); + if (elemWidth.index > bitWidth.index) { + bitWidth = elemWidth; + } + if (i == start) { + vectorType = _stack[i].type; + typed &= ValueTypeUtils.isTypedVectorElement(vectorType); + } else { + if (vectorType != _stack[i].type) { + typed = false; + } + } + } + final byteWidth = _align(bitWidth); + final fix = + typed & ValueTypeUtils.isNumber(vectorType) && + vecLength >= 2 && + vecLength <= 4; + if (keys != null) { + _writeStackValue(keys, byteWidth); + _writeUInt(1 << keys.width.index, byteWidth); + } + if (fix == false) { + _writeUInt(vecLength, byteWidth); + } + final vecOffset = _offset; + for (var i = start; i < _stack.length; i += step) { + _writeStackValue(_stack[i], byteWidth); + } + if (typed == false) { + for (var i = start; i < _stack.length; i += step) { + _writeUInt(_stack[i].storedPackedType(), 1); + } + } + if (keys != null) { + return _StackValue.withOffset(vecOffset, ValueType.Map, bitWidth); + } + if (typed) { + final vType = ValueTypeUtils.toTypedVector( + vectorType, + fix ? vecLength : 0, + ); + return _StackValue.withOffset(vecOffset, vType, bitWidth); + } + return _StackValue.withOffset(vecOffset, ValueType.Vector, bitWidth); + } + + void _endVector(_StackPointer pointer) { + final vecLength = _stack.length - pointer.stackPosition; + final vec = _createVector(pointer.stackPosition, vecLength, 1); + _stack.removeRange(pointer.stackPosition, _stack.length); + _stack.add(vec); + } + + void _sortKeysAndEndMap(_StackPointer pointer) { + if (((_stack.length - pointer.stackPosition) & 1) == 1) { + throw StateError( + 'The stack needs to hold key value pairs (even number of elements). Check if you combined [addKey] with add... method calls properly.', + ); + } + + var sorted = true; + for (var i = pointer.stackPosition; i < _stack.length - 2; i += 2) { + if (_shouldFlip(_stack[i], _stack[i + 2])) { + sorted = false; + break; + } + } + + if (sorted == false) { + for (var i = pointer.stackPosition; i < _stack.length; i += 2) { + var flipIndex = i; + for (var j = i + 2; j < _stack.length; j += 2) { + if (_shouldFlip(_stack[flipIndex], _stack[j])) { + flipIndex = j; + } + } + if (flipIndex != i) { + var k = _stack[flipIndex]; + var v = _stack[flipIndex + 1]; + _stack[flipIndex] = _stack[i]; + _stack[flipIndex + 1] = _stack[i + 1]; + _stack[i] = k; + _stack[i + 1] = v; + } + } + } + _endMap(pointer); + } + + void _endMap(_StackPointer pointer) { + final vecLength = (_stack.length - pointer.stackPosition) >> 1; + final offsets = []; + for (var i = pointer.stackPosition; i < _stack.length; i += 2) { + offsets.add(_stack[i].offset!); + } + final keysHash = _KeysHash(offsets); + _StackValue? keysStackValue; + if (_keyVectorCache.containsKey(keysHash)) { + keysStackValue = _keyVectorCache[keysHash]; + } else { + keysStackValue = _createVector(pointer.stackPosition, vecLength, 2); + _keyVectorCache[keysHash] = keysStackValue; + } + final vec = _createVector( + pointer.stackPosition + 1, + vecLength, + 2, + keysStackValue, + ); + _stack.removeRange(pointer.stackPosition, _stack.length); + _stack.add(vec); + } + + bool _shouldFlip(_StackValue v1, _StackValue v2) { + if (v1.type != ValueType.Key || v2.type != ValueType.Key) { + throw StateError( + 'Stack values are not keys $v1 | $v2. Check if you combined [addKey] with add... method calls properly.', + ); + } + + late int c1, c2; + var index = 0; + do { + c1 = _buffer.getUint8(v1.offset! + index); + c2 = _buffer.getUint8(v2.offset! + index); + if (c2 < c1) return true; + if (c1 < c2) return false; + index += 1; + } while (c1 != 0 && c2 != 0); + return false; + } + + int _align(BitWidth width) { + final byteWidth = BitWidthUtil.toByteWidth(width); + _offset += BitWidthUtil.paddingSize(_offset, byteWidth); + return byteWidth; + } + + void _writeStackValue(_StackValue value, int byteWidth) { + final newOffset = _newOffset(byteWidth); + if (value.isOffset) { + final relativeOffset = _offset - value.offset!; + if (byteWidth == 8 || relativeOffset < (1 << (byteWidth * 8))) { + _writeUInt(relativeOffset, byteWidth); + } else { + throw StateError( + 'Unexpected size $byteWidth. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new', + ); + } + } else { + _pushBuffer(value.asU8List(BitWidthUtil.fromByteWidth(byteWidth))); + } + _offset = newOffset; + } + + void _writeUInt(int value, int byteWidth) { + final newOffset = _newOffset(byteWidth); + _pushUInt(value, BitWidthUtil.fromByteWidth(byteWidth)); + _offset = newOffset; + } + + int _newOffset(int newValueSize) { + final newOffset = _offset + newValueSize; + var size = _buffer.lengthInBytes; + final prevSize = size; + while (size < newOffset) { + size <<= 1; + } + if (prevSize < size) { + final newBuf = ByteData(size); + newBuf.buffer.asUint8List().setAll(0, _buffer.buffer.asUint8List()); + } + return newOffset; + } + + void _pushInt(int value, BitWidth width) { + switch (width) { + case BitWidth.width8: + _buffer.setInt8(_offset, value); + break; + case BitWidth.width16: + _buffer.setInt16(_offset, value, Endian.little); + break; + case BitWidth.width32: + _buffer.setInt32(_offset, value, Endian.little); + break; + case BitWidth.width64: + _buffer.setInt64(_offset, value, Endian.little); + break; + } + } + + void _pushUInt(int value, BitWidth width) { + switch (width) { + case BitWidth.width8: + _buffer.setUint8(_offset, value); + break; + case BitWidth.width16: + _buffer.setUint16(_offset, value, Endian.little); + break; + case BitWidth.width32: + _buffer.setUint32(_offset, value, Endian.little); + break; + case BitWidth.width64: + _buffer.setUint64(_offset, value, Endian.little); + break; + } + } + + void _pushBuffer(List value) { + _buffer.buffer.asUint8List().setAll(_offset, value); + } +} + +class _StackValue { + late Object _value; + int? _offset; + final ValueType _type; + final BitWidth _width; + + _StackValue.withNull() : _type = ValueType.Null, _width = BitWidth.width8; + + _StackValue.withInt(int value) + : _type = ValueType.Int, + _width = BitWidthUtil.width(value), + _value = value; + + _StackValue.withBool(bool value) + : _type = ValueType.Bool, + _width = BitWidth.width8, + _value = value; + + _StackValue.withDouble(double value) + : _type = ValueType.Float, + _width = BitWidthUtil.width(value), + _value = value; + + _StackValue.withOffset(int value, ValueType type, BitWidth width) + : _offset = value, + _type = type, + _width = width; + + BitWidth storedWidth({BitWidth width = BitWidth.width8}) { + return ValueTypeUtils.isInline(_type) + ? BitWidthUtil.max(_width, width) + : _width; + } + + int storedPackedType({BitWidth width = BitWidth.width8}) { + return ValueTypeUtils.packedType(_type, storedWidth(width: width)); + } + + BitWidth elementWidth(int size, int index) { + if (ValueTypeUtils.isInline(_type)) return _width; + final offset = _offset!; + for (var i = 0; i < 4; i++) { + final width = 1 << i; + final bitWidth = BitWidthUtil.uwidth( + size + BitWidthUtil.paddingSize(size, width) + index * width - offset, + ); + if (1 << bitWidth.index == width) { + return bitWidth; + } + } + throw StateError( + 'Element is of unknown. Size: $size at index: $index. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new', + ); + } + + List asU8List(BitWidth width) { + if (ValueTypeUtils.isNumber(_type)) { + if (_type == ValueType.Float) { + if (width == BitWidth.width32) { + final result = ByteData(4); + result.setFloat32(0, _value as double, Endian.little); + return result.buffer.asUint8List(); + } else { + final result = ByteData(8); + result.setFloat64(0, _value as double, Endian.little); + return result.buffer.asUint8List(); + } + } else { + switch (width) { + case BitWidth.width8: + final result = ByteData(1); + result.setInt8(0, _value as int); + return result.buffer.asUint8List(); + case BitWidth.width16: + final result = ByteData(2); + result.setInt16(0, _value as int, Endian.little); + return result.buffer.asUint8List(); + case BitWidth.width32: + final result = ByteData(4); + result.setInt32(0, _value as int, Endian.little); + return result.buffer.asUint8List(); + case BitWidth.width64: + final result = ByteData(8); + result.setInt64(0, _value as int, Endian.little); + return result.buffer.asUint8List(); + } + } + } + if (_type == ValueType.Null) { + final result = ByteData(1); + result.setInt8(0, 0); + return result.buffer.asUint8List(); + } + if (_type == ValueType.Bool) { + final result = ByteData(1); + result.setInt8(0, _value as bool ? 1 : 0); + return result.buffer.asUint8List(); + } + + throw StateError( + 'Unexpected type: $_type. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new', + ); + } + + ValueType get type { + return _type; + } + + BitWidth get width { + return _width; + } + + bool get isOffset { + return !ValueTypeUtils.isInline(_type); + } + + int? get offset => _offset; + + bool get isFloat32 { + return _type == ValueType.Float && _width == BitWidth.width32; + } +} + +class _StackPointer { + int stackPosition; + bool isVector; + + _StackPointer(this.stackPosition, this.isVector); +} + +class _KeysHash { + final List keys; + + const _KeysHash(this.keys); + + @override + bool operator ==(Object other) { + if (other is _KeysHash) { + if (keys.length != other.keys.length) return false; + for (var i = 0; i < keys.length; i++) { + if (keys[i] != other.keys[i]) return false; + } + return true; + } + return false; + } + + @override + int get hashCode { + var result = 17; + for (var i = 0; i < keys.length; i++) { + result = result * 23 + keys[i]; + } + return result; + } +} diff --git a/third_party/flatbuffers/dart/lib/src/reference.dart b/third_party/flatbuffers/dart/lib/src/reference.dart new file mode 100644 index 00000000000..2abba107b31 --- /dev/null +++ b/third_party/flatbuffers/dart/lib/src/reference.dart @@ -0,0 +1,518 @@ +import 'dart:collection'; +import 'dart:convert'; +import 'dart:typed_data'; + +import 'types.dart'; + +/// Main class to read a value out of a FlexBuffer. +/// +/// This class let you access values stored in the buffer in a lazy fashion. +class Reference { + final ByteData _buffer; + final int _offset; + final BitWidth _parentWidth; + final String _path; + final int _byteWidth; + final ValueType _valueType; + int? _length; + + Reference._( + this._buffer, + this._offset, + this._parentWidth, + int packedType, + this._path, [ + int? byteWidth, + ValueType? valueType, + ]) : _byteWidth = byteWidth ?? 1 << (packedType & 3), + _valueType = valueType ?? ValueTypeUtils.fromInt(packedType >> 2); + + /// Use this method to access the root value of a FlexBuffer. + static Reference fromBuffer(ByteBuffer buffer) { + final len = buffer.lengthInBytes; + if (len < 3) { + throw UnsupportedError('Buffer needs to be bigger than 3'); + } + final byteData = ByteData.view(buffer); + final byteWidth = byteData.getUint8(len - 1); + final packedType = byteData.getUint8(len - 2); + final offset = len - byteWidth - 2; + return Reference._( + ByteData.view(buffer), + offset, + BitWidthUtil.fromByteWidth(byteWidth), + packedType, + "/", + ); + } + + /// Returns true if the underlying value is null. + bool get isNull => _valueType == ValueType.Null; + + /// Returns true if the underlying value can be represented as [num]. + bool get isNum => + ValueTypeUtils.isNumber(_valueType) || + ValueTypeUtils.isIndirectNumber(_valueType); + + /// Returns true if the underlying value was encoded as a float (direct or indirect). + bool get isDouble => + _valueType == ValueType.Float || _valueType == ValueType.IndirectFloat; + + /// Returns true if the underlying value was encoded as an int or uint (direct or indirect). + bool get isInt => isNum && !isDouble; + + /// Returns true if the underlying value was encoded as a string or a key. + bool get isString => + _valueType == ValueType.String || _valueType == ValueType.Key; + + /// Returns true if the underlying value was encoded as a bool. + bool get isBool => _valueType == ValueType.Bool; + + /// Returns true if the underlying value was encoded as a blob. + bool get isBlob => _valueType == ValueType.Blob; + + /// Returns true if the underlying value points to a vector. + bool get isVector => ValueTypeUtils.isAVector(_valueType); + + /// Returns true if the underlying value points to a map. + bool get isMap => _valueType == ValueType.Map; + + /// If this [isBool], returns the bool value. Otherwise, returns null. + bool? get boolValue { + if (_valueType == ValueType.Bool) { + return _readInt(_offset, _parentWidth) != 0; + } + return null; + } + + /// Returns an [int], if the underlying value can be represented as an int. + /// + /// Otherwise returns [null]. + int? get intValue { + if (_valueType == ValueType.Int) { + return _readInt(_offset, _parentWidth); + } + if (_valueType == ValueType.UInt) { + return _readUInt(_offset, _parentWidth); + } + if (_valueType == ValueType.IndirectInt) { + return _readInt(_indirect, BitWidthUtil.fromByteWidth(_byteWidth)); + } + if (_valueType == ValueType.IndirectUInt) { + return _readUInt(_indirect, BitWidthUtil.fromByteWidth(_byteWidth)); + } + return null; + } + + /// Returns [double], if the underlying value [isDouble]. + /// + /// Otherwise returns [null]. + double? get doubleValue { + if (_valueType == ValueType.Float) { + return _readFloat(_offset, _parentWidth); + } + if (_valueType == ValueType.IndirectFloat) { + return _readFloat(_indirect, BitWidthUtil.fromByteWidth(_byteWidth)); + } + return null; + } + + /// Returns [num], if the underlying value is numeric, be it int uint, or float (direct or indirect). + /// + /// Otherwise returns [null]. + num? get numValue => doubleValue ?? intValue; + + /// Returns [String] value or null otherwise. + /// + /// This method performers a utf8 decoding, as FlexBuffers format stores strings in utf8 encoding. + String? get stringValue { + if (_valueType == ValueType.String || _valueType == ValueType.Key) { + return utf8.decode(_buffer.buffer.asUint8List(_indirect, length)); + } + return null; + } + + /// Returns [Uint8List] value or null otherwise. + Uint8List? get blobValue { + if (_valueType == ValueType.Blob) { + return _buffer.buffer.asUint8List(_indirect, length); + } + return null; + } + + /// Can be used with an [int] or a [String] value for key. + /// If the underlying value in FlexBuffer is a vector, then use [int] for access. + /// If the underlying value in FlexBuffer is a map, then use [String] for access. + /// Returns [Reference] value. Throws an exception when [key] is not applicable. + Reference operator [](Object key) { + if (key is int && ValueTypeUtils.isAVector(_valueType)) { + final index = key; + if (index >= length || index < 0) { + throw ArgumentError( + 'Key: [$key] is not applicable on: $_path of: $_valueType length: $length', + ); + } + final elementOffset = _indirect + index * _byteWidth; + int packedType = 0; + int? byteWidth; + ValueType? valueType; + if (ValueTypeUtils.isTypedVector(_valueType)) { + byteWidth = 1; + valueType = ValueTypeUtils.typedVectorElementType(_valueType); + } else if (ValueTypeUtils.isFixedTypedVector(_valueType)) { + byteWidth = 1; + valueType = ValueTypeUtils.fixedTypedVectorElementType(_valueType); + } else { + packedType = _buffer.getUint8(_indirect + length * _byteWidth + index); + } + return Reference._( + _buffer, + elementOffset, + BitWidthUtil.fromByteWidth(_byteWidth), + packedType, + "$_path[$index]", + byteWidth, + valueType, + ); + } + if (key is String && _valueType == ValueType.Map) { + final index = _keyIndex(key); + if (index != null) { + return _valueForIndexWithKey(index, key); + } + } + throw ArgumentError( + 'Key: [$key] is not applicable on: $_path of: $_valueType', + ); + } + + /// Get an iterable if the underlying flexBuffer value is a vector. + /// Otherwise throws an exception. + Iterable get vectorIterable { + if (isVector == false) { + throw UnsupportedError('Value is not a vector. It is: $_valueType'); + } + return _VectorIterator(this); + } + + /// Get an iterable for keys if the underlying flexBuffer value is a map. + /// Otherwise throws an exception. + Iterable get mapKeyIterable { + if (isMap == false) { + throw UnsupportedError('Value is not a map. It is: $_valueType'); + } + return _MapKeyIterator(this); + } + + /// Get an iterable for values if the underlying flexBuffer value is a map. + /// Otherwise throws an exception. + Iterable get mapValueIterable { + if (isMap == false) { + throw UnsupportedError('Value is not a map. It is: $_valueType'); + } + return _MapValueIterator(this); + } + + /// Returns the length of the underlying FlexBuffer value. + /// If the underlying value is [null] the length is 0. + /// If the underlying value is a number, or a bool, the length is 1. + /// If the underlying value is a vector, or map, the length reflects number of elements / element pairs. + /// If the values is a string or a blob, the length reflects a number of bytes the value occupies (strings are encoded in utf8 format). + int get length { + if (_length == null) { + // needs to be checked before more generic isAVector + if (ValueTypeUtils.isFixedTypedVector(_valueType)) { + _length = ValueTypeUtils.fixedTypedVectorElementSize(_valueType); + } else if (_valueType == ValueType.Blob || + ValueTypeUtils.isAVector(_valueType) || + _valueType == ValueType.Map) { + _length = _readUInt( + _indirect - _byteWidth, + BitWidthUtil.fromByteWidth(_byteWidth), + ); + } else if (_valueType == ValueType.Null) { + _length = 0; + } else if (_valueType == ValueType.String) { + final indirect = _indirect; + var sizeByteWidth = _byteWidth; + var size = _readUInt( + indirect - sizeByteWidth, + BitWidthUtil.fromByteWidth(sizeByteWidth), + ); + while (_buffer.getInt8(indirect + size) != 0) { + sizeByteWidth <<= 1; + size = _readUInt( + indirect - sizeByteWidth, + BitWidthUtil.fromByteWidth(sizeByteWidth), + ); + } + _length = size; + } else if (_valueType == ValueType.Key) { + final indirect = _indirect; + var size = 1; + while (_buffer.getInt8(indirect + size) != 0) { + size += 1; + } + _length = size; + } else { + _length = 1; + } + } + return _length!; + } + + /// Returns a minified JSON representation of the underlying FlexBuffer value. + /// + /// This method involves materializing the entire object tree, which may be + /// expensive. It is more efficient to work with [Reference] and access only the needed data. + /// Blob values are represented as base64 encoded string. + String get json { + if (_valueType == ValueType.Bool) { + return boolValue! ? 'true' : 'false'; + } + if (_valueType == ValueType.Null) { + return 'null'; + } + if (ValueTypeUtils.isNumber(_valueType)) { + return jsonEncode(numValue); + } + if (_valueType == ValueType.String) { + return jsonEncode(stringValue); + } + if (_valueType == ValueType.Blob) { + return jsonEncode(base64Encode(blobValue!)); + } + if (ValueTypeUtils.isAVector(_valueType)) { + final result = StringBuffer(); + result.write('['); + for (var i = 0; i < length; i++) { + result.write(this[i].json); + if (i < length - 1) { + result.write(','); + } + } + result.write(']'); + return result.toString(); + } + if (_valueType == ValueType.Map) { + final result = StringBuffer(); + result.write('{'); + for (var i = 0; i < length; i++) { + result.write(jsonEncode(_keyForIndex(i))); + result.write(':'); + result.write(_valueForIndex(i).json); + if (i < length - 1) { + result.write(','); + } + } + result.write('}'); + return result.toString(); + } + throw UnsupportedError( + 'Type: $_valueType is not supported for JSON conversion', + ); + } + + /// Computes the indirect offset of the value. + /// + /// To optimize for the more common case of being called only once, this + /// value is not cached. Callers that need to use it more than once should + /// cache the return value in a local variable. + int get _indirect { + final step = _readUInt(_offset, _parentWidth); + return _offset - step; + } + + int _readInt(int offset, BitWidth width) { + _validateOffset(offset, width); + if (width == BitWidth.width8) { + return _buffer.getInt8(offset); + } + if (width == BitWidth.width16) { + return _buffer.getInt16(offset, Endian.little); + } + if (width == BitWidth.width32) { + return _buffer.getInt32(offset, Endian.little); + } + return _buffer.getInt64(offset, Endian.little); + } + + int _readUInt(int offset, BitWidth width) { + _validateOffset(offset, width); + if (width == BitWidth.width8) { + return _buffer.getUint8(offset); + } + if (width == BitWidth.width16) { + return _buffer.getUint16(offset, Endian.little); + } + if (width == BitWidth.width32) { + return _buffer.getUint32(offset, Endian.little); + } + return _buffer.getUint64(offset, Endian.little); + } + + double _readFloat(int offset, BitWidth width) { + _validateOffset(offset, width); + if (width.index < BitWidth.width32.index) { + throw StateError('Bad width: $width'); + } + + if (width == BitWidth.width32) { + return _buffer.getFloat32(offset, Endian.little); + } + + return _buffer.getFloat64(offset, Endian.little); + } + + void _validateOffset(int offset, BitWidth width) { + if (_offset < 0 || + _buffer.lengthInBytes <= offset + width.index || + offset & (BitWidthUtil.toByteWidth(width) - 1) != 0) { + throw StateError('Bad offset: $offset, width: $width'); + } + } + + int? _keyIndex(String key) { + final input = utf8.encode(key); + final keysVectorOffset = _indirect - _byteWidth * 3; + final indirectOffset = + keysVectorOffset - + _readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth)); + final byteWidth = _readUInt( + keysVectorOffset + _byteWidth, + BitWidthUtil.fromByteWidth(_byteWidth), + ); + var low = 0; + var high = length - 1; + while (low <= high) { + final mid = (high + low) >> 1; + final dif = _diffKeys(input, mid, indirectOffset, byteWidth); + if (dif == 0) return mid; + if (dif < 0) { + high = mid - 1; + } else { + low = mid + 1; + } + } + return null; + } + + int _diffKeys(List input, int index, int indirectOffset, int byteWidth) { + final keyOffset = indirectOffset + index * byteWidth; + final keyIndirectOffset = + keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth)); + for (var i = 0; i < input.length; i++) { + final dif = input[i] - _buffer.getUint8(keyIndirectOffset + i); + if (dif != 0) { + return dif; + } + } + return (_buffer.getUint8(keyIndirectOffset + input.length) == 0) ? 0 : -1; + } + + Reference _valueForIndexWithKey(int index, String key) { + final indirect = _indirect; + final elementOffset = indirect + index * _byteWidth; + final packedType = _buffer.getUint8(indirect + length * _byteWidth + index); + return Reference._( + _buffer, + elementOffset, + BitWidthUtil.fromByteWidth(_byteWidth), + packedType, + "$_path/$key", + ); + } + + Reference _valueForIndex(int index) { + final indirect = _indirect; + final elementOffset = indirect + index * _byteWidth; + final packedType = _buffer.getUint8(indirect + length * _byteWidth + index); + return Reference._( + _buffer, + elementOffset, + BitWidthUtil.fromByteWidth(_byteWidth), + packedType, + "$_path/[$index]", + ); + } + + String _keyForIndex(int index) { + final keysVectorOffset = _indirect - _byteWidth * 3; + final indirectOffset = + keysVectorOffset - + _readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth)); + final byteWidth = _readUInt( + keysVectorOffset + _byteWidth, + BitWidthUtil.fromByteWidth(_byteWidth), + ); + final keyOffset = indirectOffset + index * byteWidth; + final keyIndirectOffset = + keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth)); + var length = 0; + while (_buffer.getUint8(keyIndirectOffset + length) != 0) { + length += 1; + } + return utf8.decode(_buffer.buffer.asUint8List(keyIndirectOffset, length)); + } +} + +class _VectorIterator + with IterableMixin + implements Iterator { + final Reference _vector; + int index = -1; + + _VectorIterator(this._vector); + + @override + Reference get current => _vector[index]; + + @override + bool moveNext() { + index++; + return index < _vector.length; + } + + @override + Iterator get iterator => this; +} + +class _MapKeyIterator with IterableMixin implements Iterator { + final Reference _map; + int index = -1; + + _MapKeyIterator(this._map); + + @override + String get current => _map._keyForIndex(index); + + @override + bool moveNext() { + index++; + return index < _map.length; + } + + @override + Iterator get iterator => this; +} + +class _MapValueIterator + with IterableMixin + implements Iterator { + final Reference _map; + int index = -1; + + _MapValueIterator(this._map); + + @override + Reference get current => _map._valueForIndex(index); + + @override + bool moveNext() { + index++; + return index < _map.length; + } + + @override + Iterator get iterator => this; +} diff --git a/third_party/flatbuffers/dart/lib/src/types.dart b/third_party/flatbuffers/dart/lib/src/types.dart new file mode 100644 index 00000000000..653eabddae2 --- /dev/null +++ b/third_party/flatbuffers/dart/lib/src/types.dart @@ -0,0 +1,197 @@ +import 'dart:typed_data'; + +/// Represents the number of bits a value occupies. +enum BitWidth { width8, width16, width32, width64 } + +class BitWidthUtil { + static int toByteWidth(BitWidth self) { + return 1 << self.index; + } + + static BitWidth width(num value) { + if (value is int) { + var v = value.toInt().abs(); + if (v >> 7 == 0) return BitWidth.width8; + if (v >> 15 == 0) return BitWidth.width16; + if (v >> 31 == 0) return BitWidth.width32; + return BitWidth.width64; + } + return value == _toF32(value as double) + ? BitWidth.width32 + : BitWidth.width64; + } + + static BitWidth uwidth(num value) { + if (value.toInt() == value) { + var v = value.toInt().abs(); + if (v >> 8 == 0) return BitWidth.width8; + if (v >> 16 == 0) return BitWidth.width16; + if (v >> 32 == 0) return BitWidth.width32; + return BitWidth.width64; + } + return value == _toF32(value as double) + ? BitWidth.width32 + : BitWidth.width64; + } + + static BitWidth fromByteWidth(int value) { + if (value == 1) { + return BitWidth.width8; + } + if (value == 2) { + return BitWidth.width16; + } + if (value == 4) { + return BitWidth.width32; + } + if (value == 8) { + return BitWidth.width64; + } + throw Exception('Unexpected value $value'); + } + + static int paddingSize(int bufSize, int scalarSize) { + return (~bufSize + 1) & (scalarSize - 1); + } + + static double _toF32(double value) { + var bdata = ByteData(4); + bdata.setFloat32(0, value); + return bdata.getFloat32(0); + } + + static BitWidth max(BitWidth self, BitWidth other) { + if (self.index < other.index) { + return other; + } + return self; + } +} + +/// Represents all internal FlexBuffer types. +enum ValueType { + Null, + Int, + UInt, + Float, + Key, + String, + IndirectInt, + IndirectUInt, + IndirectFloat, + Map, + Vector, + VectorInt, + VectorUInt, + VectorFloat, + VectorKey, + @Deprecated( + 'VectorString is deprecated due to a flaw in the binary format (https://github.com/google/flatbuffers/issues/5627)', + ) + VectorString, + VectorInt2, + VectorUInt2, + VectorFloat2, + VectorInt3, + VectorUInt3, + VectorFloat3, + VectorInt4, + VectorUInt4, + VectorFloat4, + Blob, + Bool, + VectorBool, +} + +class ValueTypeUtils { + static int toInt(ValueType self) { + if (self == ValueType.VectorBool) return 36; + return self.index; + } + + static ValueType fromInt(int value) { + if (value == 36) return ValueType.VectorBool; + return ValueType.values[value]; + } + + static bool isInline(ValueType self) { + return self == ValueType.Bool || toInt(self) <= toInt(ValueType.Float); + } + + static bool isNumber(ValueType self) { + return toInt(self) >= toInt(ValueType.Int) && + toInt(self) <= toInt(ValueType.Float); + } + + static bool isIndirectNumber(ValueType self) { + return toInt(self) >= toInt(ValueType.IndirectInt) && + toInt(self) <= toInt(ValueType.IndirectFloat); + } + + static bool isTypedVectorElement(ValueType self) { + return self == ValueType.Bool || + (toInt(self) >= toInt(ValueType.Int) && + toInt(self) <= toInt(ValueType.String)); + } + + static bool isTypedVector(ValueType self) { + return self == ValueType.VectorBool || + (toInt(self) >= toInt(ValueType.VectorInt) && + toInt(self) <= toInt(ValueType.VectorString)); + } + + static bool isFixedTypedVector(ValueType self) { + return (toInt(self) >= toInt(ValueType.VectorInt2) && + toInt(self) <= toInt(ValueType.VectorFloat4)); + } + + static bool isAVector(ValueType self) { + return (isTypedVector(self) || + isFixedTypedVector(self) || + self == ValueType.Vector); + } + + static ValueType toTypedVector(ValueType self, int length) { + if (length == 0) { + return ValueTypeUtils.fromInt( + toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt), + ); + } + if (length == 2) { + return ValueTypeUtils.fromInt( + toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt2), + ); + } + if (length == 3) { + return ValueTypeUtils.fromInt( + toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt3), + ); + } + if (length == 4) { + return ValueTypeUtils.fromInt( + toInt(self) - toInt(ValueType.Int) + toInt(ValueType.VectorInt4), + ); + } + throw Exception('unexpected length ' + length.toString()); + } + + static ValueType typedVectorElementType(ValueType self) { + return ValueTypeUtils.fromInt( + toInt(self) - toInt(ValueType.VectorInt) + toInt(ValueType.Int), + ); + } + + static ValueType fixedTypedVectorElementType(ValueType self) { + return ValueTypeUtils.fromInt( + (toInt(self) - toInt(ValueType.VectorInt2)) % 3 + toInt(ValueType.Int), + ); + } + + static int fixedTypedVectorElementSize(ValueType self) { + return (toInt(self) - toInt(ValueType.VectorInt2)) ~/ 3 + 2; + } + + static int packedType(ValueType self, BitWidth bitWidth) { + return bitWidth.index | (toInt(self) << 2); + } +} diff --git a/third_party/flatbuffers/dart/publish.sh b/third_party/flatbuffers/dart/publish.sh new file mode 100755 index 00000000000..bda43ba01bf --- /dev/null +++ b/third_party/flatbuffers/dart/publish.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# Copyright 2018 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Note to pub consumers: this file is used to assist with publishing the +# pub package from the flatbuffers repository and is not meant for general use. +# As pub does not currently provide a way to exclude files, it is included here. +set -e + +command -v dart >/dev/null 2>&1 || { echo >&2 "Require `dart` but it's not installed. Aborting."; exit 1; } + +pushd ../tests +./DartTest.sh +popd + +pushd ../samples +./dart_sample.sh +popd + +dart pub publish + +rm example/monster.fbs +rm test/*.fbs +rm -rf test/sub diff --git a/third_party/flatbuffers/dart/pubspec.yaml b/third_party/flatbuffers/dart/pubspec.yaml new file mode 100644 index 00000000000..3f3545a9272 --- /dev/null +++ b/third_party/flatbuffers/dart/pubspec.yaml @@ -0,0 +1,14 @@ +name: flat_buffers +version: 25.9.23 +description: FlatBuffers reading and writing library for Dart. Based on original work by Konstantin Scheglov and Paul Berry of the Dart SDK team. +homepage: https://github.com/google/flatbuffers +documentation: https://google.github.io/flatbuffers/index.html + +environment: + sdk: '>=2.17.0 <4.0.0' + +dev_dependencies: + test: ^1.17.7 + test_reflective_loader: ^0.2.0 + path: ^1.8.0 + lints: ^1.0.1 diff --git a/third_party/flatbuffers/dart/test/bool_structs.fbs b/third_party/flatbuffers/dart/test/bool_structs.fbs new file mode 100644 index 00000000000..47b26b5b1bd --- /dev/null +++ b/third_party/flatbuffers/dart/test/bool_structs.fbs @@ -0,0 +1,10 @@ +// Test for #7355 +table Foo { + my_foo : foo_properties; +} + +struct foo_properties +{ + a : bool; + b : bool; +} diff --git a/third_party/flatbuffers/dart/test/bool_structs_generated.dart b/third_party/flatbuffers/dart/test/bool_structs_generated.dart new file mode 100644 index 00000000000..ec4732776f9 --- /dev/null +++ b/third_party/flatbuffers/dart/test/bool_structs_generated.dart @@ -0,0 +1,195 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable, constant_identifier_names + +import 'dart:typed_data' show Uint8List; + +import 'package:flat_buffers/flat_buffers.dart' as fb; + +class Foo { + Foo._(this._bc, this._bcOffset); + factory Foo(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _FooReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + FooProperties? get myFoo => + FooProperties.reader.vTableGetNullable(_bc, _bcOffset, 4); + + @override + String toString() { + return 'Foo{myFoo: ${myFoo}}'; + } + + FooT unpack() => FooT(myFoo: myFoo?.unpack()); + + static int pack(fb.Builder fbBuilder, FooT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class FooT implements fb.Packable { + FooPropertiesT? myFoo; + + FooT({this.myFoo}); + + @override + int pack(fb.Builder fbBuilder) { + fbBuilder.startTable(1); + if (myFoo != null) { + fbBuilder.addStruct(0, myFoo!.pack(fbBuilder)); + } + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'FooT{myFoo: ${myFoo}}'; + } +} + +class _FooReader extends fb.TableReader { + const _FooReader(); + + @override + Foo createObject(fb.BufferContext bc, int offset) => Foo._(bc, offset); +} + +class FooBuilder { + FooBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(1); + } + + int addMyFoo(int offset) { + fbBuilder.addStruct(0, offset); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class FooObjectBuilder extends fb.ObjectBuilder { + final FooPropertiesObjectBuilder? _myFoo; + + FooObjectBuilder({FooPropertiesObjectBuilder? myFoo}) : _myFoo = myFoo; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + fbBuilder.startTable(1); + if (_myFoo != null) { + fbBuilder.addStruct(0, _myFoo!.finish(fbBuilder)); + } + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} + +class FooProperties { + FooProperties._(this._bc, this._bcOffset); + + static const fb.Reader reader = _FooPropertiesReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + bool get a => const fb.BoolReader().read(_bc, _bcOffset + 0); + bool get b => const fb.BoolReader().read(_bc, _bcOffset + 1); + + @override + String toString() { + return 'FooProperties{a: ${a}, b: ${b}}'; + } + + FooPropertiesT unpack() => FooPropertiesT(a: a, b: b); + + static int pack(fb.Builder fbBuilder, FooPropertiesT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class FooPropertiesT implements fb.Packable { + bool a; + bool b; + + FooPropertiesT({required this.a, required this.b}); + + @override + int pack(fb.Builder fbBuilder) { + fbBuilder.putBool(b); + fbBuilder.putBool(a); + return fbBuilder.offset; + } + + @override + String toString() { + return 'FooPropertiesT{a: ${a}, b: ${b}}'; + } +} + +class _FooPropertiesReader extends fb.StructReader { + const _FooPropertiesReader(); + + @override + int get size => 2; + + @override + FooProperties createObject(fb.BufferContext bc, int offset) => + FooProperties._(bc, offset); +} + +class FooPropertiesBuilder { + FooPropertiesBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + int finish(bool a, bool b) { + fbBuilder.putBool(b); + fbBuilder.putBool(a); + return fbBuilder.offset; + } +} + +class FooPropertiesObjectBuilder extends fb.ObjectBuilder { + final bool _a; + final bool _b; + + FooPropertiesObjectBuilder({required bool a, required bool b}) + : _a = a, + _b = b; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + fbBuilder.putBool(_b); + fbBuilder.putBool(_a); + return fbBuilder.offset; + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} diff --git a/third_party/flatbuffers/dart/test/enums.fbs b/third_party/flatbuffers/dart/test/enums.fbs new file mode 100644 index 00000000000..a4272a43bc0 --- /dev/null +++ b/third_party/flatbuffers/dart/test/enums.fbs @@ -0,0 +1,10 @@ +enum OptionsEnum : uint32 +{ + A = 1, + B = 2, + C = 3 +} + +table MyTable { + options : [OptionsEnum]; +} diff --git a/third_party/flatbuffers/dart/test/enums_generated.dart b/third_party/flatbuffers/dart/test/enums_generated.dart new file mode 100644 index 00000000000..b57e8fa2221 --- /dev/null +++ b/third_party/flatbuffers/dart/test/enums_generated.dart @@ -0,0 +1,153 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable, constant_identifier_names + +import 'dart:typed_data' show Uint8List; + +import 'package:flat_buffers/flat_buffers.dart' as fb; + +enum OptionsEnum { + A(1), + B(2), + C(3); + + final int value; + const OptionsEnum(this.value); + + factory OptionsEnum.fromValue(int value) { + switch (value) { + case 1: + return OptionsEnum.A; + case 2: + return OptionsEnum.B; + case 3: + return OptionsEnum.C; + default: + throw StateError('Invalid value $value for bit flag enum'); + } + } + + static OptionsEnum? _createOrNull(int? value) => + value == null ? null : OptionsEnum.fromValue(value); + + static const int minValue = 1; + static const int maxValue = 3; + static const fb.Reader reader = _OptionsEnumReader(); +} + +class _OptionsEnumReader extends fb.Reader { + const _OptionsEnumReader(); + + @override + int get size => 4; + + @override + OptionsEnum read(fb.BufferContext bc, int offset) => + OptionsEnum.fromValue(const fb.Uint32Reader().read(bc, offset)); +} + +class MyTable { + MyTable._(this._bc, this._bcOffset); + factory MyTable(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _MyTableReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + List? get options => const fb.ListReader( + OptionsEnum.reader, + ).vTableGetNullable(_bc, _bcOffset, 4); + + @override + String toString() { + return 'MyTable{options: ${options}}'; + } + + MyTableT unpack() => MyTableT( + options: const fb.ListReader( + OptionsEnum.reader, + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 4), + ); + + static int pack(fb.Builder fbBuilder, MyTableT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class MyTableT implements fb.Packable { + List? options; + + MyTableT({this.options}); + + @override + int pack(fb.Builder fbBuilder) { + final int? optionsOffset = options == null + ? null + : fbBuilder.writeListUint32(options!.map((f) => f.value).toList()); + fbBuilder.startTable(1); + fbBuilder.addOffset(0, optionsOffset); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'MyTableT{options: ${options}}'; + } +} + +class _MyTableReader extends fb.TableReader { + const _MyTableReader(); + + @override + MyTable createObject(fb.BufferContext bc, int offset) => + MyTable._(bc, offset); +} + +class MyTableBuilder { + MyTableBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(1); + } + + int addOptionsOffset(int? offset) { + fbBuilder.addOffset(0, offset); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class MyTableObjectBuilder extends fb.ObjectBuilder { + final List? _options; + + MyTableObjectBuilder({List? options}) : _options = options; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? optionsOffset = _options == null + ? null + : fbBuilder.writeListUint32(_options!.map((f) => f.value).toList()); + fbBuilder.startTable(1); + fbBuilder.addOffset(0, optionsOffset); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} diff --git a/third_party/flatbuffers/dart/test/flat_buffers_test.dart b/third_party/flatbuffers/dart/test/flat_buffers_test.dart new file mode 100644 index 00000000000..275a2ef4092 --- /dev/null +++ b/third_party/flatbuffers/dart/test/flat_buffers_test.dart @@ -0,0 +1,1026 @@ +import 'dart:io' as io; +import 'dart:typed_data'; + +import 'package:flat_buffers/flat_buffers.dart'; +import 'package:path/path.dart' as path; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import './bool_structs_generated.dart' as example4; +import './monster_test_my_game.example2_generated.dart' as example2; +import './monster_test_my_game.example_generated.dart' as example; +import 'enums_generated.dart' as example3; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(BuilderTest); + defineReflectiveTests(ObjectAPITest); + defineReflectiveTests(CheckOtherLangaugesData); + defineReflectiveTests(GeneratorTest); + defineReflectiveTests(ListOfEnumsTest); + }); +} + +int indexToField(int index) { + return (1 + 1 + index) * 2; +} + +@reflectiveTest +class CheckOtherLangaugesData { + test_cppData() async { + List data = await io.File( + path.join(path.context.current, 'test', 'monsterdata_test.mon'), + ).readAsBytes(); + example.Monster mon = example.Monster(data); + expect(mon.hp, 80); + expect(mon.mana, 150); + expect(mon.name, 'MyMonster'); + expect(mon.pos!.x, 1.0); + expect(mon.pos!.y, 2.0); + expect(mon.pos!.z, 3.0); + expect(mon.pos!.test1, 3.0); + expect(mon.pos!.test2.value, 2.0); + expect(mon.pos!.test3.a, 5); + expect(mon.pos!.test3.b, 6); + expect(mon.testType!.value, example.AnyTypeId.Monster.value); + expect(mon.test is example.Monster, true); + final monster2 = mon.test as example.Monster; + expect(monster2.name, "Fred"); + + expect(mon.inventory!.length, 5); + expect(mon.inventory!.reduce((cur, next) => cur + next), 10); + final test4 = mon.test4!; + expect(test4.length, 2); + expect(test4[0].a + test4[0].b + test4[1].a + test4[1].b, 100); + expect(mon.testarrayofstring!.length, 2); + expect(mon.testarrayofstring![0], "test1"); + expect(mon.testarrayofstring![1], "test2"); + + // this will fail if accessing any field fails. + expect( + mon.toString(), + 'Monster{' + 'pos: Vec3{x: 1.0, y: 2.0, z: 3.0, test1: 3.0, test2: Color.Green, test3: Test{a: 5, b: 6}}, ' + 'mana: 150, hp: 80, name: MyMonster, inventory: [0, 1, 2, 3, 4], ' + 'color: Color.Blue, testType: AnyTypeId.Monster, ' + 'test: Monster{pos: null, mana: 150, hp: 100, name: Fred, ' + 'inventory: null, color: Color.Blue, testType: null, ' + 'test: null, test4: null, testarrayofstring: null, ' + 'testarrayoftables: null, enemy: null, testnestedflatbuffer: null, ' + 'testempty: null, testbool: false, testhashs32Fnv1: 0, ' + 'testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, ' + 'testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, ' + 'testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, ' + 'testf2: 3.0, testf3: 0.0, testarrayofstring2: null, ' + 'testarrayofsortedstruct: null, flex: null, test5: null, ' + 'vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, ' + 'vectorOfReferrables: null, singleWeakReference: 0, ' + 'vectorOfWeakReferences: null, vectorOfStrongReferrables: null, ' + 'coOwningReference: 0, vectorOfCoOwningReferences: null, ' + 'nonOwningReference: 0, vectorOfNonOwningReferences: null, ' + 'anyUniqueType: null, anyUnique: null, anyAmbiguousType: null, ' + 'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race.None, ' + 'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, ' + 'nativeInline: null, ' + 'longEnumNonEnumDefault: LongEnum._default, ' + 'longEnumNormalDefault: LongEnum.LongOne, nanDefault: NaN, ' + 'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: ' + 'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: ' + '-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}, ' + 'test4: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], ' + 'testarrayofstring: [test1, test2], testarrayoftables: null, ' + 'enemy: Monster{pos: null, mana: 150, hp: 100, name: Fred, ' + 'inventory: null, color: Color.Blue, testType: null, ' + 'test: null, test4: null, testarrayofstring: null, ' + 'testarrayoftables: null, enemy: null, testnestedflatbuffer: null, ' + 'testempty: null, testbool: false, testhashs32Fnv1: 0, ' + 'testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, ' + 'testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, ' + 'testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, ' + 'testf2: 3.0, testf3: 0.0, testarrayofstring2: null, ' + 'testarrayofsortedstruct: null, flex: null, test5: null, ' + 'vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, ' + 'vectorOfReferrables: null, singleWeakReference: 0, ' + 'vectorOfWeakReferences: null, vectorOfStrongReferrables: null, ' + 'coOwningReference: 0, vectorOfCoOwningReferences: null, ' + 'nonOwningReference: 0, vectorOfNonOwningReferences: null, ' + 'anyUniqueType: null, anyUnique: null, anyAmbiguousType: null, ' + 'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race.None, ' + 'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, ' + 'nativeInline: null, ' + 'longEnumNonEnumDefault: LongEnum._default, ' + 'longEnumNormalDefault: LongEnum.LongOne, nanDefault: NaN, ' + 'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: ' + 'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: ' + '-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}, ' + 'testnestedflatbuffer: null, testempty: null, testbool: true, ' + 'testhashs32Fnv1: -579221183, testhashu32Fnv1: 3715746113, ' + 'testhashs64Fnv1: 7930699090847568257, ' + 'testhashu64Fnv1: 7930699090847568257, ' + 'testhashs32Fnv1a: -1904106383, testhashu32Fnv1a: 2390860913, ' + 'testhashs64Fnv1a: 4898026182817603057, ' + 'testhashu64Fnv1a: 4898026182817603057, ' + 'testarrayofbools: [true, false, true], testf: 3.14159, testf2: 3.0, ' + 'testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: [' + 'Ability{id: 0, distance: 45}, Ability{id: 1, distance: 21}, ' + 'Ability{id: 5, distance: 12}], ' + 'flex: null, test5: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], ' + 'vectorOfLongs: [1, 100, 10000, 1000000, 100000000], ' + 'vectorOfDoubles: [-1.7976931348623157e+308, 0.0, 1.7976931348623157e+308], ' + 'parentNamespaceTest: null, vectorOfReferrables: null, ' + 'singleWeakReference: 0, vectorOfWeakReferences: null, ' + 'vectorOfStrongReferrables: null, coOwningReference: 0, ' + 'vectorOfCoOwningReferences: null, nonOwningReference: 0, ' + 'vectorOfNonOwningReferences: null, ' + 'anyUniqueType: null, anyUnique: null, ' + 'anyAmbiguousType: null, ' + 'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race.None, ' + 'testrequirednestedflatbuffer: null, scalarKeySortedTables: [Stat{id: ' + 'miss, val: 0, count: 0}, Stat{id: hit, val: 10, count: 1}], ' + 'nativeInline: Test{a: 1, b: 2}, ' + 'longEnumNonEnumDefault: LongEnum._default, ' + 'longEnumNormalDefault: LongEnum.LongOne, nanDefault: NaN, ' + 'infDefault: Infinity, positiveInfDefault: Infinity, infinityDefault: ' + 'Infinity, positiveInfinityDefault: Infinity, negativeInfDefault: ' + '-Infinity, negativeInfinityDefault: -Infinity, doubleInfDefault: Infinity}', + ); + } +} + +/// Test a custom, fixed-memory allocator (no actual allocations performed) +class CustomAllocator extends Allocator { + final _memory = ByteData(10 * 1024); + int _used = 0; + + Uint8List buffer(int size) => _memory.buffer.asUint8List(_used - size, size); + + @override + ByteData allocate(int size) { + if (size > _memory.lengthInBytes) { + throw UnsupportedError('Trying to allocate too much'); + } + _used = size; + return ByteData.sublistView(_memory, 0, size); + } + + @override + void deallocate(ByteData _) {} +} + +@reflectiveTest +class BuilderTest { + void test_monsterBuilder([Builder? builder]) { + final fbBuilder = builder ?? Builder(); + final str = fbBuilder.writeString('MyMonster'); + + fbBuilder.writeString('test1'); + fbBuilder.writeString('test2', asciiOptimization: true); + final testArrayOfString = fbBuilder.endStructVector(2); + + final fred = fbBuilder.writeString('Fred'); + + final List treasure = [0, 1, 2, 3, 4]; + final inventory = fbBuilder.writeListUint8(treasure); + + final monBuilder = example.MonsterBuilder(fbBuilder) + ..begin() + ..addNameOffset(fred); + final mon2 = monBuilder.finish(); + + final testBuilder = example.TestBuilder(fbBuilder); + testBuilder.finish(10, 20); + testBuilder.finish(30, 40); + final test4 = fbBuilder.endStructVector(2); + + monBuilder + ..begin() + ..addPos( + example.Vec3Builder(fbBuilder).finish( + 1.0, + 2.0, + 3.0, + 3.0, + example.Color.Green, + () => testBuilder.finish(5, 6), + ), + ) + ..addHp(80) + ..addNameOffset(str) + ..addInventoryOffset(inventory) + ..addTestType(example.AnyTypeId.Monster) + ..addTestOffset(mon2) + ..addTest4Offset(test4) + ..addTestarrayofstringOffset(testArrayOfString); + final mon = monBuilder.finish(); + fbBuilder.finish(mon); + + final mon3 = example.Monster(fbBuilder.buffer); + expect(mon3.name, 'MyMonster'); + expect(mon3.pos!.test1, 3.0); + } + + void test_error_addInt32_withoutStartTable([Builder? builder]) { + builder ??= Builder(); + expect(() { + builder!.addInt32(0, 0); + }, throwsA(isA())); + } + + void test_error_addOffset_withoutStartTable() { + Builder builder = Builder(); + expect(() { + builder.addOffset(0, 0); + }, throwsA(isA())); + } + + void test_error_endTable_withoutStartTable() { + Builder builder = Builder(); + expect(() { + builder.endTable(); + }, throwsA(isA())); + } + + void test_error_startTable_duringTable() { + Builder builder = Builder(); + builder.startTable(0); + expect(() { + builder.startTable(0); + }, throwsA(isA())); + } + + void test_error_writeString_duringTable() { + Builder builder = Builder(); + builder.startTable(1); + expect(() { + builder.writeString('12345'); + }, throwsA(isA())); + } + + void test_file_identifier() { + Uint8List byteList; + { + Builder builder = Builder(initialSize: 0); + builder.startTable(0); + int offset = builder.endTable(); + builder.finish(offset, 'Az~ÿ'); + byteList = builder.buffer; + } + // Convert byteList to a ByteData so that we can read data from it. + ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes); + // First 4 bytes are an offset to the table data. + int tableDataLoc = byteData.getUint32(0, Endian.little); + // Next 4 bytes are the file identifier. + expect(byteData.getUint8(4), 65); // 'a' + expect(byteData.getUint8(5), 122); // 'z' + expect(byteData.getUint8(6), 126); // '~' + expect(byteData.getUint8(7), 255); // 'ÿ' + // First 4 bytes of the table data are a backwards offset to the vtable. + int vTableLoc = + tableDataLoc - byteData.getInt32(tableDataLoc, Endian.little); + // First 2 bytes of the vtable are the size of the vtable in bytes, which + // should be 4. + expect(byteData.getUint16(vTableLoc, Endian.little), 4); + // Next 2 bytes are the size of the object in bytes (including the vtable + // pointer), which should be 4. + expect(byteData.getUint16(vTableLoc + 2, Endian.little), 4); + } + + void test_low() { + final allocator = CustomAllocator(); + final builder = Builder(initialSize: 0, allocator: allocator); + + builder.putUint8(1); + expect(allocator.buffer(builder.size()), [1]); + + builder.putUint32(2); + expect(allocator.buffer(builder.size()), [2, 0, 0, 0, 0, 0, 0, 1]); + + builder.putUint8(3); + expect(allocator.buffer(builder.size()), [ + 0, + 0, + 0, + 3, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + ]); + + builder.putUint8(4); + expect(allocator.buffer(builder.size()), [ + 0, + 0, + 4, + 3, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + ]); + + builder.putUint8(5); + expect(allocator.buffer(builder.size()), [ + 0, + 5, + 4, + 3, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + ]); + + builder.putUint32(6); + expect(allocator.buffer(builder.size()), [ + 6, + 0, + 0, + 0, + 0, + 5, + 4, + 3, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + ]); + } + + void test_table_default() { + List byteList; + { + final builder = Builder(initialSize: 0, allocator: CustomAllocator()); + builder.startTable(2); + builder.addInt32(0, 10, 10); + builder.addInt32(1, 20, 10); + int offset = builder.endTable(); + builder.finish(offset); + byteList = builder.buffer; + expect(builder.size(), byteList.length); + } + // read and verify + BufferContext buffer = BufferContext.fromBytes(byteList); + int objectOffset = buffer.derefObject(0); + // was not written, so uses the new default value + expect( + const Int32Reader().vTableGet(buffer, objectOffset, indexToField(0), 15), + 15, + ); + // has the written value + expect( + const Int32Reader().vTableGet(buffer, objectOffset, indexToField(1), 15), + 20, + ); + } + + void test_table_format([Builder? builder]) { + Uint8List byteList; + { + builder ??= Builder(initialSize: 0); + builder.startTable(3); + builder.addInt32(0, 10); + builder.addInt32(1, 20); + builder.addInt32(2, 30); + builder.finish(builder.endTable()); + byteList = builder.buffer; + } + // Convert byteList to a ByteData so that we can read data from it. + ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes); + // First 4 bytes are an offset to the table data. + int tableDataLoc = byteData.getUint32(0, Endian.little); + // First 4 bytes of the table data are a backwards offset to the vtable. + int vTableLoc = + tableDataLoc - byteData.getInt32(tableDataLoc, Endian.little); + // First 2 bytes of the vtable are the size of the vtable in bytes, which + // should be 10. + expect(byteData.getUint16(vTableLoc, Endian.little), 10); + // Next 2 bytes are the size of the object in bytes (including the vtable + // pointer), which should be 16. + expect(byteData.getUint16(vTableLoc + 2, Endian.little), 16); + // Remaining 6 bytes are the offsets within the object where the ints are + // located. + for (int i = 0; i < 3; i++) { + int offset = byteData.getUint16(vTableLoc + 4 + 2 * i, Endian.little); + expect( + byteData.getInt32(tableDataLoc + offset, Endian.little), + 10 + 10 * i, + ); + } + } + + void test_table_string() { + String latinString = 'test'; + String unicodeString = 'Проба пера'; + List byteList; + { + Builder builder = Builder(initialSize: 0); + int? latinStringOffset = builder.writeString( + latinString, + asciiOptimization: true, + ); + int? unicodeStringOffset = builder.writeString( + unicodeString, + asciiOptimization: true, + ); + builder.startTable(2); + builder.addOffset(0, latinStringOffset); + builder.addOffset(1, unicodeStringOffset); + int offset = builder.endTable(); + builder.finish(offset); + byteList = builder.buffer; + } + // read and verify + BufferContext buf = BufferContext.fromBytes(byteList); + int objectOffset = buf.derefObject(0); + expect( + const StringReader().vTableGetNullable( + buf, + objectOffset, + indexToField(0), + ), + latinString, + ); + expect( + const StringReader( + asciiOptimization: true, + ).vTableGetNullable(buf, objectOffset, indexToField(1)), + unicodeString, + ); + } + + void test_table_types([Builder? builder]) { + List byteList; + { + builder ??= Builder(initialSize: 0); + int? stringOffset = builder.writeString('12345'); + builder.startTable(7); + builder.addBool(0, true); + builder.addInt8(1, 10); + builder.addInt32(2, 20); + builder.addOffset(3, stringOffset); + builder.addInt32(4, 40); + builder.addUint32(5, 0x9ABCDEF0); + builder.addUint8(6, 0x9A); + int offset = builder.endTable(); + builder.finish(offset); + byteList = builder.buffer; + } + // read and verify + BufferContext buf = BufferContext.fromBytes(byteList); + int objectOffset = buf.derefObject(0); + expect( + const BoolReader().vTableGetNullable(buf, objectOffset, indexToField(0)), + true, + ); + expect( + const Int8Reader().vTableGetNullable(buf, objectOffset, indexToField(1)), + 10, + ); + expect( + const Int32Reader().vTableGetNullable(buf, objectOffset, indexToField(2)), + 20, + ); + expect( + const StringReader().vTableGetNullable( + buf, + objectOffset, + indexToField(3), + ), + '12345', + ); + expect( + const Int32Reader().vTableGetNullable(buf, objectOffset, indexToField(4)), + 40, + ); + expect( + const Uint32Reader().vTableGetNullable( + buf, + objectOffset, + indexToField(5), + ), + 0x9ABCDEF0, + ); + expect( + const Uint8Reader().vTableGetNullable(buf, objectOffset, indexToField(6)), + 0x9A, + ); + } + + void test_writeList_of_Uint32() { + List values = [10, 100, 12345, 0x9abcdef0]; + // write + List byteList; + { + Builder builder = Builder(initialSize: 0); + int offset = builder.writeListUint32(values); + builder.finish(offset); + byteList = builder.buffer; + } + // read and verify + BufferContext buf = BufferContext.fromBytes(byteList); + List items = const Uint32ListReader().read(buf, 0); + expect(items, hasLength(4)); + expect(items, orderedEquals(values)); + } + + void test_writeList_ofBool() { + void verifyListBooleans(int len, List trueBits) { + // write + List byteList; + { + Builder builder = Builder(initialSize: 0); + List values = List.filled(len, false); + for (int bit in trueBits) { + values[bit] = true; + } + int offset = builder.writeListBool(values); + builder.finish(offset); + byteList = builder.buffer; + } + // read and verify + BufferContext buf = BufferContext.fromBytes(byteList); + List items = const BoolListReader().read(buf, 0); + expect(items, hasLength(len)); + for (int i = 0; i < items.length; i++) { + expect(items[i], trueBits.contains(i), reason: 'bit $i of $len'); + } + } + + verifyListBooleans(0, []); + verifyListBooleans(1, []); + verifyListBooleans(1, [0]); + verifyListBooleans(31, [0, 1]); + verifyListBooleans(31, [1, 2, 24, 25, 30]); + verifyListBooleans(31, [0, 30]); + verifyListBooleans(32, [1, 2, 24, 25, 31]); + verifyListBooleans(33, [1, 2, 24, 25, 32]); + verifyListBooleans(33, [1, 2, 24, 25, 31, 32]); + verifyListBooleans(63, []); + verifyListBooleans(63, [0, 1, 2, 61, 62]); + verifyListBooleans(63, List.generate(63, (i) => i)); + verifyListBooleans(64, []); + verifyListBooleans(64, [0, 1, 2, 61, 62, 63]); + verifyListBooleans(64, [1, 2, 62]); + verifyListBooleans(64, [0, 1, 2, 63]); + verifyListBooleans(64, List.generate(64, (i) => i)); + verifyListBooleans(100, [0, 3, 30, 60, 90, 99]); + } + + void test_writeList_ofInt32() { + List byteList; + { + Builder builder = Builder(initialSize: 0); + int offset = builder.writeListInt32([1, 2, 3, 4, 5]); + builder.finish(offset); + byteList = builder.buffer; + } + // read and verify + BufferContext buf = BufferContext.fromBytes(byteList); + List items = const ListReader(Int32Reader()).read(buf, 0); + expect(items, hasLength(5)); + expect(items, orderedEquals([1, 2, 3, 4, 5])); + } + + void test_writeList_ofFloat64() { + List values = [-1.234567, 3.4E+9, -5.6E-13, 7.8, 12.13]; + // write + List byteList; + { + Builder builder = Builder(initialSize: 0); + int offset = builder.writeListFloat64(values); + builder.finish(offset); + byteList = builder.buffer; + } + + // read and verify + BufferContext buf = BufferContext.fromBytes(byteList); + List items = const Float64ListReader().read(buf, 0); + + expect(items, hasLength(values.length)); + for (int i = 0; i < values.length; i++) { + expect(values[i], closeTo(items[i], .001)); + } + } + + void test_writeList_ofFloat32() { + List values = [1.0, 2.23, -3.213, 7.8, 12.13]; + // write + List byteList; + { + Builder builder = Builder(initialSize: 0); + int offset = builder.writeListFloat32(values); + builder.finish(offset); + byteList = builder.buffer; + } + // read and verify + BufferContext buf = BufferContext.fromBytes(byteList); + List items = const Float32ListReader().read(buf, 0); + expect(items, hasLength(5)); + for (int i = 0; i < values.length; i++) { + expect(values[i], closeTo(items[i], .001)); + } + } + + void test_writeList_ofObjects([Builder? builder]) { + List byteList; + { + builder ??= Builder(initialSize: 0); + // write the object #1 + int object1; + { + builder.startTable(2); + builder.addInt32(0, 10); + builder.addInt32(1, 20); + object1 = builder.endTable(); + } + // write the object #1 + int object2; + { + builder.startTable(2); + builder.addInt32(0, 100); + builder.addInt32(1, 200); + object2 = builder.endTable(); + } + // write the list + int offset = builder.writeList([object1, object2]); + builder.finish(offset); + byteList = builder.buffer; + } + // read and verify + BufferContext buf = BufferContext.fromBytes(byteList); + List items = const ListReader( + TestPointReader(), + ).read(buf, 0); + expect(items, hasLength(2)); + expect(items[0].x, 10); + expect(items[0].y, 20); + expect(items[1].x, 100); + expect(items[1].y, 200); + } + + void test_writeList_ofStrings_asRoot() { + List byteList; + { + Builder builder = Builder(initialSize: 0); + int? str1 = builder.writeString('12345'); + int? str2 = builder.writeString('ABC'); + int offset = builder.writeList([str1, str2]); + builder.finish(offset); + byteList = builder.buffer; + } + // read and verify + BufferContext buf = BufferContext.fromBytes(byteList); + List items = const ListReader(StringReader()).read(buf, 0); + expect(items, hasLength(2)); + expect(items, contains('12345')); + expect(items, contains('ABC')); + } + + void test_writeList_ofStrings_inObject([Builder? builder]) { + List byteList; + { + builder ??= Builder(initialSize: 0); + int listOffset = builder.writeList([ + builder.writeString('12345'), + builder.writeString('ABC'), + ]); + builder.startTable(1); + builder.addOffset(0, listOffset); + int offset = builder.endTable(); + builder.finish(offset); + byteList = builder.buffer; + } + // read and verify + BufferContext buf = BufferContext.fromBytes(byteList); + StringListWrapperImpl reader = StringListWrapperReader().read(buf, 0); + List? items = reader.items; + expect(items, hasLength(2)); + expect(items, contains('12345')); + expect(items, contains('ABC')); + } + + void test_writeList_ofUint32() { + List byteList; + { + Builder builder = Builder(initialSize: 0); + int offset = builder.writeListUint32([1, 2, 0x9ABCDEF0]); + builder.finish(offset); + byteList = builder.buffer; + } + // read and verify + BufferContext buf = BufferContext.fromBytes(byteList); + List items = const Uint32ListReader().read(buf, 0); + expect(items, hasLength(3)); + expect(items, orderedEquals([1, 2, 0x9ABCDEF0])); + } + + void test_writeList_ofUint16() { + List byteList; + { + Builder builder = Builder(initialSize: 0); + int offset = builder.writeListUint16([1, 2, 60000]); + builder.finish(offset); + byteList = builder.buffer; + } + // read and verify + BufferContext buf = BufferContext.fromBytes(byteList); + List items = const Uint16ListReader().read(buf, 0); + expect(items, hasLength(3)); + expect(items, orderedEquals([1, 2, 60000])); + } + + void test_writeList_ofUint8() { + List byteList; + { + Builder builder = Builder(initialSize: 0); + int offset = builder.writeListUint8([1, 2, 3, 4, 0x9A, 0xFA]); + builder.finish(offset); + byteList = builder.buffer; + } + // read and verify + BufferContext buf = BufferContext.fromBytes(byteList); + const buffOffset = 8; // 32-bit offset to the list, + 32-bit length + for (final lazy in [true, false]) { + List items = Uint8ListReader(lazy: lazy).read(buf, 0); + expect(items, hasLength(6)); + expect(items, orderedEquals([1, 2, 3, 4, 0x9A, 0xFA])); + + // overwrite the buffer to verify the laziness + buf.buffer.setUint8(buffOffset + 1, 99); + expect(items, orderedEquals([1, lazy ? 99 : 2, 3, 4, 0x9A, 0xFA])); + + // restore the previous value for the next loop + buf.buffer.setUint8(buffOffset + 1, 2); + } + } + + void test_reset() { + // We'll run a selection of tests , reusing the builder between them. + final testCases = [ + test_monsterBuilder, + test_error_addInt32_withoutStartTable, + test_table_format, + test_table_types, + test_writeList_ofObjects, + test_writeList_ofStrings_inObject, + ]; + + // Execute all test cases in all permutations of their order. + // To do that, we generate permutations of test case indexes. + final testCasesPermutations = _permutationsOf( + List.generate(testCases.length, (index) => index), + ); + expect(testCasesPermutations.length, _factorial(testCases.length)); + + for (var indexes in testCasesPermutations) { + // print the order so failures are reproducible + printOnFailure('Running reset() test cases in order: $indexes'); + + Builder? builder; + for (var index in indexes) { + if (builder == null) { + // Initial size small enough so at least one test case increases it. + // On the other hand, it's large enough so that some test cases don't. + builder = Builder(initialSize: 32); + } else { + builder.reset(); + } + testCases[index](builder); + } + } + } + + // Generate permutations of the given list + List> _permutationsOf(List source) { + final result = >[]; + + void permutate(List items, int startAt) { + for (var i = startAt; i < items.length; i++) { + List permutation = items.toList(growable: false); + permutation[i] = items[startAt]; + permutation[startAt] = items[i]; + + // add the current list upon reaching the end + if (startAt == items.length - 1) { + result.add(items); + } else { + permutate(permutation, startAt + 1); + } + } + } + + permutate(source, 0); + return result; + } + + // a very simple implementation of n! + int _factorial(int n) { + var result = 1; + for (var i = 2; i <= n; i++) { + result *= i; + } + return result; + } +} + +@reflectiveTest +class ObjectAPITest { + void test_tableStat() { + final object1 = example.StatT(count: 3, id: "foo", val: 4); + final fbb = Builder(); + fbb.finish(object1.pack(fbb)); + final object2 = example.Stat(fbb.buffer).unpack(); + expect(object2.count, object1.count); + expect(object2.id, object1.id); + expect(object2.val, object1.val); + expect(object2.toString(), object1.toString()); + } + + void test_tableMonster() { + final monster = example.MonsterT() + ..pos = example.Vec3T( + x: 1, + y: 2, + z: 3, + test1: 4.0, + test2: example.Color.Red, + test3: example.TestT(a: 1, b: 2), + ) + ..mana = 2 + ..name = 'Monstrous' + ..inventory = [24, 42] + ..color = example.Color.Green + // TODO be smarter for unions and automatically set the `type` field? + ..testType = example.AnyTypeId.MyGame_Example2_Monster + ..test = example2.MonsterT() + ..test4 = [example.TestT(a: 3, b: 4), example.TestT(a: 5, b: 6)] + ..testarrayofstring = ["foo", "bar"] + ..testarrayoftables = [example.MonsterT(name: 'Oof')] + ..enemy = example.MonsterT(name: 'Enemy') + ..testarrayofbools = [false, true, false] + ..testf = 42.24 + ..testarrayofsortedstruct = [ + example.AbilityT(id: 1, distance: 5), + example.AbilityT(id: 3, distance: 7), + ] + ..vectorOfLongs = [5, 6, 7] + ..vectorOfDoubles = [8.9, 9.0, 10.1, 11.2] + ..anyAmbiguousType = example.AnyAmbiguousAliasesTypeId.M2 + ..anyAmbiguous = null + ..vectorOfEnums = [example.Color.Blue, example.Color.Green] + ..signedEnum = example.Race.None; + + final fbBuilder = Builder(); + final offset = monster.pack(fbBuilder); + expect(offset, isNonZero); + fbBuilder.finish(offset); + final data = fbBuilder.buffer; + + // TODO currently broken because of struct builder issue, see #6688 + // final monster2 = example.Monster(data); // Monster (reader) + // expect( + // // map Monster => MonsterT, Vec3 => Vec3T, ... + // monster2.toString().replaceAllMapped( + // RegExp('([a-zA-z0-9]+){'), (match) => match.group(1) + 'T{'), + // monster.toString()); + // + // final monster3 = monster2.unpack(); // MonsterT + // expect(monster3.toString(), monster.toString()); + } + + void test_Lists() { + // Ensure unpack() reads lists eagerly by reusing the same builder and + // overwriting data. Why: because standard reader reads lists lazily... + final fbb = Builder(); + + final object1 = example.TypeAliasesT(v8: [1, 2, 3], vf64: [5, 6]); + fbb.finish(object1.pack(fbb)); + final object1Read = example.TypeAliases(fbb.buffer).unpack(); + + // overwrite the original buffer by writing to the same builder + fbb.reset(); + final object2 = example.TypeAliasesT(v8: [7, 8, 9], vf64: [10, 11]); + fbb.finish(object2.pack(fbb)); + final object2Read = example.TypeAliases(fbb.buffer).unpack(); + + // this is fine even with lazy lists: + expect(object2.toString(), object2Read.toString()); + + // this fails with lazy lists: + expect(object1.toString(), object1Read.toString()); + + // empty list must be serialized as such (were stored NULL before v2.0) + fbb.reset(); + final object3 = example.TypeAliasesT(v8: [], vf64: null); + fbb.finish(object3.pack(fbb)); + final object3Read = example.TypeAliases(fbb.buffer).unpack(); + expect(object3.toString(), object3Read.toString()); + } +} + +class StringListWrapperImpl { + final BufferContext bp; + final int offset; + + StringListWrapperImpl(this.bp, this.offset); + + List? get items => const ListReader( + StringReader(), + ).vTableGetNullable(bp, offset, indexToField(0)); +} + +class StringListWrapperReader extends TableReader { + const StringListWrapperReader(); + + @override + StringListWrapperImpl createObject(BufferContext object, int offset) { + return StringListWrapperImpl(object, offset); + } +} + +class TestPointImpl { + final BufferContext bp; + final int offset; + + TestPointImpl(this.bp, this.offset); + + int get x => const Int32Reader().vTableGet(bp, offset, indexToField(0), 0); + + int get y => const Int32Reader().vTableGet(bp, offset, indexToField(1), 0); +} + +class TestPointReader extends TableReader { + const TestPointReader(); + + @override + TestPointImpl createObject(BufferContext object, int offset) { + return TestPointImpl(object, offset); + } +} + +@reflectiveTest +class GeneratorTest { + void test_constantEnumValues() async { + expect(example.Color.values, same(example.Color.values)); + expect(example.Race.values, same(example.Race.values)); + expect(example.AnyTypeId.values, same(example.AnyTypeId.values)); + expect( + example.AnyUniqueAliasesTypeId.values, + same(example.AnyUniqueAliasesTypeId.values), + ); + expect( + example.AnyAmbiguousAliasesTypeId.values, + same(example.AnyAmbiguousAliasesTypeId.values), + ); + } +} + +// See #6869 +@reflectiveTest +class ListOfEnumsTest { + void test_listOfEnums() async { + var mytable = example3.MyTableObjectBuilder( + options: [ + example3.OptionsEnum.A, + example3.OptionsEnum.B, + example3.OptionsEnum.C, + ], + ); + var bytes = mytable.toBytes(); + var mytable_read = example3.MyTable(bytes); + expect(mytable_read.options![0].value, example3.OptionsEnum.A.value); + expect(mytable_read.options![1].value, example3.OptionsEnum.B.value); + expect(mytable_read.options![2].value, example3.OptionsEnum.C.value); + } +} + +@reflectiveTest +class BoolInStructTest { + void test_boolInStruct() async { + var mystruct = example4.FooObjectBuilder( + myFoo: example4.FooPropertiesObjectBuilder(a: true, b: false), + ); + var bytes = mystruct.toBytes(); + var mystruct_read = example4.Foo(bytes); + expect(mystruct_read.myFoo!.a, true); + expect(mystruct_read.myFoo!.b, false); + } +} diff --git a/third_party/flatbuffers/dart/test/flex_builder_test.dart b/third_party/flatbuffers/dart/test/flex_builder_test.dart new file mode 100644 index 00000000000..0f766de7385 --- /dev/null +++ b/third_party/flatbuffers/dart/test/flex_builder_test.dart @@ -0,0 +1,647 @@ +import 'dart:typed_data'; + +import 'package:flat_buffers/flex_buffers.dart' show Builder; +import 'package:test/test.dart'; + +void main() { + test('build with single value', () { + { + var flx = Builder(); + flx.addNull(); + expect(flx.finish(), [0, 0, 1]); + } + { + var flx = Builder(); + flx.addBool(true); + expect(flx.finish(), [1, 104, 1]); + } + { + var flx = Builder(); + flx.addBool(false); + expect(flx.finish(), [0, 104, 1]); + } + { + var flx = Builder(); + flx.addInt(1); + expect(flx.finish(), [1, 4, 1]); + } + { + var flx = Builder(); + flx.addInt(230); + expect(flx.finish(), [230, 0, 5, 2]); + } + { + var flx = Builder(); + flx.addInt(1025); + expect(flx.finish(), [1, 4, 5, 2]); + } + { + var flx = Builder(); + flx.addInt(-1025); + expect(flx.finish(), [255, 251, 5, 2]); + } + { + var builder = Builder()..addDouble(1.0); + expect(builder.finish(), [0, 0, 128, 63, 14, 4]); + } + { + var flx = Builder(); + flx.addDouble(0.1); + expect(flx.finish(), [154, 153, 153, 153, 153, 153, 185, 63, 15, 8]); + } + { + var flx = Builder(); + flx.addDouble(0.5); + expect(flx.finish(), [0, 0, 0, 63, 14, 4]); + } + { + var flx = Builder(); + flx.addString('Maxim'); + expect(flx.finish(), [5, 77, 97, 120, 105, 109, 0, 6, 20, 1]); + } + { + var flx = Builder(); + flx.addString('hello 😱'); + expect(flx.finish(), [ + 10, + 104, + 101, + 108, + 108, + 111, + 32, + 240, + 159, + 152, + 177, + 0, + 11, + 20, + 1, + ]); + } + }); + + test('build vector', () { + { + var flx = Builder() + ..startVector() + ..addInt(1) + ..addInt(2) + ..end(); + expect(flx.finish(), [1, 2, 2, 64, 1]); + } + { + var flx = Builder() + ..startVector() + ..addInt(-1) + ..addInt(256) + ..end(); + expect(flx.finish(), [255, 255, 0, 1, 4, 65, 1]); + } + { + var flx = Builder() + ..startVector() + ..addInt(-45) + ..addInt(256000) + ..end(); + expect(flx.finish(), [211, 255, 255, 255, 0, 232, 3, 0, 8, 66, 1]); + } + { + var flx = Builder() + ..startVector() + ..addDouble(1.1) + ..addDouble(-256) + ..end(); + expect(flx.finish(), [ + 154, + 153, + 153, + 153, + 153, + 153, + 241, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 112, + 192, + 16, + 75, + 1, + ]); + } + { + var flx = Builder() + ..startVector() + ..addInt(1) + ..addInt(2) + ..addInt(4) + ..end(); + expect(flx.finish(), [1, 2, 4, 3, 76, 1]); + } + { + var flx = Builder() + ..startVector() + ..addInt(-1) + ..addInt(256) + ..addInt(4) + ..end(); + expect(flx.finish(), [255, 255, 0, 1, 4, 0, 6, 77, 1]); + } + { + var flx = Builder() + ..startVector() + ..startVector() + ..addInt(61) + ..end() + ..addInt(64) + ..end(); + expect(flx.finish(), [1, 61, 2, 2, 64, 44, 4, 4, 40, 1]); + } + { + var flx = Builder() + ..startVector() + ..addString('foo') + ..addString('bar') + ..addString('baz') + ..end(); + expect(flx.finish(), [ + 3, + 102, + 111, + 111, + 0, + 3, + 98, + 97, + 114, + 0, + 3, + 98, + 97, + 122, + 0, + 3, + 15, + 11, + 7, + 3, + 60, + 1, + ]); + } + { + var flx = Builder() + ..startVector() + ..addString('foo') + ..addString('bar') + ..addString('baz') + ..addString('foo') + ..addString('bar') + ..addString('baz') + ..end(); + expect(flx.finish(), [ + 3, + 102, + 111, + 111, + 0, + 3, + 98, + 97, + 114, + 0, + 3, + 98, + 97, + 122, + 0, + 6, + 15, + 11, + 7, + 18, + 14, + 10, + 6, + 60, + 1, + ]); + } + { + var flx = Builder() + ..startVector() + ..addBool(true) + ..addBool(false) + ..addBool(true) + ..end(); + expect(flx.finish(), [3, 1, 0, 1, 3, 144, 1]); + } + { + var flx = Builder() + ..startVector() + ..addString('foo') + ..addInt(1) + ..addInt(-5) + ..addDouble(1.3) + ..addBool(true) + ..end(); + expect(flx.finish(), [ + 3, + 102, + 111, + 111, + 0, + 0, + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 15, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 251, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 205, + 204, + 204, + 204, + 204, + 204, + 244, + 63, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 20, + 4, + 4, + 15, + 104, + 45, + 43, + 1, + ]); + } + }); + + test('build map', () { + { + var flx = Builder() + ..startMap() + ..addKey('a') + ..addInt(12) + ..end(); + expect(flx.finish(), [97, 0, 1, 3, 1, 1, 1, 12, 4, 2, 36, 1]); + } + { + var flx = Builder() + ..startMap() + ..addKey('a') + ..addInt(12) + ..addKey('') + ..addInt(45) + ..end(); + expect(flx.finish(), [ + 97, + 0, + 0, + 2, + 2, + 5, + 2, + 1, + 2, + 45, + 12, + 4, + 4, + 4, + 36, + 1, + ]); + } + { + var flx = Builder() + ..startVector() + ..startMap() + ..addKey('something') + ..addInt(12) + ..end() + ..startMap() + ..addKey('something') + ..addInt(45) + ..end() + ..end(); + expect(flx.finish(), [ + 115, + 111, + 109, + 101, + 116, + 104, + 105, + 110, + 103, + 0, + 1, + 11, + 1, + 1, + 1, + 12, + 4, + 6, + 1, + 1, + 45, + 4, + 2, + 8, + 4, + 36, + 36, + 4, + 40, + 1, + ]); + } + }); + + test('build blob', () { + { + var flx = Builder()..addBlob(Uint8List.fromList([1, 2, 3]).buffer); + expect(flx.finish(), [3, 1, 2, 3, 3, 100, 1]); + } + }); + + test('build from object', () { + expect( + Builder.buildFromObject( + Uint8List.fromList([1, 2, 3]).buffer, + ).asUint8List(), + [3, 1, 2, 3, 3, 100, 1], + ); + expect(Builder.buildFromObject(null).asUint8List(), [0, 0, 1]); + expect(Builder.buildFromObject(true).asUint8List(), [1, 104, 1]); + expect(Builder.buildFromObject(false).asUint8List(), [0, 104, 1]); + expect(Builder.buildFromObject(25).asUint8List(), [25, 4, 1]); + expect(Builder.buildFromObject(-250).asUint8List(), [6, 255, 5, 2]); + expect(Builder.buildFromObject(-2.50).asUint8List(), [ + 0, + 0, + 32, + 192, + 14, + 4, + ]); + expect(Builder.buildFromObject('Maxim').asUint8List(), [ + 5, + 77, + 97, + 120, + 105, + 109, + 0, + 6, + 20, + 1, + ]); + expect( + Builder.buildFromObject([1, 3.3, 'max', true, null, false]).asUint8List(), + [ + 3, + 109, + 97, + 120, + 0, + 0, + 0, + 0, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 102, + 102, + 102, + 102, + 102, + 102, + 10, + 64, + 31, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4, + 15, + 20, + 104, + 0, + 104, + 54, + 43, + 1, + ], + ); + expect( + Builder.buildFromObject([ + {'something': 12}, + {'something': 45}, + ]).asUint8List(), + [ + 115, + 111, + 109, + 101, + 116, + 104, + 105, + 110, + 103, + 0, + 1, + 11, + 1, + 1, + 1, + 12, + 4, + 6, + 1, + 1, + 45, + 4, + 2, + 8, + 4, + 36, + 36, + 4, + 40, + 1, + ], + ); + }); + + test('add double indirectly', () { + var flx = Builder()..addDoubleIndirectly(0.1); + expect(flx.finish(), [154, 153, 153, 153, 153, 153, 185, 63, 8, 35, 1]); + }); + + test('add double indirectly to vector with cache', () { + var flx = Builder() + ..startVector() + ..addDoubleIndirectly(0.1, cache: true) + ..addDoubleIndirectly(0.1, cache: true) + ..addDoubleIndirectly(0.1, cache: true) + ..addDoubleIndirectly(0.1, cache: true) + ..end(); + expect(flx.finish(), [ + 154, + 153, + 153, + 153, + 153, + 153, + 185, + 63, + 4, + 9, + 10, + 11, + 12, + 35, + 35, + 35, + 35, + 8, + 40, + 1, + ]); + }); + + test('add int indirectly', () { + var flx = Builder()..addIntIndirectly(2345234523452345); + expect(flx.finish(), [185, 115, 175, 118, 250, 84, 8, 0, 8, 27, 1]); + }); + + test('add int indirectly to vector with cache', () { + var flx = Builder() + ..startVector() + ..addIntIndirectly(2345234523452345, cache: true) + ..addIntIndirectly(2345234523452345, cache: true) + ..addIntIndirectly(2345234523452345, cache: true) + ..addIntIndirectly(2345234523452345, cache: true) + ..end(); + expect(flx.finish(), [ + 185, + 115, + 175, + 118, + 250, + 84, + 8, + 0, + 4, + 9, + 10, + 11, + 12, + 27, + 27, + 27, + 27, + 8, + 40, + 1, + ]); + }); + + test('snapshot', () { + var flx = Builder(); + flx.startVector(); + flx.addInt(12); + expect(flx.snapshot().asUint8List(), [1, 12, 1, 44, 1]); + flx.addInt(24); + expect(flx.snapshot().asUint8List(), [12, 24, 2, 64, 1]); + flx.addInt(45); + expect(flx.snapshot().asUint8List(), [12, 24, 45, 3, 76, 1]); + }); +} diff --git a/third_party/flatbuffers/dart/test/flex_reader_test.dart b/third_party/flatbuffers/dart/test/flex_reader_test.dart new file mode 100644 index 00000000000..d77d1da462c --- /dev/null +++ b/third_party/flatbuffers/dart/test/flex_reader_test.dart @@ -0,0 +1,1032 @@ +import 'dart:typed_data'; + +import 'package:flat_buffers/flex_buffers.dart' show Reference, Builder; +import 'package:test/test.dart'; + +void main() { + test('is null', () { + expect(Reference.fromBuffer(b([0, 0, 1])).isNull, isTrue); + }); + + test('bool value', () { + expect(Reference.fromBuffer(b([1, 104, 1])).boolValue, isTrue); + expect(Reference.fromBuffer(b([0, 104, 1])).boolValue, isFalse); + }); + test('int value', () { + expect(Reference.fromBuffer(b([25, 4, 1])).intValue, 25); + expect(Reference.fromBuffer(b([231, 4, 1])).intValue, -25); + expect(Reference.fromBuffer(b([230, 8, 1])).intValue, 230); + expect(Reference.fromBuffer(b([230, 0, 5, 2])).intValue, 230); + expect(Reference.fromBuffer(b([1, 4, 5, 2])).intValue, 1025); + expect(Reference.fromBuffer(b([255, 251, 5, 2])).intValue, -1025); + expect(Reference.fromBuffer(b([1, 4, 9, 2])).intValue, 1025); + expect( + Reference.fromBuffer(b([255, 255, 255, 127, 6, 4])).intValue, + 2147483647, + ); + expect(Reference.fromBuffer(b([0, 0, 0, 128, 6, 4])).intValue, -2147483648); + expect( + Reference.fromBuffer(b([255, 255, 255, 255, 0, 0, 0, 0, 7, 8])).intValue, + 4294967295, + ); + expect( + Reference.fromBuffer( + b([255, 255, 255, 255, 255, 255, 255, 127, 7, 8]), + ).intValue, + 9223372036854775807, + ); + expect( + Reference.fromBuffer(b([0, 0, 0, 0, 0, 0, 0, 128, 7, 8])).intValue, + -9223372036854775808, + ); + // Dart does not really support UInt64 + // expect(FlxValue.fromBuffer(b([255, 255, 255, 255, 255, 255, 255, 255, 11, 8])).intValue, 18446744073709551615); + }); + test('double value', () { + expect(Reference.fromBuffer(b([0, 0, 128, 63, 14, 4])).doubleValue, 1.0); + expect(Reference.fromBuffer(b([0, 0, 144, 64, 14, 4])).doubleValue, 4.5); + expect( + Reference.fromBuffer(b([205, 204, 204, 61, 14, 4])).doubleValue, + closeTo(.1, .001), + ); + expect( + Reference.fromBuffer( + b([154, 153, 153, 153, 153, 153, 185, 63, 15, 8]), + ).doubleValue, + .1, + ); + }); + test('num value', () { + expect(Reference.fromBuffer(b([0, 0, 144, 64, 14, 4])).numValue, 4.5); + expect( + Reference.fromBuffer(b([205, 204, 204, 61, 14, 4])).numValue, + closeTo(.1, .001), + ); + expect( + Reference.fromBuffer( + b([154, 153, 153, 153, 153, 153, 185, 63, 15, 8]), + ).numValue, + .1, + ); + expect(Reference.fromBuffer(b([255, 251, 5, 2])).numValue, -1025); + }); + test('string value', () { + expect( + Reference.fromBuffer( + b([5, 77, 97, 120, 105, 109, 0, 6, 20, 1]), + ).stringValue, + 'Maxim', + ); + expect( + Reference.fromBuffer( + b([10, 104, 101, 108, 108, 111, 32, 240, 159, 152, 177, 0, 11, 20, 1]), + ).stringValue, + 'hello 😱', + ); + }); + test('blob value', () { + expect(Reference.fromBuffer(b([3, 1, 2, 3, 3, 100, 1])).blobValue, [ + 1, + 2, + 3, + ]); + }); + test('bool vector', () { + var flx = Reference.fromBuffer(b([3, 1, 0, 1, 3, 144, 1])); + expect(flx[0].boolValue, true); + expect(flx[1].boolValue, false); + expect(flx[2].boolValue, true); + }); + test('number vector', () { + testNumbers([3, 1, 2, 3, 3, 44, 1], [1, 2, 3]); + testNumbers([3, 255, 2, 3, 3, 44, 1], [-1, 2, 3]); + testNumbers([3, 0, 1, 0, 43, 2, 3, 0, 6, 45, 1], [1, 555, 3]); + testNumbers( + [3, 0, 0, 0, 1, 0, 0, 0, 204, 216, 0, 0, 3, 0, 0, 0, 12, 46, 1], + [1, 55500, 3], + ); + testNumbers( + [ + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 172, + 128, + 94, + 239, + 12, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 24, + 47, + 1, + ], + [1, 55555555500, 3], + ); + testNumbers( + [3, 0, 0, 0, 0, 0, 192, 63, 0, 0, 32, 64, 0, 0, 96, 64, 12, 54, 1], + [1.5, 2.5, 3.5], + ); + testNumbers( + [ + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 154, + 153, + 153, + 153, + 153, + 153, + 241, + 63, + 154, + 153, + 153, + 153, + 153, + 153, + 1, + 64, + 102, + 102, + 102, + 102, + 102, + 102, + 10, + 64, + 24, + 55, + 1, + ], + [1.1, 2.2, 3.3], + ); + }); + test('number vector, fixed type', () { + testNumbers([1, 2, 2, 64, 1], [1, 2]); + testNumbers([255, 255, 0, 1, 4, 65, 1], [-1, 256]); + testNumbers([211, 255, 255, 255, 0, 232, 3, 0, 8, 66, 1], [-45, 256000]); + testNumbers( + [ + 211, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 127, + 16, + 67, + 1, + ], + [-45, 9223372036854775807], + ); + + testNumbers([1, 2, 2, 68, 1], [1, 2]); + testNumbers([1, 0, 0, 1, 4, 69, 1], [1, 256]); + testNumbers([45, 0, 0, 0, 0, 232, 3, 0, 8, 70, 1], [45, 256000]); + + testNumbers([205, 204, 140, 63, 0, 0, 0, 192, 8, 74, 1], [1.1, -2]); + testNumbers( + [ + 154, + 153, + 153, + 153, + 153, + 153, + 241, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 112, + 192, + 16, + 75, + 1, + ], + [1.1, -256], + ); + + testNumbers( + [211, 255, 255, 255, 0, 232, 3, 0, 4, 0, 0, 0, 12, 78, 1], + [-45, 256000, 4], + ); + + testNumbers( + [ + 211, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 127, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 9, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 32, + 91, + 1, + ], + [-45, 9223372036854775807, 4, 9], + ); + + testNumbers( + [ + 45, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 127, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 9, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 32, + 95, + 1, + ], + [45, 9223372036854775807, 4, 9], + ); + + testNumbers( + [ + 154, + 153, + 153, + 153, + 153, + 153, + 241, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 112, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 16, + 64, + 24, + 87, + 1, + ], + [1.1, 256, 4], + ); + + testNumbers( + [ + 154, + 153, + 153, + 153, + 153, + 153, + 241, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 112, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 16, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 34, + 64, + 32, + 99, + 1, + ], + [1.1, 256, 4, 9], + ); + }); + test('string vector', () { + testStrings( + [ + 3, + 102, + 111, + 111, + 0, + 3, + 98, + 97, + 114, + 0, + 3, + 98, + 97, + 122, + 0, + 3, + 15, + 11, + 7, + 3, + 60, + 1, + ], + ['foo', 'bar', 'baz'], + ); + testStrings( + [ + 3, + 102, + 111, + 111, + 0, + 3, + 98, + 97, + 114, + 0, + 3, + 98, + 97, + 122, + 0, + 6, + 15, + 11, + 7, + 18, + 14, + 10, + 6, + 60, + 1, + ], + ['foo', 'bar', 'baz', 'foo', 'bar', 'baz'], + ); + }); + test('mixed vector', () { + var flx = Reference.fromBuffer( + b([ + 3, + 102, + 111, + 111, + 0, + 0, + 0, + 0, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 15, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 251, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 205, + 204, + 204, + 204, + 204, + 204, + 244, + 63, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 20, + 4, + 4, + 15, + 104, + 45, + 43, + 1, + ]), + ); + expect(flx.length, 5); + expect(flx[0].stringValue, 'foo'); + expect(flx[1].numValue, 1); + expect(flx[2].numValue, -5); + expect(flx[3].numValue, 1.3); + expect(flx[4].boolValue, true); + }); + + test('single value map', () { + var flx = Reference.fromBuffer(b([97, 0, 1, 3, 1, 1, 1, 12, 4, 2, 36, 1])); + expect(flx.length, 1); + expect(flx['a'].numValue, 12); + }); + test('two value map', () { + var flx = Reference.fromBuffer( + b([0, 97, 0, 2, 4, 4, 2, 1, 2, 45, 12, 4, 4, 4, 36, 1]), + ); + expect(flx.length, 2); + expect(flx['a'].numValue, 12); + expect(flx[''].numValue, 45); + }); + test('complex map', () { + var flx = complexMap(); + expect(flx.length, 5); + expect(flx['age'].numValue, 35); + expect(flx['weight'].numValue, 72.5); + expect(flx['name'].stringValue, 'Maxim'); + + expect(flx['flags'].length, 4); + expect(flx['flags'][0].boolValue, true); + expect(flx['flags'][1].boolValue, false); + expect(flx['flags'][2].boolValue, true); + expect(flx['flags'][3].boolValue, true); + + expect(flx['address'].length, 3); + expect(flx['address']['city'].stringValue, 'Bla'); + expect(flx['address']['zip'].stringValue, '12345'); + expect(flx['address']['countryCode'].stringValue, 'XX'); + + expect( + () => flx['address']['country'].stringValue, + throwsA( + predicate( + (dynamic e) => + e is ArgumentError && + e.message == + 'Key: [country] is not applicable on: //address of: ValueType.Map', + ), + ), + ); + expect( + () => flx['address']['countryCode'][0], + throwsA( + predicate( + (dynamic e) => + e is ArgumentError && + e.message == + 'Key: [0] is not applicable on: //address/countryCode of: ValueType.String', + ), + ), + ); + expect( + () => flx[1], + throwsA( + predicate( + (dynamic e) => + e is ArgumentError && + e.message == 'Key: [1] is not applicable on: / of: ValueType.Map', + ), + ), + ); + expect( + () => flx['flags'][4], + throwsA( + predicate( + (dynamic e) => + e is ArgumentError && + e.message == + 'Key: [4] is not applicable on: //flags of: ValueType.VectorBool length: 4', + ), + ), + ); + expect( + () => flx['flags'][-1], + throwsA( + predicate( + (dynamic e) => + e is ArgumentError && + e.message == + 'Key: [-1] is not applicable on: //flags of: ValueType.VectorBool length: 4', + ), + ), + ); + }); + test('complex map to json', () { + var flx = complexMap(); + expect( + flx.json, + '{"address":{"city":"Bla","countryCode":"XX","zip":"12345"},"age":35,"flags":[true,false,true,true],"name":"Maxim","weight":72.5}', + ); + }); + + test('complex map iterators', () { + var flx = complexMap(); + expect(flx.mapKeyIterable.map((e) => e).toList(), [ + 'address', + 'age', + 'flags', + 'name', + 'weight', + ]); + expect(flx.mapValueIterable.map((e) => e.json).toList(), [ + flx['address'].json, + flx['age'].json, + flx['flags'].json, + flx['name'].json, + flx['weight'].json, + ]); + expect(flx['flags'].vectorIterable.map((e) => e.boolValue).toList(), [ + true, + false, + true, + true, + ]); + }); + + test('bug where offest were stored as int instead of uint', () { + const data = [ + 99, + 104, + 97, + 110, + 110, + 101, + 108, + 115, + 95, + 105, + 110, + 0, + 100, + 105, + 108, + 97, + 116, + 105, + 111, + 110, + 95, + 104, + 101, + 105, + 103, + 104, + 116, + 95, + 102, + 97, + 99, + 116, + 111, + 114, + 0, + 100, + 105, + 108, + 97, + 116, + 105, + 111, + 110, + 95, + 119, + 105, + 100, + 116, + 104, + 95, + 102, + 97, + 99, + 116, + 111, + 114, + 0, + 102, + 117, + 115, + 101, + 100, + 95, + 97, + 99, + 116, + 105, + 118, + 97, + 116, + 105, + 111, + 110, + 95, + 102, + 117, + 110, + 99, + 116, + 105, + 111, + 110, + 0, + 112, + 97, + 100, + 95, + 118, + 97, + 108, + 117, + 101, + 115, + 0, + 112, + 97, + 100, + 100, + 105, + 110, + 103, + 0, + 115, + 116, + 114, + 105, + 100, + 101, + 95, + 104, + 101, + 105, + 103, + 104, + 116, + 0, + 115, + 116, + 114, + 105, + 100, + 101, + 95, + 119, + 105, + 100, + 116, + 104, + 0, + 8, + 130, + 119, + 97, + 76, + 51, + 41, + 34, + 21, + 8, + 1, + 8, + 64, + 1, + 1, + 1, + 1, + 0, + 1, + 1, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 16, + 36, + 1, + ]; + var flx = Reference.fromBuffer(b(data)); + expect( + flx.json, + '{"channels_in":64,"dilation_height_factor":1,"dilation_width_factor":1,"fused_activation_function":1,"pad_values":1,"padding":0,"stride_height":1,"stride_width":1}', + ); + const object = { + "channels_in": 64, + "dilation_height_factor": 1, + "dilation_width_factor": 1, + "fused_activation_function": 1, + "pad_values": 1, + "padding": 0, + "stride_height": 1, + "stride_width": 1, + }; + var data1 = Builder.buildFromObject(object).asUint8List(); + expect(data1.length, data.length); + var flx1 = Reference.fromBuffer(b(data1)); + expect( + flx1.json, + '{"channels_in":64,"dilation_height_factor":1,"dilation_width_factor":1,"fused_activation_function":1,"pad_values":1,"padding":0,"stride_height":1,"stride_width":1}', + ); + }); +} + +ByteBuffer b(List values) { + var data = Uint8List.fromList(values); + return data.buffer; +} + +void testNumbers(List buffer, List numbers) { + var flx = Reference.fromBuffer(b(buffer)); + expect(flx.length, numbers.length); + for (var i = 0; i < flx.length; i++) { + expect(flx[i].numValue, closeTo(numbers[i], 0.001)); + } +} + +void testStrings(List buffer, List numbers) { + var flx = Reference.fromBuffer(b(buffer)); + expect(flx.length, numbers.length); + for (var i = 0; i < flx.length; i++) { + expect(flx[i].stringValue, numbers[i]); + } +} + +Reference complexMap() { + // { + // "age": 35, + // "flags": [True, False, True, True], + // "weight": 72.5, + // "name": "Maxim", + // "address": { + // "city": "Bla", + // "zip": "12345", + // "countryCode": "XX", + // } + // } + return Reference.fromBuffer( + b([ + 97, + 100, + 100, + 114, + 101, + 115, + 115, + 0, + 99, + 105, + 116, + 121, + 0, + 3, + 66, + 108, + 97, + 0, + 99, + 111, + 117, + 110, + 116, + 114, + 121, + 67, + 111, + 100, + 101, + 0, + 2, + 88, + 88, + 0, + 122, + 105, + 112, + 0, + 5, + 49, + 50, + 51, + 52, + 53, + 0, + 3, + 38, + 29, + 14, + 3, + 1, + 3, + 38, + 22, + 15, + 20, + 20, + 20, + 97, + 103, + 101, + 0, + 102, + 108, + 97, + 103, + 115, + 0, + 4, + 1, + 0, + 1, + 1, + 110, + 97, + 109, + 101, + 0, + 5, + 77, + 97, + 120, + 105, + 109, + 0, + 119, + 101, + 105, + 103, + 104, + 116, + 0, + 5, + 93, + 36, + 33, + 23, + 12, + 0, + 0, + 7, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 5, + 0, + 0, + 0, + 60, + 0, + 0, + 0, + 35, + 0, + 0, + 0, + 51, + 0, + 0, + 0, + 45, + 0, + 0, + 0, + 0, + 0, + 145, + 66, + 36, + 4, + 144, + 20, + 14, + 25, + 38, + 1, + ]), + ); +} diff --git a/third_party/flatbuffers/dart/test/flex_types_test.dart b/third_party/flatbuffers/dart/test/flex_types_test.dart new file mode 100644 index 00000000000..7ed1f2ab1c1 --- /dev/null +++ b/third_party/flatbuffers/dart/test/flex_types_test.dart @@ -0,0 +1,278 @@ +import 'package:flat_buffers/src/types.dart'; +import 'package:test/test.dart'; + +void main() { + test('is inline', () { + expect(ValueTypeUtils.isInline(ValueType.Bool), isTrue); + expect(ValueTypeUtils.isInline(ValueType.Int), isTrue); + expect(ValueTypeUtils.isInline(ValueType.UInt), isTrue); + expect(ValueTypeUtils.isInline(ValueType.Float), isTrue); + expect(ValueTypeUtils.isInline(ValueType.Null), isTrue); + expect(ValueTypeUtils.isInline(ValueType.String), isFalse); + }); + test('is type vector element', () { + expect(ValueTypeUtils.isTypedVectorElement(ValueType.Bool), isTrue); + expect(ValueTypeUtils.isTypedVectorElement(ValueType.Int), isTrue); + expect(ValueTypeUtils.isTypedVectorElement(ValueType.UInt), isTrue); + expect(ValueTypeUtils.isTypedVectorElement(ValueType.Float), isTrue); + expect(ValueTypeUtils.isTypedVectorElement(ValueType.Key), isTrue); + expect(ValueTypeUtils.isTypedVectorElement(ValueType.String), isTrue); + + expect(ValueTypeUtils.isTypedVectorElement(ValueType.Null), isFalse); + expect(ValueTypeUtils.isTypedVectorElement(ValueType.Blob), isFalse); + }); + test('is typed vector', () { + expect(ValueTypeUtils.isTypedVector(ValueType.VectorInt), isTrue); + expect(ValueTypeUtils.isTypedVector(ValueType.VectorUInt), isTrue); + expect(ValueTypeUtils.isTypedVector(ValueType.VectorFloat), isTrue); + expect(ValueTypeUtils.isTypedVector(ValueType.VectorBool), isTrue); + expect(ValueTypeUtils.isTypedVector(ValueType.VectorKey), isTrue); + expect(ValueTypeUtils.isTypedVector(ValueType.VectorString), isTrue); + + expect(ValueTypeUtils.isTypedVector(ValueType.Vector), isFalse); + expect(ValueTypeUtils.isTypedVector(ValueType.Map), isFalse); + expect(ValueTypeUtils.isTypedVector(ValueType.Bool), isFalse); + expect(ValueTypeUtils.isTypedVector(ValueType.VectorInt2), isFalse); + }); + test('is fixed typed vector', () { + expect(ValueTypeUtils.isFixedTypedVector(ValueType.VectorInt2), isTrue); + expect(ValueTypeUtils.isFixedTypedVector(ValueType.VectorInt3), isTrue); + expect(ValueTypeUtils.isFixedTypedVector(ValueType.VectorInt4), isTrue); + expect(ValueTypeUtils.isFixedTypedVector(ValueType.VectorUInt2), isTrue); + expect(ValueTypeUtils.isFixedTypedVector(ValueType.VectorUInt3), isTrue); + expect(ValueTypeUtils.isFixedTypedVector(ValueType.VectorUInt4), isTrue); + expect(ValueTypeUtils.isFixedTypedVector(ValueType.VectorFloat2), isTrue); + expect(ValueTypeUtils.isFixedTypedVector(ValueType.VectorFloat3), isTrue); + expect(ValueTypeUtils.isFixedTypedVector(ValueType.VectorFloat4), isTrue); + + expect(ValueTypeUtils.isFixedTypedVector(ValueType.VectorInt), isFalse); + }); + test('to typed vector', () { + expect( + ValueTypeUtils.toTypedVector(ValueType.Int, 0), + equals(ValueType.VectorInt), + ); + expect( + ValueTypeUtils.toTypedVector(ValueType.UInt, 0), + equals(ValueType.VectorUInt), + ); + expect( + ValueTypeUtils.toTypedVector(ValueType.Bool, 0), + equals(ValueType.VectorBool), + ); + expect( + ValueTypeUtils.toTypedVector(ValueType.Float, 0), + equals(ValueType.VectorFloat), + ); + expect( + ValueTypeUtils.toTypedVector(ValueType.Key, 0), + equals(ValueType.VectorKey), + ); + expect( + ValueTypeUtils.toTypedVector(ValueType.String, 0), + equals(ValueType.VectorString), + ); + + expect( + ValueTypeUtils.toTypedVector(ValueType.Int, 2), + equals(ValueType.VectorInt2), + ); + expect( + ValueTypeUtils.toTypedVector(ValueType.UInt, 2), + equals(ValueType.VectorUInt2), + ); + expect( + ValueTypeUtils.toTypedVector(ValueType.Float, 2), + equals(ValueType.VectorFloat2), + ); + + expect( + ValueTypeUtils.toTypedVector(ValueType.Int, 3), + equals(ValueType.VectorInt3), + ); + expect( + ValueTypeUtils.toTypedVector(ValueType.UInt, 3), + equals(ValueType.VectorUInt3), + ); + expect( + ValueTypeUtils.toTypedVector(ValueType.Float, 3), + equals(ValueType.VectorFloat3), + ); + + expect( + ValueTypeUtils.toTypedVector(ValueType.Int, 4), + equals(ValueType.VectorInt4), + ); + expect( + ValueTypeUtils.toTypedVector(ValueType.UInt, 4), + equals(ValueType.VectorUInt4), + ); + expect( + ValueTypeUtils.toTypedVector(ValueType.Float, 4), + equals(ValueType.VectorFloat4), + ); + }); + test('typed vector element type', () { + expect( + ValueTypeUtils.typedVectorElementType(ValueType.VectorInt), + equals(ValueType.Int), + ); + expect( + ValueTypeUtils.typedVectorElementType(ValueType.VectorUInt), + equals(ValueType.UInt), + ); + expect( + ValueTypeUtils.typedVectorElementType(ValueType.VectorFloat), + equals(ValueType.Float), + ); + expect( + ValueTypeUtils.typedVectorElementType(ValueType.VectorString), + equals(ValueType.String), + ); + expect( + ValueTypeUtils.typedVectorElementType(ValueType.VectorKey), + equals(ValueType.Key), + ); + expect( + ValueTypeUtils.typedVectorElementType(ValueType.VectorBool), + equals(ValueType.Bool), + ); + }); + test('fixed typed vector element type', () { + expect( + ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt2), + equals(ValueType.Int), + ); + expect( + ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt3), + equals(ValueType.Int), + ); + expect( + ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorInt4), + equals(ValueType.Int), + ); + + expect( + ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt2), + equals(ValueType.UInt), + ); + expect( + ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt3), + equals(ValueType.UInt), + ); + expect( + ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorUInt4), + equals(ValueType.UInt), + ); + + expect( + ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat2), + equals(ValueType.Float), + ); + expect( + ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat3), + equals(ValueType.Float), + ); + expect( + ValueTypeUtils.fixedTypedVectorElementType(ValueType.VectorFloat4), + equals(ValueType.Float), + ); + }); + test('fixed typed vector element size', () { + expect( + ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt2), + equals(2), + ); + expect( + ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt3), + equals(3), + ); + expect( + ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorInt4), + equals(4), + ); + + expect( + ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt2), + equals(2), + ); + expect( + ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt3), + equals(3), + ); + expect( + ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorUInt4), + equals(4), + ); + + expect( + ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat2), + equals(2), + ); + expect( + ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat3), + equals(3), + ); + expect( + ValueTypeUtils.fixedTypedVectorElementSize(ValueType.VectorFloat4), + equals(4), + ); + }); + test('packed type', () { + expect( + ValueTypeUtils.packedType(ValueType.Null, BitWidth.width8), + equals(0), + ); + expect( + ValueTypeUtils.packedType(ValueType.Null, BitWidth.width16), + equals(1), + ); + expect( + ValueTypeUtils.packedType(ValueType.Null, BitWidth.width32), + equals(2), + ); + expect( + ValueTypeUtils.packedType(ValueType.Null, BitWidth.width64), + equals(3), + ); + + expect( + ValueTypeUtils.packedType(ValueType.Int, BitWidth.width8), + equals(4), + ); + expect( + ValueTypeUtils.packedType(ValueType.Int, BitWidth.width16), + equals(5), + ); + expect( + ValueTypeUtils.packedType(ValueType.Int, BitWidth.width32), + equals(6), + ); + expect( + ValueTypeUtils.packedType(ValueType.Int, BitWidth.width64), + equals(7), + ); + }); + test('bit width', () { + expect(BitWidthUtil.width(0), BitWidth.width8); + expect(BitWidthUtil.width(-20), BitWidth.width8); + expect(BitWidthUtil.width(127), BitWidth.width8); + expect(BitWidthUtil.width(128), BitWidth.width16); + expect(BitWidthUtil.width(128123), BitWidth.width32); + expect(BitWidthUtil.width(12812324534), BitWidth.width64); + expect(BitWidthUtil.width(-127), BitWidth.width8); + expect(BitWidthUtil.width(-128), BitWidth.width16); + expect(BitWidthUtil.width(-12812324534), BitWidth.width64); + expect(BitWidthUtil.width(-0.1), BitWidth.width64); + expect(BitWidthUtil.width(0.25), BitWidth.width32); + }); + test('padding size', () { + expect(BitWidthUtil.paddingSize(10, 8), 6); + expect(BitWidthUtil.paddingSize(10, 4), 2); + expect(BitWidthUtil.paddingSize(15, 4), 1); + expect(BitWidthUtil.paddingSize(15, 2), 1); + expect(BitWidthUtil.paddingSize(15, 1), 0); + expect(BitWidthUtil.paddingSize(16, 8), 0); + expect(BitWidthUtil.paddingSize(17, 8), 7); + }); +} diff --git a/third_party/flatbuffers/dart/test/include_test1_generated.dart b/third_party/flatbuffers/dart/test/include_test1_generated.dart new file mode 100644 index 00000000000..2309e45722c --- /dev/null +++ b/third_party/flatbuffers/dart/test/include_test1_generated.dart @@ -0,0 +1,108 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable, constant_identifier_names + +import 'dart:typed_data' show Uint8List; + +import 'package:flat_buffers/flat_buffers.dart' as fb; + +import './include_test2_my_game.other_name_space_generated.dart' + as my_game_other_name_space; + +class TableA { + TableA._(this._bc, this._bcOffset); + factory TableA(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _TableAReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + my_game_other_name_space.TableB? get b => my_game_other_name_space + .TableB + .reader + .vTableGetNullable(_bc, _bcOffset, 4); + + @override + String toString() { + return 'TableA{b: ${b}}'; + } + + TableAT unpack() => TableAT(b: b?.unpack()); + + static int pack(fb.Builder fbBuilder, TableAT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class TableAT implements fb.Packable { + my_game_other_name_space.TableBT? b; + + TableAT({this.b}); + + @override + int pack(fb.Builder fbBuilder) { + final int? bOffset = b?.pack(fbBuilder); + fbBuilder.startTable(1); + fbBuilder.addOffset(0, bOffset); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'TableAT{b: ${b}}'; + } +} + +class _TableAReader extends fb.TableReader { + const _TableAReader(); + + @override + TableA createObject(fb.BufferContext bc, int offset) => TableA._(bc, offset); +} + +class TableABuilder { + TableABuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(1); + } + + int addBOffset(int? offset) { + fbBuilder.addOffset(0, offset); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class TableAObjectBuilder extends fb.ObjectBuilder { + final my_game_other_name_space.TableBObjectBuilder? _b; + + TableAObjectBuilder({my_game_other_name_space.TableBObjectBuilder? b}) + : _b = b; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? bOffset = _b?.getOrCreateOffset(fbBuilder); + fbBuilder.startTable(1); + fbBuilder.addOffset(0, bOffset); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} diff --git a/third_party/flatbuffers/dart/test/include_test2_my_game.other_name_space_generated.dart b/third_party/flatbuffers/dart/test/include_test2_my_game.other_name_space_generated.dart new file mode 100644 index 00000000000..975622b8fb4 --- /dev/null +++ b/third_party/flatbuffers/dart/test/include_test2_my_game.other_name_space_generated.dart @@ -0,0 +1,221 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable, constant_identifier_names + +library my_game.other_name_space; + +import 'dart:typed_data' show Uint8List; + +import 'package:flat_buffers/flat_buffers.dart' as fb; + +import './include_test1_generated.dart'; + +enum FromInclude { + IncludeVal(0); + + final int value; + const FromInclude(this.value); + + factory FromInclude.fromValue(int value) { + switch (value) { + case 0: + return FromInclude.IncludeVal; + default: + throw StateError('Invalid value $value for bit flag enum'); + } + } + + static FromInclude? _createOrNull(int? value) => + value == null ? null : FromInclude.fromValue(value); + + static const int minValue = 0; + static const int maxValue = 0; + static const fb.Reader reader = _FromIncludeReader(); +} + +class _FromIncludeReader extends fb.Reader { + const _FromIncludeReader(); + + @override + int get size => 8; + + @override + FromInclude read(fb.BufferContext bc, int offset) => + FromInclude.fromValue(const fb.Int64Reader().read(bc, offset)); +} + +class Unused { + Unused._(this._bc, this._bcOffset); + + static const fb.Reader reader = _UnusedReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + int get a => const fb.Int32Reader().read(_bc, _bcOffset + 0); + + @override + String toString() { + return 'Unused{a: ${a}}'; + } + + UnusedT unpack() => UnusedT(a: a); + + static int pack(fb.Builder fbBuilder, UnusedT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class UnusedT implements fb.Packable { + int a; + + UnusedT({required this.a}); + + @override + int pack(fb.Builder fbBuilder) { + fbBuilder.putInt32(a); + return fbBuilder.offset; + } + + @override + String toString() { + return 'UnusedT{a: ${a}}'; + } +} + +class _UnusedReader extends fb.StructReader { + const _UnusedReader(); + + @override + int get size => 4; + + @override + Unused createObject(fb.BufferContext bc, int offset) => Unused._(bc, offset); +} + +class UnusedBuilder { + UnusedBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + int finish(int a) { + fbBuilder.putInt32(a); + return fbBuilder.offset; + } +} + +class UnusedObjectBuilder extends fb.ObjectBuilder { + final int _a; + + UnusedObjectBuilder({required int a}) : _a = a; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + fbBuilder.putInt32(_a); + return fbBuilder.offset; + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} + +class TableB { + TableB._(this._bc, this._bcOffset); + factory TableB(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _TableBReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + TableA? get a => TableA.reader.vTableGetNullable(_bc, _bcOffset, 4); + + @override + String toString() { + return 'TableB{a: ${a}}'; + } + + TableBT unpack() => TableBT(a: a?.unpack()); + + static int pack(fb.Builder fbBuilder, TableBT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class TableBT implements fb.Packable { + TableAT? a; + + TableBT({this.a}); + + @override + int pack(fb.Builder fbBuilder) { + final int? aOffset = a?.pack(fbBuilder); + fbBuilder.startTable(1); + fbBuilder.addOffset(0, aOffset); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'TableBT{a: ${a}}'; + } +} + +class _TableBReader extends fb.TableReader { + const _TableBReader(); + + @override + TableB createObject(fb.BufferContext bc, int offset) => TableB._(bc, offset); +} + +class TableBBuilder { + TableBBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(1); + } + + int addAOffset(int? offset) { + fbBuilder.addOffset(0, offset); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class TableBObjectBuilder extends fb.ObjectBuilder { + final TableAObjectBuilder? _a; + + TableBObjectBuilder({TableAObjectBuilder? a}) : _a = a; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? aOffset = _a?.getOrCreateOffset(fbBuilder); + fbBuilder.startTable(1); + fbBuilder.addOffset(0, aOffset); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} diff --git a/third_party/flatbuffers/dart/test/keyword_test_keyword_test_generated.dart b/third_party/flatbuffers/dart/test/keyword_test_keyword_test_generated.dart new file mode 100644 index 00000000000..e0118af1624 --- /dev/null +++ b/third_party/flatbuffers/dart/test/keyword_test_keyword_test_generated.dart @@ -0,0 +1,369 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable, constant_identifier_names + +library keyword_test; + +import 'dart:typed_data' show Uint8List; +import 'package:flat_buffers/flat_buffers.dart' as fb; + + +enum Abc { + $void(0), + where(1), + stackalloc(2); + + final int value; + const Abc(this.value); + + factory Abc.fromValue(int value) { + switch (value) { + case 0: return Abc.$void; + case 1: return Abc.where; + case 2: return Abc.stackalloc; + default: throw StateError('Invalid value $value for bit flag enum'); + } + } + + static Abc? _createOrNull(int? value) => + value == null ? null : Abc.fromValue(value); + + static const int minValue = 0; + static const int maxValue = 2; + static const fb.Reader reader = _AbcReader(); +} + +class _AbcReader extends fb.Reader { + const _AbcReader(); + + @override + int get size => 4; + + @override + Abc read(fb.BufferContext bc, int offset) => + Abc.fromValue(const fb.Int32Reader().read(bc, offset)); +} + +enum Public { + NONE(0); + + final int value; + const Public(this.value); + + factory Public.fromValue(int value) { + switch (value) { + case 0: return Public.NONE; + default: throw StateError('Invalid value $value for bit flag enum'); + } + } + + static Public? _createOrNull(int? value) => + value == null ? null : Public.fromValue(value); + + static const int minValue = 0; + static const int maxValue = 0; + static const fb.Reader reader = _PublicReader(); +} + +class _PublicReader extends fb.Reader { + const _PublicReader(); + + @override + int get size => 4; + + @override + Public read(fb.BufferContext bc, int offset) => + Public.fromValue(const fb.Int32Reader().read(bc, offset)); +} + +enum KeywordsInUnionTypeId { + NONE(0), + $static(1), + internal(2); + + final int value; + const KeywordsInUnionTypeId(this.value); + + factory KeywordsInUnionTypeId.fromValue(int value) { + switch (value) { + case 0: return KeywordsInUnionTypeId.NONE; + case 1: return KeywordsInUnionTypeId.$static; + case 2: return KeywordsInUnionTypeId.internal; + default: throw StateError('Invalid value $value for bit flag enum'); + } + } + + static KeywordsInUnionTypeId? _createOrNull(int? value) => + value == null ? null : KeywordsInUnionTypeId.fromValue(value); + + static const int minValue = 0; + static const int maxValue = 2; + static const fb.Reader reader = _KeywordsInUnionTypeIdReader(); +} + +class _KeywordsInUnionTypeIdReader extends fb.Reader { + const _KeywordsInUnionTypeIdReader(); + + @override + int get size => 1; + + @override + KeywordsInUnionTypeId read(fb.BufferContext bc, int offset) => + KeywordsInUnionTypeId.fromValue(const fb.Uint8Reader().read(bc, offset)); +} + +class KeywordsInTable { + KeywordsInTable._(this._bc, this._bcOffset); + factory KeywordsInTable(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _KeywordsInTableReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + Abc get $is => Abc.fromValue(const fb.Int32Reader().vTableGet(_bc, _bcOffset, 4, 0)); + Public get private => Public.fromValue(const fb.Int32Reader().vTableGet(_bc, _bcOffset, 6, 0)); + int get type => const fb.Int32Reader().vTableGet(_bc, _bcOffset, 8, 0); + bool get $default => const fb.BoolReader().vTableGet(_bc, _bcOffset, 10, false); + + @override + String toString() { + return 'KeywordsInTable{\$is: ${$is}, private: ${private}, type: ${type}, \$default: ${$default}}'; + } + + KeywordsInTableT unpack() => KeywordsInTableT( + $is: $is, + private: private, + type: type, + $default: $default); + + static int pack(fb.Builder fbBuilder, KeywordsInTableT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class KeywordsInTableT implements fb.Packable { + Abc $is; + Public private; + int type; + bool $default; + + KeywordsInTableT({ + this.$is = Abc.$void, + this.private = Public.NONE, + this.type = 0, + this.$default = false}); + + @override + int pack(fb.Builder fbBuilder) { + fbBuilder.startTable(4); + fbBuilder.addInt32(0, $is.value); + fbBuilder.addInt32(1, private.value); + fbBuilder.addInt32(2, type); + fbBuilder.addBool(3, $default); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'KeywordsInTableT{\$is: ${$is}, private: ${private}, type: ${type}, \$default: ${$default}}'; + } +} + +class _KeywordsInTableReader extends fb.TableReader { + const _KeywordsInTableReader(); + + @override + KeywordsInTable createObject(fb.BufferContext bc, int offset) => + KeywordsInTable._(bc, offset); +} + +class KeywordsInTableBuilder { + KeywordsInTableBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(4); + } + + int addIs(Abc? $is) { + fbBuilder.addInt32(0, $is?.value); + return fbBuilder.offset; + } + int addPrivate(Public? private) { + fbBuilder.addInt32(1, private?.value); + return fbBuilder.offset; + } + int addType(int? type) { + fbBuilder.addInt32(2, type); + return fbBuilder.offset; + } + int addDefault(bool? $default) { + fbBuilder.addBool(3, $default); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class KeywordsInTableObjectBuilder extends fb.ObjectBuilder { + final Abc? _$is; + final Public? _private; + final int? _type; + final bool? _$default; + + KeywordsInTableObjectBuilder({ + Abc? $is, + Public? private, + int? type, + bool? $default, + }) + : _$is = $is, + _private = private, + _type = type, + _$default = $default; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + fbBuilder.startTable(4); + fbBuilder.addInt32(0, _$is?.value); + fbBuilder.addInt32(1, _private?.value); + fbBuilder.addInt32(2, _type); + fbBuilder.addBool(3, _$default); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} +class Table2 { + Table2._(this._bc, this._bcOffset); + factory Table2(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _Table2Reader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + KeywordsInUnionTypeId? get typeType => KeywordsInUnionTypeId._createOrNull(const fb.Uint8Reader().vTableGetNullable(_bc, _bcOffset, 4)); + dynamic get type { + switch (typeType?.value) { + case 1: return KeywordsInTable.reader.vTableGetNullable(_bc, _bcOffset, 6); + case 2: return KeywordsInTable.reader.vTableGetNullable(_bc, _bcOffset, 6); + default: return null; + } + } + + @override + String toString() { + return 'Table2{typeType: ${typeType}, type: ${type}}'; + } + + Table2T unpack() => Table2T( + typeType: typeType, + type: type); + + static int pack(fb.Builder fbBuilder, Table2T? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class Table2T implements fb.Packable { + KeywordsInUnionTypeId? typeType; + dynamic type; + + Table2T({ + this.typeType, + this.type}); + + @override + int pack(fb.Builder fbBuilder) { + final int? typeOffset = type?.pack(fbBuilder); + fbBuilder.startTable(2); + fbBuilder.addUint8(0, typeType?.value); + fbBuilder.addOffset(1, typeOffset); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'Table2T{typeType: ${typeType}, type: ${type}}'; + } +} + +class _Table2Reader extends fb.TableReader { + const _Table2Reader(); + + @override + Table2 createObject(fb.BufferContext bc, int offset) => + Table2._(bc, offset); +} + +class Table2Builder { + Table2Builder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(2); + } + + int addTypeType(KeywordsInUnionTypeId? typeType) { + fbBuilder.addUint8(0, typeType?.value); + return fbBuilder.offset; + } + int addTypeOffset(int? offset) { + fbBuilder.addOffset(1, offset); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class Table2ObjectBuilder extends fb.ObjectBuilder { + final KeywordsInUnionTypeId? _typeType; + final dynamic _type; + + Table2ObjectBuilder({ + KeywordsInUnionTypeId? typeType, + dynamic type, + }) + : _typeType = typeType, + _type = type; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? typeOffset = _type?.getOrCreateOffset(fbBuilder); + fbBuilder.startTable(2); + fbBuilder.addUint8(0, _typeType?.value); + fbBuilder.addOffset(1, typeOffset); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} diff --git a/third_party/flatbuffers/dart/test/monster_test.fbs b/third_party/flatbuffers/dart/test/monster_test.fbs new file mode 100644 index 00000000000..b40ecf58f95 --- /dev/null +++ b/third_party/flatbuffers/dart/test/monster_test.fbs @@ -0,0 +1,180 @@ +// test schema file + +include "include_test1.fbs"; + +namespace MyGame; + +table InParentNamespace {} + +namespace MyGame.Example2; + +table Monster {} // Test having same name as below, but in different namespace. + +namespace MyGame.Example; + +attribute "priority"; + +/// Composite components of Monster color. +enum Color:ubyte (bit_flags) { + Red = 0, // color Red = (1u << 0) + /// \brief color Green + /// Green is bit_flag with value (1u << 1) + Green, + /// \brief color Blue (1u << 3) + Blue = 3, +} + +enum Race:byte { + None = -1, + Human = 0, + Dwarf, + Elf, +} + +enum LongEnum:ulong (bit_flags) { + LongOne = 1, + LongTwo = 2, + // Because this is a bitflag, 40 will be out of range of a 32-bit integer, + // allowing us to exercise any logic special to big numbers. + LongBig = 40, +} + +union Any { Monster, TestSimpleTableWithEnum, MyGame.Example2.Monster } + +union AnyUniqueAliases { M: Monster, TS: TestSimpleTableWithEnum, M2: MyGame.Example2.Monster } +union AnyAmbiguousAliases { M1: Monster, M2: Monster, M3: Monster } + +struct Test { a:short; b:byte; } + +table TestSimpleTableWithEnum (csharp_partial, private) { + color: Color = Green; +} + +struct Vec3 (force_align: 8) { + x:float; + y:float; + z:float; + test1:double; + test2:Color; + test3:Test; +} + +struct Ability { + id:uint(key); + distance:uint; +} + +struct StructOfStructs { + a: Ability; + b: Test; + c: Ability; +} + +struct StructOfStructsOfStructs { + a: StructOfStructs; +} + +table Stat { + id:string; + val:long; + count:ushort (key); +} + +table Referrable { + id:ulong(key, hash:"fnv1a_64"); +} + +/// an example documentation comment: "monster object" +table Monster { + pos:Vec3 (id: 0); + hp:short = 100 (id: 2); + mana:short = 150 (id: 1); + name:string (id: 3, key); + color:Color = Blue (id: 6); + inventory:[ubyte] (id: 5); + friendly:bool = false (deprecated, priority: 1, id: 4); + /// an example documentation comment: this will end up in the generated code + /// multiline too + testarrayoftables:[Monster] (id: 11); + testarrayofstring:[string] (id: 10); + testarrayofstring2:[string] (id: 28); + testarrayofbools:[bool] (id: 24); + testarrayofsortedstruct:[Ability] (id: 29); + enemy:MyGame.Example.Monster (id:12); // Test referring by full namespace. + test:Any (id: 8); + test4:[Test] (id: 9); + test5:[Test] (id: 31); + testnestedflatbuffer:[ubyte] (id:13, nested_flatbuffer: "Monster"); + testempty:Stat (id:14); + testbool:bool (id:15); + testhashs32_fnv1:int (id:16, hash:"fnv1_32"); + testhashu32_fnv1:uint (id:17, hash:"fnv1_32"); + testhashs64_fnv1:long (id:18, hash:"fnv1_64"); + testhashu64_fnv1:ulong (id:19, hash:"fnv1_64"); + testhashs32_fnv1a:int (id:20, hash:"fnv1a_32"); + testhashu32_fnv1a:uint (id:21, hash:"fnv1a_32", cpp_type:"Stat"); + testhashs64_fnv1a:long (id:22, hash:"fnv1a_64"); + testhashu64_fnv1a:ulong (id:23, hash:"fnv1a_64"); + testf:float = 3.14159 (id:25); + testf2:float = 3 (id:26); + testf3:float (id:27); + flex:[ubyte] (id:30, flexbuffer); + vector_of_longs:[long] (id:32); + vector_of_doubles:[double] (id:33); + parent_namespace_test:InParentNamespace (id:34); + vector_of_referrables:[Referrable](id:35); + single_weak_reference:ulong(id:36, hash:"fnv1a_64", cpp_type:"ReferrableT"); + vector_of_weak_references:[ulong](id:37, hash:"fnv1a_64", cpp_type:"ReferrableT"); + vector_of_strong_referrables:[Referrable](id:38, cpp_ptr_type:"default_ptr_type"); //was shared_ptr + co_owning_reference:ulong(id:39, hash:"fnv1a_64", cpp_type:"ReferrableT", cpp_ptr_type:"naked"); //was shared_ptr as well + vector_of_co_owning_references:[ulong](id:40, hash:"fnv1a_64", cpp_type:"ReferrableT", cpp_ptr_type:"default_ptr_type", cpp_ptr_type_get:".get()"); //was shared_ptr + non_owning_reference:ulong(id:41, hash:"fnv1a_64", cpp_type:"ReferrableT", cpp_ptr_type:"naked", cpp_ptr_type_get:""); //was weak_ptr + vector_of_non_owning_references:[ulong](id:42, hash:"fnv1a_64", cpp_type:"ReferrableT", cpp_ptr_type:"naked", cpp_ptr_type_get:""); //was weak_ptr + any_unique:AnyUniqueAliases(id:44); + any_ambiguous:AnyAmbiguousAliases (id:46); + vector_of_enums:[Color] (id:47); + signed_enum:Race = None (id:48); + testrequirednestedflatbuffer:[ubyte] (id:49, nested_flatbuffer: "Monster"); + scalar_key_sorted_tables:[Stat] (id: 50); + native_inline:Test (id: 51, native_inline); + // The default value of this enum will be a numeric zero, which isn't a valid + // enum value. + long_enum_non_enum_default:LongEnum (id: 52); + long_enum_normal_default:LongEnum = LongOne (id: 53); + // Test that default values nan and +/-inf work. + nan_default:float = nan (id: 54); + inf_default:float = inf (id: 55); + positive_inf_default:float = +inf (id: 56); + infinity_default:float = infinity (id: 57); + positive_infinity_default:float = +infinity (id: 58); + negative_inf_default:float = -inf (id: 59); + negative_infinity_default:float = -infinity (id: 60); + double_inf_default:double = inf (id: 61); +} + +table TypeAliases { + i8:int8; + u8:uint8; + i16:int16; + u16:uint16; + i32:int32; + u32:uint32; + i64:int64; + u64:uint64; + f32:float32; + f64:float64; + v8:[int8]; + vf64:[float64]; +} + +rpc_service MonsterStorage { + Store(Monster):Stat (streaming: "none"); + Retrieve(Stat):Monster (streaming: "server", idempotent); + GetMaxHitPoint(Monster):Stat (streaming: "client"); + GetMinMaxHitPoints(Monster):Stat (streaming: "bidi"); +} + +root_type Monster; + +file_identifier "MONS"; +file_extension "mon"; diff --git a/third_party/flatbuffers/dart/test/monster_test_my_game.example2_generated.dart b/third_party/flatbuffers/dart/test/monster_test_my_game.example2_generated.dart new file mode 100644 index 00000000000..8f7893fcd17 --- /dev/null +++ b/third_party/flatbuffers/dart/test/monster_test_my_game.example2_generated.dart @@ -0,0 +1,77 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable, constant_identifier_names + +library my_game.example2; + +import 'dart:typed_data' show Uint8List; + +import 'package:flat_buffers/flat_buffers.dart' as fb; + +import './include_test1_generated.dart'; +import './monster_test_my_game.example_generated.dart' as my_game_example; +import './monster_test_my_game_generated.dart' as my_game; + +class Monster { + Monster._(this._bc, this._bcOffset); + factory Monster(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _MonsterReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + @override + String toString() { + return 'Monster{}'; + } + + MonsterT unpack() => MonsterT(); + + static int pack(fb.Builder fbBuilder, MonsterT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class MonsterT implements fb.Packable { + @override + int pack(fb.Builder fbBuilder) { + fbBuilder.startTable(0); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'MonsterT{}'; + } +} + +class _MonsterReader extends fb.TableReader { + const _MonsterReader(); + + @override + Monster createObject(fb.BufferContext bc, int offset) => + Monster._(bc, offset); +} + +class MonsterObjectBuilder extends fb.ObjectBuilder { + MonsterObjectBuilder(); + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + fbBuilder.startTable(0); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} diff --git a/third_party/flatbuffers/dart/test/monster_test_my_game.example_generated.dart b/third_party/flatbuffers/dart/test/monster_test_my_game.example_generated.dart new file mode 100644 index 00000000000..7be3afa8906 --- /dev/null +++ b/third_party/flatbuffers/dart/test/monster_test_my_game.example_generated.dart @@ -0,0 +1,2705 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable, constant_identifier_names + +library my_game.example; + +import 'dart:typed_data' show Uint8List; + +import 'package:flat_buffers/flat_buffers.dart' as fb; + +import './include_test1_generated.dart'; +import './monster_test_my_game.example2_generated.dart' as my_game_example2; +import './monster_test_my_game_generated.dart' as my_game; + +/// Composite components of Monster color. +enum Color { + Red(1), + Green(2), + Blue(8), + _default(0); + + final int value; + const Color(this.value); + + factory Color.fromValue(int value) { + switch (value) { + case 1: + return Color.Red; + case 2: + return Color.Green; + case 8: + return Color.Blue; + case 0: + return Color._default; + default: + throw StateError('Invalid value $value for bit flag enum'); + } + } + + static Color? _createOrNull(int? value) => + value == null ? null : Color.fromValue(value); + + static const fb.Reader reader = _ColorReader(); +} + +class _ColorReader extends fb.Reader { + const _ColorReader(); + + @override + int get size => 1; + + @override + Color read(fb.BufferContext bc, int offset) => + Color.fromValue(const fb.Uint8Reader().read(bc, offset)); +} + +enum Race { + None(-1), + Human(0), + Dwarf(1), + Elf(2); + + final int value; + const Race(this.value); + + factory Race.fromValue(int value) { + switch (value) { + case -1: + return Race.None; + case 0: + return Race.Human; + case 1: + return Race.Dwarf; + case 2: + return Race.Elf; + default: + throw StateError('Invalid value $value for bit flag enum'); + } + } + + static Race? _createOrNull(int? value) => + value == null ? null : Race.fromValue(value); + + static const int minValue = -1; + static const int maxValue = 2; + static const fb.Reader reader = _RaceReader(); +} + +class _RaceReader extends fb.Reader { + const _RaceReader(); + + @override + int get size => 1; + + @override + Race read(fb.BufferContext bc, int offset) => + Race.fromValue(const fb.Int8Reader().read(bc, offset)); +} + +enum LongEnum { + LongOne(2), + LongTwo(4), + LongBig(1099511627776), + _default(0); + + final int value; + const LongEnum(this.value); + + factory LongEnum.fromValue(int value) { + switch (value) { + case 2: + return LongEnum.LongOne; + case 4: + return LongEnum.LongTwo; + case 1099511627776: + return LongEnum.LongBig; + case 0: + return LongEnum._default; + default: + throw StateError('Invalid value $value for bit flag enum'); + } + } + + static LongEnum? _createOrNull(int? value) => + value == null ? null : LongEnum.fromValue(value); + + static const fb.Reader reader = _LongEnumReader(); +} + +class _LongEnumReader extends fb.Reader { + const _LongEnumReader(); + + @override + int get size => 8; + + @override + LongEnum read(fb.BufferContext bc, int offset) => + LongEnum.fromValue(const fb.Uint64Reader().read(bc, offset)); +} + +enum AnyTypeId { + NONE(0), + Monster(1), + TestSimpleTableWithEnum(2), + MyGame_Example2_Monster(3); + + final int value; + const AnyTypeId(this.value); + + factory AnyTypeId.fromValue(int value) { + switch (value) { + case 0: + return AnyTypeId.NONE; + case 1: + return AnyTypeId.Monster; + case 2: + return AnyTypeId.TestSimpleTableWithEnum; + case 3: + return AnyTypeId.MyGame_Example2_Monster; + default: + throw StateError('Invalid value $value for bit flag enum'); + } + } + + static AnyTypeId? _createOrNull(int? value) => + value == null ? null : AnyTypeId.fromValue(value); + + static const int minValue = 0; + static const int maxValue = 3; + static const fb.Reader reader = _AnyTypeIdReader(); +} + +class _AnyTypeIdReader extends fb.Reader { + const _AnyTypeIdReader(); + + @override + int get size => 1; + + @override + AnyTypeId read(fb.BufferContext bc, int offset) => + AnyTypeId.fromValue(const fb.Uint8Reader().read(bc, offset)); +} + +enum AnyUniqueAliasesTypeId { + NONE(0), + M(1), + TS(2), + M2(3); + + final int value; + const AnyUniqueAliasesTypeId(this.value); + + factory AnyUniqueAliasesTypeId.fromValue(int value) { + switch (value) { + case 0: + return AnyUniqueAliasesTypeId.NONE; + case 1: + return AnyUniqueAliasesTypeId.M; + case 2: + return AnyUniqueAliasesTypeId.TS; + case 3: + return AnyUniqueAliasesTypeId.M2; + default: + throw StateError('Invalid value $value for bit flag enum'); + } + } + + static AnyUniqueAliasesTypeId? _createOrNull(int? value) => + value == null ? null : AnyUniqueAliasesTypeId.fromValue(value); + + static const int minValue = 0; + static const int maxValue = 3; + static const fb.Reader reader = + _AnyUniqueAliasesTypeIdReader(); +} + +class _AnyUniqueAliasesTypeIdReader extends fb.Reader { + const _AnyUniqueAliasesTypeIdReader(); + + @override + int get size => 1; + + @override + AnyUniqueAliasesTypeId read(fb.BufferContext bc, int offset) => + AnyUniqueAliasesTypeId.fromValue(const fb.Uint8Reader().read(bc, offset)); +} + +enum AnyAmbiguousAliasesTypeId { + NONE(0), + M1(1), + M2(2), + M3(3); + + final int value; + const AnyAmbiguousAliasesTypeId(this.value); + + factory AnyAmbiguousAliasesTypeId.fromValue(int value) { + switch (value) { + case 0: + return AnyAmbiguousAliasesTypeId.NONE; + case 1: + return AnyAmbiguousAliasesTypeId.M1; + case 2: + return AnyAmbiguousAliasesTypeId.M2; + case 3: + return AnyAmbiguousAliasesTypeId.M3; + default: + throw StateError('Invalid value $value for bit flag enum'); + } + } + + static AnyAmbiguousAliasesTypeId? _createOrNull(int? value) => + value == null ? null : AnyAmbiguousAliasesTypeId.fromValue(value); + + static const int minValue = 0; + static const int maxValue = 3; + static const fb.Reader reader = + _AnyAmbiguousAliasesTypeIdReader(); +} + +class _AnyAmbiguousAliasesTypeIdReader + extends fb.Reader { + const _AnyAmbiguousAliasesTypeIdReader(); + + @override + int get size => 1; + + @override + AnyAmbiguousAliasesTypeId read(fb.BufferContext bc, int offset) => + AnyAmbiguousAliasesTypeId.fromValue( + const fb.Uint8Reader().read(bc, offset), + ); +} + +class Test { + Test._(this._bc, this._bcOffset); + + static const fb.Reader reader = _TestReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + int get a => const fb.Int16Reader().read(_bc, _bcOffset + 0); + int get b => const fb.Int8Reader().read(_bc, _bcOffset + 2); + + @override + String toString() { + return 'Test{a: ${a}, b: ${b}}'; + } + + TestT unpack() => TestT(a: a, b: b); + + static int pack(fb.Builder fbBuilder, TestT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class TestT implements fb.Packable { + int a; + int b; + + TestT({required this.a, required this.b}); + + @override + int pack(fb.Builder fbBuilder) { + fbBuilder.pad(1); + fbBuilder.putInt8(b); + fbBuilder.putInt16(a); + return fbBuilder.offset; + } + + @override + String toString() { + return 'TestT{a: ${a}, b: ${b}}'; + } +} + +class _TestReader extends fb.StructReader { + const _TestReader(); + + @override + int get size => 4; + + @override + Test createObject(fb.BufferContext bc, int offset) => Test._(bc, offset); +} + +class TestBuilder { + TestBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + int finish(int a, int b) { + fbBuilder.pad(1); + fbBuilder.putInt8(b); + fbBuilder.putInt16(a); + return fbBuilder.offset; + } +} + +class TestObjectBuilder extends fb.ObjectBuilder { + final int _a; + final int _b; + + TestObjectBuilder({required int a, required int b}) : _a = a, _b = b; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + fbBuilder.pad(1); + fbBuilder.putInt8(_b); + fbBuilder.putInt16(_a); + return fbBuilder.offset; + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} + +class TestSimpleTableWithEnum { + TestSimpleTableWithEnum._(this._bc, this._bcOffset); + factory TestSimpleTableWithEnum(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = + _TestSimpleTableWithEnumReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + Color get color => + Color.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 4, 2)); + + @override + String toString() { + return 'TestSimpleTableWithEnum{color: ${color}}'; + } + + TestSimpleTableWithEnumT unpack() => TestSimpleTableWithEnumT(color: color); + + static int pack(fb.Builder fbBuilder, TestSimpleTableWithEnumT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class TestSimpleTableWithEnumT implements fb.Packable { + Color color; + + TestSimpleTableWithEnumT({this.color = Color.Green}); + + @override + int pack(fb.Builder fbBuilder) { + fbBuilder.startTable(1); + fbBuilder.addUint8(0, color.value); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'TestSimpleTableWithEnumT{color: ${color}}'; + } +} + +class _TestSimpleTableWithEnumReader + extends fb.TableReader { + const _TestSimpleTableWithEnumReader(); + + @override + TestSimpleTableWithEnum createObject(fb.BufferContext bc, int offset) => + TestSimpleTableWithEnum._(bc, offset); +} + +class TestSimpleTableWithEnumBuilder { + TestSimpleTableWithEnumBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(1); + } + + int addColor(Color? color) { + fbBuilder.addUint8(0, color?.value); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class TestSimpleTableWithEnumObjectBuilder extends fb.ObjectBuilder { + final Color? _color; + + TestSimpleTableWithEnumObjectBuilder({Color? color}) : _color = color; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + fbBuilder.startTable(1); + fbBuilder.addUint8(0, _color?.value); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} + +class Vec3 { + Vec3._(this._bc, this._bcOffset); + + static const fb.Reader reader = _Vec3Reader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + double get x => const fb.Float32Reader().read(_bc, _bcOffset + 0); + double get y => const fb.Float32Reader().read(_bc, _bcOffset + 4); + double get z => const fb.Float32Reader().read(_bc, _bcOffset + 8); + double get test1 => const fb.Float64Reader().read(_bc, _bcOffset + 16); + Color get test2 => + Color.fromValue(const fb.Uint8Reader().read(_bc, _bcOffset + 24)); + Test get test3 => Test.reader.read(_bc, _bcOffset + 26); + + @override + String toString() { + return 'Vec3{x: ${x}, y: ${y}, z: ${z}, test1: ${test1}, test2: ${test2}, test3: ${test3}}'; + } + + Vec3T unpack() => Vec3T( + x: x, + y: y, + z: z, + test1: test1, + test2: test2, + test3: test3.unpack(), + ); + + static int pack(fb.Builder fbBuilder, Vec3T? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class Vec3T implements fb.Packable { + double x; + double y; + double z; + double test1; + Color test2; + TestT test3; + + Vec3T({ + required this.x, + required this.y, + required this.z, + required this.test1, + required this.test2, + required this.test3, + }); + + @override + int pack(fb.Builder fbBuilder) { + fbBuilder.pad(2); + test3.pack(fbBuilder); + fbBuilder.pad(1); + fbBuilder.putUint8(test2.value); + fbBuilder.putFloat64(test1); + fbBuilder.pad(4); + fbBuilder.putFloat32(z); + fbBuilder.putFloat32(y); + fbBuilder.putFloat32(x); + return fbBuilder.offset; + } + + @override + String toString() { + return 'Vec3T{x: ${x}, y: ${y}, z: ${z}, test1: ${test1}, test2: ${test2}, test3: ${test3}}'; + } +} + +class _Vec3Reader extends fb.StructReader { + const _Vec3Reader(); + + @override + int get size => 32; + + @override + Vec3 createObject(fb.BufferContext bc, int offset) => Vec3._(bc, offset); +} + +class Vec3Builder { + Vec3Builder(this.fbBuilder); + + final fb.Builder fbBuilder; + + int finish( + double x, + double y, + double z, + double test1, + Color test2, + fb.StructBuilder test3, + ) { + fbBuilder.pad(2); + test3(); + fbBuilder.pad(1); + fbBuilder.putUint8(test2.value); + fbBuilder.putFloat64(test1); + fbBuilder.pad(4); + fbBuilder.putFloat32(z); + fbBuilder.putFloat32(y); + fbBuilder.putFloat32(x); + return fbBuilder.offset; + } +} + +class Vec3ObjectBuilder extends fb.ObjectBuilder { + final double _x; + final double _y; + final double _z; + final double _test1; + final Color _test2; + final TestObjectBuilder _test3; + + Vec3ObjectBuilder({ + required double x, + required double y, + required double z, + required double test1, + required Color test2, + required TestObjectBuilder test3, + }) : _x = x, + _y = y, + _z = z, + _test1 = test1, + _test2 = test2, + _test3 = test3; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + fbBuilder.pad(2); + _test3.finish(fbBuilder); + fbBuilder.pad(1); + fbBuilder.putUint8(_test2.value); + fbBuilder.putFloat64(_test1); + fbBuilder.pad(4); + fbBuilder.putFloat32(_z); + fbBuilder.putFloat32(_y); + fbBuilder.putFloat32(_x); + return fbBuilder.offset; + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} + +class Ability { + Ability._(this._bc, this._bcOffset); + + static const fb.Reader reader = _AbilityReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + int get id => const fb.Uint32Reader().read(_bc, _bcOffset + 0); + int get distance => const fb.Uint32Reader().read(_bc, _bcOffset + 4); + + @override + String toString() { + return 'Ability{id: ${id}, distance: ${distance}}'; + } + + AbilityT unpack() => AbilityT(id: id, distance: distance); + + static int pack(fb.Builder fbBuilder, AbilityT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class AbilityT implements fb.Packable { + int id; + int distance; + + AbilityT({required this.id, required this.distance}); + + @override + int pack(fb.Builder fbBuilder) { + fbBuilder.putUint32(distance); + fbBuilder.putUint32(id); + return fbBuilder.offset; + } + + @override + String toString() { + return 'AbilityT{id: ${id}, distance: ${distance}}'; + } +} + +class _AbilityReader extends fb.StructReader { + const _AbilityReader(); + + @override + int get size => 8; + + @override + Ability createObject(fb.BufferContext bc, int offset) => + Ability._(bc, offset); +} + +class AbilityBuilder { + AbilityBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + int finish(int id, int distance) { + fbBuilder.putUint32(distance); + fbBuilder.putUint32(id); + return fbBuilder.offset; + } +} + +class AbilityObjectBuilder extends fb.ObjectBuilder { + final int _id; + final int _distance; + + AbilityObjectBuilder({required int id, required int distance}) + : _id = id, + _distance = distance; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + fbBuilder.putUint32(_distance); + fbBuilder.putUint32(_id); + return fbBuilder.offset; + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} + +class StructOfStructs { + StructOfStructs._(this._bc, this._bcOffset); + + static const fb.Reader reader = _StructOfStructsReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + Ability get a => Ability.reader.read(_bc, _bcOffset + 0); + Test get b => Test.reader.read(_bc, _bcOffset + 8); + Ability get c => Ability.reader.read(_bc, _bcOffset + 12); + + @override + String toString() { + return 'StructOfStructs{a: ${a}, b: ${b}, c: ${c}}'; + } + + StructOfStructsT unpack() => + StructOfStructsT(a: a.unpack(), b: b.unpack(), c: c.unpack()); + + static int pack(fb.Builder fbBuilder, StructOfStructsT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class StructOfStructsT implements fb.Packable { + AbilityT a; + TestT b; + AbilityT c; + + StructOfStructsT({required this.a, required this.b, required this.c}); + + @override + int pack(fb.Builder fbBuilder) { + c.pack(fbBuilder); + b.pack(fbBuilder); + a.pack(fbBuilder); + return fbBuilder.offset; + } + + @override + String toString() { + return 'StructOfStructsT{a: ${a}, b: ${b}, c: ${c}}'; + } +} + +class _StructOfStructsReader extends fb.StructReader { + const _StructOfStructsReader(); + + @override + int get size => 20; + + @override + StructOfStructs createObject(fb.BufferContext bc, int offset) => + StructOfStructs._(bc, offset); +} + +class StructOfStructsBuilder { + StructOfStructsBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + int finish(fb.StructBuilder a, fb.StructBuilder b, fb.StructBuilder c) { + c(); + b(); + a(); + return fbBuilder.offset; + } +} + +class StructOfStructsObjectBuilder extends fb.ObjectBuilder { + final AbilityObjectBuilder _a; + final TestObjectBuilder _b; + final AbilityObjectBuilder _c; + + StructOfStructsObjectBuilder({ + required AbilityObjectBuilder a, + required TestObjectBuilder b, + required AbilityObjectBuilder c, + }) : _a = a, + _b = b, + _c = c; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + _c.finish(fbBuilder); + _b.finish(fbBuilder); + _a.finish(fbBuilder); + return fbBuilder.offset; + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} + +class StructOfStructsOfStructs { + StructOfStructsOfStructs._(this._bc, this._bcOffset); + + static const fb.Reader reader = + _StructOfStructsOfStructsReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + StructOfStructs get a => StructOfStructs.reader.read(_bc, _bcOffset + 0); + + @override + String toString() { + return 'StructOfStructsOfStructs{a: ${a}}'; + } + + StructOfStructsOfStructsT unpack() => + StructOfStructsOfStructsT(a: a.unpack()); + + static int pack(fb.Builder fbBuilder, StructOfStructsOfStructsT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class StructOfStructsOfStructsT implements fb.Packable { + StructOfStructsT a; + + StructOfStructsOfStructsT({required this.a}); + + @override + int pack(fb.Builder fbBuilder) { + a.pack(fbBuilder); + return fbBuilder.offset; + } + + @override + String toString() { + return 'StructOfStructsOfStructsT{a: ${a}}'; + } +} + +class _StructOfStructsOfStructsReader + extends fb.StructReader { + const _StructOfStructsOfStructsReader(); + + @override + int get size => 20; + + @override + StructOfStructsOfStructs createObject(fb.BufferContext bc, int offset) => + StructOfStructsOfStructs._(bc, offset); +} + +class StructOfStructsOfStructsBuilder { + StructOfStructsOfStructsBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + int finish(fb.StructBuilder a) { + a(); + return fbBuilder.offset; + } +} + +class StructOfStructsOfStructsObjectBuilder extends fb.ObjectBuilder { + final StructOfStructsObjectBuilder _a; + + StructOfStructsOfStructsObjectBuilder({ + required StructOfStructsObjectBuilder a, + }) : _a = a; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + _a.finish(fbBuilder); + return fbBuilder.offset; + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} + +class Stat { + Stat._(this._bc, this._bcOffset); + factory Stat(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _StatReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + String? get id => + const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 4); + int get val => const fb.Int64Reader().vTableGet(_bc, _bcOffset, 6, 0); + int get count => const fb.Uint16Reader().vTableGet(_bc, _bcOffset, 8, 0); + + @override + String toString() { + return 'Stat{id: ${id}, val: ${val}, count: ${count}}'; + } + + StatT unpack() => StatT(id: id, val: val, count: count); + + static int pack(fb.Builder fbBuilder, StatT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class StatT implements fb.Packable { + String? id; + int val; + int count; + + StatT({this.id, this.val = 0, this.count = 0}); + + @override + int pack(fb.Builder fbBuilder) { + final int? idOffset = id == null ? null : fbBuilder.writeString(id!); + fbBuilder.startTable(3); + fbBuilder.addOffset(0, idOffset); + fbBuilder.addInt64(1, val); + fbBuilder.addUint16(2, count); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'StatT{id: ${id}, val: ${val}, count: ${count}}'; + } +} + +class _StatReader extends fb.TableReader { + const _StatReader(); + + @override + Stat createObject(fb.BufferContext bc, int offset) => Stat._(bc, offset); +} + +class StatBuilder { + StatBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(3); + } + + int addIdOffset(int? offset) { + fbBuilder.addOffset(0, offset); + return fbBuilder.offset; + } + + int addVal(int? val) { + fbBuilder.addInt64(1, val); + return fbBuilder.offset; + } + + int addCount(int? count) { + fbBuilder.addUint16(2, count); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class StatObjectBuilder extends fb.ObjectBuilder { + final String? _id; + final int? _val; + final int? _count; + + StatObjectBuilder({String? id, int? val, int? count}) + : _id = id, + _val = val, + _count = count; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? idOffset = _id == null ? null : fbBuilder.writeString(_id!); + fbBuilder.startTable(3); + fbBuilder.addOffset(0, idOffset); + fbBuilder.addInt64(1, _val); + fbBuilder.addUint16(2, _count); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} + +class Referrable { + Referrable._(this._bc, this._bcOffset); + factory Referrable(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _ReferrableReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + int get id => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 4, 0); + + @override + String toString() { + return 'Referrable{id: ${id}}'; + } + + ReferrableT unpack() => ReferrableT(id: id); + + static int pack(fb.Builder fbBuilder, ReferrableT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class ReferrableT implements fb.Packable { + int id; + + ReferrableT({this.id = 0}); + + @override + int pack(fb.Builder fbBuilder) { + fbBuilder.startTable(1); + fbBuilder.addUint64(0, id); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'ReferrableT{id: ${id}}'; + } +} + +class _ReferrableReader extends fb.TableReader { + const _ReferrableReader(); + + @override + Referrable createObject(fb.BufferContext bc, int offset) => + Referrable._(bc, offset); +} + +class ReferrableBuilder { + ReferrableBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(1); + } + + int addId(int? id) { + fbBuilder.addUint64(0, id); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class ReferrableObjectBuilder extends fb.ObjectBuilder { + final int? _id; + + ReferrableObjectBuilder({int? id}) : _id = id; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + fbBuilder.startTable(1); + fbBuilder.addUint64(0, _id); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} + +/// an example documentation comment: "monster object" +class Monster { + Monster._(this._bc, this._bcOffset); + factory Monster(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _MonsterReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + Vec3? get pos => Vec3.reader.vTableGetNullable(_bc, _bcOffset, 4); + int get mana => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, 150); + int get hp => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 8, 100); + String? get name => + const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 10); + List? get inventory => + const fb.Uint8ListReader().vTableGetNullable(_bc, _bcOffset, 14); + Color get color => + Color.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 16, 8)); + AnyTypeId? get testType => AnyTypeId._createOrNull( + const fb.Uint8Reader().vTableGetNullable(_bc, _bcOffset, 18), + ); + dynamic get test { + switch (testType?.value) { + case 1: + return Monster.reader.vTableGetNullable(_bc, _bcOffset, 20); + case 2: + return TestSimpleTableWithEnum.reader.vTableGetNullable( + _bc, + _bcOffset, + 20, + ); + case 3: + return my_game_example2.Monster.reader.vTableGetNullable( + _bc, + _bcOffset, + 20, + ); + default: + return null; + } + } + + List? get test4 => const fb.ListReader( + Test.reader, + ).vTableGetNullable(_bc, _bcOffset, 22); + List? get testarrayofstring => const fb.ListReader( + fb.StringReader(), + ).vTableGetNullable(_bc, _bcOffset, 24); + + /// an example documentation comment: this will end up in the generated code + /// multiline too + List? get testarrayoftables => const fb.ListReader( + Monster.reader, + ).vTableGetNullable(_bc, _bcOffset, 26); + Monster? get enemy => Monster.reader.vTableGetNullable(_bc, _bcOffset, 28); + List? get testnestedflatbuffer => + const fb.Uint8ListReader().vTableGetNullable(_bc, _bcOffset, 30); + Stat? get testempty => Stat.reader.vTableGetNullable(_bc, _bcOffset, 32); + bool get testbool => + const fb.BoolReader().vTableGet(_bc, _bcOffset, 34, false); + int get testhashs32Fnv1 => + const fb.Int32Reader().vTableGet(_bc, _bcOffset, 36, 0); + int get testhashu32Fnv1 => + const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 38, 0); + int get testhashs64Fnv1 => + const fb.Int64Reader().vTableGet(_bc, _bcOffset, 40, 0); + int get testhashu64Fnv1 => + const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 42, 0); + int get testhashs32Fnv1a => + const fb.Int32Reader().vTableGet(_bc, _bcOffset, 44, 0); + int get testhashu32Fnv1a => + const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 46, 0); + int get testhashs64Fnv1a => + const fb.Int64Reader().vTableGet(_bc, _bcOffset, 48, 0); + int get testhashu64Fnv1a => + const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 50, 0); + List? get testarrayofbools => const fb.ListReader( + fb.BoolReader(), + ).vTableGetNullable(_bc, _bcOffset, 52); + double get testf => + const fb.Float32Reader().vTableGet(_bc, _bcOffset, 54, 3.14159); + double get testf2 => + const fb.Float32Reader().vTableGet(_bc, _bcOffset, 56, 3.0); + double get testf3 => + const fb.Float32Reader().vTableGet(_bc, _bcOffset, 58, 0.0); + List? get testarrayofstring2 => const fb.ListReader( + fb.StringReader(), + ).vTableGetNullable(_bc, _bcOffset, 60); + List? get testarrayofsortedstruct => const fb.ListReader( + Ability.reader, + ).vTableGetNullable(_bc, _bcOffset, 62); + List? get flex => + const fb.Uint8ListReader().vTableGetNullable(_bc, _bcOffset, 64); + List? get test5 => const fb.ListReader( + Test.reader, + ).vTableGetNullable(_bc, _bcOffset, 66); + List? get vectorOfLongs => const fb.ListReader( + fb.Int64Reader(), + ).vTableGetNullable(_bc, _bcOffset, 68); + List? get vectorOfDoubles => const fb.ListReader( + fb.Float64Reader(), + ).vTableGetNullable(_bc, _bcOffset, 70); + my_game.InParentNamespace? get parentNamespaceTest => + my_game.InParentNamespace.reader.vTableGetNullable(_bc, _bcOffset, 72); + List? get vectorOfReferrables => const fb.ListReader( + Referrable.reader, + ).vTableGetNullable(_bc, _bcOffset, 74); + int get singleWeakReference => + const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 76, 0); + List? get vectorOfWeakReferences => const fb.ListReader( + fb.Uint64Reader(), + ).vTableGetNullable(_bc, _bcOffset, 78); + List? get vectorOfStrongReferrables => + const fb.ListReader( + Referrable.reader, + ).vTableGetNullable(_bc, _bcOffset, 80); + int get coOwningReference => + const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 82, 0); + List? get vectorOfCoOwningReferences => const fb.ListReader( + fb.Uint64Reader(), + ).vTableGetNullable(_bc, _bcOffset, 84); + int get nonOwningReference => + const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 86, 0); + List? get vectorOfNonOwningReferences => const fb.ListReader( + fb.Uint64Reader(), + ).vTableGetNullable(_bc, _bcOffset, 88); + AnyUniqueAliasesTypeId? get anyUniqueType => + AnyUniqueAliasesTypeId._createOrNull( + const fb.Uint8Reader().vTableGetNullable(_bc, _bcOffset, 90), + ); + dynamic get anyUnique { + switch (anyUniqueType?.value) { + case 1: + return Monster.reader.vTableGetNullable(_bc, _bcOffset, 92); + case 2: + return TestSimpleTableWithEnum.reader.vTableGetNullable( + _bc, + _bcOffset, + 92, + ); + case 3: + return my_game_example2.Monster.reader.vTableGetNullable( + _bc, + _bcOffset, + 92, + ); + default: + return null; + } + } + + AnyAmbiguousAliasesTypeId? get anyAmbiguousType => + AnyAmbiguousAliasesTypeId._createOrNull( + const fb.Uint8Reader().vTableGetNullable(_bc, _bcOffset, 94), + ); + dynamic get anyAmbiguous { + switch (anyAmbiguousType?.value) { + case 1: + return Monster.reader.vTableGetNullable(_bc, _bcOffset, 96); + case 2: + return Monster.reader.vTableGetNullable(_bc, _bcOffset, 96); + case 3: + return Monster.reader.vTableGetNullable(_bc, _bcOffset, 96); + default: + return null; + } + } + + List? get vectorOfEnums => const fb.ListReader( + Color.reader, + ).vTableGetNullable(_bc, _bcOffset, 98); + Race get signedEnum => + Race.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 100, -1)); + List? get testrequirednestedflatbuffer => + const fb.Uint8ListReader().vTableGetNullable(_bc, _bcOffset, 102); + List? get scalarKeySortedTables => const fb.ListReader( + Stat.reader, + ).vTableGetNullable(_bc, _bcOffset, 104); + Test? get nativeInline => Test.reader.vTableGetNullable(_bc, _bcOffset, 106); + LongEnum get longEnumNonEnumDefault => LongEnum.fromValue( + const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 108, 0), + ); + LongEnum get longEnumNormalDefault => LongEnum.fromValue( + const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 110, 2), + ); + double get nanDefault => + const fb.Float32Reader().vTableGet(_bc, _bcOffset, 112, double.nan); + double get infDefault => + const fb.Float32Reader().vTableGet(_bc, _bcOffset, 114, double.infinity); + double get positiveInfDefault => + const fb.Float32Reader().vTableGet(_bc, _bcOffset, 116, double.infinity); + double get infinityDefault => + const fb.Float32Reader().vTableGet(_bc, _bcOffset, 118, double.infinity); + double get positiveInfinityDefault => + const fb.Float32Reader().vTableGet(_bc, _bcOffset, 120, double.infinity); + double get negativeInfDefault => const fb.Float32Reader().vTableGet( + _bc, + _bcOffset, + 122, + double.negativeInfinity, + ); + double get negativeInfinityDefault => const fb.Float32Reader().vTableGet( + _bc, + _bcOffset, + 124, + double.negativeInfinity, + ); + double get doubleInfDefault => + const fb.Float64Reader().vTableGet(_bc, _bcOffset, 126, double.infinity); + + @override + String toString() { + return 'Monster{pos: ${pos}, mana: ${mana}, hp: ${hp}, name: ${name}, inventory: ${inventory}, color: ${color}, testType: ${testType}, test: ${test}, test4: ${test4}, testarrayofstring: ${testarrayofstring}, testarrayoftables: ${testarrayoftables}, enemy: ${enemy}, testnestedflatbuffer: ${testnestedflatbuffer}, testempty: ${testempty}, testbool: ${testbool}, testhashs32Fnv1: ${testhashs32Fnv1}, testhashu32Fnv1: ${testhashu32Fnv1}, testhashs64Fnv1: ${testhashs64Fnv1}, testhashu64Fnv1: ${testhashu64Fnv1}, testhashs32Fnv1a: ${testhashs32Fnv1a}, testhashu32Fnv1a: ${testhashu32Fnv1a}, testhashs64Fnv1a: ${testhashs64Fnv1a}, testhashu64Fnv1a: ${testhashu64Fnv1a}, testarrayofbools: ${testarrayofbools}, testf: ${testf}, testf2: ${testf2}, testf3: ${testf3}, testarrayofstring2: ${testarrayofstring2}, testarrayofsortedstruct: ${testarrayofsortedstruct}, flex: ${flex}, test5: ${test5}, vectorOfLongs: ${vectorOfLongs}, vectorOfDoubles: ${vectorOfDoubles}, parentNamespaceTest: ${parentNamespaceTest}, vectorOfReferrables: ${vectorOfReferrables}, singleWeakReference: ${singleWeakReference}, vectorOfWeakReferences: ${vectorOfWeakReferences}, vectorOfStrongReferrables: ${vectorOfStrongReferrables}, coOwningReference: ${coOwningReference}, vectorOfCoOwningReferences: ${vectorOfCoOwningReferences}, nonOwningReference: ${nonOwningReference}, vectorOfNonOwningReferences: ${vectorOfNonOwningReferences}, anyUniqueType: ${anyUniqueType}, anyUnique: ${anyUnique}, anyAmbiguousType: ${anyAmbiguousType}, anyAmbiguous: ${anyAmbiguous}, vectorOfEnums: ${vectorOfEnums}, signedEnum: ${signedEnum}, testrequirednestedflatbuffer: ${testrequirednestedflatbuffer}, scalarKeySortedTables: ${scalarKeySortedTables}, nativeInline: ${nativeInline}, longEnumNonEnumDefault: ${longEnumNonEnumDefault}, longEnumNormalDefault: ${longEnumNormalDefault}, nanDefault: ${nanDefault}, infDefault: ${infDefault}, positiveInfDefault: ${positiveInfDefault}, infinityDefault: ${infinityDefault}, positiveInfinityDefault: ${positiveInfinityDefault}, negativeInfDefault: ${negativeInfDefault}, negativeInfinityDefault: ${negativeInfinityDefault}, doubleInfDefault: ${doubleInfDefault}}'; + } + + MonsterT unpack() => MonsterT( + pos: pos?.unpack(), + mana: mana, + hp: hp, + name: name, + inventory: const fb.Uint8ListReader( + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 14), + color: color, + testType: testType, + test: test, + test4: test4?.map((e) => e.unpack()).toList(), + testarrayofstring: const fb.ListReader( + fb.StringReader(), + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 24), + testarrayoftables: testarrayoftables?.map((e) => e.unpack()).toList(), + enemy: enemy?.unpack(), + testnestedflatbuffer: const fb.Uint8ListReader( + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 30), + testempty: testempty?.unpack(), + testbool: testbool, + testhashs32Fnv1: testhashs32Fnv1, + testhashu32Fnv1: testhashu32Fnv1, + testhashs64Fnv1: testhashs64Fnv1, + testhashu64Fnv1: testhashu64Fnv1, + testhashs32Fnv1a: testhashs32Fnv1a, + testhashu32Fnv1a: testhashu32Fnv1a, + testhashs64Fnv1a: testhashs64Fnv1a, + testhashu64Fnv1a: testhashu64Fnv1a, + testarrayofbools: const fb.ListReader( + fb.BoolReader(), + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 52), + testf: testf, + testf2: testf2, + testf3: testf3, + testarrayofstring2: const fb.ListReader( + fb.StringReader(), + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 60), + testarrayofsortedstruct: testarrayofsortedstruct + ?.map((e) => e.unpack()) + .toList(), + flex: const fb.Uint8ListReader( + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 64), + test5: test5?.map((e) => e.unpack()).toList(), + vectorOfLongs: const fb.ListReader( + fb.Int64Reader(), + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 68), + vectorOfDoubles: const fb.ListReader( + fb.Float64Reader(), + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 70), + parentNamespaceTest: parentNamespaceTest?.unpack(), + vectorOfReferrables: vectorOfReferrables?.map((e) => e.unpack()).toList(), + singleWeakReference: singleWeakReference, + vectorOfWeakReferences: const fb.ListReader( + fb.Uint64Reader(), + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 78), + vectorOfStrongReferrables: vectorOfStrongReferrables + ?.map((e) => e.unpack()) + .toList(), + coOwningReference: coOwningReference, + vectorOfCoOwningReferences: const fb.ListReader( + fb.Uint64Reader(), + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 84), + nonOwningReference: nonOwningReference, + vectorOfNonOwningReferences: const fb.ListReader( + fb.Uint64Reader(), + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 88), + anyUniqueType: anyUniqueType, + anyUnique: anyUnique, + anyAmbiguousType: anyAmbiguousType, + anyAmbiguous: anyAmbiguous, + vectorOfEnums: const fb.ListReader( + Color.reader, + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 98), + signedEnum: signedEnum, + testrequirednestedflatbuffer: const fb.Uint8ListReader( + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 102), + scalarKeySortedTables: scalarKeySortedTables + ?.map((e) => e.unpack()) + .toList(), + nativeInline: nativeInline?.unpack(), + longEnumNonEnumDefault: longEnumNonEnumDefault, + longEnumNormalDefault: longEnumNormalDefault, + nanDefault: nanDefault, + infDefault: infDefault, + positiveInfDefault: positiveInfDefault, + infinityDefault: infinityDefault, + positiveInfinityDefault: positiveInfinityDefault, + negativeInfDefault: negativeInfDefault, + negativeInfinityDefault: negativeInfinityDefault, + doubleInfDefault: doubleInfDefault, + ); + + static int pack(fb.Builder fbBuilder, MonsterT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +/// an example documentation comment: "monster object" +class MonsterT implements fb.Packable { + Vec3T? pos; + int mana; + int hp; + String? name; + List? inventory; + Color color; + AnyTypeId? testType; + dynamic test; + List? test4; + List? testarrayofstring; + + /// an example documentation comment: this will end up in the generated code + /// multiline too + List? testarrayoftables; + MonsterT? enemy; + List? testnestedflatbuffer; + StatT? testempty; + bool testbool; + int testhashs32Fnv1; + int testhashu32Fnv1; + int testhashs64Fnv1; + int testhashu64Fnv1; + int testhashs32Fnv1a; + int testhashu32Fnv1a; + int testhashs64Fnv1a; + int testhashu64Fnv1a; + List? testarrayofbools; + double testf; + double testf2; + double testf3; + List? testarrayofstring2; + List? testarrayofsortedstruct; + List? flex; + List? test5; + List? vectorOfLongs; + List? vectorOfDoubles; + my_game.InParentNamespaceT? parentNamespaceTest; + List? vectorOfReferrables; + int singleWeakReference; + List? vectorOfWeakReferences; + List? vectorOfStrongReferrables; + int coOwningReference; + List? vectorOfCoOwningReferences; + int nonOwningReference; + List? vectorOfNonOwningReferences; + AnyUniqueAliasesTypeId? anyUniqueType; + dynamic anyUnique; + AnyAmbiguousAliasesTypeId? anyAmbiguousType; + dynamic anyAmbiguous; + List? vectorOfEnums; + Race signedEnum; + List? testrequirednestedflatbuffer; + List? scalarKeySortedTables; + TestT? nativeInline; + LongEnum longEnumNonEnumDefault; + LongEnum longEnumNormalDefault; + double nanDefault; + double infDefault; + double positiveInfDefault; + double infinityDefault; + double positiveInfinityDefault; + double negativeInfDefault; + double negativeInfinityDefault; + double doubleInfDefault; + + MonsterT({ + this.pos, + this.mana = 150, + this.hp = 100, + this.name, + this.inventory, + this.color = Color.Blue, + this.testType, + this.test, + this.test4, + this.testarrayofstring, + this.testarrayoftables, + this.enemy, + this.testnestedflatbuffer, + this.testempty, + this.testbool = false, + this.testhashs32Fnv1 = 0, + this.testhashu32Fnv1 = 0, + this.testhashs64Fnv1 = 0, + this.testhashu64Fnv1 = 0, + this.testhashs32Fnv1a = 0, + this.testhashu32Fnv1a = 0, + this.testhashs64Fnv1a = 0, + this.testhashu64Fnv1a = 0, + this.testarrayofbools, + this.testf = 3.14159, + this.testf2 = 3.0, + this.testf3 = 0.0, + this.testarrayofstring2, + this.testarrayofsortedstruct, + this.flex, + this.test5, + this.vectorOfLongs, + this.vectorOfDoubles, + this.parentNamespaceTest, + this.vectorOfReferrables, + this.singleWeakReference = 0, + this.vectorOfWeakReferences, + this.vectorOfStrongReferrables, + this.coOwningReference = 0, + this.vectorOfCoOwningReferences, + this.nonOwningReference = 0, + this.vectorOfNonOwningReferences, + this.anyUniqueType, + this.anyUnique, + this.anyAmbiguousType, + this.anyAmbiguous, + this.vectorOfEnums, + this.signedEnum = Race.None, + this.testrequirednestedflatbuffer, + this.scalarKeySortedTables, + this.nativeInline, + this.longEnumNonEnumDefault = LongEnum._default, + this.longEnumNormalDefault = LongEnum.LongOne, + this.nanDefault = double.nan, + this.infDefault = double.infinity, + this.positiveInfDefault = double.infinity, + this.infinityDefault = double.infinity, + this.positiveInfinityDefault = double.infinity, + this.negativeInfDefault = double.negativeInfinity, + this.negativeInfinityDefault = double.negativeInfinity, + this.doubleInfDefault = double.infinity, + }); + + @override + int pack(fb.Builder fbBuilder) { + final int? nameOffset = name == null ? null : fbBuilder.writeString(name!); + final int? inventoryOffset = inventory == null + ? null + : fbBuilder.writeListUint8(inventory!); + final int? testOffset = test?.pack(fbBuilder); + int? test4Offset; + if (test4 != null) { + for (var e in test4!) { + e.pack(fbBuilder); + } + test4Offset = fbBuilder.endStructVector(test4!.length); + } + final int? testarrayofstringOffset = testarrayofstring == null + ? null + : fbBuilder.writeList( + testarrayofstring!.map(fbBuilder.writeString).toList(), + ); + final int? testarrayoftablesOffset = testarrayoftables == null + ? null + : fbBuilder.writeList( + testarrayoftables!.map((b) => b.pack(fbBuilder)).toList(), + ); + final int? enemyOffset = enemy?.pack(fbBuilder); + final int? testnestedflatbufferOffset = testnestedflatbuffer == null + ? null + : fbBuilder.writeListUint8(testnestedflatbuffer!); + final int? testemptyOffset = testempty?.pack(fbBuilder); + final int? testarrayofboolsOffset = testarrayofbools == null + ? null + : fbBuilder.writeListBool(testarrayofbools!); + final int? testarrayofstring2Offset = testarrayofstring2 == null + ? null + : fbBuilder.writeList( + testarrayofstring2!.map(fbBuilder.writeString).toList(), + ); + int? testarrayofsortedstructOffset; + if (testarrayofsortedstruct != null) { + for (var e in testarrayofsortedstruct!) { + e.pack(fbBuilder); + } + testarrayofsortedstructOffset = fbBuilder.endStructVector( + testarrayofsortedstruct!.length, + ); + } + final int? flexOffset = flex == null + ? null + : fbBuilder.writeListUint8(flex!); + int? test5Offset; + if (test5 != null) { + for (var e in test5!) { + e.pack(fbBuilder); + } + test5Offset = fbBuilder.endStructVector(test5!.length); + } + final int? vectorOfLongsOffset = vectorOfLongs == null + ? null + : fbBuilder.writeListInt64(vectorOfLongs!); + final int? vectorOfDoublesOffset = vectorOfDoubles == null + ? null + : fbBuilder.writeListFloat64(vectorOfDoubles!); + final int? parentNamespaceTestOffset = parentNamespaceTest?.pack(fbBuilder); + final int? vectorOfReferrablesOffset = vectorOfReferrables == null + ? null + : fbBuilder.writeList( + vectorOfReferrables!.map((b) => b.pack(fbBuilder)).toList(), + ); + final int? vectorOfWeakReferencesOffset = vectorOfWeakReferences == null + ? null + : fbBuilder.writeListUint64(vectorOfWeakReferences!); + final int? vectorOfStrongReferrablesOffset = + vectorOfStrongReferrables == null + ? null + : fbBuilder.writeList( + vectorOfStrongReferrables!.map((b) => b.pack(fbBuilder)).toList(), + ); + final int? vectorOfCoOwningReferencesOffset = + vectorOfCoOwningReferences == null + ? null + : fbBuilder.writeListUint64(vectorOfCoOwningReferences!); + final int? vectorOfNonOwningReferencesOffset = + vectorOfNonOwningReferences == null + ? null + : fbBuilder.writeListUint64(vectorOfNonOwningReferences!); + final int? anyUniqueOffset = anyUnique?.pack(fbBuilder); + final int? anyAmbiguousOffset = anyAmbiguous?.pack(fbBuilder); + final int? vectorOfEnumsOffset = vectorOfEnums == null + ? null + : fbBuilder.writeListUint8(vectorOfEnums!.map((f) => f.value).toList()); + final int? testrequirednestedflatbufferOffset = + testrequirednestedflatbuffer == null + ? null + : fbBuilder.writeListUint8(testrequirednestedflatbuffer!); + final int? scalarKeySortedTablesOffset = scalarKeySortedTables == null + ? null + : fbBuilder.writeList( + scalarKeySortedTables!.map((b) => b.pack(fbBuilder)).toList(), + ); + fbBuilder.startTable(62); + if (pos != null) { + fbBuilder.addStruct(0, pos!.pack(fbBuilder)); + } + fbBuilder.addInt16(1, mana); + fbBuilder.addInt16(2, hp); + fbBuilder.addOffset(3, nameOffset); + fbBuilder.addOffset(5, inventoryOffset); + fbBuilder.addUint8(6, color.value); + fbBuilder.addUint8(7, testType?.value); + fbBuilder.addOffset(8, testOffset); + fbBuilder.addOffset(9, test4Offset); + fbBuilder.addOffset(10, testarrayofstringOffset); + fbBuilder.addOffset(11, testarrayoftablesOffset); + fbBuilder.addOffset(12, enemyOffset); + fbBuilder.addOffset(13, testnestedflatbufferOffset); + fbBuilder.addOffset(14, testemptyOffset); + fbBuilder.addBool(15, testbool); + fbBuilder.addInt32(16, testhashs32Fnv1); + fbBuilder.addUint32(17, testhashu32Fnv1); + fbBuilder.addInt64(18, testhashs64Fnv1); + fbBuilder.addUint64(19, testhashu64Fnv1); + fbBuilder.addInt32(20, testhashs32Fnv1a); + fbBuilder.addUint32(21, testhashu32Fnv1a); + fbBuilder.addInt64(22, testhashs64Fnv1a); + fbBuilder.addUint64(23, testhashu64Fnv1a); + fbBuilder.addOffset(24, testarrayofboolsOffset); + fbBuilder.addFloat32(25, testf); + fbBuilder.addFloat32(26, testf2); + fbBuilder.addFloat32(27, testf3); + fbBuilder.addOffset(28, testarrayofstring2Offset); + fbBuilder.addOffset(29, testarrayofsortedstructOffset); + fbBuilder.addOffset(30, flexOffset); + fbBuilder.addOffset(31, test5Offset); + fbBuilder.addOffset(32, vectorOfLongsOffset); + fbBuilder.addOffset(33, vectorOfDoublesOffset); + fbBuilder.addOffset(34, parentNamespaceTestOffset); + fbBuilder.addOffset(35, vectorOfReferrablesOffset); + fbBuilder.addUint64(36, singleWeakReference); + fbBuilder.addOffset(37, vectorOfWeakReferencesOffset); + fbBuilder.addOffset(38, vectorOfStrongReferrablesOffset); + fbBuilder.addUint64(39, coOwningReference); + fbBuilder.addOffset(40, vectorOfCoOwningReferencesOffset); + fbBuilder.addUint64(41, nonOwningReference); + fbBuilder.addOffset(42, vectorOfNonOwningReferencesOffset); + fbBuilder.addUint8(43, anyUniqueType?.value); + fbBuilder.addOffset(44, anyUniqueOffset); + fbBuilder.addUint8(45, anyAmbiguousType?.value); + fbBuilder.addOffset(46, anyAmbiguousOffset); + fbBuilder.addOffset(47, vectorOfEnumsOffset); + fbBuilder.addInt8(48, signedEnum.value); + fbBuilder.addOffset(49, testrequirednestedflatbufferOffset); + fbBuilder.addOffset(50, scalarKeySortedTablesOffset); + if (nativeInline != null) { + fbBuilder.addStruct(51, nativeInline!.pack(fbBuilder)); + } + fbBuilder.addUint64(52, longEnumNonEnumDefault.value); + fbBuilder.addUint64(53, longEnumNormalDefault.value); + fbBuilder.addFloat32(54, nanDefault); + fbBuilder.addFloat32(55, infDefault); + fbBuilder.addFloat32(56, positiveInfDefault); + fbBuilder.addFloat32(57, infinityDefault); + fbBuilder.addFloat32(58, positiveInfinityDefault); + fbBuilder.addFloat32(59, negativeInfDefault); + fbBuilder.addFloat32(60, negativeInfinityDefault); + fbBuilder.addFloat64(61, doubleInfDefault); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'MonsterT{pos: ${pos}, mana: ${mana}, hp: ${hp}, name: ${name}, inventory: ${inventory}, color: ${color}, testType: ${testType}, test: ${test}, test4: ${test4}, testarrayofstring: ${testarrayofstring}, testarrayoftables: ${testarrayoftables}, enemy: ${enemy}, testnestedflatbuffer: ${testnestedflatbuffer}, testempty: ${testempty}, testbool: ${testbool}, testhashs32Fnv1: ${testhashs32Fnv1}, testhashu32Fnv1: ${testhashu32Fnv1}, testhashs64Fnv1: ${testhashs64Fnv1}, testhashu64Fnv1: ${testhashu64Fnv1}, testhashs32Fnv1a: ${testhashs32Fnv1a}, testhashu32Fnv1a: ${testhashu32Fnv1a}, testhashs64Fnv1a: ${testhashs64Fnv1a}, testhashu64Fnv1a: ${testhashu64Fnv1a}, testarrayofbools: ${testarrayofbools}, testf: ${testf}, testf2: ${testf2}, testf3: ${testf3}, testarrayofstring2: ${testarrayofstring2}, testarrayofsortedstruct: ${testarrayofsortedstruct}, flex: ${flex}, test5: ${test5}, vectorOfLongs: ${vectorOfLongs}, vectorOfDoubles: ${vectorOfDoubles}, parentNamespaceTest: ${parentNamespaceTest}, vectorOfReferrables: ${vectorOfReferrables}, singleWeakReference: ${singleWeakReference}, vectorOfWeakReferences: ${vectorOfWeakReferences}, vectorOfStrongReferrables: ${vectorOfStrongReferrables}, coOwningReference: ${coOwningReference}, vectorOfCoOwningReferences: ${vectorOfCoOwningReferences}, nonOwningReference: ${nonOwningReference}, vectorOfNonOwningReferences: ${vectorOfNonOwningReferences}, anyUniqueType: ${anyUniqueType}, anyUnique: ${anyUnique}, anyAmbiguousType: ${anyAmbiguousType}, anyAmbiguous: ${anyAmbiguous}, vectorOfEnums: ${vectorOfEnums}, signedEnum: ${signedEnum}, testrequirednestedflatbuffer: ${testrequirednestedflatbuffer}, scalarKeySortedTables: ${scalarKeySortedTables}, nativeInline: ${nativeInline}, longEnumNonEnumDefault: ${longEnumNonEnumDefault}, longEnumNormalDefault: ${longEnumNormalDefault}, nanDefault: ${nanDefault}, infDefault: ${infDefault}, positiveInfDefault: ${positiveInfDefault}, infinityDefault: ${infinityDefault}, positiveInfinityDefault: ${positiveInfinityDefault}, negativeInfDefault: ${negativeInfDefault}, negativeInfinityDefault: ${negativeInfinityDefault}, doubleInfDefault: ${doubleInfDefault}}'; + } +} + +class _MonsterReader extends fb.TableReader { + const _MonsterReader(); + + @override + Monster createObject(fb.BufferContext bc, int offset) => + Monster._(bc, offset); +} + +class MonsterBuilder { + MonsterBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(62); + } + + int addPos(int offset) { + fbBuilder.addStruct(0, offset); + return fbBuilder.offset; + } + + int addMana(int? mana) { + fbBuilder.addInt16(1, mana); + return fbBuilder.offset; + } + + int addHp(int? hp) { + fbBuilder.addInt16(2, hp); + return fbBuilder.offset; + } + + int addNameOffset(int? offset) { + fbBuilder.addOffset(3, offset); + return fbBuilder.offset; + } + + int addInventoryOffset(int? offset) { + fbBuilder.addOffset(5, offset); + return fbBuilder.offset; + } + + int addColor(Color? color) { + fbBuilder.addUint8(6, color?.value); + return fbBuilder.offset; + } + + int addTestType(AnyTypeId? testType) { + fbBuilder.addUint8(7, testType?.value); + return fbBuilder.offset; + } + + int addTestOffset(int? offset) { + fbBuilder.addOffset(8, offset); + return fbBuilder.offset; + } + + int addTest4Offset(int? offset) { + fbBuilder.addOffset(9, offset); + return fbBuilder.offset; + } + + int addTestarrayofstringOffset(int? offset) { + fbBuilder.addOffset(10, offset); + return fbBuilder.offset; + } + + int addTestarrayoftablesOffset(int? offset) { + fbBuilder.addOffset(11, offset); + return fbBuilder.offset; + } + + int addEnemyOffset(int? offset) { + fbBuilder.addOffset(12, offset); + return fbBuilder.offset; + } + + int addTestnestedflatbufferOffset(int? offset) { + fbBuilder.addOffset(13, offset); + return fbBuilder.offset; + } + + int addTestemptyOffset(int? offset) { + fbBuilder.addOffset(14, offset); + return fbBuilder.offset; + } + + int addTestbool(bool? testbool) { + fbBuilder.addBool(15, testbool); + return fbBuilder.offset; + } + + int addTesthashs32Fnv1(int? testhashs32Fnv1) { + fbBuilder.addInt32(16, testhashs32Fnv1); + return fbBuilder.offset; + } + + int addTesthashu32Fnv1(int? testhashu32Fnv1) { + fbBuilder.addUint32(17, testhashu32Fnv1); + return fbBuilder.offset; + } + + int addTesthashs64Fnv1(int? testhashs64Fnv1) { + fbBuilder.addInt64(18, testhashs64Fnv1); + return fbBuilder.offset; + } + + int addTesthashu64Fnv1(int? testhashu64Fnv1) { + fbBuilder.addUint64(19, testhashu64Fnv1); + return fbBuilder.offset; + } + + int addTesthashs32Fnv1a(int? testhashs32Fnv1a) { + fbBuilder.addInt32(20, testhashs32Fnv1a); + return fbBuilder.offset; + } + + int addTesthashu32Fnv1a(int? testhashu32Fnv1a) { + fbBuilder.addUint32(21, testhashu32Fnv1a); + return fbBuilder.offset; + } + + int addTesthashs64Fnv1a(int? testhashs64Fnv1a) { + fbBuilder.addInt64(22, testhashs64Fnv1a); + return fbBuilder.offset; + } + + int addTesthashu64Fnv1a(int? testhashu64Fnv1a) { + fbBuilder.addUint64(23, testhashu64Fnv1a); + return fbBuilder.offset; + } + + int addTestarrayofboolsOffset(int? offset) { + fbBuilder.addOffset(24, offset); + return fbBuilder.offset; + } + + int addTestf(double? testf) { + fbBuilder.addFloat32(25, testf); + return fbBuilder.offset; + } + + int addTestf2(double? testf2) { + fbBuilder.addFloat32(26, testf2); + return fbBuilder.offset; + } + + int addTestf3(double? testf3) { + fbBuilder.addFloat32(27, testf3); + return fbBuilder.offset; + } + + int addTestarrayofstring2Offset(int? offset) { + fbBuilder.addOffset(28, offset); + return fbBuilder.offset; + } + + int addTestarrayofsortedstructOffset(int? offset) { + fbBuilder.addOffset(29, offset); + return fbBuilder.offset; + } + + int addFlexOffset(int? offset) { + fbBuilder.addOffset(30, offset); + return fbBuilder.offset; + } + + int addTest5Offset(int? offset) { + fbBuilder.addOffset(31, offset); + return fbBuilder.offset; + } + + int addVectorOfLongsOffset(int? offset) { + fbBuilder.addOffset(32, offset); + return fbBuilder.offset; + } + + int addVectorOfDoublesOffset(int? offset) { + fbBuilder.addOffset(33, offset); + return fbBuilder.offset; + } + + int addParentNamespaceTestOffset(int? offset) { + fbBuilder.addOffset(34, offset); + return fbBuilder.offset; + } + + int addVectorOfReferrablesOffset(int? offset) { + fbBuilder.addOffset(35, offset); + return fbBuilder.offset; + } + + int addSingleWeakReference(int? singleWeakReference) { + fbBuilder.addUint64(36, singleWeakReference); + return fbBuilder.offset; + } + + int addVectorOfWeakReferencesOffset(int? offset) { + fbBuilder.addOffset(37, offset); + return fbBuilder.offset; + } + + int addVectorOfStrongReferrablesOffset(int? offset) { + fbBuilder.addOffset(38, offset); + return fbBuilder.offset; + } + + int addCoOwningReference(int? coOwningReference) { + fbBuilder.addUint64(39, coOwningReference); + return fbBuilder.offset; + } + + int addVectorOfCoOwningReferencesOffset(int? offset) { + fbBuilder.addOffset(40, offset); + return fbBuilder.offset; + } + + int addNonOwningReference(int? nonOwningReference) { + fbBuilder.addUint64(41, nonOwningReference); + return fbBuilder.offset; + } + + int addVectorOfNonOwningReferencesOffset(int? offset) { + fbBuilder.addOffset(42, offset); + return fbBuilder.offset; + } + + int addAnyUniqueType(AnyUniqueAliasesTypeId? anyUniqueType) { + fbBuilder.addUint8(43, anyUniqueType?.value); + return fbBuilder.offset; + } + + int addAnyUniqueOffset(int? offset) { + fbBuilder.addOffset(44, offset); + return fbBuilder.offset; + } + + int addAnyAmbiguousType(AnyAmbiguousAliasesTypeId? anyAmbiguousType) { + fbBuilder.addUint8(45, anyAmbiguousType?.value); + return fbBuilder.offset; + } + + int addAnyAmbiguousOffset(int? offset) { + fbBuilder.addOffset(46, offset); + return fbBuilder.offset; + } + + int addVectorOfEnumsOffset(int? offset) { + fbBuilder.addOffset(47, offset); + return fbBuilder.offset; + } + + int addSignedEnum(Race? signedEnum) { + fbBuilder.addInt8(48, signedEnum?.value); + return fbBuilder.offset; + } + + int addTestrequirednestedflatbufferOffset(int? offset) { + fbBuilder.addOffset(49, offset); + return fbBuilder.offset; + } + + int addScalarKeySortedTablesOffset(int? offset) { + fbBuilder.addOffset(50, offset); + return fbBuilder.offset; + } + + int addNativeInline(int offset) { + fbBuilder.addStruct(51, offset); + return fbBuilder.offset; + } + + int addLongEnumNonEnumDefault(LongEnum? longEnumNonEnumDefault) { + fbBuilder.addUint64(52, longEnumNonEnumDefault?.value); + return fbBuilder.offset; + } + + int addLongEnumNormalDefault(LongEnum? longEnumNormalDefault) { + fbBuilder.addUint64(53, longEnumNormalDefault?.value); + return fbBuilder.offset; + } + + int addNanDefault(double? nanDefault) { + fbBuilder.addFloat32(54, nanDefault); + return fbBuilder.offset; + } + + int addInfDefault(double? infDefault) { + fbBuilder.addFloat32(55, infDefault); + return fbBuilder.offset; + } + + int addPositiveInfDefault(double? positiveInfDefault) { + fbBuilder.addFloat32(56, positiveInfDefault); + return fbBuilder.offset; + } + + int addInfinityDefault(double? infinityDefault) { + fbBuilder.addFloat32(57, infinityDefault); + return fbBuilder.offset; + } + + int addPositiveInfinityDefault(double? positiveInfinityDefault) { + fbBuilder.addFloat32(58, positiveInfinityDefault); + return fbBuilder.offset; + } + + int addNegativeInfDefault(double? negativeInfDefault) { + fbBuilder.addFloat32(59, negativeInfDefault); + return fbBuilder.offset; + } + + int addNegativeInfinityDefault(double? negativeInfinityDefault) { + fbBuilder.addFloat32(60, negativeInfinityDefault); + return fbBuilder.offset; + } + + int addDoubleInfDefault(double? doubleInfDefault) { + fbBuilder.addFloat64(61, doubleInfDefault); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class MonsterObjectBuilder extends fb.ObjectBuilder { + final Vec3ObjectBuilder? _pos; + final int? _mana; + final int? _hp; + final String? _name; + final List? _inventory; + final Color? _color; + final AnyTypeId? _testType; + final dynamic _test; + final List? _test4; + final List? _testarrayofstring; + final List? _testarrayoftables; + final MonsterObjectBuilder? _enemy; + final List? _testnestedflatbuffer; + final StatObjectBuilder? _testempty; + final bool? _testbool; + final int? _testhashs32Fnv1; + final int? _testhashu32Fnv1; + final int? _testhashs64Fnv1; + final int? _testhashu64Fnv1; + final int? _testhashs32Fnv1a; + final int? _testhashu32Fnv1a; + final int? _testhashs64Fnv1a; + final int? _testhashu64Fnv1a; + final List? _testarrayofbools; + final double? _testf; + final double? _testf2; + final double? _testf3; + final List? _testarrayofstring2; + final List? _testarrayofsortedstruct; + final List? _flex; + final List? _test5; + final List? _vectorOfLongs; + final List? _vectorOfDoubles; + final my_game.InParentNamespaceObjectBuilder? _parentNamespaceTest; + final List? _vectorOfReferrables; + final int? _singleWeakReference; + final List? _vectorOfWeakReferences; + final List? _vectorOfStrongReferrables; + final int? _coOwningReference; + final List? _vectorOfCoOwningReferences; + final int? _nonOwningReference; + final List? _vectorOfNonOwningReferences; + final AnyUniqueAliasesTypeId? _anyUniqueType; + final dynamic _anyUnique; + final AnyAmbiguousAliasesTypeId? _anyAmbiguousType; + final dynamic _anyAmbiguous; + final List? _vectorOfEnums; + final Race? _signedEnum; + final List? _testrequirednestedflatbuffer; + final List? _scalarKeySortedTables; + final TestObjectBuilder? _nativeInline; + final LongEnum? _longEnumNonEnumDefault; + final LongEnum? _longEnumNormalDefault; + final double? _nanDefault; + final double? _infDefault; + final double? _positiveInfDefault; + final double? _infinityDefault; + final double? _positiveInfinityDefault; + final double? _negativeInfDefault; + final double? _negativeInfinityDefault; + final double? _doubleInfDefault; + + MonsterObjectBuilder({ + Vec3ObjectBuilder? pos, + int? mana, + int? hp, + String? name, + List? inventory, + Color? color, + AnyTypeId? testType, + dynamic test, + List? test4, + List? testarrayofstring, + List? testarrayoftables, + MonsterObjectBuilder? enemy, + List? testnestedflatbuffer, + StatObjectBuilder? testempty, + bool? testbool, + int? testhashs32Fnv1, + int? testhashu32Fnv1, + int? testhashs64Fnv1, + int? testhashu64Fnv1, + int? testhashs32Fnv1a, + int? testhashu32Fnv1a, + int? testhashs64Fnv1a, + int? testhashu64Fnv1a, + List? testarrayofbools, + double? testf, + double? testf2, + double? testf3, + List? testarrayofstring2, + List? testarrayofsortedstruct, + List? flex, + List? test5, + List? vectorOfLongs, + List? vectorOfDoubles, + my_game.InParentNamespaceObjectBuilder? parentNamespaceTest, + List? vectorOfReferrables, + int? singleWeakReference, + List? vectorOfWeakReferences, + List? vectorOfStrongReferrables, + int? coOwningReference, + List? vectorOfCoOwningReferences, + int? nonOwningReference, + List? vectorOfNonOwningReferences, + AnyUniqueAliasesTypeId? anyUniqueType, + dynamic anyUnique, + AnyAmbiguousAliasesTypeId? anyAmbiguousType, + dynamic anyAmbiguous, + List? vectorOfEnums, + Race? signedEnum, + List? testrequirednestedflatbuffer, + List? scalarKeySortedTables, + TestObjectBuilder? nativeInline, + LongEnum? longEnumNonEnumDefault, + LongEnum? longEnumNormalDefault, + double? nanDefault, + double? infDefault, + double? positiveInfDefault, + double? infinityDefault, + double? positiveInfinityDefault, + double? negativeInfDefault, + double? negativeInfinityDefault, + double? doubleInfDefault, + }) : _pos = pos, + _mana = mana, + _hp = hp, + _name = name, + _inventory = inventory, + _color = color, + _testType = testType, + _test = test, + _test4 = test4, + _testarrayofstring = testarrayofstring, + _testarrayoftables = testarrayoftables, + _enemy = enemy, + _testnestedflatbuffer = testnestedflatbuffer, + _testempty = testempty, + _testbool = testbool, + _testhashs32Fnv1 = testhashs32Fnv1, + _testhashu32Fnv1 = testhashu32Fnv1, + _testhashs64Fnv1 = testhashs64Fnv1, + _testhashu64Fnv1 = testhashu64Fnv1, + _testhashs32Fnv1a = testhashs32Fnv1a, + _testhashu32Fnv1a = testhashu32Fnv1a, + _testhashs64Fnv1a = testhashs64Fnv1a, + _testhashu64Fnv1a = testhashu64Fnv1a, + _testarrayofbools = testarrayofbools, + _testf = testf, + _testf2 = testf2, + _testf3 = testf3, + _testarrayofstring2 = testarrayofstring2, + _testarrayofsortedstruct = testarrayofsortedstruct, + _flex = flex, + _test5 = test5, + _vectorOfLongs = vectorOfLongs, + _vectorOfDoubles = vectorOfDoubles, + _parentNamespaceTest = parentNamespaceTest, + _vectorOfReferrables = vectorOfReferrables, + _singleWeakReference = singleWeakReference, + _vectorOfWeakReferences = vectorOfWeakReferences, + _vectorOfStrongReferrables = vectorOfStrongReferrables, + _coOwningReference = coOwningReference, + _vectorOfCoOwningReferences = vectorOfCoOwningReferences, + _nonOwningReference = nonOwningReference, + _vectorOfNonOwningReferences = vectorOfNonOwningReferences, + _anyUniqueType = anyUniqueType, + _anyUnique = anyUnique, + _anyAmbiguousType = anyAmbiguousType, + _anyAmbiguous = anyAmbiguous, + _vectorOfEnums = vectorOfEnums, + _signedEnum = signedEnum, + _testrequirednestedflatbuffer = testrequirednestedflatbuffer, + _scalarKeySortedTables = scalarKeySortedTables, + _nativeInline = nativeInline, + _longEnumNonEnumDefault = longEnumNonEnumDefault, + _longEnumNormalDefault = longEnumNormalDefault, + _nanDefault = nanDefault, + _infDefault = infDefault, + _positiveInfDefault = positiveInfDefault, + _infinityDefault = infinityDefault, + _positiveInfinityDefault = positiveInfinityDefault, + _negativeInfDefault = negativeInfDefault, + _negativeInfinityDefault = negativeInfinityDefault, + _doubleInfDefault = doubleInfDefault; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? nameOffset = _name == null + ? null + : fbBuilder.writeString(_name!); + final int? inventoryOffset = _inventory == null + ? null + : fbBuilder.writeListUint8(_inventory!); + final int? testOffset = _test?.getOrCreateOffset(fbBuilder); + final int? test4Offset = _test4 == null + ? null + : fbBuilder.writeListOfStructs(_test4!); + final int? testarrayofstringOffset = _testarrayofstring == null + ? null + : fbBuilder.writeList( + _testarrayofstring!.map(fbBuilder.writeString).toList(), + ); + final int? testarrayoftablesOffset = _testarrayoftables == null + ? null + : fbBuilder.writeList( + _testarrayoftables! + .map((b) => b.getOrCreateOffset(fbBuilder)) + .toList(), + ); + final int? enemyOffset = _enemy?.getOrCreateOffset(fbBuilder); + final int? testnestedflatbufferOffset = _testnestedflatbuffer == null + ? null + : fbBuilder.writeListUint8(_testnestedflatbuffer!); + final int? testemptyOffset = _testempty?.getOrCreateOffset(fbBuilder); + final int? testarrayofboolsOffset = _testarrayofbools == null + ? null + : fbBuilder.writeListBool(_testarrayofbools!); + final int? testarrayofstring2Offset = _testarrayofstring2 == null + ? null + : fbBuilder.writeList( + _testarrayofstring2!.map(fbBuilder.writeString).toList(), + ); + final int? testarrayofsortedstructOffset = _testarrayofsortedstruct == null + ? null + : fbBuilder.writeListOfStructs(_testarrayofsortedstruct!); + final int? flexOffset = _flex == null + ? null + : fbBuilder.writeListUint8(_flex!); + final int? test5Offset = _test5 == null + ? null + : fbBuilder.writeListOfStructs(_test5!); + final int? vectorOfLongsOffset = _vectorOfLongs == null + ? null + : fbBuilder.writeListInt64(_vectorOfLongs!); + final int? vectorOfDoublesOffset = _vectorOfDoubles == null + ? null + : fbBuilder.writeListFloat64(_vectorOfDoubles!); + final int? parentNamespaceTestOffset = _parentNamespaceTest + ?.getOrCreateOffset(fbBuilder); + final int? vectorOfReferrablesOffset = _vectorOfReferrables == null + ? null + : fbBuilder.writeList( + _vectorOfReferrables! + .map((b) => b.getOrCreateOffset(fbBuilder)) + .toList(), + ); + final int? vectorOfWeakReferencesOffset = _vectorOfWeakReferences == null + ? null + : fbBuilder.writeListUint64(_vectorOfWeakReferences!); + final int? vectorOfStrongReferrablesOffset = + _vectorOfStrongReferrables == null + ? null + : fbBuilder.writeList( + _vectorOfStrongReferrables! + .map((b) => b.getOrCreateOffset(fbBuilder)) + .toList(), + ); + final int? vectorOfCoOwningReferencesOffset = + _vectorOfCoOwningReferences == null + ? null + : fbBuilder.writeListUint64(_vectorOfCoOwningReferences!); + final int? vectorOfNonOwningReferencesOffset = + _vectorOfNonOwningReferences == null + ? null + : fbBuilder.writeListUint64(_vectorOfNonOwningReferences!); + final int? anyUniqueOffset = _anyUnique?.getOrCreateOffset(fbBuilder); + final int? anyAmbiguousOffset = _anyAmbiguous?.getOrCreateOffset(fbBuilder); + final int? vectorOfEnumsOffset = _vectorOfEnums == null + ? null + : fbBuilder.writeListUint8( + _vectorOfEnums!.map((f) => f.value).toList(), + ); + final int? testrequirednestedflatbufferOffset = + _testrequirednestedflatbuffer == null + ? null + : fbBuilder.writeListUint8(_testrequirednestedflatbuffer!); + final int? scalarKeySortedTablesOffset = _scalarKeySortedTables == null + ? null + : fbBuilder.writeList( + _scalarKeySortedTables! + .map((b) => b.getOrCreateOffset(fbBuilder)) + .toList(), + ); + fbBuilder.startTable(62); + if (_pos != null) { + fbBuilder.addStruct(0, _pos!.finish(fbBuilder)); + } + fbBuilder.addInt16(1, _mana); + fbBuilder.addInt16(2, _hp); + fbBuilder.addOffset(3, nameOffset); + fbBuilder.addOffset(5, inventoryOffset); + fbBuilder.addUint8(6, _color?.value); + fbBuilder.addUint8(7, _testType?.value); + fbBuilder.addOffset(8, testOffset); + fbBuilder.addOffset(9, test4Offset); + fbBuilder.addOffset(10, testarrayofstringOffset); + fbBuilder.addOffset(11, testarrayoftablesOffset); + fbBuilder.addOffset(12, enemyOffset); + fbBuilder.addOffset(13, testnestedflatbufferOffset); + fbBuilder.addOffset(14, testemptyOffset); + fbBuilder.addBool(15, _testbool); + fbBuilder.addInt32(16, _testhashs32Fnv1); + fbBuilder.addUint32(17, _testhashu32Fnv1); + fbBuilder.addInt64(18, _testhashs64Fnv1); + fbBuilder.addUint64(19, _testhashu64Fnv1); + fbBuilder.addInt32(20, _testhashs32Fnv1a); + fbBuilder.addUint32(21, _testhashu32Fnv1a); + fbBuilder.addInt64(22, _testhashs64Fnv1a); + fbBuilder.addUint64(23, _testhashu64Fnv1a); + fbBuilder.addOffset(24, testarrayofboolsOffset); + fbBuilder.addFloat32(25, _testf); + fbBuilder.addFloat32(26, _testf2); + fbBuilder.addFloat32(27, _testf3); + fbBuilder.addOffset(28, testarrayofstring2Offset); + fbBuilder.addOffset(29, testarrayofsortedstructOffset); + fbBuilder.addOffset(30, flexOffset); + fbBuilder.addOffset(31, test5Offset); + fbBuilder.addOffset(32, vectorOfLongsOffset); + fbBuilder.addOffset(33, vectorOfDoublesOffset); + fbBuilder.addOffset(34, parentNamespaceTestOffset); + fbBuilder.addOffset(35, vectorOfReferrablesOffset); + fbBuilder.addUint64(36, _singleWeakReference); + fbBuilder.addOffset(37, vectorOfWeakReferencesOffset); + fbBuilder.addOffset(38, vectorOfStrongReferrablesOffset); + fbBuilder.addUint64(39, _coOwningReference); + fbBuilder.addOffset(40, vectorOfCoOwningReferencesOffset); + fbBuilder.addUint64(41, _nonOwningReference); + fbBuilder.addOffset(42, vectorOfNonOwningReferencesOffset); + fbBuilder.addUint8(43, _anyUniqueType?.value); + fbBuilder.addOffset(44, anyUniqueOffset); + fbBuilder.addUint8(45, _anyAmbiguousType?.value); + fbBuilder.addOffset(46, anyAmbiguousOffset); + fbBuilder.addOffset(47, vectorOfEnumsOffset); + fbBuilder.addInt8(48, _signedEnum?.value); + fbBuilder.addOffset(49, testrequirednestedflatbufferOffset); + fbBuilder.addOffset(50, scalarKeySortedTablesOffset); + if (_nativeInline != null) { + fbBuilder.addStruct(51, _nativeInline!.finish(fbBuilder)); + } + fbBuilder.addUint64(52, _longEnumNonEnumDefault?.value); + fbBuilder.addUint64(53, _longEnumNormalDefault?.value); + fbBuilder.addFloat32(54, _nanDefault); + fbBuilder.addFloat32(55, _infDefault); + fbBuilder.addFloat32(56, _positiveInfDefault); + fbBuilder.addFloat32(57, _infinityDefault); + fbBuilder.addFloat32(58, _positiveInfinityDefault); + fbBuilder.addFloat32(59, _negativeInfDefault); + fbBuilder.addFloat32(60, _negativeInfinityDefault); + fbBuilder.addFloat64(61, _doubleInfDefault); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} + +class TypeAliases { + TypeAliases._(this._bc, this._bcOffset); + factory TypeAliases(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _TypeAliasesReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + int get i8 => const fb.Int8Reader().vTableGet(_bc, _bcOffset, 4, 0); + int get u8 => const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 6, 0); + int get i16 => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 8, 0); + int get u16 => const fb.Uint16Reader().vTableGet(_bc, _bcOffset, 10, 0); + int get i32 => const fb.Int32Reader().vTableGet(_bc, _bcOffset, 12, 0); + int get u32 => const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 14, 0); + int get i64 => const fb.Int64Reader().vTableGet(_bc, _bcOffset, 16, 0); + int get u64 => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 18, 0); + double get f32 => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 20, 0.0); + double get f64 => const fb.Float64Reader().vTableGet(_bc, _bcOffset, 22, 0.0); + List? get v8 => + const fb.Int8ListReader().vTableGetNullable(_bc, _bcOffset, 24); + List? get vf64 => const fb.ListReader( + fb.Float64Reader(), + ).vTableGetNullable(_bc, _bcOffset, 26); + + @override + String toString() { + return 'TypeAliases{i8: ${i8}, u8: ${u8}, i16: ${i16}, u16: ${u16}, i32: ${i32}, u32: ${u32}, i64: ${i64}, u64: ${u64}, f32: ${f32}, f64: ${f64}, v8: ${v8}, vf64: ${vf64}}'; + } + + TypeAliasesT unpack() => TypeAliasesT( + i8: i8, + u8: u8, + i16: i16, + u16: u16, + i32: i32, + u32: u32, + i64: i64, + u64: u64, + f32: f32, + f64: f64, + v8: const fb.Int8ListReader( + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 24), + vf64: const fb.ListReader( + fb.Float64Reader(), + lazy: false, + ).vTableGetNullable(_bc, _bcOffset, 26), + ); + + static int pack(fb.Builder fbBuilder, TypeAliasesT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class TypeAliasesT implements fb.Packable { + int i8; + int u8; + int i16; + int u16; + int i32; + int u32; + int i64; + int u64; + double f32; + double f64; + List? v8; + List? vf64; + + TypeAliasesT({ + this.i8 = 0, + this.u8 = 0, + this.i16 = 0, + this.u16 = 0, + this.i32 = 0, + this.u32 = 0, + this.i64 = 0, + this.u64 = 0, + this.f32 = 0.0, + this.f64 = 0.0, + this.v8, + this.vf64, + }); + + @override + int pack(fb.Builder fbBuilder) { + final int? v8Offset = v8 == null ? null : fbBuilder.writeListInt8(v8!); + final int? vf64Offset = vf64 == null + ? null + : fbBuilder.writeListFloat64(vf64!); + fbBuilder.startTable(12); + fbBuilder.addInt8(0, i8); + fbBuilder.addUint8(1, u8); + fbBuilder.addInt16(2, i16); + fbBuilder.addUint16(3, u16); + fbBuilder.addInt32(4, i32); + fbBuilder.addUint32(5, u32); + fbBuilder.addInt64(6, i64); + fbBuilder.addUint64(7, u64); + fbBuilder.addFloat32(8, f32); + fbBuilder.addFloat64(9, f64); + fbBuilder.addOffset(10, v8Offset); + fbBuilder.addOffset(11, vf64Offset); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'TypeAliasesT{i8: ${i8}, u8: ${u8}, i16: ${i16}, u16: ${u16}, i32: ${i32}, u32: ${u32}, i64: ${i64}, u64: ${u64}, f32: ${f32}, f64: ${f64}, v8: ${v8}, vf64: ${vf64}}'; + } +} + +class _TypeAliasesReader extends fb.TableReader { + const _TypeAliasesReader(); + + @override + TypeAliases createObject(fb.BufferContext bc, int offset) => + TypeAliases._(bc, offset); +} + +class TypeAliasesBuilder { + TypeAliasesBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(12); + } + + int addI8(int? i8) { + fbBuilder.addInt8(0, i8); + return fbBuilder.offset; + } + + int addU8(int? u8) { + fbBuilder.addUint8(1, u8); + return fbBuilder.offset; + } + + int addI16(int? i16) { + fbBuilder.addInt16(2, i16); + return fbBuilder.offset; + } + + int addU16(int? u16) { + fbBuilder.addUint16(3, u16); + return fbBuilder.offset; + } + + int addI32(int? i32) { + fbBuilder.addInt32(4, i32); + return fbBuilder.offset; + } + + int addU32(int? u32) { + fbBuilder.addUint32(5, u32); + return fbBuilder.offset; + } + + int addI64(int? i64) { + fbBuilder.addInt64(6, i64); + return fbBuilder.offset; + } + + int addU64(int? u64) { + fbBuilder.addUint64(7, u64); + return fbBuilder.offset; + } + + int addF32(double? f32) { + fbBuilder.addFloat32(8, f32); + return fbBuilder.offset; + } + + int addF64(double? f64) { + fbBuilder.addFloat64(9, f64); + return fbBuilder.offset; + } + + int addV8Offset(int? offset) { + fbBuilder.addOffset(10, offset); + return fbBuilder.offset; + } + + int addVf64Offset(int? offset) { + fbBuilder.addOffset(11, offset); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class TypeAliasesObjectBuilder extends fb.ObjectBuilder { + final int? _i8; + final int? _u8; + final int? _i16; + final int? _u16; + final int? _i32; + final int? _u32; + final int? _i64; + final int? _u64; + final double? _f32; + final double? _f64; + final List? _v8; + final List? _vf64; + + TypeAliasesObjectBuilder({ + int? i8, + int? u8, + int? i16, + int? u16, + int? i32, + int? u32, + int? i64, + int? u64, + double? f32, + double? f64, + List? v8, + List? vf64, + }) : _i8 = i8, + _u8 = u8, + _i16 = i16, + _u16 = u16, + _i32 = i32, + _u32 = u32, + _i64 = i64, + _u64 = u64, + _f32 = f32, + _f64 = f64, + _v8 = v8, + _vf64 = vf64; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? v8Offset = _v8 == null ? null : fbBuilder.writeListInt8(_v8!); + final int? vf64Offset = _vf64 == null + ? null + : fbBuilder.writeListFloat64(_vf64!); + fbBuilder.startTable(12); + fbBuilder.addInt8(0, _i8); + fbBuilder.addUint8(1, _u8); + fbBuilder.addInt16(2, _i16); + fbBuilder.addUint16(3, _u16); + fbBuilder.addInt32(4, _i32); + fbBuilder.addUint32(5, _u32); + fbBuilder.addInt64(6, _i64); + fbBuilder.addUint64(7, _u64); + fbBuilder.addFloat32(8, _f32); + fbBuilder.addFloat64(9, _f64); + fbBuilder.addOffset(10, v8Offset); + fbBuilder.addOffset(11, vf64Offset); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} diff --git a/third_party/flatbuffers/dart/test/monster_test_my_game_generated.dart b/third_party/flatbuffers/dart/test/monster_test_my_game_generated.dart new file mode 100644 index 00000000000..7b856bf725a --- /dev/null +++ b/third_party/flatbuffers/dart/test/monster_test_my_game_generated.dart @@ -0,0 +1,77 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable, constant_identifier_names + +library my_game; + +import 'dart:typed_data' show Uint8List; + +import 'package:flat_buffers/flat_buffers.dart' as fb; + +import './include_test1_generated.dart'; +import './monster_test_my_game.example2_generated.dart' as my_game_example2; +import './monster_test_my_game.example_generated.dart' as my_game_example; + +class InParentNamespace { + InParentNamespace._(this._bc, this._bcOffset); + factory InParentNamespace(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _InParentNamespaceReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + @override + String toString() { + return 'InParentNamespace{}'; + } + + InParentNamespaceT unpack() => InParentNamespaceT(); + + static int pack(fb.Builder fbBuilder, InParentNamespaceT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class InParentNamespaceT implements fb.Packable { + @override + int pack(fb.Builder fbBuilder) { + fbBuilder.startTable(0); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'InParentNamespaceT{}'; + } +} + +class _InParentNamespaceReader extends fb.TableReader { + const _InParentNamespaceReader(); + + @override + InParentNamespace createObject(fb.BufferContext bc, int offset) => + InParentNamespace._(bc, offset); +} + +class InParentNamespaceObjectBuilder extends fb.ObjectBuilder { + InParentNamespaceObjectBuilder(); + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + fbBuilder.startTable(0); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} diff --git a/third_party/flatbuffers/dart/test/monsterdata_test.mon b/third_party/flatbuffers/dart/test/monsterdata_test.mon new file mode 100644 index 00000000000..da0ed8698fc Binary files /dev/null and b/third_party/flatbuffers/dart/test/monsterdata_test.mon differ diff --git a/third_party/flatbuffers/docs/README.md b/third_party/flatbuffers/docs/README.md new file mode 100644 index 00000000000..06e4310f270 --- /dev/null +++ b/third_party/flatbuffers/docs/README.md @@ -0,0 +1,24 @@ +# Documentation + +This is the source of the FlatBuffers documentation, that is served at +https://flatbuffers.dev. + + +## Local Building + +The documentation can be built and served locally during development, see for full details. + +__tl;dr__ + +Install: + +``` +pip install mkdocs-material +pip install mkdocs-redirects +``` + +Build and Serve: + +``` +mkdocs serve -f docs/mkdocs.yml +``` diff --git a/third_party/flatbuffers/docs/mkdocs.yml b/third_party/flatbuffers/docs/mkdocs.yml new file mode 100644 index 00000000000..cbcbb48de28 --- /dev/null +++ b/third_party/flatbuffers/docs/mkdocs.yml @@ -0,0 +1,159 @@ +site_name: FlatBuffers Docs +docs_dir: source +site_url: https://flatbuffers.dev +repo_name: google/FlatBuffers +repo_url: https://github.com/google/flatbuffers +edit_uri: edit/master/docs/source/ +copyright: Copyright © 2025 Google +theme: + name: material + logo: assets/flatbuffers_logo.svg + icon: + repo: fontawesome/brands/github + custom_dir: overrides + palette: + # Palette toggle for light mode + - scheme: default + toggle: + icon: material/brightness-7 + name: Switch to dark mode + + # Palette toggle for dark mode + - scheme: slate + toggle: + icon: material/brightness-4 + name: Switch to light mode + + features: + # Allows code block annotations + - content.code.annotate + + # Allows content tabs to link together + - content.tabs.link + + # Expand nav folders by default + - navigation.expand + + # Enable the footer + - navigation.footer + + # Auto hide the header after scrolling + - header.autohide + + - content.action.edit + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/google/flatbuffers + + - icon: fontawesome/brands/discord + link: https:///discord.gg/6qgKs3R + + - icon: fontawesome/brands/x-twitter + link: https://twitter.com/dbaileychess + +plugins: + # Use redirects to update links from the original docs to the new ones. + # + # https://github.com/mkdocs/mkdocs-redirects + - redirects: + # Note the .html are suffixed with .md to avoid warnings. Got from + # https://github.com/mkdocs/mkdocs-redirects/issues/51#issuecomment-2408548029 + redirect_maps: + 'flatbuffers_guide_building.html.md': 'building.md' + 'flatbuffers_guide_tutorial.html.md': 'tutorial.md' + 'flatbuffers_guide_using_schema_compiler.html.md': 'flatc.md' + 'flatbuffers_guide_writing_schema.html.md': 'schema.md' + 'md__schemas.html.md': 'schema.md' # issue #8485 + 'flatbuffers_guide_use_c.html.md': 'languages/c.md' + 'flatbuffers_guide_use_cpp.html.md': 'languages/cpp.md' + 'flatbuffers_guide_use_c-sharp.html.md': 'languages/c_sharp.md' + 'flatbuffers_guide_use_dart.html.md': 'languages/dart.md' + 'flatbuffers_guide_use_go.html.md': 'languages/go.md' + 'flatbuffers_guide_use_java.html.md': 'languages/java.md' + 'flatbuffers_guide_use_javascript.html.md': 'languages/javascript.md' + 'flatbuffers_guide_use_lobster.html.md': 'languages/lobster.md' + 'flatbuffers_guide_use_lua.html.md': 'languages/lua.md' + 'flatbuffers_guide_use_php.html.md': 'languages/php.md' + 'flatbuffers_guide_use_python.html.md': 'languages/python.md' + 'flatbuffers_guide_use_rust.html.md': 'languages/rust.md' + 'flatbuffers_guide_use_swift.html.md': 'languages/swift.md' + 'flatbuffers_guide_use_typescript.html.md': 'languages/typescript.md' + 'flatbuffers_grpc_guide_use_cpp.html.md' : "languages/cpp.md#grpc" + 'flatbuffers_support.html.md': 'support.md' + 'flatbuffers_white_paper.html.md': 'white_paper.md' + 'flatbuffers_grammar.html.md': 'grammar.md' + 'flatbuffers_internals.html.md': 'internals.md' + 'intermediate_representation.html.md': 'intermediate_representation.md' + 'flatbuffers_benchmarks.html.md': 'benchmarks.md' + 'flexbuffers.html.md': 'flexbuffers.md' + 'contributing.html.md': 'contributing.md' + + +markdown_extensions: + - admonition + - attr_list + - md_in_html + - pymdownx.critic + - pymdownx.details + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.snippets: + # Allows direct embedded of remote files + url_download: true + - pymdownx.superfences + - pymdownx.tabbed: + alternate_style: true + slugify: !!python/object/apply:pymdownx.slugs.slugify + kwds: + case: lower + - pymdownx.highlight: + extend_pygments_lang: + # PHP wasn't highlighting correctly. This is a work around found + # https://github.com/squidfunk/mkdocs-material/issues/138#issuecomment-2294025627 + - name: php + lang: php + options: + startinline: true + - tables + + + +nav: + - Overview: "index.md" + - Quick Start: "quick_start.md" + - Tutorial: "tutorial.md" + - Compiler (flatc): + - Building: "building.md" + - Using: "flatc.md" + - Schema (.fbs): + - Overview: "schema.md" + - Evolution: "evolution.md" + - Grammar: "grammar.md" + - Language Guides: + - C: "languages/c.md" + - C++: "languages/cpp.md" + - C#: "languages/c_sharp.md" + - Dart: "languages/dart.md" + - Go: "languages/go.md" + - Java: "languages/java.md" + - JavaScript: "languages/javascript.md" + - Kotlin: "languages/kotlin.md" + - Lobster: "languages/lobster.md" + - Lua: "languages/lua.md" + - PHP: "languages/php.md" + - Python: "languages/python.md" + - Rust: "languages/rust.md" + - Swift: "languages/swift.md" + - TypeScript: "languages/typescript.md" + - Supported Configurations: "support.md" + - White Paper: "white_paper.md" + - Advanced: + - FlatBuffers Internals: "internals.md" + - Intermediate Representation: "intermediate_representation.md" + - Annotating Buffers (.afb): "annotation.md" + - Benchmarks: "benchmarks.md" + - FlexBuffers (Schema-less version): "flexbuffers.md" + - Contributing: "contributing.md" diff --git a/third_party/flatbuffers/docs/overrides/404.html b/third_party/flatbuffers/docs/overrides/404.html new file mode 100644 index 00000000000..f7981fcf4f5 --- /dev/null +++ b/third_party/flatbuffers/docs/overrides/404.html @@ -0,0 +1,10 @@ +{% extends "main.html" %} + + +{% block content %} +

404 - Not found

+
+ FlatBuffers has migrated their documentation system recently. + + Please file an issue indicating the broken link. +{% endblock %} \ No newline at end of file diff --git a/third_party/flatbuffers/docs/overrides/main.html b/third_party/flatbuffers/docs/overrides/main.html new file mode 100644 index 00000000000..94d9808cc76 --- /dev/null +++ b/third_party/flatbuffers/docs/overrides/main.html @@ -0,0 +1 @@ +{% extends "base.html" %} diff --git a/third_party/flatbuffers/docs/source/CNAME b/third_party/flatbuffers/docs/source/CNAME new file mode 100644 index 00000000000..398878ab794 --- /dev/null +++ b/third_party/flatbuffers/docs/source/CNAME @@ -0,0 +1 @@ +flatbuffers.dev \ No newline at end of file diff --git a/third_party/flatbuffers/docs/source/annotation.md b/third_party/flatbuffers/docs/source/annotation.md new file mode 100644 index 00000000000..1e66eb67c4f --- /dev/null +++ b/third_party/flatbuffers/docs/source/annotation.md @@ -0,0 +1,149 @@ +# Annotating FlatBuffers + +This provides a way to annotate flatbuffer binary data, byte-by-byte, with a +schema. It is useful for development purposes and understanding the details of +the internal format. + +## Annotating + +Given a `schema`, as either a plain-text (`.fbs`) or a binary schema (`.bfbs`), +and `binary` file(s) that were created by the `schema`. You can annotate them +using: + +```sh +flatc --annotate SCHEMA -- BINARY_FILES... +``` + +This will produce a set of annotated files (`.afb` Annotated FlatBuffer) +corresponding to the input binary files. + +### Example + +Taken from the [tests/annotated_binary](https://github.com/google/flatbuffers/tree/master/tests/annotated_binary). + +```sh +cd tests/annotated_binary +../../flatc --annotate annotated_binary.fbs -- annotated_binary.bin +``` + +Which will produce a `annotated_binary.afb` file in the current directory. + +The `annotated_binary.bin` is the flatbufer binary of the data contained within +`annotated_binary.json`, which was made by the following command: + +```sh +..\..\flatc -b annotated_binary.fbs annotated_binary.json +``` + +## .afb Text Format + +Currently there is a built-in text-based format for outputting the annotations. +A full example is shown here: +[`annotated_binary.afb`](https://github.com/google/flatbuffers/blob/master/tests/annotated_binary/annotated_binary.afb) + +The data is organized as a table with fixed [columns](#columns) grouped into +Binary [sections](#binary-sections) and [regions](#binary-regions), starting +from the beginning of the binary (offset `0`). + +### Columns + +The columns are as follows: + +1. The offset from the start of the binary, expressed in hexadecimal format + (e.g. `+0x003c`). + + The prefix `+` is added to make searching for the offset (compared to some + random value) a bit easier. + +2. The raw binary data, expressed in hexadecimal format. + + This is in the little endian format the buffer uses internally and what you + would see with a normal binary text viewer. + +3. The type of the data. + + This may be the type specified in the schema or some internally defined + types: + + + | Internal Type | Purpose | + |---------------|----------------------------------------------------| + | `VOffset16` | Virtual table offset, relative to the table offset | + | `UOffset32` | Unsigned offset, relative to the current offset | + | `SOffset32` | Signed offset, relative to the current offset | + + +4. The value of the data. + + This is shown in big endian format that is generally written for humans to + consume (e.g. `0x0013`). As well as the "casted" value (e.g. `0x0013 `is + `19` in decimal) in parentheses. + +5. Notes about the particular data. + + This describes what the data is about, either some internal usage, or tied + to the schema. + +### Binary Sections + +The file is broken up into Binary Sections, which are comprised of contiguous +[binary regions](#binary-regions) that are logically grouped together. For +example, a binary section may be a single instance of a flatbuffer `Table` or +its `vtable`. The sections may be labelled with the name of the associated type, +as defined in the input schema. + +An example of a `vtable` Binary Section that is associated with the user-defined +`AnnotateBinary.Bar` table. + +``` +vtable (AnnotatedBinary.Bar): + +0x00A0 | 08 00 | uint16_t | 0x0008 (8) | size of this vtable + +0x00A2 | 13 00 | uint16_t | 0x0013 (19) | size of referring table + +0x00A4 | 08 00 | VOffset16 | 0x0008 (8) | offset to field `a` (id: 0) + +0x00A6 | 04 00 | VOffset16 | 0x0004 (4) | offset to field `b` (id: 1) +``` + +These are purely annotative, there is no embedded information about these +regions in the flatbuffer itself. + +### Binary Regions + +Binary regions are contiguous bytes regions that are grouped together to form +some sort of value, e.g. a `scalar` or an array of scalars. A binary region may +be split up over multiple text lines, if the size of the region is large. + +#### Annotation Example + +Looking at an example binary region: + +``` +vtable (AnnotatedBinary.Bar): + +0x00A0 | 08 00 | uint16_t | 0x0008 (8) | size of this vtable +``` + +The first column (`+0x00A0`) is the offset to this region from the beginning of +the buffer. + +The second column are the raw bytes (hexadecimal) that make up this region. +These are expressed in the little-endian format that flatbuffers uses for the +wire format. + +The third column is the type to interpret the bytes as. For the above example, +the type is `uint16_t` which is a 16-bit unsigned integer type. + +The fourth column shows the raw bytes as a compacted, big-endian value. The raw +bytes are duplicated in this fashion since it is more intuitive to read the data +in the big-endian format (e.g., `0x0008`). This value is followed by the decimal +representation of the value (e.g., `(8)`). For strings, the raw string value is +shown instead. + +The fifth column is a textual comment on what the value is. As much metadata as +known is provided. + +### Offsets + +If the type in the 3rd column is of an absolute offset (`SOffet32` or +`Offset32`), the fourth column also shows an `Loc: +0x025A` value which shows +where in the binary this region is pointing to. These values are absolute from +the beginning of the file, their calculation from the raw value in the 4th +column depends on the context. \ No newline at end of file diff --git a/third_party/flatbuffers/docs/source/assets/flatbuffers_logo.svg b/third_party/flatbuffers/docs/source/assets/flatbuffers_logo.svg new file mode 100644 index 00000000000..e302c07dff0 --- /dev/null +++ b/third_party/flatbuffers/docs/source/assets/flatbuffers_logo.svg @@ -0,0 +1,318 @@ + + + + diff --git a/third_party/flatbuffers/docs/source/benchmarks.md b/third_party/flatbuffers/docs/source/benchmarks.md new file mode 100644 index 00000000000..848f4e39b5c --- /dev/null +++ b/third_party/flatbuffers/docs/source/benchmarks.md @@ -0,0 +1,63 @@ +C++ Benchmarks {#flatbuffers_benchmarks} +========== + +Comparing against other serialization solutions, running on Windows 7 +64bit. We use the LITE runtime for Protocol Buffers (less code / lower +overhead), Rapid JSON (one of the fastest C++ JSON parsers around), +and pugixml, also one of the fastest XML parsers. + +We also compare against code that doesn't use a serialization library +at all (the column "Raw structs"), which is what you get if you write +hardcoded code that just writes structs. This is the fastest possible, +but of course is not cross platform nor has any kind of forwards / +backwards compatibility. + +We compare against Flatbuffers with the binary wire format (as +intended), and also with JSON as the wire format with the optional JSON +parser (which, using a schema, parses JSON into a binary buffer that can +then be accessed as before). + +The benchmark object is a set of about 10 objects containing an array, 4 +strings, and a large variety of int/float scalar values of all sizes, +meant to be representative of game data, e.g. a scene format. + +| | FlatBuffers (binary) | Protocol Buffers LITE | Rapid JSON | FlatBuffers (JSON) | pugixml | Raw structs | +|--------------------------------------------------------|-----------------------|-----------------------|-----------------------|------------------------| ----------------------| ----------------------| +| Decode + Traverse + Dealloc (1 million times, seconds) | 0.08 | 302 | 583 | 105 | 196 | 0.02 | +| Decode / Traverse / Dealloc (breakdown) | 0 / 0.08 / 0 | 220 / 0.15 / 81 | 294 / 0.9 / 287 | 70 / 0.08 / 35 | 41 / 3.9 / 150 | 0 / 0.02 / 0 | +| Encode (1 million times, seconds) | 3.2 | 185 | 650 | 169 | 273 | 0.15 | +| Wire format size (normal / zlib, bytes) | 344 / 220 | 228 / 174 | 1475 / 322 | 1029 / 298 | 1137 / 341 | 312 / 187 | +| Memory needed to store decoded wire (bytes / blocks) | 0 / 0 | 760 / 20 | 65689 / 4 | 328 / 1 | 34194 / 3 | 0 / 0 | +| Transient memory allocated during decode (KB) | 0 | 1 | 131 | 4 | 34 | 0 | +| Generated source code size (KB) | 4 | 61 | 0 | 4 | 0 | 0 | +| Field access in handwritten traversal code | typed accessors | typed accessors | manual error checking | typed accessors | manual error checking | typed but no safety | +| Library source code (KB) | 15 | some subset of 3800 | 87 | 43 | 327 | 0 | + +### Some other serialization systems we compared against but did not benchmark (yet), in rough order of applicability: + +- Cap'n'Proto promises to reduce Protocol Buffers much like FlatBuffers does, + though with a more complicated binary encoding and less flexibility (no + optional fields to allow deprecating fields or serializing with missing + fields for which defaults exist). + It currently also isn't fully cross-platform portable (lack of VS support). +- msgpack: has very minimal forwards/backwards compatibility support when used + with the typed C++ interface. Also lacks VS2010 support. +- Thrift: very similar to Protocol Buffers, but appears to be less efficient, + and have more dependencies. +- YAML: a superset of JSON and otherwise very similar. Used by e.g. Unity. +- C# comes with built-in serialization functionality, as used by Unity also. + Being tied to the language, and having no automatic versioning support + limits its applicability. +- Project Anarchy (the free mobile engine by Havok) comes with a serialization + system, that however does no automatic versioning (have to code around new + fields manually), is very much tied to the rest of the engine, and works + without a schema to generate code (tied to your C++ class definition). + +### Code for benchmarks + +Code for these benchmarks sits in `benchmarks/` in git branch `benchmarks`. +It sits in its own branch because it has submodule dependencies that the main +project doesn't need, and the code standards do not meet those of the main +project. Please read `benchmarks/cpp/README.txt` before working with the code. + +
diff --git a/third_party/flatbuffers/docs/source/building.md b/third_party/flatbuffers/docs/source/building.md new file mode 100644 index 00000000000..93c4d2b84b1 --- /dev/null +++ b/third_party/flatbuffers/docs/source/building.md @@ -0,0 +1,177 @@ +# Building + +## Building with CMake + +The distribution main build system is configured by +[`cmake`](https://www.cmake.org) which allows you to build the project for any +platform. + +### Configuration + +Use `cmake` to configure a project based on your environment and platform. + +=== "Unix" + + ```sh + cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release + ``` + +To use `clang` instead of `gcc` you may need to set prepend some environment +variables e.g. `CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake -G "Unix +MakeFiles"` + +=== "Windows" + + ```sh + cmake -G "Visual Studio 17 2022" -DCMAKE_BUILD_TYPE=Release + ``` + +=== "MacOS" + + ```sh + cmake -G "Xcode" -DCMAKE_BUILD_TYPE=Release + ``` + +#### Strict Mode + +By default, `cmake` will configure targets to **not** build with strict warnings +on (e.g. `-Werror` or `/WX`). This may cause into issues when submitting code +changes since our CI requires the code to compile in strict mode. + +To enable the extra warnings, turn on strict mode with the +`FLATBUFFERS_STRICT_MODE` cmake option. + +```cmake +cmake -DFLATBUFFERS_STRICT_MODE=ON +``` + + +### Building + +Once the project files are generated, build as normal for your platform. + +=== "Unix" + + ```sh + make -j + ``` + +=== "Windows" + + ```sh + msbuild.exe FlatBuffers.sln + ``` + +=== "MacOS" + + ```sh + xcodebuild -toolchain clang -configuration Release + ``` + + + + + + +## Building with Bazel + +You can use [Bazelisk](https://github.com/bazelbuild/bazelisk) to manage your Bazel environment. +For Swift support, you also need Clang and [Swift SDK](https://download.swift.org/). + +```sh +curl -sL --fail https://github.com/bazelbuild/bazelisk/releases/download/v1.25.0/bazelisk-linux-amd64 -o bazelisk && chmod +x bazelisk +sudo apt install -y clang +SWIFT_VERSION="6.0.3" +curl -L https://download.swift.org/swift-${SWIFT_VERSION}-release/debian12/swift-${SWIFT_VERSION}-RELEASE/swift-${SWIFT_VERSION}-RELEASE-debian12.tar.gz | tar xz +CC=clang PATH=$PATH:$(pwd)/swift-${SWIFT_VERSION}-RELEASE-debian12/usr/bin bazel build //... +CC=clang PATH=$PATH:$(pwd)/swift-${SWIFT_VERSION}-RELEASE-debian12/usr/bin bazel test //... +``` + +If you are unsure which versions to use, check our CI config at `.bazelci/presubmit.yml`. + +## Building with VCPKG + +You can download and install flatbuffers using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager: + + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + ./vcpkg install flatbuffers + +The flatbuffers port in vcpkg is kept up to date by Microsoft team members and community contributors. +If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. + + + +## Building for Android + +There is a `flatbuffers/android` directory that contains all you need to build +the test executable on android (use the included `build_apk.sh` script, or use +`ndk_build` / `adb` etc. as usual). Upon running, it will output to the log +if tests succeeded or not. + +You may also run an android sample from inside the `flatbuffers/samples`, by +running the `android_sample.sh` script. Optionally, you may go to the +`flatbuffers/samples/android` folder and build the sample with the +`build_apk.sh` script or `ndk_build` / `adb` etc. + +## Using FlatBuffers in your own projects + +For C++, there is usually no runtime to compile, as the code consists of a +single header, `include/flatbuffers/flatbuffers.h`. You should add the +`include` folder to your include paths. If you wish to be +able to load schemas and/or parse text into binary buffers at runtime, +you additionally need the other headers in `include/flatbuffers`. You must +also compile/link `src/idl_parser.cpp` (and `src/idl_gen_text.cpp` if you +also want to be able convert binary to text). + +To see how to include FlatBuffers in any of our supported languages, please +view the [Tutorial](tutorial.md) and select your appropriate +language using the radio buttons. + +### Using in CMake-based projects +If you want to use FlatBuffers in a project which already uses CMake, then a more +robust and flexible approach is to build FlatBuffers as part of that project directly. +This is done by making the FlatBuffers source code available to the main build +and adding it using CMake's `add_subdirectory()` command. This has the +significant advantage that the same compiler and linker settings are used +between FlatBuffers and the rest of your project, so issues associated with using +incompatible libraries (eg debug/release), etc. are avoided. This is +particularly useful on Windows. + +Suppose you put FlatBuffers source code in directory `${FLATBUFFERS_SRC_DIR}`. +To build it as part of your project, add following code to your `CMakeLists.txt` file: +```cmake +# Add FlatBuffers directly to our build. This defines the `flatbuffers` target. +add_subdirectory(${FLATBUFFERS_SRC_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-build + EXCLUDE_FROM_ALL) + +# Now simply link against flatbuffers as needed to your already declared target. +# The flatbuffers target carry header search path automatically if CMake > 2.8.11. +target_link_libraries(own_project_target PRIVATE flatbuffers) +``` +When build your project the `flatbuffers` library will be compiled and linked +to a target as part of your project. + +#### Override default depth limit of nested objects +To override [the depth limit of recursion](languages/cpp.md), +add this directive: +```cmake +set(FLATBUFFERS_MAX_PARSING_DEPTH 16) +``` +to `CMakeLists.txt` file before `add_subdirectory(${FLATBUFFERS_SRC_DIR})` line. + +## Downloading binaries +You can download the binaries from the +[GitHub release page](https://github.com/google/flatbuffers/releases). + +We generate [SLSA3 signatures](http://slsa.dev) using the OpenSSF's [slsa-framework/slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator). To verify the binaries: +1. Install the verification tool from [slsa-framework/slsa-verifier#installation](https://github.com/slsa-framework/slsa-verifier#installation) +1. Download the file named `attestation.intoto.jsonl` from the GitHub release +1. Run: +```shell +$ slsa-verifier -artifact-path -provenance attestation.intoto.jsonl -source github.com/google/flatbuffers -tag + PASSED: Verified SLSA provenance +``` \ No newline at end of file diff --git a/third_party/flatbuffers/docs/source/contributing.md b/third_party/flatbuffers/docs/source/contributing.md new file mode 100644 index 00000000000..a65b60ac5ee --- /dev/null +++ b/third_party/flatbuffers/docs/source/contributing.md @@ -0,0 +1,80 @@ +# Contributing + +We encourage community contributions to FlatBuffers through pull requests at the +main +[http://github.com/google/flatbuffers](http://github.com/google/flatbuffers) +repository. + +!!! note + + The FlatBuffers project is not staffed by any full time Google employee, and + is managed by a small team of 20%ers. So response time and expertise vary. + +## Before you contribute + +Before we can use your contributions, you __must__ sign one of the following license agreements. The agreements are self-served at the following links. + +Our code review process will automatically check if you have signed the CLA, so +don't fret. Though it may be prudent to check before spending a lot of time on +contribution. + +### Individual Contributions + +For individuals, the [Google Individual +Contributor License Agreement +(CLA)](https://cla.developers.google.com/about/google-individual?csw=1) which is +self served at the link. The CLA is required since you own the copyright to your +changes, even after your contribution becomes part of our codebase, so we need +your permission to use and distribute your code. + +### Corporate Contributions + +Contributions made by corporations are covered by the [Google Software Grant and +Corporate Contributor License +Agreement](https://cla.developers.google.com/about/google-corporate). + +## Code Reviews + +All submissions require a code review via Github Pull Requests. + +1. Please adhere to the [Google Style Guide](https://google.github.io/styleguide/cppguide.html) for the language(s) you are submitting in. +2. Keep PRs small and focused. Its good practice and makes it more likely your PR will be approved. +3. Please add tests if possible. +4. Include descriptive commit messages and context to the change/issues fixed. + +## Documentation + +FlatBuffers uses [MkDocs](https://www.mkdocs.org/) to generate the static +documentation pages served at +[https://flatbuffers.dev](https://flatbuffers.dev). Specifically, we use the +[Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) framework. + +The documentation source is contained in the main repo under the +[docs/](https://github.com/google/flatbuffers/tree/master/docs) directory. This +[automatically](https://github.com/google/flatbuffers/blob/46cc3d6432da17cca7694777dcce12e49dd48387/.github/workflows/docs.yml#L6-L11) get built and published when the commit is made. + +### Local Development + +We encourage contributors to keep the documentation up-to-date as well, and it +is easy to with `MkDocs` local building and serving tools. + +First install `mkdocs-material` (see +[Installation](https://squidfunk.github.io/mkdocs-material/getting-started/) for +other ways) + +``` +pip install mkdocs-material +pip install mkdocs-redirects +``` + +Then, in the `root` directory of flatbuffers, run + +``` +mkdocs serve -f docs/mkdocs.yml +``` + +This will continually watch the repo for changes to the documentation and serve +the rendered pages locally. + +Submit your documentation changes with your code changes and they will +automatically get published when your code is submitted. \ No newline at end of file diff --git a/third_party/flatbuffers/docs/source/evolution.md b/third_party/flatbuffers/docs/source/evolution.md new file mode 100644 index 00000000000..0f22cac722b --- /dev/null +++ b/third_party/flatbuffers/docs/source/evolution.md @@ -0,0 +1,276 @@ +# Evolution + +FlatBuffers enables the [schema](schema.md) to evolve over time while still +maintaining forwards and backwards compatibility with old flatbuffers. + +Some rules must be followed to ensure the evolution of a schema is valid. + +## Rules + +Adding new tables, vectors, structs to the schema is always allowed. Its only +when you add a new field to a [`table`](schema.md#tables) that certain rules +must be followed. + +### Addition + +**New fields MUST be added to the end of the table definition.** + +This allows older data to still be read correctly (giving you the default value +of the added field if accessed). + +Older code will simply ignore the new field in the flatbuffer. + +You can ignore this rule if you use the `id` attribute on all the fields of a +table. + +### Removal + +**You MUST not remove a field from the schema, even if you don't use it +anymore.** You simply stop writing them to the buffer. + +Its encouraged to mark the field deprecated by adding the `deprecated` +attribute. This will skip the generation of accessors and setters in the code, +to enforce the field not to be used any more. + +### Name Changes + +Its generally OK to change the name of tables and fields, as these are not +serialized to the buffer. It may break code that would have to be refactored +with the updated name. + +## Examples + +The following examples uses a base schema and attempts to evolve it a few times. +The versions are tracked by `V1`, `V2`, etc.. and `CodeV1` means code compiled +against the `V1` schema. + +### Table Evolution + +Lets start with a simple table `T` with two fields. + +```c++ title="Schema V1" +table T { + a:int; + b:int; +} +``` + +=== "Well Evolved" + + First lets extend the table with a new field. + + ```c++ title="Schema V2" + table T { + a:int; + b:int; + c:int; + } + ``` + + This is OK. `CodeV1` reading `V2` data will simply ignore the presence of the + new field `c`. `CodeV2` reading `V1` data will get a default value (0) when + reading `c`. + + ```c++ title="Schema V3" + table T { + a:int (deprecated); + b:int; + c:int; + } + ``` + + This is OK, removing field `a` via deprecation. `CodeV1`, `CodeV2` and `CodeV3` + reading `V3` data will now always get the default value of `a`, since it is not + present. `CodeV3` cannot write `a` anymore. `CodeV3` reading old data (`V1` or + `V2`) will not be able to access the field anymore, since no generated accessors + are omitted. + +=== "Improper Addition" + + Add a new field, but this time at the beginning. + + ```c++ title="Schema V2" + table T { + c:int; + a:int; + b:int; + } + ``` + + This is NOT OK, as it makes `V2` incompatible. `CodeV1` reading `V2` data + will access `a` but will read `c` data. + + `CodeV2` reading `V1` data will access `c` but will read `a` data. + +=== "Improper Deletion" + + Remove a field from the schema. + + ```c++ title="Schema V2" + table T { + b:int; + } + ``` + + This is NOT OK. `CodeV1` reading `V2` data will access `a` but read `b` data. + + `CodeV2` reading `V1` data will access `b` but will read `a` data. + +=== "Proper Reordering" + + Lets add a new field to the beginning, but use `id` attributes. + + ```c++ title="Schema V2" + table T { + c:int (id: 2); + a:int (id: 0); + b:int (id: 1); + } + ``` + + This is OK. This adds the a new field in the beginning, but because all the + `id` attributes were added, it is OK. + +=== "Changing Types" + + Let change the types of the fields. + + ```c++ title="Schema V2" + table T { + a:uint; + b:uint; + } + ``` + + This is MAYBE OK, and only in the case where the type change is the same + width. This is tricky if the `V1` data contained any negative numbers. So + this should be done with care. + +=== "Changing Defaults" + + Lets change the default values of the existing fields. + + ```c++ title="Schema V2" + table T { + a:int = 1; + b:int = 2; + } + ``` + + This is NOT OK. Any `V1` data that did not have a value written to the + buffer relied on generated code to provide the default value. + + There MAY be cases where this is OK, if you control all the producers and + consumers, and you can update them in tandem. + +=== "Renaming Fields" + + Lets change the name of the fields + + ```c++ title="Schema V2" + table T { + aa:int; + bb:int; + } + ``` + + This is generally OK. You've renamed fields will break all code and JSON + files that use this schema, but you can refactor those without affecting the + binary data, since the binary only address fields by id and offset, not by + names. + +### Union Evolution + +Lets start with a simple union `U` with two members. + +```c++ title="Schema V1" +union U { + A, + B +} +``` + +=== "Well Evolved" + + Lets add a another variant to the end. + + ```c++ title="Schema V2" + union U { + A, + B, + another_a: A + } + ``` + + This is OK. `CodeV1` will not recognize the `another_a`. + +=== "Improper Evolved" + + Lets add a another variant to the middle. + + ```c++ title="Schema V2" + union U { + A, + another_a: A, + B + } + ``` + + This is NOT OK. `CodeV1` reading `V2` data will interpret `B` as `another_a`. + `CodeV2` reading `V1` data will interpret `another_a` as `B`. + +=== "Evolved With Discriminant" + + Lets add a another variant to the middle, this time adding a union "discriminant". + + ```c++ title="Schema V2" + union U { + A = 1, + another_a: A = 3, + B = 2 + } + ``` + + This is OK. Its like you added it to the end, but using the discriminant + value to physically place it elsewhere in the union. + +## Version Control + +FlatBuffers relies on new field declarations being added at the end, and earlier +declarations to not be removed, but be marked deprecated when needed. We think +this is an improvement over the manual number assignment that happens in +Protocol Buffers (and which is still an option using the `id` attribute +mentioned above). + +One place where this is possibly problematic however is source control. If user +`A` adds a field, generates new binary data with this new schema, then tries to +commit both to source control after user `B` already committed a new field also, +and just auto-merges the schema, the binary files are now invalid compared to +the new schema. + +The solution of course is that you should not be generating binary data before +your schema changes have been committed, ensuring consistency with the rest of +the world. If this is not practical for you, use explicit field `id`s, which +should always generate a merge conflict if two people try to allocate the same +id. + +## Checking Conformity + +To check that schema are properly evolved, the [`flatc`](flatc.md) compiler has +a [option](flatc.md#additional-options) to do just that: + +```sh +--conform FILE +``` + +Where `FILE` is the base schema the rest of the input schemas must evolve from. +It returns `0` if they are properly evolved, otherwise returns a non-zero value +and provides errors on the reason why the schema are not properly evolved. + +As an example, the following checks if `schema_v2.fbs` is properly evolved from +`schema_v1.fbs`. + +```sh +flatc --conform schema_v1.fbs schema_v2.fbs +``` + diff --git a/third_party/flatbuffers/docs/source/flatc.md b/third_party/flatbuffers/docs/source/flatc.md new file mode 100644 index 00000000000..5ef6b4e3387 --- /dev/null +++ b/third_party/flatbuffers/docs/source/flatc.md @@ -0,0 +1,305 @@ +# FlatBuffers Compiler (`flatc`) + +The main compiler for FlatBuffers is called `flatc` and is used to convert +schema definitions into generated code files for a variety of languages. + +After [building](building.md) `flatc`, it is used as follows: + +```sh +flatc [ GENERATOR_OPTIONS ] [ -o PATH ] [- I PATH ] + FILES... + [ -- BINARY_FILES... ] +``` + +* The `GENERATOR_OPTIONS` specify the language(s) to compile code for as well as +various features to enable/disable. + +* The `-o PATH` specifies the path where the generated files are placed. It +defaults to the current path if not specified. + +* The `-I PATH` specifies the paths where included schema files are located. It + defaults to the current path if not specified. + +## Input Files + +`FILES...` specifies one or more schema or data files to process. They are +processed in the order provided. + +### Schema Files + +For schema files, language specifiers indicate what languages to generate code +for. + + * `--cpp`: C++ + * `--java`: Java + * `--kotlin`: Kotlin + * `--csharp`: C# + * `--go`: Golang + * `--python`: Python + * `--js`: JavaScript + * `--ts`: TypeScript + * `--php`: PHP + * `--dart`: Dart + * `--lua`: Lua + * `--lobster`: Lobster + * `--rust`: Rust + * `--swift`: Swift + * `--nim`: Nim + +Additionally, adding: + + * `--grpc` Will generate RPC stub code for gRPC (not available in all + languages) + +### Data Files + +If `FILES...` contain data files, they can be exported to either a binary or +JSON representation. + +* `--binary`, `-b`: Generate a binary file containing a serialized flatbuffer. +* `--json`, `-j`: Generate JSON file from a serialized flatbuffer. + +Both options require the corresponding schema file to be included first in the +list of `FILES...`. + +=== "To Binary" + + To serialize the JSON data in `mydata.json` using the schema `myschema.fbs`: + + ```sh + flatc --binary myschema.fbs mydata.json + ``` + + This will generate a `mydata_wire.bin` file containing the serialized + flatbuffer data. + +=== "To JSON" + + To convert the serialized binary flatbuffer `mydata.bin` using the schema + `myschema.fbs` to JSON: + + ```sh + flatc --json myschema.fbs mydata.bin + ``` + + This will generate a `mydata.json` file. + + +### Additional options + +- `-o PATH` : Output all generated files to PATH (either absolute, or + relative to the current directory). If omitted, PATH will be the + current directory. PATH should end in your systems path separator, + e.g. `/` or `\`. + +- `-I PATH` : when encountering `include` statements, attempt to load the + files from this path. Paths will be tried in the order given, and if all + fail (or none are specified) it will try to load relative to the path of + the schema file being parsed. + +- `-M` : Print make rules for generated files. + +- `--strict-json` : Require & generate strict JSON (field names are enclosed + in quotes, no trailing commas in tables/vectors). By default, no quotes are + required/generated, and trailing commas are allowed. + +- `--allow-non-utf8` : Pass non-UTF-8 input through parser and emit nonstandard + \x escapes in JSON. (Default is to raise parse error on non-UTF-8 input.) + +- `--natural-utf8` : Output strings with UTF-8 as human-readable strings. + By default, UTF-8 characters are printed as \uXXXX escapes." + +- `--defaults-json` : Output fields whose value is equal to the default value + when writing JSON text. + +- `--no-prefix` : Don't prefix enum values in generated C++ by their enum + type. + +- `--scoped-enums` : Use C++11 style scoped and strongly typed enums in + generated C++. This also implies `--no-prefix`. + +- `--no-emit-min-max-enum-values` : Disable generation of MIN and MAX + enumerated values for scoped enums and prefixed enums. + +- `--gen-includes` : (deprecated), this is the default behavior. + If the original behavior is required (no include + statements) use `--no-includes.` + +- `--no-includes` : Don't generate include statements for included schemas the + generated file depends on (C++ / Python). + +- `--gen-mutable` : Generate additional non-const accessors for mutating + FlatBuffers in-place. + +- `--gen-onefile` : Generate a single output file for C#, Go, Java, Kotlin and Python. + +- `--gen-name-strings` : Generate type name functions for C++. + +- `--gen-object-api` : Generate an additional object-based API. This API is + more convenient for object construction and mutation than the base API, + at the cost of efficiency (object allocation). Recommended only to be used + if other options are insufficient. + +- `--gen-compare` : Generate operator== for object-based API types. + +- `--gen-nullable` : Add Clang \_Nullable for C++ pointer. or @Nullable for Java. + +- `--gen-generated` : Add @Generated annotation for Java. + +- `--gen-jvmstatic` : Add @JvmStatic annotation for Kotlin methods + in companion object for interop from Java to Kotlin. + +- `--gen-all` : Generate not just code for the current schema files, but + for all files it includes as well. If the language uses a single file for + output (by default the case for C++ and JS), all code will end up in + this one file. + +- `--cpp-include` : Adds an #include in generated file + +- `--cpp-ptr-type T` : Set object API pointer type (default std::unique_ptr) + +- `--cpp-str-type T` : Set object API string type (default std::string) + T::c_str(), T::length() and T::empty() must be supported. + The custom type also needs to be constructible from std::string (see the + --cpp-str-flex-ctor option to change this behavior). + +- `--cpp-str-flex-ctor` : Don't construct custom string types by passing + std::string from Flatbuffers, but (char* + length). This allows efficient + construction of custom string types, including zero-copy construction. + +- `--no-cpp-direct-copy` : Don't generate direct copy methods for C++ + object-based API. + +- `--cpp-std CPP_STD` : Generate a C++ code using features of selected C++ standard. + Supported `CPP_STD` values: + * `c++0x` - generate code compatible with old compilers (VS2010), + * `c++11` - use C++11 code generator (default), + * `c++17` - use C++17 features in generated code (experimental). + +- `--object-prefix` : Customise class prefix for C++ object-based API. + +- `--object-suffix` : Customise class suffix for C++ object-based API. + +- `--go-namespace` : Generate the overrided namespace in Golang. + +- `--go-import` : Generate the overrided import for flatbuffers in Golang. + (default is "github.com/google/flatbuffers/go"). + +- `--raw-binary` : Allow binaries without a file_indentifier to be read. + This may crash flatc given a mismatched schema. + +- `--size-prefixed` : Input binaries are size prefixed buffers. + +- `--proto`: Expect input files to be .proto files (protocol buffers). + Output the corresponding .fbs file. + Currently supports: `package`, `message`, `enum`, nested declarations, + `import` (use `-I` for paths), `extend`, `oneof`, `group`. + Does not support, but will skip without error: `option`, `service`, + `extensions`, and most everything else. + +- `--oneof-union` : Translate .proto oneofs to flatbuffer unions. + +- `--grpc` : Generate GRPC interfaces for the specified languages. + +- `--schema`: Serialize schemas instead of JSON (use with -b). This will + output a binary version of the specified schema that itself corresponds + to the reflection/reflection.fbs schema. Loading this binary file is the + basis for reflection functionality. + +- `--bfbs-comments`: Add doc comments to the binary schema files. + +- `--conform FILE` : Specify a schema the following schemas should be + an evolution of. Gives errors if not. Useful to check if schema + modifications don't break schema evolution rules. + +- `--conform-includes PATH` : Include path for the schema given with + `--conform PATH`. + +- `--filename-suffix SUFFIX` : The suffix appended to the generated + file names. Default is '\_generated'. + +- `--filename-ext EXTENSION` : The extension appended to the generated + file names. Default is language-specific (e.g. "h" for C++). This + should not be used when multiple languages are specified. + +- `--include-prefix PATH` : Prefix this path to any generated include + statements. + +- `--keep-prefix` : Keep original prefix of schema include statement. + +- `--reflect-types` : Add minimal type reflection to code generation. + +- `--reflect-names` : Add minimal type/name reflection. + +- `--root-type T` : Select or override the default root_type. + +- `--require-explicit-ids` : When parsing schemas, require explicit ids (id: x). + +- `--force-defaults` : Emit default values in binary output from JSON. + +- `--force-empty` : When serializing from object API representation, force + strings and vectors to empty rather than null. + +- `--force-empty-vectors` : When serializing from object API representation, force + vectors to empty rather than null. + +- `--flexbuffers` : Used with "binary" and "json" options, it generates + data using schema-less FlexBuffers. + +- `--no-warnings` : Inhibit all warning messages. + +- `--cs-global-alias` : Prepend `global::` to all user generated csharp classes and structs. + +- `--json-nested-bytes` : Allow a nested_flatbuffer field to be parsed as a + vector of bytes in JSON, which is unsafe unless checked by a verifier + afterwards. + +- `--python-no-type-prefix-suffix` : Skip emission of Python functions that are prefixed + with typenames + +- `--python-typing` : Generate Python type annotations + +- `--python-decode-obj-api-strings` : Decode bytes automaticaly with utf-8 + +Additional gRPC options: + +- `--grpc-filename-suffix`: `[C++]` An optional suffix for the generated + files' names. For example, compiling gRPC for C++ with + `--grpc-filename-suffix=.fbs` will generate `{name}.fbs.h` and + `{name}.fbs.cc` files. + +- `--grpc-additional-header`: `[C++]` Additional headers to include in the + generated files. + +- `--grpc-search-path`: `[C++]` An optional prefix for the gRPC runtime path. + For example, compiling gRPC for C++ with `--grpc-search-path=some/path` will + generate the following includes: + + ```cpp + #include "some/path/grpcpp/impl/codegen/async_stream.h" + #include "some/path/grpcpp/impl/codegen/async_unary_call.h" + #include "some/path/grpcpp/impl/codegen/method_handler.h" + ... + ``` + +- `--grpc-use-system-headers`: `[C++]` Whether to generate `#include
` + instead of `#include "header.h"` for all headers when compiling gRPC for + C++. For example, compiling gRPC for C++ with `--grpc-use-system-headers` + will generate the following includes: + + ```cpp + #include + #include + #include + ... + ``` + + NOTE: This option can be negated with `--no-grpc-use-system-headers`. + +- `--grpc-python-typed-handlers`: `[Python]` Whether to generate the typed + handlers that use the generated Python classes instead of raw bytes for + requests/responses. + +NOTE: short-form options for generators are deprecated, use the long form +whenever possible. + diff --git a/third_party/flatbuffers/docs/source/flexbuffers.md b/third_party/flatbuffers/docs/source/flexbuffers.md new file mode 100644 index 00000000000..bf8bbcc474a --- /dev/null +++ b/third_party/flatbuffers/docs/source/flexbuffers.md @@ -0,0 +1,204 @@ +FlexBuffers {#flexbuffers} +========== + +FlatBuffers was designed around schemas, because when you want maximum +performance and data consistency, strong typing is helpful. + +There are however times when you want to store data that doesn't fit a +schema, because you can't know ahead of time what all needs to be stored. + +For this, FlatBuffers has a dedicated format, called FlexBuffers. +This is a binary format that can be used in conjunction +with FlatBuffers (by storing a part of a buffer in FlexBuffers +format), or also as its own independent serialization format. + +While it loses the strong typing, you retain the most unique advantage +FlatBuffers has over other serialization formats (schema-based or not): +FlexBuffers can also be accessed without parsing / copying / object allocation. +This is a huge win in efficiency / memory friendly-ness, and allows unique +use cases such as mmap-ing large amounts of free-form data. + +FlexBuffers' design and implementation allows for a very compact encoding, +combining automatic pooling of strings with automatic sizing of containers to +their smallest possible representation (8/16/32/64 bits). Many values and +offsets can be encoded in just 8 bits. While a schema-less representation is +usually more bulky because of the need to be self-descriptive, FlexBuffers +generates smaller binaries for many cases than regular FlatBuffers. + +FlexBuffers is still slower than regular FlatBuffers though, so we recommend to +only use it if you need it. + + +# Usage in C++ + +Include the header `flexbuffers.h`, which in turn depends on `flatbuffers.h` +and `util.h`. + +To create a buffer: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} +flexbuffers::Builder fbb; +fbb.Int(13); +fbb.Finish(); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You create any value, followed by `Finish`. Unlike FlatBuffers which requires +the root value to be a table, here any value can be the root, including a lonely +int value. + +You can now access the `std::vector` that contains the encoded value +as `fbb.GetBuffer()`. Write it, send it, or store it in a parent FlatBuffer. In +this case, the buffer is just 3 bytes in size. + +To read this value back, you could just say: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} +auto root = flexbuffers::GetRoot(my_buffer); +int64_t i = root.AsInt64(); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +FlexBuffers stores ints only as big as needed, so it doesn't differentiate +between different sizes of ints. You can ask for the 64 bit version, +regardless of what you put in. In fact, since you demand to read the root +as an int, if you supply a buffer that actually contains a float, or a +string with numbers in it, it will convert it for you on the fly as well, +or return 0 if it can't. If instead you actually want to know what is inside +the buffer before you access it, you can call `root.GetType()` or `root.IsInt()` +etc. + +Here's a slightly more complex value you could write instead of `fbb.Int` above: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} +fbb.Map([&]() { + fbb.Vector("vec", [&]() { + fbb.Int(-100); + fbb.String("Fred"); + fbb.IndirectFloat(4.0f); + }); + fbb.UInt("foo", 100); +}); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This stores the equivalent of the JSON value +`{ vec: [ -100, "Fred", 4.0 ], foo: 100 }`. The root is a dictionary that has +just two key-value pairs, with keys `vec` and `foo`. Unlike FlatBuffers, it +actually has to store these keys in the buffer (which it does only once if +you store multiple such objects, by pooling key values), but also unlike +FlatBuffers it has no restriction on the keys (fields) that you use. + +The map constructor uses a C++11 Lambda to group its children, but you can +also use more conventional start/end calls if you prefer. + +The first value in the map is a vector. You'll notice that unlike FlatBuffers, +you can use mixed types. There is also a `TypedVector` variant that only +allows a single type, and uses a bit less memory. + +`IndirectFloat` is an interesting feature that allows you to store values +by offset rather than inline. Though that doesn't make any visible change +to the user, the consequence is that large values (especially doubles or +64 bit ints) that occur more than once can be shared (see ReuseValue). +Another use case is inside of vectors, where the largest element makes +up the size of all elements (e.g. a single double forces all elements to +64bit), so storing a lot of small integers together with a double is more efficient if the double is indirect. + +Accessing it: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} +auto map = flexbuffers::GetRoot(my_buffer).AsMap(); +map.size(); // 2 +auto vec = map["vec"].AsVector(); +vec.size(); // 3 +vec[0].AsInt64(); // -100; +vec[1].AsString().c_str(); // "Fred"; +vec[1].AsInt64(); // 0 (Number parsing failed). +vec[2].AsDouble(); // 4.0 +vec[2].AsString().IsTheEmptyString(); // true (Wrong Type). +vec[2].AsString().c_str(); // "" (This still works though). +vec[2].ToString().c_str(); // "4" (Or have it converted). +map["foo"].AsUInt8(); // 100 +map["unknown"].IsNull(); // true +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +# Usage in Java + +Java implementation follows the C++ one, closely. + +For creating the equivalent of the same JSON `{ vec: [ -100, "Fred", 4.0 ], foo: 100 }`, +one could use the following code: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java} +FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(512), + FlexBuffersBuilder.BUILDER_FLAG_SHARE_KEYS_AND_STRINGS); +int smap = builder.startMap(); +int svec = builder.startVector(); +builder.putInt(-100); +builder.putString("Fred"); +builder.putFloat(4.0); +builder.endVector("vec", svec, false, false); +builder.putInt("foo", 100); +builder.endMap(null, smap); +ByteBuffer bb = builder.finish(); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Similarly, to read the data, just: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java} +FlexBuffers.Map map = FlexBuffers.getRoot(bb).asMap(); +map.size(); // 2 +FlexBuffers.Vector vec = map.get("vec").asVector(); +vec.size(); // 3 +vec.get(0).asLong(); // -100; +vec.get(1).asString(); // "Fred"; +vec.get(1).asLong(); // 0 (Number parsing failed). +vec.get(2).asFloat(); // 4.0 +vec.get(2).asString().isEmpty(); // true (Wrong Type). +vec.get(2).asString(); // "" (This still works though). +vec.get(2).toString(); // "4.0" (Or have it converted). +map.get("foo").asUInt(); // 100 +map.get("unknown").isNull(); // true +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +# Binary encoding + +A description of how FlexBuffers are encoded is in the +[internals](internals.md) document. + + +# Nesting inside a FlatBuffer + +You can mark a field as containing a FlexBuffer, e.g. + + a:[ubyte] (flexbuffer); + +A special accessor will be generated that allows you to access the root value +directly, e.g. `a_flexbuffer_root().AsInt64()`. + + +# Efficiency tips + +* Vectors generally are a lot more efficient than maps, so prefer them over maps + when possible for small objects. Instead of a map with keys `x`, `y` and `z`, + use a vector. Better yet, use a typed vector. Or even better, use a fixed + size typed vector. +* Maps are backwards compatible with vectors, and can be iterated as such. + You can iterate either just the values (`map.Values()`), or in parallel with + the keys vector (`map.Keys()`). If you intend + to access most or all elements, this is faster than looking up each element + by key, since that involves a binary search of the key vector. +* When possible, don't mix values that require a big bit width (such as double) + in a large vector of smaller values, since all elements will take on this + width. Use `IndirectDouble` when this is a possibility. Note that + integers automatically use the smallest width possible, i.e. if you ask + to serialize an int64_t whose value is actually small, you will use less + bits. Doubles are represented as floats whenever possible losslessly, but + this is only possible for few values. + Since nested vectors/maps are stored over offsets, they typically don't + affect the vector width. +* To store large arrays of byte data, use a blob. If you'd use a typed + vector, the bit width of the size field may make it use more space than + expected, and may not be compatible with `memcpy`. + Similarly, large arrays of (u)int16_t may be better off stored as a + binary blob if their size could exceed 64k elements. + Construction and use are otherwise similar to strings. diff --git a/third_party/flatbuffers/docs/source/grammar.md b/third_party/flatbuffers/docs/source/grammar.md new file mode 100644 index 00000000000..ab0a5bf2ad6 --- /dev/null +++ b/third_party/flatbuffers/docs/source/grammar.md @@ -0,0 +1,73 @@ +## EBNF + +```ebnf +schema = include* ( namespace_decl | type_decl | enum_decl | root_decl | + file_extension_decl | file_identifier_decl | + attribute_decl | rpc_decl | object )* + +include = `include` string_constant `;` + +namespace_decl = `namespace` ident ( `.` ident )* `;` + +attribute_decl = `attribute` ident | `"` ident `"` `;` + +type_decl = ( `table` | `struct` ) ident metadata `{` field_decl+ `}` + +enum_decl = ( `enum` ident `:` type | `union` ident ) metadata `{` +commasep( enumval_decl ) `}` + +root_decl = `root_type` ident `;` + +field_decl = ident `:` type [ `=` scalar ] metadata `;` + +rpc_decl = `rpc_service` ident `{` rpc_method+ `}` + +rpc_method = ident `(` ident `)` `:` ident metadata `;` + +type = `bool` | `byte` | `ubyte` | `short` | `ushort` | `int` | `uint` | + `float` | `long` | `ulong` | `double` | `int8` | `uint8` | `int16` | + `uint16` | `int32` | `uint32`| `int64` | `uint64` | `float32` | + `float64` | `string` | `[` type `]` | ident + +enumval_decl = ident [ `=` integer_constant ] metadata + +metadata = [ `(` commasep( ident [ `:` single_value ] ) `)` ] + +scalar = boolean_constant | integer_constant | float_constant + +object = `{` commasep( ident `:` value ) `}` + +single_value = scalar | string_constant + +value = single_value | object | `[` commasep( value ) `]` + +commasep(x) = [ x ( `,` x )\* ] + +file_extension_decl = `file_extension` string_constant `;` + +file_identifier_decl = `file_identifier` string_constant `;` + +string_constant = `\".*?\"` + +ident = `[a-zA-Z_][a-zA-Z0-9_]*` + +`[:digit:]` = `[0-9]` + +`[:xdigit:]` = `[0-9a-fA-F]` + +dec_integer_constant = `[-+]?[:digit:]+` + +hex_integer_constant = `[-+]?0[xX][:xdigit:]+` + +integer_constant = dec_integer_constant | hex_integer_constant + +dec_float_constant = `[-+]?(([.][:digit:]+)|([:digit:]+[.][:digit:]*)|([:digit:]+))([eE][-+]?[:digit:]+)?` + +hex_float_constant = `[-+]?0[xX](([.][:xdigit:]+)|([:xdigit:]+[.][:xdigit:]*)|([:xdigit:]+))([pP][-+]?[:digit:]+)` + +special_float_constant = `[-+]?(nan|inf|infinity)` + +float_constant = dec_float_constant | hex_float_constant | special_float_constant + +boolean_constant = `true` | `false` +``` diff --git a/third_party/flatbuffers/docs/source/index.md b/third_party/flatbuffers/docs/source/index.md new file mode 100644 index 00000000000..042ad8bc447 --- /dev/null +++ b/third_party/flatbuffers/docs/source/index.md @@ -0,0 +1,59 @@ +# Overview + +FlatBuffers is an efficient cross platform serialization library for C++, C#, C, +Go, Java, Kotlin, JavaScript, Lobster, Lua, TypeScript, PHP, Python, Rust and +Swift. It was originally created at Google for game development and other +performance-critical applications. + +It is available as Open Source on +[GitHub](https://github.com/google/flatbuffers) under the Apache license v2.0. + +## Why Use FlatBuffers? + +
+ +- :material-clock-fast:{ .lg .middle } **Access to serialized data without + parsing/unpacking** + + --- + Access the data directly without unpacking or parsing. + +- :material-memory:{ .lg .middle } **Memory Efficiency and Speed** + + --- + The only memory needed to access your data is that of the buffer. + No heap is required. + +- :material-compare-horizontal:{ .lg .middle } **Backwards and Forwards + Compatibility** + + --- + FlatBuffers enables the schema to evolve over time while still maintaining + forwards and backwards compatibility with old flatbuffers. + +- :material-scale-off:{ .lg .middle } **Small Footprint** + + --- + Minimal dependencies and small code footprint. + +
+ +## Why not use... + +=== "Protocol Buffers" + + Protocol Buffers is indeed relatively similar to FlatBuffers, with the primary + difference being that FlatBuffers does not need a parsing/unpacking step to a + secondary representation before you can access data, often coupled with + per-object memory allocation. The code is an order of magnitude bigger, too. + +=== "JSON" + + JSON is very readable (which is why we use it as our optional text format) and + very convenient when used together with dynamically typed languages (such as + JavaScript). When serializing data from statically typed languages, however, + JSON not only has the obvious drawback of runtime inefficiency, but also forces + you to write more code to access data (counterintuitively) due to its + dynamic-typing serialization system. In this context, it is only a better choice + for systems that have very little to no information ahead of time about what + data needs to be stored. diff --git a/third_party/flatbuffers/docs/source/intermediate_representation.md b/third_party/flatbuffers/docs/source/intermediate_representation.md new file mode 100644 index 00000000000..f4eb0753900 --- /dev/null +++ b/third_party/flatbuffers/docs/source/intermediate_representation.md @@ -0,0 +1,35 @@ +# Flatbuffers Intermediate Representation {#intermediate_representation} + +We use [reflection.fbs](https://github.com/google/flatbuffers/blob/master/reflection/reflection.fbs) +as our intermediate representation. `flatc` parses `.fbs` files, checks them for +errors and stores the resulting data in this IR, outputting `.bfbs` files. +Since this IR is a Flatbuffer, you can load and use it at runtime for runtime +reflection purposes. + +There are some quirks: +- Tables and Structs are serialized as `Object`s. +- Unions and Enums are serialized as `Enum`s. +- It is the responsibility of the code generator to check the `advanced_features` + field of `Schema`. These mark the presence of new, backwards incompatible, + schema features. Code generators must error if generating a schema with + unrecognized advanced features. +- Filenames are relative to a "project root" denoted by "//" in the path. This + may be specified in flatc with `--bfbs-filenames=$PROJECT_ROOT`, or it will be + inferred to be the directory containing the first provided schema file. + + +## Invocation +You can invoke it like so +```{.sh} +flatc -b --schema ${your_fbs_files} +``` +This generates `.bfbs` (binary flatbuffer schema) files. + +Some information is not included by default. See the `--bfbs-filenames` and +`--bfbs-comments` flags. These may be necessary for code-generators, so they can +add documentation and maybe name generated files (depending on the generator). + + +TODO(cneo): Flags to output bfbs as flexbuffers or json. + +TODO(cneo): Tutorial for building a flatc plugin. diff --git a/third_party/flatbuffers/docs/source/internals.md b/third_party/flatbuffers/docs/source/internals.md new file mode 100644 index 00000000000..5b126ba75fd --- /dev/null +++ b/third_party/flatbuffers/docs/source/internals.md @@ -0,0 +1,466 @@ +FlatBuffer Internals {#flatbuffers_internals} +==================== + +This section is entirely optional for the use of FlatBuffers. In normal +usage, you should never need the information contained herein. If you're +interested however, it should give you more of an appreciation of why +FlatBuffers is both efficient and convenient. + +### Format components + +A FlatBuffer is a binary file and in-memory format consisting mostly of +scalars of various sizes, all aligned to their own size. Each scalar is +also always represented in little-endian format, as this corresponds to +all commonly used CPUs today. FlatBuffers will also work on big-endian +machines, but will be slightly slower because of additional +byte-swap intrinsics. + +It is assumed that the following conditions are met, to ensure +cross-platform interoperability: +- The binary `IEEE-754` format is used for floating-point numbers. +- The `two's complemented` representation is used for signed integers. +- The endianness is the same for floating-point numbers as for integers. + +On purpose, the format leaves a lot of details about where exactly +things live in memory undefined, e.g. fields in a table can have any +order, and objects to some extent can be stored in many orders. This is +because the format doesn't need this information to be efficient, and it +leaves room for optimization and extension (for example, fields can be +packed in a way that is most compact). Instead, the format is defined in +terms of offsets and adjacency only. This may mean two different +implementations may produce different binaries given the same input +values, and this is perfectly valid. + +### Format identification + +The format also doesn't contain information for format identification +and versioning, which is also by design. FlatBuffers is a statically typed +system, meaning the user of a buffer needs to know what kind of buffer +it is. FlatBuffers can of course be wrapped inside other containers +where needed, or you can use its union feature to dynamically identify +multiple possible sub-objects stored. Additionally, it can be used +together with the schema parser if full reflective capabilities are +desired. + +Versioning is something that is intrinsically part of the format (the +optionality / extensibility of fields), so the format itself does not +need a version number (it's a meta-format, in a sense). We're hoping +that this format can accommodate all data needed. If format breaking +changes are ever necessary, it would become a new kind of format rather +than just a variation. + +### Offsets + +The most important and generic offset type (see `flatbuffers.h`) is +`uoffset_t`, which is currently always a `uint32_t`, and is used to +refer to all tables/unions/strings/vectors (these are never stored +in-line). 32bit is +intentional, since we want to keep the format binary compatible between +32 and 64bit systems, and a 64bit offset would bloat the size for almost +all uses. A version of this format with 64bit (or 16bit) offsets is easy to set +when needed. Unsigned means they can only point in one direction, which +typically is forward (towards a higher memory location). Any backwards +offsets will be explicitly marked as such. + +The format starts with an `uoffset_t` to the root table in the buffer. + +We have two kinds of objects, structs and tables. + +### Structs + +These are the simplest, and as mentioned, intended for simple data that +benefits from being extra efficient and doesn't need versioning / +extensibility. They are always stored inline in their parent (a struct, +table, or vector) for maximum compactness. Structs define a consistent +memory layout where all components are aligned to their size, and +structs aligned to their largest scalar member. This is done independent +of the alignment rules of the underlying compiler to guarantee a cross +platform compatible layout. This layout is then enforced in the generated +code. + +### Tables + +Unlike structs, these are not stored in inline in their parent, but are +referred to by offset. + +They start with an `soffset_t` to a vtable. This is a signed version of +`uoffset_t`, since vtables may be stored anywhere relative to the object. +This offset is subtracted (not added) from the object start to arrive at +the vtable start. This offset is followed by all the +fields as aligned scalars (or offsets). Unlike structs, not all fields +need to be present. There is no set order and layout. A table may contain +field offsets that point to the same value if the user explicitly +serializes the same offset twice. + +To be able to access fields regardless of these uncertainties, we go +through a vtable of offsets. Vtables are shared between any objects that +happen to have the same vtable values. + +The elements of a vtable are all of type `voffset_t`, which is +a `uint16_t`. The first element is the size of the vtable in bytes, +including the size element. The second one is the size of the object, in bytes +(including the vtable offset). This size could be used for streaming, to know +how many bytes to read to be able to access all *inline* fields of the object. +The remaining elements are the N offsets, where N is the amount of fields +declared in the schema when the code that constructed this buffer was +compiled (thus, the size of the table is N + 2). + +All accessor functions in the generated code for tables contain the +offset into this table as a constant. This offset is checked against the +first field (the number of elements), to protect against newer code +reading older data. If this offset is out of range, or the vtable entry +is 0, that means the field is not present in this object, and the +default value is return. Otherwise, the entry is used as offset to the +field to be read. + +### Unions + +Unions are encoded as the combination of two fields: an enum representing the +union choice and the offset to the actual element. FlatBuffers reserves the +enumeration constant `NONE` (encoded as 0) to mean that the union field is not +set. + +### Strings and Vectors + +Strings are simply a vector of bytes, and are always +null-terminated. Vectors are stored as contiguous aligned scalar +elements prefixed by a 32bit element count (not including any +null termination). Neither is stored inline in their parent, but are referred to +by offset. A vector may consist of more than one offset pointing to the same +value if the user explicitly serializes the same offset twice. + +### Construction + +The current implementation constructs these buffers backwards (starting +at the highest memory address of the buffer), since +that significantly reduces the amount of bookkeeping and simplifies the +construction API. + +### Code example + +Here's an example of the code that gets generated for the `samples/monster.fbs`. +What follows is the entire file, broken up by comments: + + // automatically generated, do not modify + + #include "flatbuffers/flatbuffers.h" + + namespace MyGame { + namespace Sample { + +Nested namespace support. + + enum { + Color_Red = 0, + Color_Green = 1, + Color_Blue = 2, + }; + + inline const char **EnumNamesColor() { + static const char *names[] = { "Red", "Green", "Blue", nullptr }; + return names; + } + + inline const char *EnumNameColor(int e) { return EnumNamesColor()[e]; } + +Enums and convenient reverse lookup. + + enum { + Any_NONE = 0, + Any_Monster = 1, + }; + + inline const char **EnumNamesAny() { + static const char *names[] = { "NONE", "Monster", nullptr }; + return names; + } + + inline const char *EnumNameAny(int e) { return EnumNamesAny()[e]; } + +Unions share a lot with enums. + + struct Vec3; + struct Monster; + +Predeclare all data types since circular references between types are allowed +(circular references between object are not, though). + + FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vec3 { + private: + float x_; + float y_; + float z_; + + public: + Vec3(float x, float y, float z) + : x_(flatbuffers::EndianScalar(x)), y_(flatbuffers::EndianScalar(y)), z_(flatbuffers::EndianScalar(z)) {} + + float x() const { return flatbuffers::EndianScalar(x_); } + float y() const { return flatbuffers::EndianScalar(y_); } + float z() const { return flatbuffers::EndianScalar(z_); } + }; + FLATBUFFERS_STRUCT_END(Vec3, 12); + +These ugly macros do a couple of things: they turn off any padding the compiler +might normally do, since we add padding manually (though none in this example), +and they enforce alignment chosen by FlatBuffers. This ensures the layout of +this struct will look the same regardless of compiler and platform. Note that +the fields are private: this is because these store little endian scalars +regardless of platform (since this is part of the serialized data). +`EndianScalar` then converts back and forth, which is a no-op on all current +mobile and desktop platforms, and a single machine instruction on the few +remaining big endian platforms. + + struct Monster : private flatbuffers::Table { + const Vec3 *pos() const { return GetStruct(4); } + int16_t mana() const { return GetField(6, 150); } + int16_t hp() const { return GetField(8, 100); } + const flatbuffers::String *name() const { return GetPointer(10); } + const flatbuffers::Vector *inventory() const { return GetPointer *>(14); } + int8_t color() const { return GetField(16, 2); } + }; + +Tables are a bit more complicated. A table accessor struct is used to point at +the serialized data for a table, which always starts with an offset to its +vtable. It derives from `Table`, which contains the `GetField` helper functions. +GetField takes a vtable offset, and a default value. It will look in the vtable +at that offset. If the offset is out of bounds (data from an older version) or +the vtable entry is 0, the field is not present and the default is returned. +Otherwise, it uses the entry as an offset into the table to locate the field. + + struct MonsterBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_pos(const Vec3 *pos) { fbb_.AddStruct(4, pos); } + void add_mana(int16_t mana) { fbb_.AddElement(6, mana, 150); } + void add_hp(int16_t hp) { fbb_.AddElement(8, hp, 100); } + void add_name(flatbuffers::Offset name) { fbb_.AddOffset(10, name); } + void add_inventory(flatbuffers::Offset> inventory) { fbb_.AddOffset(14, inventory); } + void add_color(int8_t color) { fbb_.AddElement(16, color, 2); } + MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + flatbuffers::Offset Finish() { return flatbuffers::Offset(fbb_.EndTable(start_, 7)); } + }; + +`MonsterBuilder` is the base helper struct to construct a table using a +`FlatBufferBuilder`. You can add the fields in any order, and the `Finish` +call will ensure the correct vtable gets generated. + + inline flatbuffers::Offset CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, + const Vec3 *pos, int16_t mana, + int16_t hp, + flatbuffers::Offset name, + flatbuffers::Offset> inventory, + int8_t color) { + MonsterBuilder builder_(_fbb); + builder_.add_inventory(inventory); + builder_.add_name(name); + builder_.add_pos(pos); + builder_.add_hp(hp); + builder_.add_mana(mana); + builder_.add_color(color); + return builder_.Finish(); + } + +`CreateMonster` is a convenience function that calls all functions in +`MonsterBuilder` above for you. Note that if you pass values which are +defaults as arguments, it will not actually construct that field, so +you can probably use this function instead of the builder class in +almost all cases. + + inline const Monster *GetMonster(const void *buf) { return flatbuffers::GetRoot(buf); } + +This function is only generated for the root table type, to be able to +start traversing a FlatBuffer from a raw buffer pointer. + + }; // namespace MyGame + }; // namespace Sample + +### Encoding example. + +Below is a sample encoding for the following JSON corresponding to the above +schema: + + { pos: { x: 1, y: 2, z: 3 }, name: "fred", hp: 50 } + +Resulting in this binary buffer: + + // Start of the buffer: + uint32_t 20 // Offset to the root table. + + // Start of the vtable. Not shared in this example, but could be: + uint16_t 16 // Size of table, starting from here. + uint16_t 22 // Size of object inline data. + uint16_t 4, 0, 20, 16, 0, 0 // Offsets to fields from start of (root) table, 0 for not present. + + // Start of the root table: + int32_t 16 // Offset to vtable used (default negative direction) + float 1, 2, 3 // the Vec3 struct, inline. + uint32_t 8 // Offset to the name string. + int16_t 50 // hp field. + int16_t 0 // Padding for alignment. + + // Start of name string: + uint32_t 4 // Length of string. + int8_t 'f', 'r', 'e', 'd', 0, 0, 0, 0 // Text + 0 termination + padding. + +Note that this not the only possible encoding, since the writer has some +flexibility in which of the children of root object to write first (though in +this case there's only one string), and what order to write the fields in. +Different orders may also cause different alignments to happen. + +### Additional reading. + +The author of the C language implementation has made a similar +[document](https://github.com/dvidelabs/flatcc/blob/master/doc/binary-format.md#flatbuffers-binary-format) +that may further help clarify the format. + +# FlexBuffers + +The [schema-less](flexbuffers.md) version of FlatBuffers have their +own encoding, detailed here. + +It shares many properties mentioned above, in that all data is accessed +over offsets, all scalars are aligned to their own size, and +all data is always stored in little endian format. + +One difference is that FlexBuffers are built front to back, so children are +stored before parents, and the root of the data starts at the last byte. + +Another difference is that scalar data is stored with a variable number of bits +(8/16/32/64). The current width is always determined by the *parent*, i.e. if +the scalar sits in a vector, the vector determines the bit width for all +elements at once. Selecting the minimum bit width for a particular vector is +something the encoder does automatically and thus is typically of no concern +to the user, though being aware of this feature (and not sticking a double in +the same vector as a bunch of byte sized elements) is helpful for efficiency. + +Unlike FlatBuffers there is only one kind of offset, and that is an unsigned +integer indicating the number of bytes in a negative direction from the address +of itself (where the offset is stored). + +### Vectors + +The representation of the vector is at the core of how FlexBuffers works (since +maps are really just a combination of 2 vectors), so it is worth starting there. + +As mentioned, a vector is governed by a single bit width (supplied by its +parent). This includes the size field. For example, a vector that stores the +integer values `1, 2, 3` is encoded as follows: + + uint8_t 3, 1, 2, 3, 4, 4, 4 + +The first `3` is the size field, and is placed before the vector (an offset +from the parent to this vector points to the first element, not the size +field, so the size field is effectively at index -1). +Since this is an untyped vector `SL_VECTOR`, it is followed by 3 type +bytes (one per element of the vector), which are always following the vector, +and are always a uint8_t even if the vector is made up of bigger scalars. + +A vector may include more than one offset pointing to the same value if the +user explicitly serializes the same offset twice. + +### Types + +A type byte is made up of 2 components (see flexbuffers.h for exact values): + +* 2 lower bits representing the bit-width of the child (8, 16, 32, 64). + This is only used if the child is accessed over an offset, such as a child + vector. It is ignored for inline types. +* 6 bits representing the actual type (see flexbuffers.h). + +Thus, in this example `4` means 8 bit child (value 0, unused, since the value is +in-line), type `SL_INT` (value 1). + +### Typed Vectors + +These are like the Vectors above, but omit the type bytes. The type is instead +determined by the vector type supplied by the parent. Typed vectors are only +available for a subset of types for which these savings can be significant, +namely inline signed/unsigned integers (`TYPE_VECTOR_INT` / `TYPE_VECTOR_UINT`), +floats (`TYPE_VECTOR_FLOAT`), and keys (`TYPE_VECTOR_KEY`, see below). + +Additionally, for scalars, there are fixed length vectors of sizes 2 / 3 / 4 +that don't store the size (`TYPE_VECTOR_INT2` etc.), for an additional savings +in space when storing common vector or color data. + +### Scalars + +FlexBuffers supports integers (`TYPE_INT` and `TYPE_UINT`) and floats +(`TYPE_FLOAT`), available in the bit-widths mentioned above. They can be stored +both inline and over an offset (`TYPE_INDIRECT_*`). + +The offset version is useful to encode costly 64bit (or even 32bit) quantities +into vectors / maps of smaller sizes, and to share / repeat a value multiple +times. + +### Booleans and Nulls + +Booleans (`TYPE_BOOL`) and nulls (`TYPE_NULL`) are encoded as inlined unsigned integers. + +### Blobs, Strings and Keys. + +A blob (`TYPE_BLOB`) is encoded similar to a vector, with one difference: the +elements are always `uint8_t`. The parent bit width only determines the width of +the size field, allowing blobs to be large without the elements being large. + +Strings (`TYPE_STRING`) are similar to blobs, except they have an additional 0 +termination byte for convenience, and they MUST be UTF-8 encoded (since an +accessor in a language that does not support pointers to UTF-8 data may have to +convert them to a native string type). + +A "Key" (`TYPE_KEY`) is similar to a string, but doesn't store the size +field. They're so named because they are used with maps, which don't care +for the size, and can thus be even more compact. Unlike strings, keys cannot +contain bytes of value 0 as part of their data (size can only be determined by +`strlen`), so while you can use them outside the context of maps if you so +desire, you're usually better off with strings. + +### Maps + +A map (`TYPE_MAP`) is like an (untyped) vector, but with 2 prefixes before the +size field: + +| index | field | +| ----: | :----------------------------------------------------------- | +| -3 | An offset to the keys vector (may be shared between tables). | +| -2 | Byte width of the keys vector. | +| -1 | Size (from here on it is compatible with `TYPE_VECTOR`) | +| 0 | Elements. | +| Size | Types. | + +Since a map is otherwise the same as a vector, it can be iterated like +a vector (which is probably faster than lookup by key). + +The keys vector is a typed vector of keys. Both the keys and corresponding +values *have* to be stored in sorted order (as determined by `strcmp`), such +that lookups can be made using binary search. + +The reason the key vector is a separate structure from the value vector is +such that it can be shared between multiple value vectors, and also to +allow it to be treated as its own individual vector in code. + +An example map { foo: 13, bar: 14 } would be encoded as: + + 0 : uint8_t 'b', 'a', 'r', 0 + 4 : uint8_t 'f', 'o', 'o', 0 + 8 : uint8_t 2 // key vector of size 2 + // key vector offset points here + 9 : uint8_t 9, 6 // offsets to bar_key and foo_key + 11: uint8_t 2, 1 // offset to key vector, and its byte width + 13: uint8_t 2 // value vector of size + // value vector offset points here + 14: uint8_t 14, 13 // values + 16: uint8_t 4, 4 // types + +### The root + +As mentioned, the root starts at the end of the buffer. +The last uint8_t is the width in bytes of the root (normally the parent +determines the width, but the root has no parent). The uint8_t before this is +the type of the root, and the bytes before that are the root value (of the +number of bytes specified by the last byte). + +So for example, the integer value `13` as root would be: + + uint8_t 13, 4, 1 // Value, type, root byte width. + diff --git a/third_party/flatbuffers/docs/source/languages/c.md b/third_party/flatbuffers/docs/source/languages/c.md new file mode 100644 index 00000000000..a0c2690874e --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/c.md @@ -0,0 +1,224 @@ +Use in C {#flatbuffers_guide_use_c} +========== + +The C language binding exists in a separate project named [FlatCC](https://github.com/dvidelabs/flatcc). + +The `flatcc` C schema compiler can generate code offline as well as +online via a C library. It can also generate buffer verifiers and fast +JSON parsers, printers. + +Great care has been taken to ensure compatibility with the main `flatc` +project. + +## General Documention + +- [Tutorial](../tutorial.md) - select C as language + when scrolling down +- [FlatCC Guide](https://github.com/dvidelabs/flatcc#flatcc-flatbuffers-in-c-for-c) +- [The C Builder Interface](https://github.com/dvidelabs/flatcc/blob/master/doc/builder.md#the-builder-interface) +- [The Monster Sample in C](https://github.com/dvidelabs/flatcc/blob/master/samples/monster/monster.c) +- [GitHub](https://github.com/dvidelabs/flatcc) + + +## Supported Platforms + +- Ubuntu (clang / gcc, ninja / gnu make) +- OS-X (clang / gcc, ninja / gnu make) +- Windows MSVC 2010, 2013, 2015 + +CI builds recent versions of gcc, clang and MSVC on OS-X, Ubuntu, and +Windows, and occasionally older compiler versions. See main project [Status](https://github.com/dvidelabs/flatcc#status). + +Other platforms may well work, including Centos, but are not tested +regularly. + +The monster sample project was specifically written for C99 in order to +follow the C++ version and for that reason it will not work with MSVC +2010. + +## Modular Object Creation + +In the tutorial we used the call `Monster_create_as_root` to create the +root buffer object since this is easier in simple use cases. Sometimes +we need more modularity so we can reuse a function to create nested +tables and root tables the same way. For this we need the +`flatcc_builder_buffer_create_call`. It is best to keep `flatcc_builder` +calls isolated at the top driver level, so we get: + +
+~~~{.c} + ns(Monster_ref_t) create_orc(flatcc_builder_t *B) + { + // ... same as in the tutorial. + return s(Monster_create(B, ...)); + } + + void create_monster_buffer() + { + uint8_t *buf; + size_t size; + flatcc_builder_t builder, *B; + + // Initialize the builder object. + B = &builder; + flatcc_builder_init(B); + // Only use `buffer_create` without `create/start/end_as_root`. + flatcc_builder_buffer_create(create_orc(B)); + // Allocate and copy buffer to user memory. + buf = flatcc_builder_finalize_buffer(B, &size); + // ... write the buffer to disk or network, or something. + + free(buf); + flatcc_builder_clear(B); + } +~~~ +
+ +The same principle applies with `start/end` vs `start/end_as_root` in +the top-down approach. + + +## Top Down Example + +The tutorial uses a bottom up approach. In C it is also possible to use +a top-down approach by starting and ending objects nested within each +other. In the tutorial there is no deep nesting, so the difference is +limited, but it shows the idea: + +
+
+~~~{.c} + uint8_t treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + size_t treasure_count = c_vec_len(treasure); + ns(Weapon_ref_t) axe; + + // NOTE: if we use end_as_root, we MUST also start as root. + ns(Monster_start_as_root(B)); + ns(Monster_pos_create(B, 1.0f, 2.0f, 3.0f)); + ns(Monster_hp_add(B, 300)); + ns(Monster_mana_add(B, 150)); + // We use create_str instead of add because we have no existing string reference. + ns(Monster_name_create_str(B, "Orc")); + // Again we use create because we no existing vector object, only a C-array. + ns(Monster_inventory_create(B, treasure, treasure_count)); + ns(Monster_color_add(B, ns(Color_Red))); + if (1) { + ns(Monster_weapons_start(B)); + ns(Monster_weapons_push_create(B, flatbuffers_string_create_str(B, "Sword"), 3)); + // We reuse the axe object later. Note that we dereference a pointer + // because push always returns a short-term pointer to the stored element. + // We could also have created the axe object first and simply pushed it. + axe = *ns(Monster_weapons_push_create(B, flatbuffers_string_create_str(B, "Axe"), 5)); + ns(Monster_weapons_end(B)); + } else { + // We can have more control with the table elements added to a vector: + // + ns(Monster_weapons_start(B)); + ns(Monster_weapons_push_start(B)); + ns(Weapon_name_create_str(B, "Sword")); + ns(Weapon_damage_add(B, 3)); + ns(Monster_weapons_push_end(B)); + ns(Monster_weapons_push_start(B)); + ns(Monster_weapons_push_start(B)); + ns(Weapon_name_create_str(B, "Axe")); + ns(Weapon_damage_add(B, 5)); + axe = *ns(Monster_weapons_push_end(B)); + ns(Monster_weapons_end(B)); + } + // Unions can get their type by using a type-specific add/create/start method. + ns(Monster_equipped_Weapon_add(B, axe)); + + ns(Monster_end_as_root(B)); +~~~ +
+ + +## Basic Reflection + +The C-API does support reading binary schema (.bfbs) +files via code generated from the `reflection.fbs` schema, and an +[example usage](https://github.com/dvidelabs/flatcc/tree/master/samples/reflection) +shows how to use this. The reflection schema files are pre-generated +in the [runtime distribution](https://github.com/dvidelabs/flatcc/tree/master/include/flatcc/reflection). + + +## Mutations and Reflection + +The C-API does not support mutating reflection like C++ does, nor does +the reader interface support mutating scalars (and it is generally +unsafe to do so even after verification). + +The generated reader interface supports sorting vectors in-place after +casting them to a mutating type because it is not practical to do so +while building a buffer. This is covered in the builder documentation. +The reflection example makes use of this feature to look up objects by +name. + +It is possible to build new buffers using complex objects from existing +buffers as source. This can be very efficient due to direct copy +semantics without endian conversion or temporary stack allocation. + +Scalars, structs and strings can be used as source, as well vectors of +these. + +It is currently not possible to use an existing table or vector of table +as source, but it would be possible to add support for this at some +point. + + +## Namespaces + +The `FLATBUFFERS_WRAP_NAMESPACE` approach used in the tutorial is convenient +when each function has a very long namespace prefix. But it isn't always +the best approach. If the namespace is absent, or simple and +informative, we might as well use the prefix directly. The +[reflection example](https://github.com/dvidelabs/flatcc/blob/master/samples/reflection/bfbs2json.c) +mentioned above uses this approach. + + +## Checking for Present Members + +Not all languages support testing if a field is present, but in C we can +elaborate the reader section of the tutorial with tests for this. Recall +that `mana` was set to the default value `150` and therefore shouldn't +be present. + +
+~~~{.c} + int hp_present = ns(Monster_hp_is_present(monster)); // 1 + int mana_present = ns(Monster_mana_is_present(monster)); // 0 +~~~ +
+ +## Alternative ways to add a Union + +In the tutorial we used a single call to add a union. Here we show +different ways to accomplish the same thing. The last form is rarely +used, but is the low-level way to do it. It can be used to group small +values together in the table by adding type and data at different +points in time. + +
+~~~{.c} + ns(Equipment_union_ref_t) equipped = ns(Equipment_as_Weapon(axe)); + ns(Monster_equipped_add(B, equipped)); + // or alternatively + ns(Monster_equipped_Weapon_add(B, axe); + // or alternatively + ns(Monster_equipped_add_type(B, ns(Equipment_Weapon)); + ns(Monster_equipped_add_member(B, axe)); +~~~ +
+ +## Why not integrate with the `flatc` tool? + +[It was considered how the C code generator could be integrated into the +`flatc` tool](https://github.com/dvidelabs/flatcc/issues/1), but it +would either require that the standalone C implementation of the schema +compiler was dropped, or it would lead to excessive code duplication, or +a complicated intermediate representation would have to be invented. +Neither of these alternatives are very attractive, and it isn't a big +deal to use the `flatcc` tool instead of `flatc` given that the +FlatBuffers C runtime library needs to be made available regardless. + + diff --git a/third_party/flatbuffers/docs/source/languages/c_sharp.md b/third_party/flatbuffers/docs/source/languages/c_sharp.md new file mode 100644 index 00000000000..07f879a4765 --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/c_sharp.md @@ -0,0 +1,265 @@ +Use in C\# {#flatbuffers_guide_use_c-sharp} +============== + +## Before you get started + +Before diving into the FlatBuffers usage in C#, it should be noted that +the [Tutorial](../tutorial.md) page has a complete guide to +general FlatBuffers usage in all of the supported languages (including C#). +This page is designed to cover the nuances of FlatBuffers usage, +specific to C#. + +You should also have read the [Building](../building.md) +documentation to build `flatc` and should be familiar with +[Using the schema compiler](../flatc.md) and +[Writing a schema](../schema.md). + +## FlatBuffers C# code location + +The code for the FlatBuffers C# library can be found at +`flatbuffers/net/FlatBuffers`. You can browse the library on the +[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/net/ +FlatBuffers). + +## Building the FlatBuffers C# library + +The `FlatBuffers.csproj` project contains multitargeting for .NET Standard 2.1, +.NET 6 and .NET 8. + +You can build for a specific framework target when using the cross-platform +[.NET Core SDK](https://dotnet.microsoft.com/download) by adding the `-f` +command line option: + +~~~{.sh} + dotnet build -f netstandard2.1 "FlatBuffers.csproj" +~~~ + +The `FlatBuffers.csproj` project also provides support for defining various +conditional compilation symbols (see "Conditional compilation symbols" section +below) using the `-p` command line option: + +~~~{.sh} + dotnet build -f netstandard2.1 -p:ENABLE_SPAN_T=true -p:UNSAFE_BYTEBUFFER=true "FlatBuffers.csproj" +~~~ + +## Testing the FlatBuffers C# library + +The code to test the libraries can be found at `flatbuffers/tests`. + +The test code for C# is located in the [FlatBuffers.Test](https://github.com/ +google/flatbuffers/tree/master/tests/FlatBuffers.Test) subfolder. To run the +tests, open `FlatBuffers.Test.csproj` in [Visual Studio]( +https://www.visualstudio.com), and compile/run the project. + +Optionally, you can run this using [Mono](http://www.mono-project.com/) instead. +Once you have installed Mono, you can run the tests from the command line +by running the following commands from inside the `FlatBuffers.Test` folder: + +~~~{.sh} + mcs *.cs ../MyGame/Example/*.cs ../../net/FlatBuffers/*.cs + mono Assert.exe +~~~ + +## Using the FlatBuffers C# library + +*Note: See [Tutorial](../tutorial.md) for a more in-depth +example of how to use FlatBuffers in C#.* + +FlatBuffers supports reading and writing binary FlatBuffers in C#. + +To use FlatBuffers in your own code, first generate C# classes from your +schema with the `--csharp` option to `flatc`. +Then you can include both FlatBuffers and the generated code to read +or write a FlatBuffer. + +For example, here is how you would read a FlatBuffer binary file in C#: +First, import the library and generated code. Then, you read a FlatBuffer binary +file into a `byte[]`. You then turn the `byte[]` into a `ByteBuffer`, which you +pass to the `GetRootAsMyRootType` function: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs} + using MyGame.Example; + using Google.FlatBuffers; + + // This snippet ignores exceptions for brevity. + byte[] data = File.ReadAllBytes("monsterdata_test.mon"); + + ByteBuffer bb = new ByteBuffer(data); + Monster monster = Monster.GetRootAsMonster(bb); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now you can access the data from the `Monster monster`: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs} + short hp = monster.Hp; + Vec3 pos = monster.Pos; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +C# code naming follows standard C# style with PascalCasing identifiers, +e.g. `GetRootAsMyRootType`. Also, values (except vectors and unions) are +available as properties instead of parameterless accessor methods. +The performance-enhancing methods to which you can pass an already created +object are prefixed with `Get`, e.g.: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs} + // property + var pos = monster.Pos; + + // method filling a preconstructed object + var preconstructedPos = new Vec3(); + monster.GetPos(preconstructedPos); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Storing dictionaries in a FlatBuffer + +FlatBuffers doesn't support dictionaries natively, but there is support to +emulate their behavior with vectors and binary search, which means you +can have fast lookups directly from a FlatBuffer without having to unpack +your data into a `Dictionary` or similar. + +To use it: +- Designate one of the fields in a table as the "key" field. You do this + by setting the `key` attribute on this field, e.g. + `name:string (key)`. + You may only have one key field, and it must be of string or scalar type. +- Write out tables of this type as usual, collect their offsets in an + array. +- Instead of calling standard generated method, + e.g.: `Monster.createTestarrayoftablesVector`, + call `CreateSortedVectorOfMonster` in C# + which will first sort all offsets such that the tables they refer to + are sorted by the key field, then serialize it. +- Now when you're accessing the FlatBuffer, you can use + the `ByKey` accessor to access elements of the vector, e.g.: + `monster.TestarrayoftablesByKey("Frodo")` in C#, + which returns an object of the corresponding table type, + or `null` if not found. + `ByKey` performs a binary search, so should have a similar + speed to `Dictionary`, though may be faster because of better caching. + `ByKey` only works if the vector has been sorted, it will + likely not find elements if it hasn't been sorted. + +## Buffer verification + +As mentioned in [C++ Usage](cpp.md) buffer +accessor functions do not verify buffer offsets at run-time. +If it is necessary, you can optionally use a buffer verifier before you +access the data. This verifier will check all offsets, all sizes of +fields, and null termination of strings to ensure that when a buffer +is accessed, all reads will end up inside the buffer. + +Each root type will have a verification function generated for it, +e.g. `Monster.VerifyMonster`. This can be called as shown: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs} + var ok = Monster.VerifyMonster(buf); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +if `ok` is true, the buffer is safe to read. + +For a more detailed control of verification `MonsterVerify.Verify` +for `Monster` type can be used: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs} + # Sequence of calls + FlatBuffers.Verifier verifier = new FlatBuffers.Verifier(buf); + var ok = verifier.VerifyBuffer("MONS", false, MonsterVerify.Verify); + + # Or single line call + var ok = new FlatBuffers.Verifier(bb).setStringCheck(true).\ + VerifyBuffer("MONS", false, MonsterVerify.Verify); + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +if `ok` is true, the buffer is safe to read. + +A second parameter of `verifyBuffer` specifies whether buffer content is +size prefixed or not. In the example above, the buffer is assumed to not include +size prefix (`false`). + +Verifier supports options that can be set using appropriate fluent methods: +* SetMaxDepth - limit the nesting depth. Default: 1000000 +* SetMaxTables - total amount of tables the verifier may encounter. Default: 64 +* SetAlignmentCheck - check content alignment. Default: True +* SetStringCheck - check if strings contain termination '0' character. Default: true + + +## Text parsing + +There currently is no support for parsing text (Schema's and JSON) directly +from C#, though you could use the C++ parser through native call +interfaces available to each language. Please see the +C++ documentation for more on text parsing. + +## Object based API + +FlatBuffers is all about memory efficiency, which is why its base API is written +around using as little as possible of it. This does make the API clumsier +(requiring pre-order construction of all data, and making mutation harder). + +For times when efficiency is less important a more convenient object based API +can be used (through `--gen-object-api`) that is able to unpack & pack a +FlatBuffer into objects and standard `System.Collections.Generic` containers, +allowing for convenient construction, access and mutation. + +To use: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs} + // Deserialize from buffer into object. + MonsterT monsterobj = GetMonster(flatbuffer).UnPack(); + + // Update object directly like a C# class instance. + Console.WriteLine(monsterobj.Name); + monsterobj.Name = "Bob"; // Change the name. + + // Serialize into new flatbuffer. + FlatBufferBuilder fbb = new FlatBufferBuilder(1); + fbb.Finish(Monster.Pack(fbb, monsterobj).Value); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +### Json Serialization + +An additional feature of the object API is the ability to allow you to +serialize & deserialize a JSON text. +To use Json Serialization, add `--cs-gen-json-serializer` option to `flatc` and +add `Newtonsoft.Json` nuget package to csproj. This requires explicitly setting +the `--gen-object-api` option as well. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs} + // Deserialize MonsterT from json + string jsonText = File.ReadAllText(@"Resources/monsterdata_test.json"); + MonsterT mon = MonsterT.DeserializeFromJson(jsonText); + + // Serialize MonsterT to json + string jsonText2 = mon.SerializeToJson(); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Limitation + * `hash` attribute currently not supported. +* NuGet package Dependency + * [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) + +## Conditional compilation symbols + +There are three conditional compilation symbols that have an impact on +performance/features of the C# `ByteBuffer` implementation. + +* `UNSAFE_BYTEBUFFER` + + This will use unsafe code to manipulate the underlying byte array. This can + yield a reasonable performance increase. + +* `BYTEBUFFER_NO_BOUNDS_CHECK` + + This will disable the bounds check asserts to the byte array. This can yield a + small performance gain in normal code. + +* `ENABLE_SPAN_T` + + This will enable reading and writing blocks of memory with a `Span` instead + of just `T[]`. You can also enable writing directly to shared memory or other + types of memory by providing a custom implementation of `ByteBufferAllocator`. + `ENABLE_SPAN_T` also requires `UNSAFE_BYTEBUFFER` to be defined, or .NET + Standard 2.1. + +Using `UNSAFE_BYTEBUFFER` and `BYTEBUFFER_NO_BOUNDS_CHECK` together can yield a +performance gain of ~15% for some operations, however doing so is potentially +dangerous. Do so at your own risk! + +
diff --git a/third_party/flatbuffers/docs/source/languages/cpp.md b/third_party/flatbuffers/docs/source/languages/cpp.md new file mode 100644 index 00000000000..7e99d4efd15 --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/cpp.md @@ -0,0 +1,673 @@ +# Language Guide: C++ + +## Before you get started + +Before diving into the FlatBuffers usage in C++, it should be noted that +the [Tutorial](../tutorial.md) page has a complete guide +to general FlatBuffers usage in all of the supported languages (including C++). +This page is designed to cover the nuances of FlatBuffers usage, specific to +C++. + +#### Prerequisites + +This page assumes you have written a FlatBuffers schema and compiled it +with the Schema Compiler. If you have not, please see +[Using the schema compiler](../flatc.md) +and [Writing a schema](../schema.md). + +Assuming you wrote a schema, say `mygame.fbs` (though the extension doesn't +matter), you've generated a C++ header called `mygame_generated.h` using the +compiler (e.g. `flatc -c mygame.fbs`), you can now start using this in +your program by including the header. As noted, this header relies on +`flatbuffers/flatbuffers.h`, which should be in your include path. + +## FlatBuffers C++ library code location + +The code for the FlatBuffers C++ library can be found at +`flatbuffers/include/flatbuffers`. You can browse the library code on the +[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/include/flatbuffers). + +## Testing the FlatBuffers C++ library + +The code to test the C++ library can be found at `flatbuffers/tests`. +The test code itself is located in +[test.cpp](https://github.com/google/flatbuffers/blob/master/tests/test.cpp). + +This test file is built alongside `flatc`. To review how to build the project, +please read the [Building](../building.md) documentation. + +To run the tests, execute `flattests` from the root `flatbuffers/` directory. +For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply +run: `./flattests`. + +## Using the FlatBuffers C++ library + +*Note: See [Tutorial](../tutorial.md) for a more in-depth +example of how to use FlatBuffers in C++.* + +FlatBuffers supports both reading and writing FlatBuffers in C++. + +To use FlatBuffers in your code, first generate the C++ classes from your +schema with the `--cpp` option to `flatc`. Then you can include both FlatBuffers +and the generated code to read or write FlatBuffers. + +For example, here is how you would read a FlatBuffer binary file in C++: +First, include the library and generated code. Then read the file into +a `char *` array, which you pass to `GetMonster()`. + +```cpp + #include "flatbuffers/flatbuffers.h" + #include "monster_test_generate.h" + #include // C++ header file for printing + #include // C++ header file for file access + + + std::ifstream infile; + infile.open("monsterdata_test.mon", std::ios::binary | std::ios::in); + infile.seekg(0,std::ios::end); + int length = infile.tellg(); + infile.seekg(0,std::ios::beg); + char *data = new char[length]; + infile.read(data, length); + infile.close(); + + auto monster = GetMonster(data); +``` + +`monster` is of type `Monster *`, and points to somewhere *inside* your +buffer (root object pointers are not the same as `buffer_pointer` \!). +If you look in your generated header, you'll see it has +convenient accessors for all fields, e.g. `hp()`, `mana()`, etc: + +```cpp + std::cout << "hp : " << monster->hp() << std::endl; // '80' + std::cout << "mana : " << monster->mana() << std::endl; // default value of '150' + std::cout << "name : " << monster->name()->c_str() << std::endl; // "MyMonster" +``` + +*Note: That we never stored a `mana` value, so it will return the default.* + +The following attributes are supported: + +- `shared` (on a field): For string fields, this enables the usage of string + pooling (i.e. `CreateSharedString`) as default serialization behavior. + + Specifically, `CreateXxxDirect` functions and `Pack` functions for object + based API (see below) will use `CreateSharedString` to create strings. + +## Object based API + +FlatBuffers is all about memory efficiency, which is why its base API is written +around using as little as possible of it. This does make the API clumsier +(requiring pre-order construction of all data, and making mutation harder). + +For times when efficiency is less important a more convenient object based API +can be used (through `--gen-object-api`) that is able to unpack & pack a +FlatBuffer into objects and standard STL containers, allowing for convenient +construction, access and mutation. + +To use: + +```cpp + // Autogenerated class from table Monster. + MonsterT monsterobj; + + // Deserialize from buffer into object. + GetMonster(flatbuffer)->UnPackTo(&monsterobj); + + // Update object directly like a C++ class instance. + cout << monsterobj.name; // This is now a std::string! + monsterobj.name = "Bob"; // Change the name. + + // Serialize into new flatbuffer. + FlatBufferBuilder fbb; + fbb.Finish(Monster::Pack(fbb, &monsterobj)); +``` + +The following attributes are specific to the object-based API code generation: + +- `native_inline` (on a field): Because FlatBuffer tables and structs are + optionally present in a given buffer, they are best represented as pointers + (specifically std::unique_ptrs) in the native class since they can be null. + This attribute changes the member declaration to use the type directly + rather than wrapped in a unique_ptr. + +- `native_default("value")` (on a field): For members that are declared + "native_inline", the value specified with this attribute will be included + verbatim in the class constructor initializer list for this member. + +- `native_custom_alloc("custom_allocator")` (on a table or struct): When using the + object-based API all generated NativeTables that are allocated when unpacking + your flatbuffer will use "custom allocator". The allocator is also used by + any std::vector that appears in a table defined with `native_custom_alloc`. + This can be used to provide allocation from a pool for example, for faster + unpacking when using the object-based API. + +Minimal Example: + +schema: + +```cpp + table mytable(native_custom_alloc:"custom_allocator") { + ... + } +``` + +with `custom_allocator` defined before `flatbuffers.h` is included, as: + +```cpp + template struct custom_allocator : public std::allocator { + + typedef T *pointer; + + template + struct rebind { + typedef custom_allocator other; + }; + + pointer allocate(const std::size_t n) { + return std::allocator::allocate(n); + } + + void deallocate(T* ptr, std::size_t n) { + return std::allocator::deallocate(ptr,n); + } + + custom_allocator() throw() {} + + template + custom_allocator(const custom_allocator&) throw() {} + }; +``` + +- `native_type("type")` (on a struct): In some cases, a more optimal C++ data +type exists for a given struct. For example, the following schema: + +```cpp + struct Vec2 { + x: float; + y: float; + } +``` + +generates the following Object-Based API class: + +```cpp + struct Vec2T : flatbuffers::NativeTable { + float x; + float y; + }; +``` + +However, it can be useful to instead use a user-defined C++ type since it +can provide more functionality, eg. + +```cpp + struct vector2 { + float x = 0, y = 0; + vector2 operator+(vector2 rhs) const { ... } + vector2 operator-(vector2 rhs) const { ... } + float length() const { ... } + // etc. + }; +``` + +The `native_type` attribute will replace the usage of the generated class +with the given type. So, continuing with the example, the generated +code would use `vector2` in place of `Vec2T` for all generated code of +the Object-Based API. + +However, because the `native_type` is unknown to flatbuffers, the user must +provide the following functions to aide in the serialization process: + +```cpp + namespace flatbuffers { + Vec2 Pack(const vector2& obj); + vector2 UnPack(const Vec2& obj); + } +``` + +- `native_type_pack_name("name")` (on a struct when `native_type` is + specified, too): when you want to use the same `native_type` multiple times + (e. g. with different precision) you must make the names of the Pack/UnPack + functions unique, otherwise you will run into compile errors. This attribute + appends a name to the expected Pack/UnPack functions. So when you + specify `native_type_pack_name("Vec2")` in the above example you now need to + implement these serialization functions instead: + +```cpp + namespace flatbuffers { + Vec2 PackVec2(const vector2& obj); + vector2 UnPackVec2(const Vec2& obj); + } +``` + +Finally, the following top-level attributes: + +- `native_include("path")` (at file level): Because the `native_type` attribute + can be used to introduce types that are unknown to flatbuffers, it may be + necessary to include "external" header files in the generated code. This + attribute can be used to directly add an #include directive to the top of + the generated code that includes the specified path directly. + +- `force_align`: this attribute may not be respected in the object API, + depending on the aligned of the allocator used with `new`. + +## External references + +An additional feature of the object API is the ability to allow you to load +multiple independent FlatBuffers, and have them refer to eachothers objects +using hashes which are then represented as typed pointers in the object API. + +To make this work have a field in the objects you want to referred to which is +using the string hashing feature (see `hash` attribute in the +[schema](../schema.md) documentation). Then you have +a similar hash in the field referring to it, along with a `cpp_type` +attribute specifying the C++ type this will refer to (this can be any C++ +type, and will get a `*` added). + +Then, in JSON or however you create these buffers, make sure they use the +same string (or hash). + +When you call `UnPack` (or `Create`), you'll need a function that maps from +hash to the object (see `resolver_function_t` for details). + +## Using different pointer types + +By default the object tree is built out of `std::unique_ptr`, but you can +influence this either globally (using the `--cpp-ptr-type` argument to +`flatc`) or per field (using the `cpp_ptr_type` attribute) to by any smart +pointer type (`my_ptr`), or by specifying `naked` as the type to get `T *` +pointers. Unlike the smart pointers, naked pointers do not manage memory for +you, so you'll have to manage their lifecycles manually. To reference the +pointer type specified by the `--cpp-ptr-type` argument to `flatc` from a +flatbuffer field set the `cpp_ptr_type` attribute to `default_ptr_type`. + +## Using different string type + +By default the object tree is built out of `std::string`, but you can +influence this either globally (using the `--cpp-str-type` argument to +`flatc`) or per field using the `cpp_str_type` attribute. + +The type must support `T::c_str()`, `T::length()` and `T::empty()` as member functions. + +Further, the type must be constructible from std::string, as by default a +std::string instance is constructed and then used to initialize the custom +string type. This behavior impedes efficient and zero-copy construction of +custom string types; the `--cpp-str-flex-ctor` argument to `flatc` or the +per field attribute `cpp_str_flex_ctor` can be used to change this behavior, +so that the custom string type is constructed by passing the pointer and +length of the FlatBuffers String. The custom string class will require a +constructor in the following format: `custom_str_class(const char *, size_t)`. +Please note that the character array is not guaranteed to be NULL terminated, +you should always use the provided size to determine end of string. + +## Reflection (& Resizing) + +There is experimental support for reflection in FlatBuffers, allowing you to +read and write data even if you don't know the exact format of a buffer, and +even allows you to change sizes of strings and vectors in-place. + +The way this works is very elegant; there is actually a FlatBuffer schema that +describes schemas (\!) which you can find in `reflection/reflection.fbs`. +The compiler, `flatc`, can write out any schemas it has just parsed as a binary +FlatBuffer, corresponding to this meta-schema. + +Loading in one of these binary schemas at runtime allows you traverse any +FlatBuffer data that corresponds to it without knowing the exact format. You +can query what fields are present, and then read/write them after. + +For convenient field manipulation, you can include the header +`flatbuffers/reflection.h` which includes both the generated code from the meta +schema, as well as a lot of helper functions. + +And example of usage, for the time being, can be found in +`test.cpp/ReflectionTest()`. + +## Mini Reflection + +A more limited form of reflection is available for direct inclusion in +generated code, which doesn't do any (binary) schema access at all. It was designed +to keep the overhead of reflection as low as possible (on the order of 2-6 +bytes per field added to your executable), but doesn't contain all the +information the (binary) schema contains. + +You add this information to your generated code by specifying `--reflect-types` +(or instead `--reflect-names` if you also want field / enum names). + +You can now use this information, for example to print a FlatBuffer to text: + + auto s = flatbuffers::FlatBufferToString(flatbuf, MonsterTypeTable()); + +`MonsterTypeTable()` is declared in the generated code for each type. The +string produced is very similar to the JSON produced by the `Parser` based +text generator. + +You'll need `flatbuffers/minireflect.h` for this functionality. In there is also +a convenient visitor/iterator so you can write your own output / functionality +based on the mini reflection tables without having to know the FlatBuffers or +reflection encoding. + +## Storing maps / dictionaries in a FlatBuffer + +FlatBuffers doesn't support maps natively, but there is support to +emulate their behavior with vectors and binary search, which means you +can have fast lookups directly from a FlatBuffer without having to unpack +your data into a `std::map` or similar. + +To use it: +- Designate one of the fields in a table as they "key" field. You do this + by setting the `key` attribute on this field, e.g. + `name:string (key)`. + You may only have one key field, and it must be of string or scalar type. +- Write out tables of this type as usual, collect their offsets in an + array or vector. +- Instead of `CreateVector`, call `CreateVectorOfSortedTables`, + which will first sort all offsets such that the tables they refer to + are sorted by the key field, then serialize it. +- Now when you're accessing the FlatBuffer, you can use `Vector::LookupByKey` + instead of just `Vector::Get` to access elements of the vector, e.g.: + `myvector->LookupByKey("Fred")`, which returns a pointer to the + corresponding table type, or `nullptr` if not found. + `LookupByKey` performs a binary search, so should have a similar speed to + `std::map`, though may be faster because of better caching. `LookupByKey` + only works if the vector has been sorted, it will likely not find elements + if it hasn't been sorted. + +## Direct memory access + +As you can see from the above examples, all elements in a buffer are +accessed through generated accessors. This is because everything is +stored in little endian format on all platforms (the accessor +performs a swap operation on big endian machines), and also because +the layout of things is generally not known to the user. + +For structs, layout is deterministic and guaranteed to be the same +across platforms (scalars are aligned to their +own size, and structs themselves to their largest member), and you +are allowed to access this memory directly by using `sizeof()` and +`memcpy` on the pointer to a struct, or even an array of structs. + +To compute offsets to sub-elements of a struct, make sure they +are a structs themselves, as then you can use the pointers to +figure out the offset without having to hardcode it. This is +handy for use of arrays of structs with calls like `glVertexAttribPointer` +in OpenGL or similar APIs. + +It is important to note is that structs are still little endian on all +machines, so only use tricks like this if you can guarantee you're not +shipping on a big endian machine (an `assert(FLATBUFFERS_LITTLEENDIAN)` +would be wise). + +## Access of untrusted buffers + +The generated accessor functions access fields over offsets, which is +very quick. These offsets are not verified at run-time, so a malformed +buffer could cause a program to crash by accessing random memory. + +When you're processing large amounts of data from a source you know (e.g. +your own generated data on disk), this is acceptable, but when reading +data from the network that can potentially have been modified by an +attacker, this is undesirable. + +For this reason, you can optionally use a buffer verifier before you +access the data. This verifier will check all offsets, all sizes of +fields, and null termination of strings to ensure that when a buffer +is accessed, all reads will end up inside the buffer. + +Each root type will have a verification function generated for it, +e.g. for `Monster`, you can call: + +```cpp + Verifier verifier(buf, len); + bool ok = VerifyMonsterBuffer(verifier); +``` + +if `ok` is true, the buffer is safe to read. + +Besides untrusted data, this function may be useful to call in debug +mode, as extra insurance against data being corrupted somewhere along +the way. + +While verifying a buffer isn't "free", it is typically faster than +a full traversal (since any scalar data is not actually touched), +and since it may cause the buffer to be brought into cache before +reading, the actual overhead may be even lower than expected. + +In specialized cases where a denial of service attack is possible, +the verifier has two additional constructor arguments that allow +you to limit the nesting depth and total amount of tables the +verifier may encounter before declaring the buffer malformed. The default is +`Verifier(buf, len, 64 /* max depth */, 1000000, /* max tables */)` which +should be sufficient for most uses. + +## Text & schema parsing + +Using binary buffers with the generated header provides a super low +overhead use of FlatBuffer data. There are, however, times when you want +to use text formats, for example because it interacts better with source +control, or you want to give your users easy access to data. + +Another reason might be that you already have a lot of data in JSON +format, or a tool that generates JSON, and if you can write a schema for +it, this will provide you an easy way to use that data directly. + +(see the schema documentation for some specifics on the JSON format +accepted). + +Schema evolution compatibility for the JSON format follows the same rules as the binary format (JSON formatted data will be forwards/backwards compatible with schemas that evolve in a compatible way). + +There are two ways to use text formats: + +#### Using the compiler as a conversion tool + +This is the preferred path, as it doesn't require you to add any new +code to your program, and is maximally efficient since you can ship with +binary data. The disadvantage is that it is an extra step for your +users/developers to perform, though you might be able to automate it. + + flatc -b myschema.fbs mydata.json + +This will generate the binary file `mydata_wire.bin` which can be loaded +as before. + +#### Making your program capable of loading text directly + +This gives you maximum flexibility. You could even opt to support both, +i.e. check for both files, and regenerate the binary from text when +required, otherwise just load the binary. + +This option is currently only available for C++, or Java through JNI. + +As mentioned in the section "Building" above, this technique requires +you to link a few more files into your program, and you'll want to include +`flatbuffers/idl.h`. + +Load text (either a schema or json) into an in-memory buffer (there is a +convenient `LoadFile()` utility function in `flatbuffers/util.h` if you +wish). Construct a parser: + +```cpp + flatbuffers::Parser parser; +``` + +Now you can parse any number of text files in sequence: + +```cpp + parser.Parse(text_file.c_str()); +``` + +This works similarly to how the command-line compiler works: a sequence +of files parsed by the same `Parser` object allow later files to +reference definitions in earlier files. Typically this means you first +load a schema file (which populates `Parser` with definitions), followed +by one or more JSON files. + +As optional argument to `Parse`, you may specify a null-terminated list of +include paths. If not specified, any include statements try to resolve from +the current directory. + +If there were any parsing errors, `Parse` will return `false`, and +`Parser::error_` contains a human readable error string with a line number +etc, which you should present to the creator of that file. + +After each JSON file, the `Parser::fbb` member variable is the +`FlatBufferBuilder` that contains the binary buffer version of that +file, that you can access as described above. + +`samples/sample_text.cpp` is a code sample showing the above operations. + +## Threading + +Reading a FlatBuffer does not touch any memory outside the original buffer, +and is entirely read-only (all const), so is safe to access from multiple +threads even without synchronisation primitives. + +Creating a FlatBuffer is not thread safe. All state related to building +a FlatBuffer is contained in a FlatBufferBuilder instance, and no memory +outside of it is touched. To make this thread safe, either do not +share instances of FlatBufferBuilder between threads (recommended), or +manually wrap it in synchronisation primitives. There's no automatic way to +accomplish this, by design, as we feel multithreaded construction +of a single buffer will be rare, and synchronisation overhead would be costly. + +## Advanced union features + +The C++ implementation currently supports vectors of unions (i.e. you can +declare a field as `[T]` where `T` is a union type instead of a table type). It +also supports structs and strings in unions, besides tables. + +For an example of these features, see `tests/union_vector`, and +`UnionVectorTest` in `test.cpp`. + +Since these features haven't been ported to other languages yet, if you +choose to use them, you won't be able to use these buffers in other languages +(`flatc` will refuse to compile a schema that uses these features). + +These features reduce the amount of "table wrapping" that was previously +needed to use unions. + +To use scalars, simply wrap them in a struct. + +## Depth limit of nested objects and stack-overflow control +The parser of Flatbuffers schema or json-files is kind of recursive parser. +To avoid stack-overflow problem the parser has a built-in limiter of +recursion depth. Number of nested declarations in a schema or number of +nested json-objects is limited. By default, this depth limit set to `64`. +It is possible to override this limit with `FLATBUFFERS_MAX_PARSING_DEPTH` +definition. This definition can be helpful for testing purposes or embedded +applications. For details see [build](../building.md) of +CMake-based projects. + +## Dependence from C-locale {#flatbuffers_locale_cpp} +The Flatbuffers [grammar](../grammar.md) uses ASCII +character set for identifiers, alphanumeric literals, reserved words. + +Internal implementation of the Flatbuffers depends from functions which +depend from C-locale: `strtod()` or `strtof()`, for example. +The library expects the dot `.` symbol as the separator of an integer +part from the fractional part of a float number. +Another separator symbols (`,` for example) will break the compatibility +and may lead to an error while parsing a Flatbuffers schema or a json file. + +The Standard C locale is a global resource, there is only one locale for +the entire application. Some modern compilers and platforms have +locale-independent or locale-narrow functions `strtof_l`, `strtod_l`, +`strtoll_l`, `strtoull_l` to resolve this dependency. +These functions use specified locale rather than the global or per-thread +locale instead. They are part of POSIX-2008 but not part of the C/C++ +standard library, therefore, may be missing on some platforms. +The Flatbuffers library try to detect these functions at configuration and +compile time: +- CMake `"CMakeLists.txt"`: + - Check existence of `strtol_l` and `strtod_l` in the ``. +- Compile-time `"/include/base.h"`: + - `_MSC_VER >= 1900`: MSVC2012 or higher if build with MSVC. + - `_XOPEN_SOURCE>=700`: POSIX-2008 if build with GCC/Clang. + +After detection, the definition `FLATBUFFERS_LOCALE_INDEPENDENT` will be +set to `0` or `1`. +To override or stop this detection use CMake `-DFLATBUFFERS_LOCALE_INDEPENDENT={0|1}` +or predefine `FLATBUFFERS_LOCALE_INDEPENDENT` symbol. + +To test the compatibility of the Flatbuffers library with +a specific locale use the environment variable `FLATBUFFERS_TEST_LOCALE`: +```sh +>FLATBUFFERS_TEST_LOCALE="" ./flattests +>FLATBUFFERS_TEST_LOCALE="ru_RU.CP1251" ./flattests +``` + +## Support of floating-point numbers +The Flatbuffers library assumes that a C++ compiler and a CPU are +compatible with the `IEEE-754` floating-point standard. +The schema and json parser may fail if `fast-math` or `/fp:fast` mode is active. + +### Support of hexadecimal and special floating-point numbers +According to the [grammar](../grammar.md) `fbs` and `json` files +may use hexadecimal and special (`NaN`, `Inf`) floating-point literals. +The Flatbuffers uses `strtof` and `strtod` functions to parse floating-point +literals. The Flatbuffers library has a code to detect a compiler compatibility +with the literals. If necessary conditions are met the preprocessor constant +`FLATBUFFERS_HAS_NEW_STRTOD` will be set to `1`. +The support of floating-point literals will be limited at compile time +if `FLATBUFFERS_HAS_NEW_STRTOD` constant is less than `1`. +In this case, schemas with hexadecimal or special literals cannot be used. + +### Comparison of floating-point NaN values +The floating-point `NaN` (`not a number`) is special value which +representing an undefined or unrepresentable value. +`NaN` may be explicitly assigned to variables, typically as a representation +for missing values or may be a result of a mathematical operation. +The `IEEE-754` defines two kind of `NaNs`: +- Quiet NaNs, or `qNaNs`. +- Signaling NaNs, or `sNaNs`. + +According to the `IEEE-754`, a comparison with `NaN` always returns +an unordered result even when compared with itself. As a result, a whole +Flatbuffers object will be not equal to itself if has one or more `NaN`. +Flatbuffers scalar fields that have the default value are not actually stored +in the serialized data but are generated in code (see [Writing a schema](../schema.md)). +Scalar fields with `NaN` defaults break this behavior. +If a schema has a lot of `NaN` defaults the Flatbuffers can override +the unordered comparison by the ordered: `(NaN==NaN)->true`. +This ordered comparison is enabled when compiling a program with the symbol +`FLATBUFFERS_NAN_DEFAULTS` defined. +Additional computations added by `FLATBUFFERS_NAN_DEFAULTS` are very cheap +if GCC or Clang used. These compilers have a compile-time implementation +of `isnan` checking which MSVC does not. + +## gRPC + +### Before you get started + +Before diving into the FlatBuffers gRPC usage in C++, you should already be +familiar with the following: + +- FlatBuffers as a serialization format +- [gRPC](http://www.grpc.io/docs/) usage + +### Using the FlatBuffers gRPC C++ library + +NOTE: The examples below are also in the `grpc/samples/greeter` directory. + +We will illustrate usage with the following schema: + +```c++ title="grpc/samples/greeter/greeter.fbs" +--8<-- "https://raw.githubusercontent.com/google/flatbuffers/refs/heads/master/grpc/samples/greeter/greeter.fbs" +``` + +When we run `flatc`, we pass in the `--grpc` option and generage an additional +`greeter.grpc.fb.h` and `greeter.grpc.fb.cc`. + +Example server code looks like this: + +```c++ title="grpc/samples/greeter/server.cpp" +--8<-- "https://raw.githubusercontent.com/google/flatbuffers/refs/heads/master/grpc/samples/greeter/server.cpp" +``` + +Example client code looks like this: + +```c++ title="grpc/samples/greeter/client.cpp" +--8<-- "https://raw.githubusercontent.com/google/flatbuffers/refs/heads/master/grpc/samples/greeter/client.cpp" +``` + diff --git a/third_party/flatbuffers/docs/source/languages/dart.md b/third_party/flatbuffers/docs/source/languages/dart.md new file mode 100644 index 00000000000..ca370c71f3d --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/dart.md @@ -0,0 +1,131 @@ +Use in Dart {#flatbuffers_guide_use_dart} +=========== + +## Before you get started + +Before diving into the FlatBuffers usage in Dart, it should be noted that +the [Tutorial](../tutorial.md) page has a complete guide +to general FlatBuffers usage in all of the supported languages (including Dart). +This page is designed to cover the nuances of FlatBuffers usage, specific to +Dart. + +You should also have read the [Building](../building.md) +documentation to build `flatc` and should be familiar with +[Using the schema compiler](../flatc.md) and +[Writing a schema](../schema.md). + +## FlatBuffers Dart library code location + +The code for the FlatBuffers Dart library can be found at +`flatbuffers/dart`. You can browse the library code on the [FlatBuffers +GitHub page](https://github.com/google/flatbuffers/tree/master/dart). + +## Testing the FlatBuffers Dart library + +The code to test the Dart library can be found at `flatbuffers/tests`. +The test code itself is located in [dart_test.dart](https://github.com/google/ +flatbuffers/blob/master/tests/dart_test.dart). + +To run the tests, use the [DartTest.sh](https://github.com/google/flatbuffers/ +blob/master/tests/DartTest.sh) shell script. + +*Note: The shell script requires the [Dart SDK](https://www.dartlang.org/tools/sdk) +to be installed.* + +## Using the FlatBuffers Dart library + +*Note: See [Tutorial](../tutorial.md) for a more in-depth +example of how to use FlatBuffers in Dart.* + +FlatBuffers supports reading and writing binary FlatBuffers in Dart. + +To use FlatBuffers in your own code, first generate Dart classes from your +schema with the `--dart` option to `flatc`. Then you can include both FlatBuffers +and the generated code to read or write a FlatBuffer. + +For example, here is how you would read a FlatBuffer binary file in Dart: First, +include the library and generated code. Then read a FlatBuffer binary file into +a `List`, which you pass to the factory constructor for `Monster`: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.dart} +import 'dart:io' as io; + +import 'package:flat_buffers/flat_buffers.dart' as fb; +import './monster_my_game.sample_generated.dart' as myGame; + +List data = await new io.File('monster.dat').readAsBytes(); +var monster = new myGame.Monster(data); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now you can access values like this: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.dart} +var hp = monster.hp; +var pos = monster.pos; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Differences from the Dart SDK Front End flat_buffers + +The work in this repository is signfiicantly based on the implementation used +internally by the Dart SDK in the front end/analyzer package. Several +significant changes have been made. + +1. Support for packed boolean lists has been removed. This is not standard + in other implementations and is not compatible with them. Do note that, + like in the JavaScript implementation, __null values in boolean lists + will be treated as false__. It is also still entirely possible to pack data + in a single scalar field, but that would have to be done on the application + side. +2. The SDK implementation supports enums with regular Dart enums, which + works if enums are always indexed at 1; however, FlatBuffers does not + require that. This implementation uses specialized enum-like classes to + ensure proper mapping from FlatBuffers to Dart and other platforms. +3. The SDK implementation does not appear to support FlatBuffer structs or + vectors of structs - it treated everything as a built-in scalar or a table. + This implementation treats structs in a way that is compatible with other + non-Dart implementations, and properly handles vectors of structs. Many of + the methods prefixed with 'low' have been prepurposed to support this. +4. The SDK implementation treats int64 and uint64 as float64s. This + implementation does not. This may cause problems with JavaScript + compatibility - however, it should be possible to use the JavaScript + implementation, or to do a customized implementation that treats all 64 bit + numbers as floats. Supporting the Dart VM and Flutter was a more important + goal of this implementation. Support for 16 bit integers was also added. +5. The code generation in this offers an "ObjectBuilder", which generates code + very similar to the SDK classes that consume FlatBuffers, as well as Builder + classes, which produces code which more closely resembles the builders in + other languages. The ObjectBuilder classes are easier to use, at the cost of + additional references allocated. + +## Text Parsing + +There currently is no support for parsing text (Schema's and JSON) directly +from Dart, though you could use the C++ parser through Dart Native Extensions. +Please see the C++ documentation for more on text parsing (note that this is +not currently an option in Flutter - follow [this issue](https://github.com/flutter/flutter/issues/7053) +for the latest). + +## Object based API + +FlatBuffers is all about memory efficiency, which is why its base API is written +around using as little as possible of it. This does make the API clumsier +(requiring pre-order construction of all data, and making mutation harder). + +For times when efficiency is less important a more convenient object based API +can be used (through `--gen-object-api`) that is able to unpack & pack a FlatBuffer +into objects and lists, allowing for convenient construction, access and mutation. + +To use: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.dart} + // Deserialize from buffer into object. + MonsterT monster = Monster(flatbuffer).unpack(); + + // Update object directly like a Dart class instance. + print(monster.Name); + monster.Name = "Bob"; // Change the name. + + // Serialize into new flatbuffer. + final fbb = Builder(); + fbb.Finish(monster.pack(fbb)); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/third_party/flatbuffers/docs/source/languages/go.md b/third_party/flatbuffers/docs/source/languages/go.md new file mode 100644 index 00000000000..75ee79dfee1 --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/go.md @@ -0,0 +1,99 @@ +Use in Go {#flatbuffers_guide_use_go} +========= + +## Before you get started + +Before diving into the FlatBuffers usage in Go, it should be noted that +the [Tutorial](../tutorial.md) page has a complete guide +to general FlatBuffers usage in all of the supported languages (including Go). +This page is designed to cover the nuances of FlatBuffers usage, specific to +Go. + +You should also have read the [Building](../building.md) +documentation to build `flatc` and should be familiar with +[Using the schema compiler](../flatc.md) and +[Writing a schema](../schema.md). + +## FlatBuffers Go library code location + +The code for the FlatBuffers Go library can be found at +`flatbuffers/go`. You can browse the library code on the [FlatBuffers +GitHub page](https://github.com/google/flatbuffers/tree/master/go). + +## Testing the FlatBuffers Go library + +The code to test the Go library can be found at `flatbuffers/tests`. +The test code itself is located in [go_test.go](https://github.com/google/ +flatbuffers/blob/master/tests/go_test.go). + +To run the tests, use the [GoTest.sh](https://github.com/google/flatbuffers/ +blob/master/tests/GoTest.sh) shell script. + +*Note: The shell script requires [Go](https://golang.org/doc/install) to +be installed.* + +## Using the FlatBuffers Go library + +*Note: See [Tutorial](../tutorial.md) for a more in-depth +example of how to use FlatBuffers in Go.* + +FlatBuffers supports reading and writing binary FlatBuffers in Go. + +To use FlatBuffers in your own code, first generate Go classes from your +schema with the `--go` option to `flatc`. Then you can include both FlatBuffers +and the generated code to read or write a FlatBuffer. + +For example, here is how you would read a FlatBuffer binary file in Go: First, +include the library and generated code. Then read a FlatBuffer binary file into +a `[]byte`, which you pass to the `GetRootAsMonster` function: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go} + import ( + example "MyGame/Example" + flatbuffers "github.com/google/flatbuffers/go" + + "os" + ) + + buf, err := os.ReadFile("monster.dat") + // handle err + monster := example.GetRootAsMonster(buf, 0) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now you can access values like this: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go} + hp := monster.Hp() + pos := monster.Pos(nil) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +In some cases it's necessary to modify values in an existing FlatBuffer in place (without creating a copy). For this reason, scalar fields of a Flatbuffer table or struct can be mutated. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go} + monster := example.GetRootAsMonster(buf, 0) + + // Set table field. + if ok := monster.MutateHp(10); !ok { + panic("failed to mutate Hp") + } + + // Set struct field. + monster.Pos().MutateZ(4) + + // This mutation will fail because the mana field is not available in + // the buffer. It should be set when creating the buffer. + if ok := monster.MutateMana(20); !ok { + panic("failed to mutate Hp") + } +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The term `mutate` is used instead of `set` to indicate that this is a special use case. All mutate functions return a boolean value which is false if the field we're trying to mutate is not available in the buffer. + +## Text Parsing + +There currently is no support for parsing text (Schema's and JSON) directly +from Go, though you could use the C++ parser through cgo. Please see the +C++ documentation for more on text parsing. + +
diff --git a/third_party/flatbuffers/docs/source/languages/java.md b/third_party/flatbuffers/docs/source/languages/java.md new file mode 100644 index 00000000000..bfbd3e41cc7 --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/java.md @@ -0,0 +1,114 @@ +Use in Java {#flatbuffers_guide_use_java} +============== + +## Before you get started + +Before diving into the FlatBuffers usage in Java, it should be noted that +the [Tutorial](../tutorial.md) page has a complete guide to +general FlatBuffers usage in all of the supported languages (including Java). +This page is designed to cover the nuances of FlatBuffers usage, +specific to Java. + +You should also have read the [Building](../building.md) +documentation to build `flatc` and should be familiar with +[Using the schema compiler](../flatc.md) and +[Writing a schema](../schema.md). + +## FlatBuffers Java code location + +The code for the FlatBuffers Java library can be found at +`flatbuffers/java/com/google/flatbuffers`. You can browse the library on the +[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/ +java/com/google/flatbuffers). + +## Testing the FlatBuffers Java libraries + +The code to test the libraries can be found at `flatbuffers/tests`. + +The test code for Java is located in [JavaTest.java](https://github.com/google +/flatbuffers/blob/master/tests/JavaTest.java). + +To run the tests, use either [JavaTest.sh](https://github.com/google/ +flatbuffers/blob/master/tests/JavaTest.sh) or [JavaTest.bat](https://github.com/ +google/flatbuffers/blob/master/tests/JavaTest.bat), depending on your operating +system. + +*Note: These scripts require that [Java](https://www.oracle.com/java/index.html) +is installed.* + +## Using the FlatBuffers Java library + +*Note: See [Tutorial](../tutorial.md) for a more in-depth +example of how to use FlatBuffers in Java.* + +FlatBuffers supports reading and writing binary FlatBuffers in Java. + +To use FlatBuffers in your own code, first generate Java classes from your +schema with the `--java` option to `flatc`. +Then you can include both FlatBuffers and the generated code to read +or write a FlatBuffer. + +For example, here is how you would read a FlatBuffer binary file in Java: +First, import the library and generated code. Then, you read a FlatBuffer binary +file into a `byte[]`. You then turn the `byte[]` into a `ByteBuffer`, which you +pass to the `getRootAsMyRootType` function: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java} + import MyGame.Example.*; + import com.google.flatbuffers.FlatBufferBuilder; + + // This snippet ignores exceptions for brevity. + File file = new File("monsterdata_test.mon"); + RandomAccessFile f = new RandomAccessFile(file, "r"); + byte[] data = new byte[(int)f.length()]; + f.readFully(data); + f.close(); + + ByteBuffer bb = ByteBuffer.wrap(data); + Monster monster = Monster.getRootAsMonster(bb); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now you can access the data from the `Monster monster`: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java} + short hp = monster.hp(); + Vec3 pos = monster.pos(); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Storing dictionaries in a FlatBuffer + +FlatBuffers doesn't support dictionaries natively, but there is support to +emulate their behavior with vectors and binary search, which means you +can have fast lookups directly from a FlatBuffer without having to unpack +your data into a `Dictionary` or similar. + +To use it: +- Designate one of the fields in a table as the "key" field. You do this + by setting the `key` attribute on this field, e.g. + `name:string (key)`. + You may only have one key field, and it must be of string or scalar type. +- Write out tables of this type as usual, collect their offsets in an + array. +- Instead of calling standard generated method, + e.g.: `Monster.createTestarrayoftablesVector`, + call `createSortedVectorOfTables` (from the `FlatBufferBuilder` object). + which will first sort all offsets such that the tables they refer to + are sorted by the key field, then serialize it. +- Now when you're accessing the FlatBuffer, you can use + the `ByKey` accessor to access elements of the vector, e.g.: + `monster.testarrayoftablesByKey("Frodo")`. + which returns an object of the corresponding table type, + or `null` if not found. + `ByKey` performs a binary search, so should have a similar + speed to `Dictionary`, though may be faster because of better caching. + `ByKey` only works if the vector has been sorted, it will + likely not find elements if it hasn't been sorted. + +## Text parsing + +There currently is no support for parsing text (Schema's and JSON) directly +from Java, though you could use the C++ parser through native call +interfaces available to each language. Please see the +C++ documentation for more on text parsing. + +
diff --git a/third_party/flatbuffers/docs/source/languages/javascript.md b/third_party/flatbuffers/docs/source/languages/javascript.md new file mode 100644 index 00000000000..d75442d23b3 --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/javascript.md @@ -0,0 +1,93 @@ +Use in JavaScript {#flatbuffers_guide_use_javascript} +================= + +## Before you get started + +Before diving into the FlatBuffers usage in JavaScript, it should be noted that +the [Tutorial](../tutorial.md) page has a complete guide to +general FlatBuffers usage in all of the supported languages +(including JavaScript). This page is specifically designed to cover the nuances +of FlatBuffers usage in JavaScript. + +You should also have read the [Building](../building.md) +documentation to build `flatc` and should be familiar with +[Using the schema compiler](../flatc.md) and +[Writing a schema](../schema.md). + +## FlatBuffers JavaScript library code location + +The generated code for the FlatBuffers JavaScript library can be found at +https://www.npmjs.com/package/flatbuffers. To use it from sources: + +1. Run `npm run compile` from the main folder to generate JS files from TS. +1. In your project, install it as a normal dependency, using the flatbuffers +folder as the source. + +## Using the FlatBuffers JavaScript library + +*Note: See [Tutorial](../tutorial.md) for a more in-depth +example of how to use FlatBuffers.* + +Due to the complexity related with large amounts of JS flavors and module types, +native JS support has been replaced in 2.0 by transpilation from TypeScript. + +Please look at [TypeScript usage](typescript.md) and +transpile your sources to desired JS flavor. The minimal steps to get up and +running with JS are: + +1. Generate TS files from `*.fbs` by using the `--ts` option. +1. Transpile resulting TS files to desired JS flavor using `tsc` (see + https://www.typescriptlang.org/download for installation instructions). + +~~~{.js} + // Note: These require functions are an example - use your desired module flavor. + var fs = require('fs'); + + var flatbuffers = require('../flatbuffers').flatbuffers; + var MyGame = require('./monster_generated').MyGame; + + var data = new Uint8Array(fs.readFileSync('monster.dat')); + var buf = new flatbuffers.ByteBuffer(data); + + var monster = MyGame.Example.Monster.getRootAsMonster(buf); + + //--------------------------------------------------------------------------// + + // Note: This code is an example of browser-based HTML/JavaScript. See above + // for the code using JavaScript module loaders (e.g. Node.js). + + + + + // Open the HTML file in a browser and select "monster.dat" from with the + // field. + +~~~ + +Now you can access values like this: + +~~~{.js} + var hp = monster.hp(); + var pos = monster.pos(); +~~~ + +## Text parsing FlatBuffers in JavaScript + +There currently is no support for parsing text (Schema's and JSON) directly +from JavaScript. diff --git a/third_party/flatbuffers/docs/source/languages/kotlin.md b/third_party/flatbuffers/docs/source/languages/kotlin.md new file mode 100644 index 00000000000..43e7eaa0ec6 --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/kotlin.md @@ -0,0 +1,84 @@ +Use in Kotlin {#flatbuffers_guide_use_kotlin} +============== + +## Before you get started + +Before diving into the FlatBuffers usage in Kotlin, it should be noted that +the [Tutorial](../tutorial.md) page has a complete guide to +general FlatBuffers usage in all of the supported languages (including K). + +This page is designed to cover the nuances of FlatBuffers usage, specific to Kotlin. + +You should also have read the [Building](../building.md) +documentation to build `flatc` and should be familiar with +[Using the schema compiler](../flatc.md) and +[Writing a schema](../schema.md). + +## Kotlin and FlatBuffers Java code location + +Code generated for Kotlin currently uses the flatbuffers java runtime library. That means that Kotlin generated code can only have Java virtual machine as target architecture (which includes Android). Kotlin Native and Kotlin.js are currently not supported. + +The code for the FlatBuffers Java library can be found at +`flatbuffers/java/com/google/flatbuffers`. You can browse the library on the +[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/ +java/com/google/flatbuffers). + +## Testing FlatBuffers Kotlin + +The test code for Java is located in [KotlinTest.java](https://github.com/google +/flatbuffers/blob/master/tests/KotlinTest.kt). + +To run the tests, use [KotlinTest.sh](https://github.com/google/ +flatbuffers/blob/master/tests/KotlinTest.sh) shell script. + +*Note: These scripts require that [Kotlin](https://kotlinlang.org/) is installed.* + +## Using the FlatBuffers Kotlin library + +*Note: See [Tutorial](../tutorial.md) for a more in-depth +example of how to use FlatBuffers in Kotlin.* + +FlatBuffers supports reading and writing binary FlatBuffers in Kotlin. + +To use FlatBuffers in your own code, first generate Java classes from your +schema with the `--kotlin` option to `flatc`. +Then you can include both FlatBuffers and the generated code to read +or write a FlatBuffer. + +For example, here is how you would read a FlatBuffer binary file in Kotlin: +First, import the library and generated code. Then, you read a FlatBuffer binary +file into a `ByteArray`. You then turn the `ByteArray` into a `ByteBuffer`, which you +pass to the `getRootAsMyRootType` function: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.kt} + import MyGame.Example.* + import com.google.flatbuffers.FlatBufferBuilder + + // This snippet ignores exceptions for brevity. + val data = RandomAccessFile(File("monsterdata_test.mon"), "r").use { + val temp = ByteArray(it.length().toInt()) + it.readFully(temp) + temp + } + + val bb = ByteBuffer.wrap(data) + val monster = Monster.getRootAsMonster(bb) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now you can access the data from the `Monster monster`: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.kt} + val hp = monster.hp + val pos = monster.pos!!; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +## Differences between Kotlin and Java code + +Kotlin generated code was designed to be as close as possible to the java counterpart, as for now, we only support kotlin on java virtual machine. So the differences in implementation and usage are basically the ones introduced by the Kotlin language itself. You can find more in-depth information [here](https://kotlinlang.org/docs/reference/comparison-to-java.html). + +The most obvious ones are: + +* Fields as accessed as Kotlin [properties](https://kotlinlang.org/docs/reference/properties.html) +* Static methods are accessed in [companion object](https://kotlinlang.org/docs/reference/classes.html#companion-objects) \ No newline at end of file diff --git a/third_party/flatbuffers/docs/source/languages/lobster.md b/third_party/flatbuffers/docs/source/languages/lobster.md new file mode 100644 index 00000000000..109341f7154 --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/lobster.md @@ -0,0 +1,85 @@ +Use in Lobster {#flatbuffers_guide_use_lobster} +============== + +## Before you get started + +Before diving into the FlatBuffers usage in Lobster, it should be noted that the +[Tutorial](../tutorial.md) page has a complete guide to general +FlatBuffers usage in all of the supported languages (including Lobster). This +page is designed to cover the nuances of FlatBuffers usage, specific to +Lobster. + +You should also have read the [Building](../building.md) +documentation to build `flatc` and should be familiar with +[Using the schema compiler](../flatc.md) and +[Writing a schema](../schema.md). + +## FlatBuffers Lobster library code location + +The code for the FlatBuffers Lobster library can be found at +`flatbuffers/lobster`. You can browse the library code on the +[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/ +lobster). + +## Testing the FlatBuffers Lobster library + +The code to test the Lobster library can be found at `flatbuffers/tests`. +The test code itself is located in [lobstertest.lobster](https://github.com/google/ +flatbuffers/blob/master/tests/lobstertest.lobster). + +To run the tests, run `lobster lobstertest.lobster`. To obtain Lobster itself, +go to the [Lobster homepage](http://strlen.com/lobster) or +[github](https://github.com/aardappel/lobster) to learn how to build it for your +platform. + +## Using the FlatBuffers Lobster library + +*Note: See [Tutorial](../tutorial.md) for a more in-depth +example of how to use FlatBuffers in Lobster.* + +There is support for both reading and writing FlatBuffers in Lobster. + +To use FlatBuffers in your own code, first generate Lobster classes from your +schema with the `--lobster` option to `flatc`. Then you can include both +FlatBuffers and the generated code to read or write a FlatBuffer. + +For example, here is how you would read a FlatBuffer binary file in Lobster: +First, import the library and the generated code. Then read a FlatBuffer binary +file into a string, which you pass to the `GetRootAsMonster` function: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lobster} + include "monster_generated.lobster" + + let fb = read_file("monsterdata_test.mon") + assert fb + let monster = MyGame_Example_GetRootAsMonster(fb) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now you can access values like this: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lobster} + let hp = monster.hp + let pos = monster.pos +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As you can see, even though `hp` and `pos` are functions that access FlatBuffer +data in-place in the string buffer, they appear as field accesses. + +## Speed + +Using FlatBuffers in Lobster should be relatively fast, as the implementation +makes use of native support for writing binary values, and access of vtables. +Both generated code and the runtime library are therefore small and fast. + +Actual speed will depend on whether you use Lobster as bytecode VM or compiled to +C++. + +## Text Parsing + +Lobster has full support for parsing JSON into FlatBuffers, or generating +JSON from FlatBuffers. See `samples/sample_test.lobster` for an example. + +This uses the C++ parser and generator underneath, so should be both fast and +conformant. + +
diff --git a/third_party/flatbuffers/docs/source/languages/lua.md b/third_party/flatbuffers/docs/source/languages/lua.md new file mode 100644 index 00000000000..6843d468f82 --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/lua.md @@ -0,0 +1,81 @@ +Use in Lua {#flatbuffers_guide_use_lua} +============= + +## Before you get started + +Before diving into the FlatBuffers usage in Lua, it should be noted that the +[Tutorial](../tutorial.md) page has a complete guide to general +FlatBuffers usage in all of the supported languages (including Lua). This +page is designed to cover the nuances of FlatBuffers usage, specific to +Lua. + +You should also have read the [Building](../building.md) +documentation to build `flatc` and should be familiar with +[Using the schema compiler](../flatc.md) and +[Writing a schema](../schema.md). + +## FlatBuffers Lua library code location + +The code for the FlatBuffers Lua library can be found at +`flatbuffers/lua`. You can browse the library code on the +[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/lua). + +## Testing the FlatBuffers Lua library + +The code to test the Lua library can be found at `flatbuffers/tests`. +The test code itself is located in [luatest.lua](https://github.com/google/ +flatbuffers/blob/master/tests/luatest.lua). + +To run the tests, use the [LuaTest.sh](https://github.com/google/flatbuffers/ +blob/master/tests/LuaTest.sh) shell script. + +*Note: This script requires [Lua 5.3](https://www.lua.org/) and +[LuaJIT](http://luajit.org/) to be installed.* + +## Using the FlatBuffers Lua library + +*Note: See [Tutorial](../tutorial.md) for a more in-depth +example of how to use FlatBuffers in Lua.* + +There is support for both reading and writing FlatBuffers in Lua. + +To use FlatBuffers in your own code, first generate Lua classes from your +schema with the `--lua` option to `flatc`. Then you can include both +FlatBuffers and the generated code to read or write a FlatBuffer. + +For example, here is how you would read a FlatBuffer binary file in Lua: +First, require the module and the generated code. Then read a FlatBuffer binary +file into a `string`, which you pass to the `GetRootAsMonster` function: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lua} + -- require the library + local flatbuffers = require("flatbuffers") + + -- require the generated code + local monster = require("MyGame.Sample.Monster") + + -- read the flatbuffer from a file into a string + local f = io.open('monster.dat', 'rb') + local buf = f:read('*a') + f:close() + + -- parse the flatbuffer to get an instance to the root monster + local monster1 = monster.GetRootAsMonster(buf, 0) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now you can access values like this: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lua} + -- use the : notation to access member data + local hp = monster1:Hp() + local pos = monster1:Pos() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +## Text Parsing + +There currently is no support for parsing text (Schema's and JSON) directly +from Lua, though you could use the C++ parser through SWIG or ctypes. Please +see the C++ documentation for more on text parsing. + +
diff --git a/third_party/flatbuffers/docs/source/languages/php.md b/third_party/flatbuffers/docs/source/languages/php.md new file mode 100644 index 00000000000..e4391e03a54 --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/php.md @@ -0,0 +1,89 @@ +Use in PHP {#flatbuffers_guide_use_php} +========== + +## Before you get started + +Before diving into the FlatBuffers usage in PHP, it should be noted that +the [Tutorial](../tutorial.md) page has a complete guide to +general FlatBuffers usage in all of the supported languages +(including PHP). This page is specifically designed to cover the nuances of +FlatBuffers usage in PHP. + +You should also have read the [Building](../building.md) +documentation to build `flatc` and should be familiar with +[Using the schema compiler](../flatc.md) and +[Writing a schema](../schema.md). + +## FlatBuffers PHP library code location + +The code for FlatBuffers PHP library can be found at `flatbuffers/php`. You +can browse the library code on the [FlatBuffers +GitHub page](https://github.com/google/flatbuffers/tree/master/php). + +## Testing the FlatBuffers JavaScript library + +The code to test the PHP library can be found at `flatbuffers/tests`. +The test code itself is located in [phpTest.php](https://github.com/google/ +flatbuffers/blob/master/tests/phpTest.php). + +You can run the test with `php phpTest.php` from the command line. + +*Note: The PHP test file requires +[PHP](http://php.net/manual/en/install.php) to be installed.* + +## Using theFlatBuffers PHP library + +*Note: See [Tutorial](../tutorial.md) for a more in-depth +example of how to use FlatBuffers in PHP.* + +FlatBuffers supports both reading and writing FlatBuffers in PHP. + +To use FlatBuffers in your own code, first generate PHP classes from your schema +with the `--php` option to `flatc`. Then you can include both FlatBuffers and +the generated code to read or write a FlatBuffer. + +For example, here is how you would read a FlatBuffer binary file in PHP: +First, include the library and generated code (using the PSR `autoload` +function). Then you can read a FlatBuffer binary file, which you +pass the contents of to the `GetRootAsMonster` function: + +~~~{.php} + // It is recommended that you use PSR autoload when using FlatBuffers in PHP. + // Here is an example: + function __autoload($class_name) { + // The last segment of the class name matches the file name. + $class = substr($class_name, strrpos($class_name, "\\") + 1); + $root_dir = join(DIRECTORY_SEPARATOR, array(dirname(dirname(__FILE__)))); // `flatbuffers` root. + + // Contains the `*.php` files for the FlatBuffers library and the `flatc` generated files. + $paths = array(join(DIRECTORY_SEPARATOR, array($root_dir, "php")), + join(DIRECTORY_SEPARATOR, array($root_dir, "tests", "MyGame", "Example"))); + foreach ($paths as $path) { + $file = join(DIRECTORY_SEPARATOR, array($path, $class . ".php")); + if (file_exists($file)) { + require($file); + break; + } + } + + // Read the contents of the FlatBuffer binary file. + $filename = "monster.dat"; + $handle = fopen($filename, "rb"); + $contents = fread($handle, filesize($filename)); + fclose($handle); + + // Pass the contents to `GetRootAsMonster`. + $monster = \MyGame\Example\Monster::GetRootAsMonster($contents); +~~~ + +Now you can access values like this: + +~~~{.php} + $hp = $monster->GetHp(); + $pos = $monster->GetPos(); +~~~ + +## Text Parsing + +There currently is no support for parsing text (Schema's and JSON) directly +from PHP. diff --git a/third_party/flatbuffers/docs/source/languages/python.md b/third_party/flatbuffers/docs/source/languages/python.md new file mode 100644 index 00000000000..a16ed6c6e65 --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/python.md @@ -0,0 +1,100 @@ +Use in Python {#flatbuffers_guide_use_python} +============= + +## Before you get started + +Before diving into the FlatBuffers usage in Python, it should be noted that the +[Tutorial](../tutorial.md) page has a complete guide to general +FlatBuffers usage in all of the supported languages (including Python). This +page is designed to cover the nuances of FlatBuffers usage, specific to +Python. + +You should also have read the [Building](../building.md) +documentation to build `flatc` and should be familiar with +[Using the schema compiler](../flatc.md) and +[Writing a schema](../schema.md). + +## FlatBuffers Python library code location + +The code for the FlatBuffers Python library can be found at +`flatbuffers/python/flatbuffers`. You can browse the library code on the +[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/ +python). + +## Testing the FlatBuffers Python library + +The code to test the Python library can be found at `flatbuffers/tests`. +The test code itself is located in [py_test.py](https://github.com/google/ +flatbuffers/blob/master/tests/py_test.py). + +To run the tests, use the [PythonTest.sh](https://github.com/google/flatbuffers/ +blob/master/tests/PythonTest.sh) shell script. + +*Note: This script requires [python](https://www.python.org/) to be +installed.* + +## Using the FlatBuffers Python library + +*Note: See [Tutorial](../tutorial.md) for a more in-depth +example of how to use FlatBuffers in Python.* + +There is support for both reading and writing FlatBuffers in Python. + +To use FlatBuffers in your own code, first generate Python classes from your +schema with the `--python` option to `flatc`. Then you can include both +FlatBuffers and the generated code to read or write a FlatBuffer. + +For example, here is how you would read a FlatBuffer binary file in Python: +First, import the library and the generated code. Then read a FlatBuffer binary +file into a `bytearray`, which you pass to the `GetRootAsMonster` function: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py} + import MyGame.Example as example + import flatbuffers + + buf = open('monster.dat', 'rb').read() + buf = bytearray(buf) + monster = example.GetRootAsMonster(buf, 0) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now you can access values like this: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py} + hp = monster.Hp() + pos = monster.Pos() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Support for Numpy arrays + +The Flatbuffers python library also has support for accessing scalar +vectors as numpy arrays. This can be orders of magnitude faster than +iterating over the vector one element at a time, and is particularly +useful when unpacking large nested flatbuffers. The generated code for +a scalar vector will have a method `AsNumpy()`. In the +case of the Monster example, you could access the inventory vector +like this: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py} + inventory = monster.InventoryAsNumpy() + # inventory is a numpy array of type np.dtype('uint8') +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +instead of + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py} + inventory = [] + for i in range(monster.InventoryLength()): + inventory.append(int(monster.Inventory(i))) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Numpy is not a requirement. If numpy is not installed on your system, +then attempting to access one of the `*asNumpy()` methods will result +in a `NumpyRequiredForThisFeature` exception. + +## Text Parsing + +There currently is no support for parsing text (Schema's and JSON) directly +from Python, though you could use the C++ parser through SWIG or ctypes. Please +see the C++ documentation for more on text parsing. + +
diff --git a/third_party/flatbuffers/docs/source/languages/rust.md b/third_party/flatbuffers/docs/source/languages/rust.md new file mode 100644 index 00000000000..04f7f02e669 --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/rust.md @@ -0,0 +1,214 @@ +Use in Rust {#flatbuffers_guide_use_rust} +========== + +## Before you get started + +Before diving into the FlatBuffers usage in Rust, it should be noted that +the [Tutorial](../tutorial.md) page has a complete guide +to general FlatBuffers usage in all of the supported languages (including Rust). +This page is designed to cover the nuances of FlatBuffers usage, specific to +Rust. + +#### Prerequisites + +This page assumes you have written a FlatBuffers schema and compiled it +with the Schema Compiler. If you have not, please see +[Using the schema compiler](../flatc.md) +and [Writing a schema](../schema.md). + +Assuming you wrote a schema, say `mygame.fbs` (though the extension doesn't +matter), you've generated a Rust file called `mygame_generated.rs` using the +compiler (e.g. `flatc --rust mygame.fbs` or via helpers listed in "Useful +tools created by others" section bellow), you can now start using this in +your program by including the file. As noted, this header relies on the crate +`flatbuffers`, which should be in your include `Cargo.toml`. + +## FlatBuffers Rust library code location + +The code for the FlatBuffers Rust library can be found at +`flatbuffers/rust`. You can browse the library code on the +[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/rust). + +## Testing the FlatBuffers Rust library + +The code to test the Rust library can be found at `flatbuffers/tests/rust_usage_test`. +The test code itself is located in +[integration_test.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/tests/integration_test.rs) + +This test file requires `flatc` to be present. To review how to build the project, +please read the [Building](../building.md) documentation. + +To run the tests, execute `RustTest.sh` from the `flatbuffers/tests` directory. +For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply +run: `cd tests && ./RustTest.sh`. + +*Note: The shell script requires [Rust](https://www.rust-lang.org) to +be installed.* + +## Using the FlatBuffers Rust library + +*Note: See [Tutorial](../tutorial.md) for a more in-depth +example of how to use FlatBuffers in Rust.* + +FlatBuffers supports both reading and writing FlatBuffers in Rust. + +To use FlatBuffers in your code, first generate the Rust modules from your +schema with the `--rust` option to `flatc`. Then you can import both FlatBuffers +and the generated code to read or write FlatBuffers. + +For example, here is how you would read a FlatBuffer binary file in Rust: +First, include the library and generated code. Then read the file into +a `u8` vector, which you pass, as a byte slice, to `root_as_monster()`. + +This full example program is available in the Rust test suite: +[monster_example.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/bin/monster_example.rs) + +It can be run by `cd`ing to the `rust_usage_test` directory and executing: `cargo run monster_example`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs} + extern crate flatbuffers; + + #[allow(dead_code, unused_imports)] + #[path = "../../monster_test_generated.rs"] + mod monster_test_generated; + pub use monster_test_generated::my_game; + + use std::io::Read; + + fn main() { + let mut f = std::fs::File::open("../monsterdata_test.mon").unwrap(); + let mut buf = Vec::new(); + f.read_to_end(&mut buf).expect("file reading failed"); + + let monster = my_game::example::root_as_monster(&buf[..]); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +`monster` is of type `Monster`, and points to somewhere *inside* your +buffer (root object pointers are not the same as `buffer_pointer` !). +If you look in your generated header, you'll see it has +convenient accessors for all fields, e.g. `hp()`, `mana()`, etc: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs} + println!("{}", monster.hp()); // `80` + println!("{}", monster.mana()); // default value of `150` + println!("{:?}", monster.name()); // Some("MyMonster") + } +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +*Note: That we never stored a `mana` value, so it will return the default.* + +## Direct memory access + +As you can see from the above examples, all elements in a buffer are +accessed through generated accessors. This is because everything is +stored in little endian format on all platforms (the accessor +performs a swap operation on big endian machines), and also because +the layout of things is generally not known to the user. + +For structs, layout is deterministic and guaranteed to be the same +across platforms (scalars are aligned to their +own size, and structs themselves to their largest member), and you +are allowed to access this memory directly by using `safe_slice` +on the reference to a struct, or even an array of structs. + +To compute offsets to sub-elements of a struct, make sure they +are structs themselves, as then you can use the pointers to +figure out the offset without having to hardcode it. This is +handy for use of arrays of structs with calls like `glVertexAttribPointer` +in OpenGL or similar APIs. + +It is important to note is that structs are still little endian on all +machines, so the functions to enable tricks like this are only exposed on little +endian machines. If you also ship on big endian machines, using an +`#[cfg(target_endian = "little")]` attribute would be wise or your code will not +compile. + +The special function `safe_slice` is implemented on Vector objects that are +represented in memory the same way as they are represented on the wire. This +function is always available on vectors of struct, bool, u8, and i8. It is +conditionally-compiled on little-endian systems for all the remaining scalar +types. + +The FlatBufferBuilder function `create_vector_direct` is implemented for all +types that are endian-safe to write with a `memcpy`. It is the write-equivalent +of `safe_slice`. + +## Access of untrusted buffers + +The safe Rust functions to interpret a slice as a table (`root`, +`size_prefixed_root`, `root_with_opts`, and `size_prefixed_root_with_opts`) +verify the data first. This has some performance cost, but is intended to be +safe for use on flatbuffers from untrusted sources. There are corresponding +`unsafe` versions with names ending in `_unchecked` which skip this +verification, and may access arbitrary memory. + +The generated accessor functions access fields over offsets, which is +very quick. The current implementation uses these to access memory without any +further bounds checking. All of the safe Rust APIs ensure the verifier is run +over these flatbuffers before accessing them. + +When you're processing large amounts of data from a source you know (e.g. +your own generated data on disk), the `_unchecked` versions are acceptable, but +when reading data from the network that can potentially have been modified by an +attacker, it is desirable to use the safe versions which use the verifier. + +## Threading + +Reading a FlatBuffer does not touch any memory outside the original buffer, +and is entirely read-only (all immutable), so is safe to access from multiple +threads even without synchronisation primitives. + +Creating a FlatBuffer is not thread safe. All state related to building +a FlatBuffer is contained in a FlatBufferBuilder instance, and no memory +outside of it is touched. To make this thread safe, either do not +share instances of FlatBufferBuilder between threads (recommended), or +manually wrap it in synchronisation primitives. There's no automatic way to +accomplish this, by design, as we feel multithreaded construction +of a single buffer will be rare, and synchronisation overhead would be costly. + +Unlike most other languages, in Rust these properties are exposed to and +enforced by the type system. `flatbuffers::Table` and the generated table types +are `Send + Sync`, indicating they may be freely shared across threads and data +may be accessed from any thread which receives a const (aka shared) reference. +There are no functions which require a mutable (aka exclusive) reference, which +means all the available functions may be called like this. +`flatbuffers::FlatBufferBuilder` is also `Send + Sync`, but all of the mutating +functions require a mutable (aka exclusive) reference which can only be created +when no other references to the `FlatBufferBuilder` exist, and may not be copied +within the same thread, let alone to a second thread. + +## Reflection (& Resizing) + +There is experimental support for reflection in FlatBuffers, allowing you to +read and write data even if you don't know the exact format of a buffer, and +even allows you to change sizes of strings in-place. + +The way this works is very elegant; there is actually a FlatBuffer schema that +describes schemas (\!) which you can find in `reflection/reflection.fbs`. +The compiler, `flatc`, can write out any schemas it has just parsed as a binary +FlatBuffer, corresponding to this meta-schema. + +Loading in one of these binary schemas at runtime allows you to traverse any +FlatBuffer data that corresponds to it without knowing the exact format. You +can query what fields are present, and then read/write them after. + +For convenient field manipulation, you can use the crate +`flatbuffers-reflection` which includes both the generated code from the meta +schema, as well as a lot of helper functions. + +And example of usage, for the time being, can be found in +`tests/rust_reflection_test/src/lib.rs`. Two sets of APIs are provided: + +- [Unsafe getters/setters](https://docs.rs/flatbuffers-reflection/latest/flatbuffers_reflection/#functions), + which you can use when you are processing trusted data (either from a source you know, or has been verified) + +- Safe getters in [SafeBuffer](https://docs.rs/flatbuffers-reflection/latest/flatbuffers_reflection/struct.SafeBuffer.html), + which does verification when constructed so you can use it for any data source + +## Useful tools created by others + +* [flatc-rust](https://github.com/frol/flatc-rust) - FlatBuffers compiler +(flatc) as API for transparent `.fbs` to `.rs` code-generation via Cargo +build scripts integration. + +
diff --git a/third_party/flatbuffers/docs/source/languages/swift.md b/third_party/flatbuffers/docs/source/languages/swift.md new file mode 100644 index 00000000000..78046c0d444 --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/swift.md @@ -0,0 +1,97 @@ +Use in Swift {#flatbuffers_guide_use_swift} +========= + +## Before you get started + +Before diving into the FlatBuffers usage in Swift, it should be noted that +the [Tutorial](../tutorial.md) page has a complete guide +to general FlatBuffers usage in all of the supported languages (including Swift). +This page is designed to cover the nuances of FlatBuffers usage, specific to +Swift. + +You should also have read the [Building](../building.md) +documentation to build `flatc` and should be familiar with +[Using the schema compiler](../flatc.md) and +[Writing a schema](../schema.md). + +## FlatBuffers Swift library code location + +The code for the FlatBuffers Swift library can be found at +`flatbuffers/swift`. You can browse the library code on the [FlatBuffers +GitHub page](https://github.com/google/flatbuffers/tree/master/swift). + +## Testing the FlatBuffers Swift library + +The code to test the Swift library can be found at `flatbuffers/tests/swift/tests`. +The test code itself is located in [flatbuffers/tests/swift/tests](https://github.com/google/flatbuffers/blob/master/tests/swift/tests). + +To run the tests, use the [SwiftTest.sh](https://github.com/google/flatbuffers/blob/master/tests/swift/tests/SwiftTest.sh) shell script. + +*Note: The shell script requires [Swift](https://swift.org) to +be installed.* + +## Using the FlatBuffers Swift library + +*Note: See [Tutorial](../tutorial.md) for a more in-depth +example of how to use FlatBuffers in Swift.* + +FlatBuffers supports reading and writing binary FlatBuffers in Swift. + +To use FlatBuffers in your own code, first generate Swift structs from your +schema with the `--swift` option to `flatc`. Then include FlatBuffers using `SPM` in +by adding the path to `FlatBuffers/swift` into it. The generated code should also be +added to xcode or the path of the package you will be using. Note: sometimes xcode cant +and wont see the generated files, so it's better that you copy them to xcode. + +For example, here is how you would read a FlatBuffer binary file in Swift: First, +include the library and copy thegenerated code. Then read a FlatBuffer binary file or +a data object from the server, which you can pass into the `GetRootAsMonster` function. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift} + import FlatBuffers + + typealias Monster1 = MyGame.Sample.Monster + typealias Vec3 = MyGame.Sample.Vec3 + + let path = FileManager.default.currentDirectoryPath + let url = URL(fileURLWithPath: path, isDirectory: true).appendingPathComponent("monsterdata_test").appendingPathExtension("mon") + guard let data = try? Data(contentsOf: url) else { return } + + let monster: Monster = try! getCheckedRoot(byteBuffer: &byteBuffer) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now you can access values like this: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift} + let hp = monster.hp + let pos = monster.pos // uses native swift structs + let pos = monster.mutablePos // uses flatbuffers structs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +In some cases it's necessary to modify values in an existing FlatBuffer in place (without creating a copy). For this reason, scalar fields of a Flatbuffer table or struct can be mutated. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift} + var byteBuffer = ByteBuffer(bytes: data) + // Get an accessor to the root object inside the buffer. + let monster: Monster = try! getCheckedRoot(byteBuffer: &byteBuffer) + // let monster: Monster = getRoot(byteBuffer: &byteBuffer) + + if !monster.mutate(hp: 10) { + fatalError("couldn't mutate") + } + // mutate a struct field using flatbuffers struct + // DONT use monster.pos to mutate since swift copy on write + // will not mutate the value in the buffer + let vec = monster.mutablePos.mutate(z: 4) + + // This mutation will fail because the mana field is not available in + // the buffer. It should be set when creating the buffer. + if !monster.mutate(mana: 20) { + fatalError("couldn't mutate") + } +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The term `mutate` is used instead of `set` to indicate that this is a special use case. All mutate functions return a boolean value which is false if the field we're trying to mutate is not available in the buffer. + +
diff --git a/third_party/flatbuffers/docs/source/languages/typescript.md b/third_party/flatbuffers/docs/source/languages/typescript.md new file mode 100644 index 00000000000..f0e333c588e --- /dev/null +++ b/third_party/flatbuffers/docs/source/languages/typescript.md @@ -0,0 +1,96 @@ +Use in TypeScript {#flatbuffers_guide_use_typescript} +================= + +## Before you get started + +Before diving into the FlatBuffers usage in TypeScript, it should be noted that +the [Tutorial](../tutorial.md) page has a complete guide to +general FlatBuffers usage in all of the supported languages +(including TypeScript). This page is specifically designed to cover the nuances +of FlatBuffers usage in TypeScript. + +You should also have read the [Building](../building.md) +documentation to build `flatc` and should be familiar with +[Using the schema compiler](../flatc.md) and +[Writing a schema](../schema.md). + +## FlatBuffers TypeScript library code location + +The code for the FlatBuffers TypeScript library can be found at +https://www.npmjs.com/package/flatbuffers. + +## Testing the FlatBuffers TypeScript library + +To run the tests, use the [TypeScriptTest.py](https://github.com/google/ +flatbuffers/blob/master/tests/TypeScriptTest.py) Python3 script. + +*Note: The TypeScript test file requires [Node.js](https://nodejs.org/en/).* + +## Using the FlatBuffers TypeScript library + +*Note: See [Tutorial](../tutorial.md) for a more in-depth +example of how to use FlatBuffers in TypeScript.* + +FlatBuffers supports both reading and writing FlatBuffers in TypeScript. + +To use FlatBuffers in your own code, first generate TypeScript classes from your +schema with the `--ts` option to `flatc`. Then you can include both FlatBuffers +and the generated code to read or write a FlatBuffer. + +For example, here is how you would read a FlatBuffer binary file in TypeScript: +First, include the library and generated code. Then read the file into an +`Uint8Array`. Make a `flatbuffers.ByteBuffer` out of the `Uint8Array`, and pass +the ByteBuffer to the `getRootAsMonster` function. + +~~~{.ts} + import * as flatbuffers from 'flatbuffers'; + + import { MyGame } from './monster_generated'; + + let data = new Uint8Array(fs.readFileSync('monster.dat')); + let buf = new flatbuffers.ByteBuffer(data); + + let monster = MyGame.Example.Monster.getRootAsMonster(buf); +~~~ + +Now you can access values like this: + +~~~{.ts} + let hp = monster.hp(); + let pos = monster.pos(); +~~~ + +## Object based API + +FlatBuffers is all about memory efficiency, which is why its base API is written +around using as little as possible of it. This does make the API clumsier +(requiring pre-order construction of all data, and making mutation harder). + +For times when efficiency is less important a more convenient object based API +can be used (through `--gen-object-api`) that is able to unpack & pack a +FlatBuffer into objects and standard TS types. + +To use: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.ts} + // Autogenerated class from table Monster. + let monsterobj = new MonsterT(); + + // Deserialize from buffer into object. + Monster.getRootAsMonster(flatbuffer).unpackTo(monsterobj); + // or + let monsterobj = Monster.getRootAsMonster(flatbuffer).unpack(); + + // Update object directly like a regular TS class instance. + console.log(monsterobj.name); + monsterobj.name = "Bob"; + + // Serialize into new flatbuffer. + let fbb = new flatbuffers.Builder(1); + Monster.finishMonsterBuffer(fbb, monsterobj.pack(fbb)); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Text parsing FlatBuffers in TypeScript + +There currently is no support for parsing text (Schema's and JSON) directly +from TypeScript. diff --git a/third_party/flatbuffers/docs/source/quick_start.md b/third_party/flatbuffers/docs/source/quick_start.md new file mode 100644 index 00000000000..2f642f34ba6 --- /dev/null +++ b/third_party/flatbuffers/docs/source/quick_start.md @@ -0,0 +1,90 @@ +# Quick Start + +This will quickly go over the parts of using FlatBuffers to serialize some data. +See the [Tutorial](tutorial.md) for a more in depth guide. + +1. **Build the compiler for FlatBuffers ([`flatc`](flatc.md))** + + ```sh + cmake -G "Unix Makefiles" + make -j + ``` + +2. **Define your FlatBuffer [schema](schema.md) (`.fbs`)** + + ```c title="monster.fbs" linenums="1" + table Monster { + name:string; + health:int; + } + + root_type Monster; + ``` + + See [monster.fbs](https://github.com/google/flatbuffers/blob/master/samples/monster.fbs) + for an complete example. + +3. **Generate code for your language(s)** + + Use the `flatc` compiler to take your schema and generate language-specific + code: + + ```sh + ./flatc --cpp --rust monster.fbs + ``` + + Which generates `monster_generated.h` and `monster_generated.rs` files. + +4. **Serialize data** + + Use the generated code files, as well as the `FlatBufferBuilder` to construct + your serialized buffer. + + ```c++ title="my_monster_factory.cc" linenums="1" + #include "flatbuffers.h" + #include "monster_generated.h" + + int main() { + // Used to build the flatbuffer + FlatBufferBuilder builder; + + // Auto-generated function emitted from `flatc` and the input + // `monster.fbs` schema. + auto monster = CreateMonsterDirect(builder, "Abominable Snowman", 100); + + // Finalize the buffer. + builder.Finish(monster); + } + ``` + + See complete [C++ Example](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.cpp#L24-L56). + +5. **Transmit/Store the serialized FlatBuffer** + + Use your serialized buffer however you want. Send it to someone, save if for + later, etc... + + ```c++ title="my_monster_factory.cc" linenums="13" + // Get a pointer to the flatbuffer. + const uint8_t* flatbuffer = builder.GetBufferPointer(); + ``` + +6. **Read the data** + + Use the generated accessors to read the data from the serialized buffer. + + It doesn't need to be the same language, or even schema version (see + [Evolving](evolution.md)), FlatBuffers ensures the data is readable across + languages and schema versions. + + ```c++ title="my_monster_factory.cc" linenums="15" + // Get a view of the root monster from the flatbuffer. + const Monster snowman = GetMonster(flatbuffer); + + // Access the monster's fields directly. + ASSERT_EQ(snowman->name(), "Abominable Snowman"); + ASSERT_EQ(snowman->health(), 100); + ``` + + See [`Rust` examples](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.rs#L92-L106) + for reading the data written by `C++`. diff --git a/third_party/flatbuffers/docs/source/schema.md b/third_party/flatbuffers/docs/source/schema.md new file mode 100644 index 00000000000..2baa5b78a1d --- /dev/null +++ b/third_party/flatbuffers/docs/source/schema.md @@ -0,0 +1,645 @@ +# Schema + +The syntax of the schema language (aka IDL, +[Interface Definition Language](https://en.wikipedia.org/wiki/Interface_description_language)) +should look quite familiar to users of any of the C family of languages, and +also to users of other IDLs. Let's look at an example first: + +```c title="monster.fbs" linenums="1" +// example IDL file + +namespace MyGame; + +attribute "priority"; + +enum Color : byte { Red = 1, Green, Blue } + +union Any { Monster, Weapon, Pickup } + +struct Vec3 { + x:float; + y:float; + z:float; +} + +table Monster { + pos:Vec3; + mana:short = 150; + hp:short = 100; + name:string; + friendly:bool = false (deprecated, priority: 1); + inventory:[ubyte]; + color:Color = Blue; + test:Any; +} + +table Weapon {} +table Pickup {} + +root_type Monster; +``` + +## Tables + +Tables are the main way of defining objects in FlatBuffers. + +```c title="monster.fbs - Example Table" linenums="17" +table Monster { + pos:Vec3; + mana:short = 150; + hp:short = 100; + name:string; + friendly:bool = false (deprecated, priority: 1); + inventory:[ubyte]; + color:Color = Blue; + test:Any; +} +``` + +They consist of a name (here `Monster`) and a list of [fields](#fields). This +field list can be appended to (and deprecated from) while still maintaining +compatibility. + +### Fields + +Table fields have a name identifier, a [type](#types), optional default value, +optional [attributes](#attributes) and ends with a `;`. See the +[grammar](grammar.md) for full details. + +```ebnf +field_decl = ident `:` type [ `=` scalar ] metadata `;` +``` + +Fields do not have to appear in the wire representation, and you can choose to +omit fields when constructing an object. You have the flexibility to add fields +without fear of bloating your data. This design is also FlatBuffer's mechanism +for forward and backwards compatibility. + +There are three, mutually exclusive, reactions to the non-presence of a table's +field in the binary data. + +#### 1. Default + +Default value fields with return the default value as defined in the schema. If +the default value is not specified in the schema, it will be `0` for scalar +types, or `null` for other types. + +```c++ +mana:short = 150; +hp:short; +inventory:[ubyte]; +``` + +Here `mana` would default to the value `150`, `hp` to value `0`, and `inventory` +to `null`, if those fields are not set. + +Only scalar values can have explicit defaults, non-scalar fields (strings, +vectors, tables) are `null` when not present. + +This is the normal mode that fields will take. + +??? danger "Don't change Default values" + + You generally do not want to change default values after they're initially + defined. Fields that have the default value are not actually stored in the + serialized data (see also Gotchas below). Values explicitly written by code + generated by the old schema old version, if they happen to be the default, will + be read as a different value by code generated with the new schema. This is + slightly less bad when converting an optional scalar into a default valued + scalar since non-presence would not be overloaded with a previous default value. + There are situations, however, where this may be desirable, especially if you + can ensure a simultaneous rebuild of all code. + +#### 2. Optional + +Optional value fields will return some form of `null` in the language generated. + +=== "C++" + + ```c++ + std::optional field; + ``` + +For optional scalars, just set the field default value to `null`. If the +producer of the buffer does not explicitly set that field, it will be marked +`null`. + +```c++ + hp:short = null; +``` + +!!! note + + Not every languages support scalar defaults yet + +#### 3. Required + +Required valued fields will cause an error if they are not set. The FlatBuffers +verifier would consider the whole buffer invalid. + +This is enabled by the [`required` attribute](#required) on the field. + +``` + hp:short (required) +``` + +You cannot have `required` set with an explicit default value, it will result in +a compiler error. + +## Structs + +Similar to a table, `structs` consist of fields are required (so no defaults +either), and fields may not be added or be deprecated. + +```c title="monster.fbs - Example Struct" linenums="11" +struct Vec3 { + x:float; + y:float; + z:float; +} +``` + +Structs may only contain scalars or other structs. Use this for simple objects +where you are very sure no changes will ever be made (as quite clear in the +example `Vec3`). Structs use less memory than tables and are even faster to +access (they are always stored in-line in their parent object, and use no +virtual table). + +### Arrays + +Arrays are a convenience short-hand for a fixed-length collection of elements. +Arrays allow the following syntax, while maintaining binary equivalency. + +
+ +- **Normal Syntax** + + === + + ```c++ + struct Vec3 { + x:float; + y:float; + z:float; + } + ``` + +- **Array Syntax** + + === + + ```c++ + struct Vec3 { + v:[float:3]; + } + ``` + +
+ +Arrays are currently only supported in a `struct`. + +## Types + +The following are the built-in types that can be used in FlatBuffers. + +### Scalars + +The standard assortment of fixed sized scalars are available. There are no +variable sized integers (e.g., `varints`). + +| Size | Signed | Unsigned | Floating Point | +| ------ | ----------------- | ------------------- | -------------------- | +| 8-bit | `byte`, `bool` | `ubyte` (`uint8`) | | +| 16-bit | `short` (`int16`) | `ushort` (`uint16`) | +| 32-bit | `int` (`int32`) | `uint` (`uint32`) | `float` (`float32`) | +| 64-bit | `long` (`int64`) | `ulong` (`uint64`) | `double` (`float64`) | + +The type names in parentheses are alias names such that for example `uint8` can +be used in place of `ubyte`, and `int32` can be used in place of `int` without +affecting code generation. + +### Non-scalars + +#### Vectors + +Vector of any other type (denoted with `[type]`). + +```c++ +inventory:[ubyte]; +``` + +!!! note "Nesting vectors" + + Nesting vectors is not supported, instead you can wrap the inner vector with + a table. + + ``` + table nest{ + a:[ubyte] + } + + table monster { + a:[nest] + } + ``` + +#### Strings + +Strings (indicated by `string`) are zero-terminated strings, prefixed by their +length. Strings may only hold UTF-8 or 7-bit ASCII. For other text encodings or +general binary data use vectors (`[byte]` or `[ubyte]`) instead. + +```c++ +name:string; +``` + +## Enums + +Define a sequence of named constants, each with a given value, or increasing by +one from the previous one. The default first value is `0`. As you can see in the +enum declaration, you specify the underlying integral type of the enum with `:` +(in this case `byte`), which then determines the type of any fields declared +with this enum type. + +Only integer types are allowed, i.e. `byte`, `ubyte`, `short` `ushort`, `int`, +`uint`, `long` and `ulong`. + +Typically, enum values should only ever be added, never removed (there is no +deprecation for enums). This requires code to handle forwards compatibility +itself, by handling unknown enum values. + +## Unions + +Unions share a lot of properties with enums, but instead of new names for +constants, you use names of tables. You can then declare a union field, which +can hold a reference to any of those types, and additionally a field with the +suffix `_type` is generated that holds the corresponding enum value, allowing +you to know which type to cast to at runtime. + +It's possible to give an alias name to a type union. This way a type can even be +used to mean different things depending on the name used: + +```txt +table PointPosition { x:uint; y:uint; } +table MarkerPosition {} +union Position { + Start:MarkerPosition, + Point:PointPosition, + Finish:MarkerPosition +} +``` + +Unions contain a special `NONE` marker to denote that no value is stored so that +name cannot be used as an alias. + +Unions are a good way to be able to send multiple message types as a FlatBuffer. +Note that because a union field is really two fields, it must always be part of +a table, it cannot be the root of a FlatBuffer by itself. + +If you have a need to distinguish between different FlatBuffers in a more +open-ended way, for example for use as files, see the file identification +feature below. + +There is an experimental support only in C++ for a vector of unions (and types). +In the example IDL file above, use [Any] to add a vector of Any to Monster +table. There is also experimental support for other types besides tables in +unions, in particular structs and strings. There's no direct support for scalars +in unions, but they can be wrapped in a struct at no space cost. + +## Namespaces + +These will generate the corresponding namespace in C++ for all helper code, and +packages in Java. You can use `.` to specify nested namespaces / packages. + +## Includes + +You can include other schemas files in your current one, e.g.: + +```txt +include "mydefinitions.fbs"; +``` + +This makes it easier to refer to types defined elsewhere. `include` +automatically ensures each file is parsed just once, even when referred to more +than once. + +When using the `flatc` compiler to generate code for schema definitions, only +definitions in the current file will be generated, not those from the included +files (those you still generate separately). + +## Root type + +This declares what you consider to be the root table of the serialized data. +This is particularly important for parsing JSON data, which doesn't include +object type information. + +## File identification and extension + +Typically, a FlatBuffer binary buffer is not self-describing, i.e. it needs you +to know its schema to parse it correctly. But if you want to use a FlatBuffer as +a file format, it would be convenient to be able to have a "magic number" in +there, like most file formats have, to be able to do a sanity check to see if +you're reading the kind of file you're expecting. + +Now, you can always prefix a FlatBuffer with your own file header, but +FlatBuffers has a built-in way to add an identifier to a FlatBuffer that takes +up minimal space, and keeps the buffer compatible with buffers that don't have +such an identifier. + +You can specify in a schema, similar to `root_type`, that you intend for this +type of FlatBuffer to be used as a file format: + +```txt +file_identifier "MYFI"; +``` + +Identifiers must always be exactly 4 characters long. These 4 characters will +end up as bytes at offsets 4-7 (inclusive) in the buffer. + +For any schema that has such an identifier, `flatc` will automatically add the +identifier to any binaries it generates (with `-b`), and generated calls like +`FinishMonsterBuffer` also add the identifier. If you have specified an +identifier and wish to generate a buffer without one, you can always still do so +by calling `FlatBufferBuilder::Finish` explicitly. + +After loading a buffer, you can use a call like `MonsterBufferHasIdentifier` to +check if the identifier is present. + +Note that this is best for open-ended uses such as files. If you simply wanted +to send one of a set of possible messages over a network for example, you'd be +better off with a union. + +Additionally, by default `flatc` will output binary files as `.bin`. This +declaration in the schema will change that to whatever you want: + +```txt +file_extension "ext"; +``` + +## RPC interface declarations + +You can declare RPC calls in a schema, that define a set of functions that take +a FlatBuffer as an argument (the request) and return a FlatBuffer as the +response (both of which must be table types): + +```txt +rpc_service MonsterStorage { + Store(Monster):StoreResponse; + Retrieve(MonsterId):Monster; +} +``` + +What code this produces and how it is used depends on language and RPC system +used, there is preliminary support for GRPC through the `--grpc` code generator, +see `grpc/tests` for an example. + +## Comments & documentation + +May be written as in most C-based languages. Additionally, a triple comment +(`///`) on a line by itself signals that a comment is documentation for whatever +is declared on the line after it (table/struct/field/enum/union/element), and +the comment is output in the corresponding C++ code. Multiple such lines per +item are allowed. + +## Attributes + +Attributes may be attached to a declaration, behind a field/enum value, or after +the name of a table/struct/enum/union. These may either have a value or not. +Some attributes like `deprecated` are understood by the compiler; user defined +ones need to be declared with the attribute declaration (like `priority` in the +example above), and are available to query if you parse the schema at runtime. +This is useful if you write your own code generators/editors etc., and you wish +to add additional information specific to your tool (such as a help text). + +Current understood attributes: + +- `id: n` (on a table field): manually set the field identifier to `n`. If you + use this attribute, you must use it on ALL fields of this table, and the + numbers must be a contiguous range from 0 onwards. Additionally, since a union + type effectively adds two fields, its id must be that of the second field (the + first field is the type field and not explicitly declared in the schema). For + example, if the last field before the union field had id 6, the union field + should have id 8, and the unions type field will implicitly be 7. IDs allow + the fields to be placed in any order in the schema. When a new field is added + to the schema it must use the next available ID. +- `deprecated` (on a field): do not generate accessors for this field anymore, + code should stop using this data. Old data may still contain this field, but + it won't be accessible anymore by newer code. Note that if you deprecate a + field that was previous required, old code may fail to validate new data (when + using the optional verifier). + +### `required` + +- `required` (on a non-scalar table field): this field must always be set. By + default, fields do not need to be present in the binary. This is desirable, as + it helps with forwards/backwards compatibility, and flexibility of data + structures. By specifying this attribute, you make non- presence in an error + for both reader and writer. The reading code may access the field directly, + without checking for null. If the constructing code does not initialize this + field, they will get an assert, and also the verifier will fail on buffers + that have missing required fields. Both adding and removing this attribute may + be forwards/backwards incompatible as readers will be unable read old or new + data, respectively, unless the data happens to always have the field set. +- `force_align: size` (on a struct): force the alignment of this struct to be + something higher than what it is naturally aligned to. Causes these structs to + be aligned to that amount inside a buffer, IF that buffer is allocated with + that alignment (which is not necessarily the case for buffers accessed + directly inside a `FlatBufferBuilder`). Note: currently not guaranteed to have + an effect when used with `--object-api`, since that may allocate objects at + alignments less than what you specify with `force_align`. +- `force_align: size` (on a vector): force the alignment of this vector to be + something different than what the element size would normally dictate. Note: + Now only work for generated C++ code. +- `bit_flags` (on an unsigned enum): the values of this field indicate bits, + meaning that any unsigned value N specified in the schema will end up + representing 1< diff --git a/third_party/flatbuffers/docs/source/tutorial.md b/third_party/flatbuffers/docs/source/tutorial.md new file mode 100644 index 00000000000..e43e1367cfa --- /dev/null +++ b/third_party/flatbuffers/docs/source/tutorial.md @@ -0,0 +1,3003 @@ +# Tutorial + +This tutorial provides an example of how to work with FlatBuffers in a variety +of languages. The following topics will cover all the steps of using FlatBuffers +in your application. + +1. Writing a FlatBuffers schema file (`.fbs`). +2. Using the `flatc` compiler to transform the schema into language-specific + code. +3. Importing the generated code and libraries into your application. +4. Serializing data into a flatbuffer. +5. Deserializing a flatbuffer. + +The tutorial is structured to be language agnostic, with language specifics in +code blocks providing more context. Additionally, this tries to cover the major +parts and type system of flatbuffers to give a general overview. It's not +expected to be an exhaustive list of all features, or provide the best way to do +things. + +## FlatBuffers Schema (`.fbs`) + +To start working with FlatBuffers, you first need to create a +[schema](schema.md) file which defines the format of the data structures you +wish to serialize. The schema is processed by the `flatc` compiler to generate +language-specific code that you use in your projects. + +The following +[`monster.fbs`](https://github.com/google/flatbuffers/blob/master/samples/monster.fbs) +schema will be used for this tutorial. This is part of the FlatBuffers +[sample code](https://github.com/google/flatbuffers/tree/master/samples) to give +complete sample binaries demonstrations. + +FlatBuffers schema is a Interface Definition Language (IDL) that has a couple +data structures, see the [schema](schema.md) documentation for a detail +description. Use the inline code annotations to get a brief synopsis of each +part of the schema. + +```proto title="monster.fbs" linenums="1" +// Example IDL file for our monster's schema. + +namespace MyGame.Sample; //(1)! + +enum Color:byte { Red = 0, Green, Blue = 2 } //(2)! + +// Optionally add more tables. +union Equipment { Weapon } //(3)! + +struct Vec3 { //(4)! + x:float; //(5)! + y:float; + z:float; +} + +table Monster { //(6)! + pos:Vec3; //(7)! + mana:short = 150; //(8)! + hp:short = 100; + name:string; //(9)! + friendly:bool = false (deprecated); //(10)! + inventory:[ubyte]; //(11)! + color:Color = Blue; + weapons:[Weapon]; //(12)! + equipped:Equipment; //(13)! + path:[Vec3]; +} + +table Weapon { + name:string; + damage:short; +} + +root_type Monster; //(14)! +``` + +1. FlatBuffers has support for namespaces to place the generated code into. + There is mixed level of support for namespaces (some languages don't have + namespaces), but for the C family of languages, it is fully supported. + +2. Enums definitions can be defined with the backing numerical type. Implicit + numbering is supported, so that `Green` would have a value of 1. + +3. A union represents a single value from a set of possible values. Its + effectively an enum (to represent the type actually store) and a value, + combined into one. In this example, the union is not very useful, since it + only has a single type. + +4. A struct is a collection of scalar fields with names. It is itself a scalar + type, which uses less memory and has faster lookup. However, once a struct is + defined, it cannot be changed. Use tables for data structures that can evolve + over time. + +5. FlatBuffers has the standard set of scalar numerical types (`int8`, `int16`, + `int32`, `int64`, `uint8`, `uint16`, `uint32`, `uint64`, `float`, `double`), + as well as `bool`. Note, scalars are fixed width, `varints` are not + supported. + +6. Tables are the main data structure for grouping data together. It can evolve + by adding and deprecating fields over time, while preserving forward and + backwards compatibility. + +7. A field that happens to be a `struct`. This means the data of the `Vec3` + struct will be serialized inline in the table without any need for offset. + +8. Fields can be provided a default value. Default values can be configured to + not be serialized at all while still providing the default value while + deserializing. However, once set, a default value cannot be changed. + +9. A `string` field which points to a serialized string external to the table. + +10. A deprecated field that is no longer being used. This is used instead of + removing the field outright. + +11. A `vector` field that points to a vector of bytes. Like `strings`, the + vector data is serialized elsewhere and this field just stores an offset to + the vector. + +12. Vector of `tables` and `structs` are also possible. + +13. A field to a `union` type. + +14. The root of the flatbuffer is always a `table`. This indicates the type of + `table` the "entry" point of the flatbuffer will point to. + +## Compiling Schema to Code (`flatc`) + +After a schema file is written, you compile it to code in the languages you wish +to work with. This compilation is done by the [FlatBuffers Compiler](flatc.md) +(`flatc`) which is one of the binaries built in the repo. + +### Building `flatc` + +FlatBuffers uses [`cmake`](https://cmake.org/) to build projects files for your +environment. + +=== "Unix" + + ```sh + cmake -G "Unix Makefiles" + make flatc + ``` + +=== "Windows" + + ```sh + cmake -G "Visual Studio 17 2022" + msbuild.exe FlatBuffers.sln + ``` + +See the documentation on [building](building.md) for more details and other +environments. Some languages also include a prebuilt `flatc` via their package +manager. + +### Compiling Schema + +To compile the schema, invoke `flatc` with the schema file and the language +flags you wish to generate code for. This compilation will generate files that +you include in your application code. These files provide convenient APIs for +serializing and deserializing the flatbuffer binary data. + +=== "C++" + + ```sh + flatc --cpp monster.fbs + ``` + +=== "C" + + !!! Note + + If you're working in C, you need to use the separate project + [FlatCC](https://github.com/dvidelabs/flatcc) which contains a schema + compiler and runtime library in C for C. See + [flatcc build instructions](https://github.com/dvidelabs/flatcc#building). + + Please be aware of the difference between `flatc` and `flatcc` tools. + + ```sh + cd flatcc + mkdir -p build/tmp/samples/monster + bin/flatcc -a -o build/tmp/samples/monster samples/monster/monster.fbs + # or just + flatcc/samples/monster/build.sh + ``` + +=== "C#" + + ```sh + flatc --csharp monster.fbs + ``` + +=== "Dart" + + ```sh + flatc --dart monster.fbs + ``` + +=== "Go" + + ```sh + flatc --go monster.fbs + ``` + +=== "Java" + + ```sh + flatc --java monster.fbs + ``` + +=== "JavaScript" + + ```sh + flatc --js monster.fbs + ``` + +=== "Kotlin" + + ```sh + flatc --kotlin monster.fbs + ``` + +=== "Lobster" + + ```sh + flatc --lobster monster.fbs + ``` + +=== "Lua" + + ```sh + flatc --lua monster.fbs + ``` + +=== "PHP" + + ```sh + flatc --php monster.fbs + ``` + +=== "Python" + + ```sh + flatc --python monster.fbs + ``` + +=== "Rust" + + ```sh + flatc --rust monster.fbs + ``` + +=== "Swift" + + ```sh + flatc --swift monster.fbs + ``` + +=== "TypeScript" + + ```sh + flatc --ts monster.fbs + ``` + +You can deserialize flatbuffers in languages that differ from the language that +serialized it. For purpose of this tutorial, we assume one language is used for +both serializing and deserializing. + +## Application Integration + +The generated files are then included in your project to be built into your +application. This is heavily dependent on your build system and language, but +generally involves two things: + +1. Importing the generated code. +2. Importing the "runtime" libraries. + +=== "C++" + + ```c++ + #include "monster_generated.h" // This was generated by `flatc` + #include "flatbuffers.h" // The runtime library for C++ + + // Simplifies naming in the following examples. + using namespace MyGame::Sample; // Specified in the schema. + ``` + +=== "C" + + ```c + #include "monster_builder.h" // Generated by `flatcc`. + + // Convenient namespace macro to manage long namespace prefix. + #undef ns + // Specified in the schema. + #define ns(x) FLATBUFFERS_WRAP_NAMESPACE(MyGame_Sample, x) + + // A helper to simplify creating vectors from C-arrays. + #define c_vec_len(V) (sizeof(V)/sizeof((V)[0])) + ``` + +=== "C#" + + ```c# + using Google.FlatBuffers; // The runtime library for C# + using MyGame.Sample; // The generated files from `flatc` + ``` + +=== "Dart" + + ```dart + import 'package:flat_buffers/flat_buffers.dart' as fb; + + // Generated by `flatc`. + import 'monster_my_game.sample_generated.dart' as myGame; + ``` + +=== "Go" + + ```go + import ( + flatbuffers "github.com/google/flatbuffers/go" + sample "MyGame/Sample" + ) + ``` + +=== "Java" + + ```java + import MyGame.Sample.*; //The `flatc` generated files. (Monster, Vec3, etc.) + + import com.google.flatbuffers.FlatBufferBuilder; + ``` + +=== "JavaScript" + + ```javascript + // The following code is an example - use your desired module flavor by + // transpiling from TS. + var flatbuffers = require('/js/flatbuffers').flatbuffers; + var MyGame = require('./monster_generated').MyGame; // Generated by `flatc`. + + //------------------------------------------------------------------------// + + // The following code is for browser-based HTML/JavaScript. Use the above + // code for JavaScript module loaders (e.g. Node.js). + + // Generated by `flatc`. + ``` + +=== "Kotlin" + + ```kotlin + import MyGame.Sample.* //The `flatc` generated files. (Monster, Vec3, etc.) + + import com.google.flatbuffers.FlatBufferBuilder + ``` + +=== "Lobster" + + ```lobster + import from "../lobster/" // Where to find flatbuffers.lobster + import monster_generated + ``` + +=== "Lua" + + ```lua + -- require the flatbuffers module + local flatbuffers = require("flatbuffers") + + -- require the generated files from `flatc`. + local color = require("MyGame.Sample.Color") + local equipment = require("MyGame.Sample.Equipment") + local monster = require("MyGame.Sample.Monster") + local vec3 = require("MyGame.Sample.Vec3") + local weapon = require("MyGame.Sample.Weapon") + ``` + +=== "PHP" + + ```php + // It is recommended that your use PSR autoload when using FlatBuffers in + // PHP. Here is an example from `SampleBinary.php`: + function __autoload($class_name) { + // The last segment of the class name matches the file name. + $class = substr($class_name, strrpos($class_name, "\\") + 1); + // `flatbuffers` root. + $root_dir = join(DIRECTORY_SEPARATOR, array(dirname(dirname(__FILE__)))); + + // Contains the `*.php` files for the FlatBuffers library and the `flatc` + // generated files. + $paths = array(join(DIRECTORY_SEPARATOR, array($root_dir, "php")), + join(DIRECTORY_SEPARATOR, + array($root_dir, "samples", "MyGame", "Sample"))); + foreach ($paths as $path) { + $file = join(DIRECTORY_SEPARATOR, array($path, $class . ".php")); + if (file_exists($file)) { + require($file); + break; + } + } + } + ``` + +=== "Python" + + ```py + import flatbuffers + + # Generated by `flatc`. + import MyGame.Sample.Color + import MyGame.Sample.Equipment + import MyGame.Sample.Monster + import MyGame.Sample.Vec3 + import MyGame.Sample.Weapon + ``` + +=== "Rust" + + ```rust + // import the flatbuffers runtime library + extern crate flatbuffers; + + // import the generated code + #[allow(dead_code, unused_imports)] + #[path = "./monster_generated.rs"] + mod monster_generated; + pub use monster_generated::my_game::sample::{root_as_monster, + Color, Equipment, + Monster, MonsterArgs, + Vec3, + Weapon, WeaponArgs}; + ``` + +=== "Swift" + + ```swift + /** + // make sure that monster_generated.swift is included in your project + */ + import Flatbuffers + + // typealiases for convenience + typealias Monster = MyGame1_Sample_Monster + typealias Weapon = MyGame1_Sample_Weapon + typealias Color = MyGame1_Sample_Color + typealias Vec3 = MyGame1_Sample_Vec3 + ``` + +=== "TypeScript" + + ```ts + // note: import flatbuffers with your desired import method + + import { MyGame } from './monster_generated'; + ``` + +For some languages the runtime libraries are just code files you compile into +your application. While other languages provide packaged libraries via their +package managers. + +The generated files include APIs for both serializing and deserializing +FlatBuffers. So these steps are identical for both the consumer and producer. + +## Serialization + +Once all the files are included into your application, it's time to start +serializing some data! + +With FlatBuffers, serialization can be a bit verbose, since each piece of data +must be serialized separately and in a particular order (depth-first, pre-order +traversal). The verbosity allows efficient serialization without heap +allocations, at the cost of more complex serialization APIs. + +For example, any reference type (e.g. `table`, `vector`, `string`) must be +serialized before it can be referred to by other structures. So its typical to +serialize the data from leaf to root node, as will be shown below. + +### FlatBufferBuilder + +Most languages use a Builder object for managing the binary array that the data +is serialized into. It provides an API for serializing data, as well as keeps +track of some internal state. The generated code wraps methods on the Builder +object to provide an API tailored to the schema. + +First instantiate a Builder (or reuse an existing one) and specify some memory +for it. The builder will automatically resize the backing buffer when necessary. + +=== "C++" + + ```c++ + // Construct a Builder with 1024 byte backing array. + flatbuffers::FlatBufferBuilder builder(1024); + ``` + +=== "C" + + ```c + flatcc_builder_t builder, *B; + B = &builder; + // Initialize the builder object. + flatcc_builder_init(B); + ``` + +=== "C#" + + ```c# + // Construct a Builder with 1024 byte backing array. + FlatBufferBuilder builder = new FlatBufferBuilder(1024); + ``` + +=== "Dart" + + ```dart + // Construct a Builder with 1024 byte backing array. + var builder = new fb.Builder(initialSize: 1024); + ``` + +=== "Go" + + ```go + // Construct a Builder with 1024 byte backing array. + builder := flatbuffers.NewBuilder(1024) + ``` + +=== "Java" + + ```java + // Construct a Builder with 1024 byte backing array. + FlatBufferBuilder builder = new FlatBufferBuilder(1024); + ``` + +=== "JavaScript" + + ```javascript + // Construct a Builder with 1024 byte backing array. + var builder = new flatbuffers.Builder(1024); + ``` + +=== "Kotlin" + + ```kotlin + // Construct a Builder with 1024 byte backing array. + val builder = FlatBufferBuilder(1024) + ``` + +=== "Lobster" + + ```lobster + // Construct a Builder with 1024 byte backing array. + let builder = flatbuffers_builder {} + ``` + +=== "Lua" + + ```lua + -- Construct a Builder with 1024 byte backing array. + local builder = flatbuffers.Builder(1024) + ``` + +=== "PHP" + + ```php + // Construct a Builder with 1024 byte backing array. + $builder = new Google\FlatBuffers\FlatbufferBuilder(1024); + ``` + +=== "Python" + + ```py + # Construct a Builder with 1024 byte backing array. + builder = flatbuffers.Builder(1024) + ``` + +=== "Rust" + + ```rust + // Construct a Builder with 1024 byte backing array. + let mut builder = flatbuffers::FlatBufferBuilder::with_capacity(1024); + ``` + +=== "Swift" + + ```swift + // Construct a Builder with 1024 byte backing array. + let builder = FlatBufferBuilder(initialSize: 1024) + ``` + +=== "TypeScript" + + ```ts + // Construct a Builder with 1024 byte backing array. + let builder = new flatbuffers.Builder(1024); + ``` + +Once a Builder is available, data can be serialized to it via the Builder APIs +and the generated code. + +### Serializing Data + +In this tutorial, we are building `Monsters` and `Weapons` for a computer game. +A `Weapon` is represented by a flatbuffer `table` with some fields. One field is +the `name` field, which is type `string` and the other `damage` field is a +numerical scalar. + +```c title="monster.fbs" linenums="28" +table Weapon { + name:string; + damage:short; +} +``` + +#### Strings + +Since `string` is a reference type, we first need to serialize it before +assigning it to the `name` field of the `Weapon` table. This is done through the +Builder `CreateString` method. + +Let's serialize two weapon strings. + +=== "C++" + + ```c++ + flatbuffers::Offset weapon_one_name = builder.CreateString("Sword"); + flatbuffers::Offset weapon_two_name = builder.CreateString("Axe"); + ``` + + `flatbuffers::Offset<>` is a just a "typed" integer tied to a particular + type. It helps make the numerical offset more strongly typed. + +=== "C" + + ```c + flatbuffers_string_ref_t weapon_one_name + = flatbuffers_string_create_str(B, "Sword"); + flatbuffers_string_ref_t weapon_two_name + = flatbuffers_string_create_str(B, "Axe"); + ``` + +=== "C#" + + ```c# + Offset weaponOneName = builder.CreateString("Sword"); + Offset weaponTwoName = builder.CreateString("Axe"); + ``` + +=== "Dart" + + ```dart + final int weaponOneName = builder.writeString("Sword"); + final int weaponTwoName = builder.writeString("Axe"); + ``` + +=== "Go" + + ```go + weaponOne := builder.CreateString("Sword") + weaponTwo := builder.CreateString("Axe") + ``` + +=== "Java" + + ```java + int weaponOneName = builder.createString("Sword") + int weaponTwoName = builder.createString("Axe"); + ``` + +=== "JavaScript" + + ```javascript + var weaponOne = builder.createString('Sword'); + var weaponTwo = builder.createString('Axe'); + ``` + +=== "Kotlin" + + ```kotlin + val weaponOneName = builder.createString("Sword") + val weaponTwoName = builder.createString("Axe") + ``` + +=== "Lobster" + + ```lobster + let weapon_one = builder.CreateString("Sword") + let weapon_two = builder.CreateString("Axe") + ``` + +=== "Lua" + + ```lua + local weaponOne = builder:CreateString("Sword") + local weaponTwo = builder:CreateString("Axe") + ``` + +=== "PHP" + + ```php + $weapon_one_name = $builder->createString("Sword") + $weapon_two_name = $builder->createString("Axe"); + ``` + +=== "Python" + + ```py + weapon_one = builder.CreateString('Sword') + weapon_two = builder.CreateString('Axe') + ``` + +=== "Rust" + + ```rust + let weapon_one_name = builder.create_string("Sword"); + let weapon_two_name = builder.create_string("Axe"); + ``` + +=== "Swift" + + ```swift + let weapon1Name = builder.create(string: "Sword") + let weapon2Name = builder.create(string: "Axe") + ``` + +=== "TypeScript" + + ```ts + let weaponOne = builder.createString('Sword'); + let weaponTwo = builder.createString('Axe'); + ``` + + +This performs the actual serialization (the string data is copied into the +backing array) and returns an offset. Think of the offset as a handle to that +reference. It's just a "typed" numerical offset to where that data resides in +the buffer. + +#### Tables + +Now that we have some names serialized, we can serialize the `Weapon` tables. +Here we will use one of the generated helper functions that was emitted by +`flatc`. The `CreateWeapon` function takes in the Builder object, as well as the +offset to the weapon's name and a numerical value for the damage field. + +=== "C++" + + ```c++ + short weapon_one_damage = 3; + short weapon_two_damage = 5; + + // Use the `CreateWeapon()` shortcut to create Weapons with all the fields + // set. + flatbuffers::Offset sword = + CreateWeapon(builder, weapon_one_name, weapon_one_damage); + flatbuffers::Offset axe = + CreateWeapon(builder, weapon_two_name, weapon_two_damage); + ``` + +=== "C" + + ```c + uint16_t weapon_one_damage = 3; + uint16_t weapon_two_damage = 5; + + ns(Weapon_ref_t) sword + = ns(Weapon_create(B, weapon_one_name, weapon_one_damage)); + ns(Weapon_ref_t) axe + = ns(Weapon_create(B, weapon_two_name, weapon_two_damage)); + ``` + +=== "C#" + + ```c# + short weaponOneDamage = 3; + short weaponTwoDamage = 5; + + // Use the `CreateWeapon()` helper function to create the weapons, since we + // set every field. + Offset sword = + Weapon.CreateWeapon(builder, weaponOneName, weaponOneDamage); + Offset axe = + Weapon.CreateWeapon(builder, weaponTwoName, weaponTwoDamage); + ``` + +=== "Dart" + + ```dart + final int weaponOneDamage = 3; + final int weaponTwoDamage = 5; + + final swordBuilder = new myGame.WeaponBuilder(builder) + ..begin() + ..addNameOffset(weaponOneName) + ..addDamage(weaponOneDamage); + final int sword = swordBuilder.finish(); + + final axeBuilder = new myGame.WeaponBuilder(builder) + ..begin() + ..addNameOffset(weaponTwoName) + ..addDamage(weaponTwoDamage); + final int axe = axeBuilder.finish(); + ``` + + Note, as an alternative, the previous steps can be combined using the + generative Builder classes. + + ```dart + final myGame.WeaponBuilder sword = new myGame.WeaponObjectBuilder( + name: "Sword", + damage: 3, + ); + + final myGame.WeaponBuilder axe = new myGame.WeaponObjectBuilder( + name: "Axe", + damage: 5, + ); + ``` + +=== "Go" + + ```go + // Create the first `Weapon` ("Sword"). + sample.WeaponStart(builder) + sample.WeaponAddName(builder, weaponOne) + sample.WeaponAddDamage(builder, 3) + sword := sample.WeaponEnd(builder) + + // Create the second `Weapon` ("Axe"). + sample.WeaponStart(builder) + sample.WeaponAddName(builder, weaponTwo) + sample.WeaponAddDamage(builder, 5) + axe := sample.WeaponEnd(builder) + ``` + +=== "Java" + + ```java + short weaponOneDamage = 3; + short weaponTwoDamage = 5; + + // Use the `createWeapon()` helper function to create the weapons, since we + // set every field. + int sword = Weapon.createWeapon(builder, weaponOneName, weaponOneDamage); + int axe = Weapon.createWeapon(builder, weaponTwoName, weaponTwoDamage); + ``` + +=== "JavaScript" + + ```javascript + // Create the first `Weapon` ('Sword'). + MyGame.Sample.Weapon.startWeapon(builder); + MyGame.Sample.Weapon.addName(builder, weaponOne); + MyGame.Sample.Weapon.addDamage(builder, 3); + var sword = MyGame.Sample.Weapon.endWeapon(builder); + + // Create the second `Weapon` ('Axe'). + MyGame.Sample.Weapon.startWeapon(builder); + MyGame.Sample.Weapon.addName(builder, weaponTwo); + MyGame.Sample.Weapon.addDamage(builder, 5); + var axe = MyGame.Sample.Weapon.endWeapon(builder); + ``` + +=== "Kotlin" + + ```kotlin + val weaponOneDamage: Short = 3; + val weaponTwoDamage: Short = 5; + + // Use the `createWeapon()` helper function to create the weapons, since we + // set every field. + val sword = Weapon.createWeapon(builder, weaponOneName, weaponOneDamage) + val axe = Weapon.createWeapon(builder, weaponTwoName, weaponTwoDamage) + ``` + +=== "Lobster" + + ```lobster + let sword = MyGame_Sample_WeaponBuilder { b } + .start() + .add_name(weapon_one) + .add_damage(3) + .end() + + let axe = MyGame_Sample_WeaponBuilder { b } + .start() + .add_name(weapon_two) + .add_damage(5) + .end() + ``` + +=== "Lua" + + ```lua + -- Create the first 'Weapon' + weapon.Start(builder) + weapon.AddName(builder, weaponOne) + weapon.AddDamage(builder, 3) + local sword = weapon.End(builder) + + -- Create the second 'Weapon' + weapon.Start(builder) + weapon.AddName(builder, weaponTwo) + weapon.AddDamage(builder, 5) + local axe = weapon.End(builder) + ``` + +=== "PHP" + + ```php + $sword = \MyGame\Sample\Weapon::CreateWeapon($builder, $weapon_one_name, 3); + $axe = \MyGame\Sample\Weapon::CreateWeapon($builder, $weapon_two_name, 5); + ``` + +=== "Python" + + ```py + # Create the first `Weapon` ('Sword'). + MyGame.Sample.Weapon.Start(builder) + MyGame.Sample.Weapon.AddName(builder, weapon_one) + MyGame.Sample.Weapon.AddDamage(builder, 3) + sword = MyGame.Sample.Weapon.End(builder) + + # Create the second `Weapon` ('Axe'). + MyGame.Sample.Weapon.Start(builder) + MyGame.Sample.Weapon.AddName(builder, weapon_two) + MyGame.Sample.Weapon.AddDamage(builder, 5) + axe = MyGame.Sample.Weapon.End(builder) + ``` + +=== "Rust" + + ```rust + // Use the `Weapon::create` shortcut to create Weapons with named field + // arguments. + let sword = Weapon::create(&mut builder, &WeaponArgs{ + name: Some(weapon_one_name), + damage: 3, + }); + let axe = Weapon::create(&mut builder, &WeaponArgs{ + name: Some(weapon_two_name), + damage: 5, + }); + ``` + +=== "Swift" + + ```swift + // start creating the weapon by calling startWeapon + let weapon1Start = Weapon.startWeapon(&builder) + Weapon.add(name: weapon1Name, &builder) + Weapon.add(damage: 3, &builder) + // end the object by passing the start point for the weapon 1 + let sword = Weapon.endWeapon(&builder, start: weapon1Start) + + let weapon2Start = Weapon.startWeapon(&builder) + Weapon.add(name: weapon2Name, &builder) + Weapon.add(damage: 5, &builder) + let axe = Weapon.endWeapon(&builder, start: weapon2Start) + ``` + +=== "TypeScript" + + ```ts + // Create the first `Weapon` ('Sword'). + MyGame.Sample.Weapon.startWeapon(builder); + MyGame.Sample.Weapon.addName(builder, weaponOne); + MyGame.Sample.Weapon.addDamage(builder, 3); + let sword = MyGame.Sample.Weapon.endWeapon(builder); + + // Create the second `Weapon` ('Axe'). + MyGame.Sample.Weapon.startWeapon(builder); + MyGame.Sample.Weapon.addName(builder, weaponTwo); + MyGame.Sample.Weapon.addDamage(builder, 5); + let axe = MyGame.Sample.Weapon.endWeapon(builder); + ``` + + +The generated functions from `flatc`, like `CreateWeapon`, are just composed of +various Builder API methods. So its not required to use the generated code, but +it does make things much simpler and compact. + +Just like the `CreateString` methods, the table serialization functions return +an offset to the location of the serialized `Weapon` table. + +Now that we have some `Weapons` serialized, we can serialize a `Monster`. +Looking at the schema again, this table has a lot more fields of various types. +Some of these need to be serialized beforehand, for the same reason we +serialized the name string before the weapon table. + +!!! note inline end + + There is no prescribed ordering of which table fields must be serialized + first, you could serialize in any order you want. You can also not serialize + a field to provide a `null` value, this is done by using an 0 offset value. + +```c title="monster.fbs" linenums="15" +table Monster { + pos:Vec3; + mana:short = 150; + hp:short = 100; + name:string; + friendly:bool = false (deprecated); + inventory:[ubyte]; + color:Color = Blue; + weapons:[Weapon]; + equipped:Equipment; + path:[Vec3]; +} +``` + +#### Vectors + +The `weapons` field is a `vector` of `Weapon` tables. We already have two +`Weapons` serialized, so we just need to serialize a `vector` of those offsets. +The Builder provides multiple ways to create `vectors`. + +=== "C++" + + ```c++ + // Create a std::vector of the offsets we had previous made. + std::vector> weapons_vector; + weapons_vector.push_back(sword); + weapons_vector.push_back(axe); + + // Then serialize that std::vector into the buffer and again get an Offset + // to that vector. Use `auto` here since the full type is long, and it just + // a "typed" number. + auto weapons = builder.CreateVector(weapons_vector); + ``` + +=== "C" + + ```c + // We use the internal builder stack to implement a dynamic vector. + ns(Weapon_vec_start(B)); + ns(Weapon_vec_push(B, sword)); + ns(Weapon_vec_push(B, axe)); + ns(Weapon_vec_ref_t) weapons = ns(Weapon_vec_end(B)); + ``` + +=== "C#" + + ```c# + // Create an array of the two weapon offsets. + var weaps = new Offset[2]; + weaps[0] = sword; + weaps[1] = axe; + + // Pass the `weaps` array into the `CreateWeaponsVector()` method to create + // a FlatBuffer vector. + var weapons = Monster.CreateWeaponsVector(builder, weaps); + ``` + +=== "Dart" + + ```dart + // If using the Builder classes, serialize the `[sword,axe]` + final weapons = builder.writeList([sword, axe]); + + // If using the ObjectBuilders, just create an array from the two `Weapon`s + final List weaps = [sword, axe]; + ``` + +=== "Go" + + ```go + // Create a FlatBuffer vector and prepend the weapons. + // Note: Since we prepend the data, prepend them in reverse order. + sample.MonsterStartWeaponsVector(builder, 2) + builder.PrependUOffsetT(axe) + builder.PrependUOffsetT(sword) + weapons := builder.EndVector(2) + ``` + +=== "Java" + + ```java + // Place the two weapons into an array, and pass it to the + // `createWeaponsVector()` method to create a FlatBuffer vector. + int[] weaps = new int[2]; + weaps[0] = sword; + weaps[1] = axe; + + // Pass the `weaps` array into the `createWeaponsVector()` method to create + // a FlatBuffer vector. + int weapons = Monster.createWeaponsVector(builder, weaps); + ``` + +=== "JavaScript" + + ```javascript + // Create an array from the two `Weapon`s and pass it to the + // `createWeaponsVector()` method to create a FlatBuffer vector. + var weaps = [sword, axe]; + var weapons = MyGame.Sample.Monster.createWeaponsVector(builder, weaps); + ``` + +=== "Kotlin" + + ```kotlin + // Place the two weapons into an array, and pass it to the + // `createWeaponsVector()` method to create a FlatBuffer vector. + val weaps = intArrayOf(sword, axe) + + // Pass the `weaps` array into the `createWeaponsVector()` method to create + // a FlatBuffer vector. + val weapons = Monster.createWeaponsVector(builder, weaps) + ``` + +=== "Lobster" + + ```lobster + let weapons = builder.MyGame_Sample_MonsterCreateWeaponsVector([sword, axe]) + ``` + +=== "Lua" + + ```lua + -- Create a FlatBuffer vector and prepend the weapons. + -- Note: Since we prepend the data, prepend them in reverse order. + monster.StartWeaponsVector(builder, 2) + builder:PrependUOffsetTRelative(axe) + builder:PrependUOffsetTRelative(sword) + local weapons = builder:EndVector(2) + ``` + +=== "PHP" + + ```php + // Create an array from the two `Weapon`s and pass it to the + // `CreateWeaponsVector()` method to create a FlatBuffer vector. + $weaps = array($sword, $axe); + $weapons = \MyGame\Sample\Monster::CreateWeaponsVector($builder, $weaps); + ``` + +=== "Python" + + ```py + # Create a FlatBuffer vector and prepend the weapons. + # Note: Since we prepend the data, prepend them in reverse order. + MyGame.Sample.Monster.StartWeaponsVector(builder, 2) + builder.PrependUOffsetTRelative(axe) + builder.PrependUOffsetTRelative(sword) + weapons = builder.EndVector() + ``` + +=== "Rust" + + ```rust + // Create a FlatBuffer `vector` that contains offsets to the sword and axe + // we created above. + let weapons = builder.create_vector(&[sword, axe]); + ``` + +=== "Swift" + + ```swift + // Create a FlatBuffer `vector` that contains offsets to the sword and axe + // we created above. + let weaponsOffset = builder.createVector(ofOffsets: [sword, axe]) + ``` + +=== "TypeScript" + + ```ts + // Create an array from the two `Weapon`s and pass it to the + // `createWeaponsVector()` method to create a FlatBuffer vector. + let weaps = [sword, axe]; + let weapons = MyGame.Sample.Monster.createWeaponsVector(builder, weaps); + ``` + + +While we are at it, let us serialize the other two vector fields: the +`inventory` field is just a vector of scalars, and the `path` field is a vector +of structs (which are scalar data as well). So these vectors can be serialized a +bit more directly. + +=== "C++" + + ```c++ + // Create a `vector` representing the inventory of the Orc. Each number + // could correspond to an item that can be claimed after he is slain. + unsigned char treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + flatbuffers::Offset> inventory = + builder.CreateVector(treasure, 10); + + // Construct an array of two `Vec3` structs. + Vec3 points[] = { Vec3(1.0f, 2.0f, 3.0f), Vec3(4.0f, 5.0f, 6.0f) }; + + // Serialize it as a vector of structs. + flatbuffers::Offset> path = + builder.CreateVectorOfStructs(points, 2); + ``` + +=== "C" + + ```c + // Create a `vector` representing the inventory of the Orc. Each number + // could correspond to an item that can be claimed after he is slain. + uint8_t treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + flatbuffers_uint8_vec_ref_t inventory; + // `c_vec_len` is the convenience macro we defined earlier. + inventory = flatbuffers_uint8_vec_create(B, treasure, c_vec_len(treasure)); + ``` + +=== "C#" + + ```c# + // Create a `vector` representing the inventory of the Orc. Each number + // could correspond to an item that can be claimed after he is slain. + // Note: Since we prepend the bytes, this loop iterates in reverse order. + Monster.StartInventoryVector(builder, 10); + for (int i = 9; i >= 0; i--) + { + builder.AddByte((byte)i); + } + Offset> inventory = builder.EndVector(); + + // Start building a path vector of length 2. + Monster.StartPathVector(fbb, 2); + + // Serialize the individual Vec3 structs + Vec3.CreateVec3(builder, 1.0f, 2.0f, 3.0f); + Vec3.CreateVec3(builder, 4.0f, 5.0f, 6.0f); + + // End the vector to get the offset + Offset> path = fbb.EndVector(); + ``` + +=== "Dart" + + ```dart + // Create a list representing the inventory of the Orc. Each number + // could correspond to an item that can be claimed after he is slain. + final List treasure = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + final inventory = builder.writeListUint8(treasure); + + // Using the Builder classes, you can write a list of structs like so: + // Note that the intended order should be reversed if order is important. + final vec3Builder = new myGame.Vec3Builder(builder); + vec3Builder.finish(4.0, 5.0, 6.0); + vec3Builder.finish(1.0, 2.0, 3.0); + final int path = builder.endStructVector(2); // the length of the vector + ``` + +=== "Go" + + ```go + // Create a `vector` representing the inventory of the Orc. Each number + // could correspond to an item that can be claimed after he is slain. + // Note: Since we prepend the bytes, this loop iterates in reverse. + sample.MonsterStartInventoryVector(builder, 10) + for i := 9; i >= 0; i-- { + builder.PrependByte(byte(i)) + } + inv := builder.EndVector(10) + + sample.MonsterStartPathVector(builder, 2) + sample.CreateVec3(builder, 1.0, 2.0, 3.0) + sample.CreateVec3(builder, 4.0, 5.0, 6.0) + path := builder.EndVector(2) + ``` + +=== "Java" + + ```java + // Create a `vector` representing the inventory of the Orc. Each number + // could correspond to an item that can be claimed after he is slain. + byte[] treasure = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int inv = Monster.createInventoryVector(builder, treasure); + + Monster.startPathVector(fbb, 2); + Vec3.createVec3(builder, 1.0f, 2.0f, 3.0f); + Vec3.createVec3(builder, 4.0f, 5.0f, 6.0f); + int path = fbb.endVector(); + ``` + +=== "JavaScript" + + ```javascript + // Create a `vector` representing the inventory of the Orc. Each number + // could correspond to an item that can be claimed after he is slain. + var treasure = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + var inv = MyGame.Sample.Monster.createInventoryVector(builder, treasure); + + MyGame.Sample.Monster.startPathVector(builder, 2); + MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0); + MyGame.Sample.Vec3.createVec3(builder, 4.0, 5.0, 6.0); + var path = builder.endVector(); + ``` + +=== "Kotlin" + + ```kotlin + // Create a `vector` representing the inventory of the Orc. Each number + // could correspond to an item that can be claimed after he is slain. + val treasure = byteArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + val inv = Monster.createInventoryVector(builder, treasure) + + Monster.startPathVector(fbb, 2) + Vec3.createVec3(builder, 1.0f, 2.0f, 3.0f) + Vec3.createVec3(builder, 4.0f, 5.0f, 6.0f) + val path = fbb.endVector() + ``` + +=== "Lobster" + + ```lobster + // Inventory. + let inv = builder.MyGame_Sample_MonsterCreateInventoryVector(map(10): _) + + builder.MyGame_Sample_MonsterStartPathVector(2) + builder.MyGame_Sample_CreateVec3(1.0, 2.0, 3.0) + builder.MyGame_Sample_CreateVec3(4.0, 5.0, 6.0) + let path = builder.EndVector(2) + ``` + +=== "Lua" + + ```lua + -- Create a `vector` representing the inventory of the Orc. Each number + -- could correspond to an item that can be claimed after he is slain. + -- Note: Since we prepend the bytes, this loop iterates in reverse. + monster.StartInventoryVector(builder, 10) + for i=10,1,-1 do + builder:PrependByte(i) + end + local inv = builder:EndVector(10) + + -- Create a FlatBuffer vector and prepend the path locations. + -- Note: Since we prepend the data, prepend them in reverse order. + monster.StartPathVector(builder, 2) + vec3.CreateVec3(builder, 1.0, 2.0, 3.0) + vec3.CreateVec3(builder, 4.0, 5.0, 6.0) + local path = builder:EndVector(2) + ``` + +=== "PHP" + + ```php + // Create a `vector` representing the inventory of the Orc. Each number + // could correspond to an item that can be claimed after he is slain. + $treasure = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + $inv = \MyGame\Sample\Monster::CreateInventoryVector($builder, $treasure); + + \MyGame\Example\Monster::StartPathVector($builder, 2); + \MyGame\Sample\Vec3::CreateVec3($builder, 1.0, 2.0, 3.0); + \MyGame\Sample\Vec3::CreateVec3($builder, 1.0, 2.0, 3.0); + $path = $builder->endVector(); + ``` + +=== "Python" + + ```py + # Create a `vector` representing the inventory of the Orc. Each number + # could correspond to an item that can be claimed after he is slain. + # Note: Since we prepend the bytes, this loop iterates in reverse. + MyGame.Sample.Monster.StartInventoryVector(builder, 10) + for i in reversed(range(0, 10)): + builder.PrependByte(i) + inv = builder.EndVector() + + MyGame.Sample.Monster.StartPathVector(builder, 2) + MyGame.Sample.Vec3.CreateVec3(builder, 1.0, 2.0, 3.0) + MyGame.Sample.Vec3.CreateVec3(builder, 4.0, 5.0, 6.0) + path = builder.EndVector() + ``` + +=== "Rust" + + ```rust + // Inventory. + let inventory = builder.create_vector(&[0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + + // Create the path vector of Vec3 objects. + let x = Vec3::new(1.0, 2.0, 3.0); + let y = Vec3::new(4.0, 5.0, 6.0); + let path = builder.create_vector(&[x, y]); + ``` + +=== "Swift" + + ```swift + // create inventory + let inventory: [Byte] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + let inventoryOffset = builder.createVector(inventory) + + let path = fbb.createVector(ofStructs: [ + Vec3(x: 1, y: 2, z: 3), + Vec3(x: 4, y: 5, z: 6) + ]) + ``` + +=== "TypeScript" + + ```ts + // Create a `vector` representing the inventory of the Orc. Each number + // could correspond to an item that can be claimed after he is slain. + let treasure = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + let inv = MyGame.Sample.Monster.createInventoryVector(builder, treasure); + + MyGame.Sample.Monster.startPathVector(builder, 2); + MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0); + MyGame.Sample.Vec3.createVec3(builder, 4.0, 5.0, 6.0); + let path = builder.endVector(); + ``` + + +#### Unions + +The last non-scalar data field for the `Monster` table is the `equipped` `union` +field. For this case, we will reuse an already serialized `Weapon` (the only +type in the union), without needing to reserialize it. Union fields implicitly +add a hidden `_type` field that stores the type of value stored in the union. +When serializing a union, you must explicitly set this type field, along with +providing the union value. + +We will also serialize the other scalar data at the same time, since we have all +the necessary values and Offsets to make a `Monster`. + +=== "C++" + + ```c++ + // Create the remaining data needed for the Monster. + auto name = builder.CreateString("Orc"); + + // Create the position struct + auto position = Vec3(1.0f, 2.0f, 3.0f); + + // Set his hit points to 300 and his mana to 150. + int hp = 300; + int mana = 150; + + // Finally, create the monster using the `CreateMonster` helper function + // to set all fields. + // + // Here we set the union field by using the `.Union()` method of the + // `Offset` axe we already serialized above. We just have to specify + // which type of object we put in the union, and do that with the + // auto-generated `Equipment_Weapon` enum. + flatbuffers::Offset orc = + CreateMonster(builder, &position, mana, hp, name, inventory, + Color_Red, weapons, Equipment_Weapon, axe.Union(), + path); + + ``` + +=== "C" + + ```c + // Serialize a name for our monster, called "Orc". + // The _str suffix indicates the source is an ascii-z string. + flatbuffers_string_ref_t name = flatbuffers_string_create_str(B, "Orc"); + + // Set his hit points to 300 and his mana to 150. + uint16_t hp = 300; + uint16_t mana = 150; + + // Define an equipment union. `create` calls in C has a single + // argument for unions where C++ has both a type and a data argument. + ns(Equipment_union_ref_t) equipped = ns(Equipment_as_Weapon(axe)); + ns(Vec3_t) pos = { 1.0f, 2.0f, 3.0f }; + ns(Monster_create_as_root(B, &pos, mana, hp, name, inventory, ns(Color_Red), + weapons, equipped, path)); + ``` + +=== "C#" + + ```c# + // Create the remaining data needed for the Monster. + var name = builder.CreateString("Orc"); + + // Create our monster using `StartMonster()` and `EndMonster()`. + Monster.StartMonster(builder); + Monster.AddPos(builder, Vec3.CreateVec3(builder, 1.0f, 2.0f, 3.0f)); + Monster.AddHp(builder, (short)300); + Monster.AddName(builder, name); + Monster.AddInventory(builder, inv); + Monster.AddColor(builder, Color.Red); + Monster.AddWeapons(builder, weapons); + // For union fields, we explicitly add the auto-generated enum for the type + // of value stored in the union. + Monster.AddEquippedType(builder, Equipment.Weapon); + // And we just use the `.Value` property of the already serialized axe. + Monster.AddEquipped(builder, axe.Value); // Axe + Monster.AddPath(builder, path); + Offset orc = Monster.EndMonster(builder); + ``` + +=== "Dart" + + ```dart + // Serialize a name for our monster, called "Orc". + final int name = builder.writeString('Orc'); + + // Using the Builder API: + // Set his hit points to 300 and his mana to 150. + final int hp = 300; + final int mana = 150; + + final monster = new myGame.MonsterBuilder(builder) + ..begin() + ..addNameOffset(name) + ..addInventoryOffset(inventory) + ..addWeaponsOffset(weapons) + ..addEquippedType(myGame.EquipmentTypeId.Weapon) + ..addEquippedOffset(axe) + ..addHp(hp) + ..addMana(mana) + ..addPos(vec3Builder.finish(1.0, 2.0, 3.0)) + ..addPathOffset(path) + ..addColor(myGame.Color.Red); + + final int orc = monster.finish(); + ``` + +=== "Go" + + ```go + // Serialize a name for our monster, called "Orc". + name := builder.CreateString("Orc") + + // Create our monster using `MonsterStart()` and `MonsterEnd()`. + sample.MonsterStart(builder) + sample.MonsterAddPos(builder, sample.CreateVec3(builder, 1.0, 2.0, 3.0)) + sample.MonsterAddHp(builder, 300) + sample.MonsterAddName(builder, name) + sample.MonsterAddInventory(builder, inv) + sample.MonsterAddColor(builder, sample.ColorRed) + sample.MonsterAddWeapons(builder, weapons) + sample.MonsterAddEquippedType(builder, sample.EquipmentWeapon) + sample.MonsterAddEquipped(builder, axe) + sample.MonsterAddPath(builder, path) + orc := sample.MonsterEnd(builder) + ``` + +=== "Java" + + ```java + // Serialize a name for our monster, called "Orc". + int name = builder.createString("Orc"); + + // Create our monster using `startMonster()` and `endMonster()`. + Monster.startMonster(builder); + Monster.addPos(builder, Vec3.createVec3(builder, 1.0f, 2.0f, 3.0f)); + Monster.addName(builder, name); + Monster.addColor(builder, Color.Red); + Monster.addHp(builder, (short)300); + Monster.addInventory(builder, inv); + Monster.addWeapons(builder, weapons); + Monster.addEquippedType(builder, Equipment.Weapon); + Monster.addEquipped(builder, axe); + Monster.addPath(builder, path); + int orc = Monster.endMonster(builder); + ``` + +=== "JavaScript" + + ```javascript + // Serialize a name for our monster, called 'Orc'. + var name = builder.createString('Orc'); + + // Create our monster by using `startMonster()` and `endMonster()`. + MyGame.Sample.Monster.startMonster(builder); + MyGame.Sample.Monster.addPos(builder, + MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0)); + MyGame.Sample.Monster.addHp(builder, 300); + MyGame.Sample.Monster.addColor(builder, MyGame.Sample.Color.Red) + MyGame.Sample.Monster.addName(builder, name); + MyGame.Sample.Monster.addInventory(builder, inv); + MyGame.Sample.Monster.addWeapons(builder, weapons); + MyGame.Sample.Monster.addEquippedType(builder, + MyGame.Sample.Equipment.Weapon); + MyGame.Sample.Monster.addEquipped(builder, axe); + MyGame.Sample.Monster.addPath(builder, path); + var orc = MyGame.Sample.Monster.endMonster(builder); + ``` + +=== "Kotlin" + + ```kotlin + // Serialize a name for our monster, called "Orc". + val name = builder.createString("Orc") + + // Create our monster using `startMonster()` and `endMonster()`. + Monster.startMonster(builder) + Monster.addPos(builder, Vec3.createVec3(builder, 1.0f, 2.0f, 3.0f)) + Monster.addName(builder, name) + Monster.addColor(builder, Color.Red) + Monster.addHp(builder, 300.toShort()) + Monster.addInventory(builder, inv) + Monster.addWeapons(builder, weapons) + Monster.addEquippedType(builder, Equipment.Weapon) + Monster.addEquipped(builder, axe) + Monster.addPath(builder, path) + val orc = Monster.endMonster(builder) + ``` + +=== "Lobster" + + ```lobster + // Name of the monster. + let name = builder.CreateString("Orc") + + let orc = MyGame_Sample_MonsterBuilder { b } + .start() + .add_pos(b.MyGame_Sample_CreateVec3(1.0, 2.0, 3.0)) + .add_hp(300) + .add_name(name) + .add_inventory(inv) + .add_color(MyGame_Sample_Color_Red) + .add_weapons(weapons) + .add_equipped_type(MyGame_Sample_Equipment_Weapon) + .add_equipped(weapon_offsets[1]) + .add_path(path) + .end() + ``` + +=== "Lua" + + ```lua + -- Serialize a name for our monster, called 'orc' + local name = builder:CreateString("Orc") + + -- Create our monster by using Start() andEnd() + monster.Start(builder) + monster.AddPos(builder, vec3.CreateVec3(builder, 1.0, 2.0, 3.0)) + monster.AddHp(builder, 300) + monster.AddName(builder, name) + monster.AddInventory(builder, inv) + monster.AddColor(builder, color.Red) + monster.AddWeapons(builder, weapons) + monster.AddEquippedType(builder, equipment.Weapon) + monster.AddEquipped(builder, axe) + monster.AddPath(builder, path) + local orc = monster.End(builder) + ``` + +=== "PHP" + + ```php + // Serialize a name for our monster, called "Orc". + $name = $builder->createString("Orc"); + + // Create our monster by using `StartMonster()` and `EndMonster()`. + \MyGame\Sample\Monster::StartMonster($builder); + \MyGame\Sample\Monster::AddPos($builder, + \MyGame\Sample\Vec3::CreateVec3($builder, 1.0, 2.0, 3.0)); + \MyGame\Sample\Monster::AddHp($builder, 300); + \MyGame\Sample\Monster::AddName($builder, $name); + \MyGame\Sample\Monster::AddInventory($builder, $inv); + \MyGame\Sample\Monster::AddColor($builder, \MyGame\Sample\Color::Red); + \MyGame\Sample\Monster::AddWeapons($builder, $weapons); + \MyGame\Sample\Monster::AddEquippedType($builder, + \MyGame\Sample\Equipment::Weapon); + \MyGame\Sample\Monster::AddEquipped($builder, $axe); + \MyGame\Sample\Monster::AddPath($builder, $path); + $orc = \MyGame\Sample\Monster::EndMonster($builder); + ``` + +=== "Python" + + ```py + # Serialize a name for our monster, called "Orc". + name = builder.CreateString("Orc") + + # Create our monster by using `Monster.Start()` and `Monster.End()`. + MyGame.Sample.Monster.Start(builder) + MyGame.Sample.Monster.AddPos(builder, + MyGame.Sample.Vec3.CreateVec3(builder, 1.0, 2.0, 3.0)) + MyGame.Sample.Monster.AddHp(builder, 300) + MyGame.Sample.Monster.AddName(builder, name) + MyGame.Sample.Monster.AddInventory(builder, inv) + MyGame.Sample.Monster.AddColor(builder, + MyGame.Sample.Color.Color().Red) + MyGame.Sample.Monster.AddWeapons(builder, weapons) + MyGame.Sample.Monster.AddEquippedType( + builder, MyGame.Sample.Equipment.Equipment().Weapon) + MyGame.Sample.Monster.AddEquipped(builder, axe) + MyGame.Sample.Monster.AddPath(builder, path) + orc = MyGame.Sample.Monster.End(builder) + ``` + +=== "Rust" + + ```rust + // Name of the Monster. + let name = builder.create_string("Orc"); + + // Create the monster using the `Monster::create` helper function. This + // function accepts a `MonsterArgs` struct, which supplies all of the data + // needed to build a `Monster`. To supply empty/default fields, just use the + // Rust built-in `Default::default()` function, as demonstrated below. + let orc = Monster::create(&mut builder, &MonsterArgs{ + pos: Some(&Vec3::new(1.0f32, 2.0f32, 3.0f32)), + mana: 150, + hp: 80, + name: Some(name), + inventory: Some(inventory), + color: Color::Red, + weapons: Some(weapons), + equipped_type: Equipment::Weapon, + equipped: Some(axe.as_union_value()), + path: Some(path), + ..Default::default() + }); + ``` + +=== "Swift" + + ```swift + // Name of the Monster. + let name = builder.create(string: "Orc") + + let orc = Monster.createMonster( + &builder, + pos: MyGame_Sample_Vec3(x: 1, y: 2, z: 3), + hp: 300, + nameOffset: name, + inventoryVectorOffset: inventoryOffset, + color: .red, + weaponsVectorOffset: weaponsOffset, + equippedType: .weapon, + equippedOffset: axe) + ``` + +=== "TypeScript" + + ```ts + // Serialize a name for our monster, called 'Orc'. + let name = builder.createString('Orc'); + + // Create our monster by using `startMonster()` and `endMonster()`. + MyGame.Sample.Monster.startMonster(builder); + MyGame.Sample.Monster.addPos(builder, + MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0)); + MyGame.Sample.Monster.addHp(builder, 300); + MyGame.Sample.Monster.addColor(builder, MyGame.Sample.Color.Red) + MyGame.Sample.Monster.addName(builder, name); + MyGame.Sample.Monster.addInventory(builder, inv); + MyGame.Sample.Monster.addWeapons(builder, weapons); + MyGame.Sample.Monster.addEquippedType(builder, + MyGame.Sample.Equipment.Weapon); + MyGame.Sample.Monster.addEquipped(builder, axe); + MyGame.Sample.Monster.addPath(builder, path); + let orc = MyGame.Sample.Monster.endMonster(builder); + ``` + + +### Finishing + +At this point, we have serialized a `Monster` we've named "orc" to the +flatbuffer and have its offset. The `root_type` of the schema is also a +`Monster`, so we have everything we need to finish the serialization step. + +This is done by calling the appropriate `finish` method on the Builder, passing +in the orc offset to indicate this `table` is the "entry" point when +deserializing the buffer later. + +=== "C++" + + ```c++ + // Call `Finish()` to instruct the builder that this monster is complete. + // You could also call `FinishMonsterBuffer(builder, orc);` + builder.Finish(orc); + ``` + +=== "C" + + ```c + // Because we used `Monster_create_as_root`, we do not need a `finish` call + // in C. + ``` + +=== "C#" + + ```c# + // Call `Finish()` to instruct the builder that this monster is complete. + // You could also call `Monster.FinishMonsterBuffer(builder, orc);` + builder.Finish(orc.Value); + ``` + +=== "Dart" + + ```dart + // Call `finish()` to instruct the builder that this monster is complete. + // See the next code section, as in Dart `finish` will also return the byte + // array. + ``` + +=== "Go" + + ```go + // Call `Finish()` to instruct the builder that this monster is complete. + builder.Finish(orc) + ``` + +=== "Java" + + ```java + // Call `finish()` to instruct the builder that this monster is complete. + builder.finish(orc); + ``` + +=== "JavaScript" + + ```javascript + // Call `finish()` to instruct the builder that this monster is complete. + builder.finish(orc); + ``` + +=== "Kotlin" + + ```kotlin + // Call `finish()` to instruct the builder that this monster is complete. + builder.finish(orc) ; + ``` + +=== "Lobster" + + ```lobster + // Call `Finish()` to instruct the builder that this monster is complete. + builder.Finish(orc) + ``` + +=== "Lua" + + ```lua + -- Call 'Finish()' to instruct the builder that this monster is complete. + builder:Finish(orc) + ``` + +=== "PHP" + + ```php + // Call `finish()` to instruct the builder that this monster is complete. + $builder->finish($orc); + ``` + +=== "Python" + + ```py + # Call `Finish()` to instruct the builder that this monster is complete. + builder.Finish(orc) + ``` + +=== "Rust" + + ```rust + // Call `finish()` to instruct the builder that this monster is complete. + builder.finish(orc, None); + ``` + +=== "Swift" + + ```swift + // Call `finish()` to instruct the builder that this monster is complete. + builder.finish(offset: orc) + ``` + +=== "TypeScript" + + ```ts + // Call `finish()` to instruct the builder that this monster is complete. + builder.finish(orc); + ``` + + +Once you finish a Builder, you can no longer serialize more data to it. + +#### Buffer Access + +The flatbuffer is now ready to be stored somewhere, sent over the network, +compressed, or whatever you would like to do with it. You access the raw buffer +like so: + +=== "C++" + + ```c++ + // This must be called after `Finish()`. + uint8_t *buf = builder.GetBufferPointer(); + + // Returns the size of the buffer that `GetBufferPointer()` points to. + int size = builder.GetSize(); + ``` + +=== "C" + + ```c + uint8_t *buf; + size_t size; + + // Allocate and extract a readable buffer from internal builder heap. + // The returned buffer must be deallocated using `free`. + // NOTE: Finalizing the buffer does NOT change the builder, it + // just creates a snapshot of the builder content. + buf = flatcc_builder_finalize_buffer(B, &size); + // use buf + free(buf); + + // Optionally reset builder to reuse builder without deallocating + // internal stack and heap. + flatcc_builder_reset(B); + // build next buffer. + // ... + + // Cleanup. + flatcc_builder_clear(B); + ``` + +=== "C#" + + ```c# + // This must be called after `Finish()`. + // + // The data in this ByteBuffer does NOT start at 0, but at buf.Position. + // The end of the data is marked by buf.Length, so the size is + // buf.Length - buf.Position. + FlatBuffers.ByteBuffer dataBuffer = builder.DataBuffer; + + // Alternatively this copies the above data out of the ByteBuffer for you: + byte[] buf = builder.SizedByteArray(); + ``` + +=== "Dart" + + ```dart + final Uint8List buf = builder.finish(orc); + ``` + +=== "Go" + + ```go + // This must be called after `Finish()`. + buf := builder.FinishedBytes() // Of type `byte[]`. + ``` + +=== "Java" + + ```java + // This must be called after `finish()`. + java.nio.ByteBuffer buf = builder.dataBuffer(); + // The data in this ByteBuffer does NOT start at 0, but at buf.position(). + // The number of bytes is buf.remaining(). + + // Alternatively this copies the above data out of the ByteBuffer for you: + byte[] buf = builder.sizedByteArray(); + ``` + +=== "JavaScript" + + ```javascript + // This must be called after `finish()`. + var buf = builder.asUint8Array(); // Of type `Uint8Array`. + ``` + +=== "Kotlin" + + ```kotlin + // This must be called after `finish()`. + val buf = builder.dataBuffer() + // The data in this ByteBuffer does NOT start at 0, but at buf.position(). + // The number of bytes is buf.remaining(). + + // Alternatively this copies the above data out of the ByteBuffer for you: + val buf = builder.sizedByteArray() + ``` + +=== "Lobster" + + ```lobster + // This must be called after `Finish()`. + let buf = builder.SizedCopy() // Of type `string`. + ``` + +=== "Lua" + + ```lua + local bufAsString = builder:Output() + ``` + +=== "PHP" + + ```php + // This must be called after `finish()`. + $buf = $builder->dataBuffer(); // Of type `Google\FlatBuffers\ByteBuffer` + // The data in this ByteBuffer does NOT start at 0, but at + // buf->getPosition(). + // The end of the data is marked by buf->capacity(), so the size is + // buf->capacity() - buf->getPosition(). + ``` + +=== "Python" + + ```py + # This must be called after `Finish()`. + buf = builder.Output() // Of type `bytearray`. + ``` + +=== "Rust" + + ```rust + // This must be called after `finish()`. + // `finished_data` returns a byte slice. + let buf = builder.finished_data(); // Of type `&[u8]` + ``` + +=== "Swift" + + ```swift + // This must be called after `finish()`. + // `sizedByteArray` returns the finished buf of type [UInt8]. + let buf = builder.sizedByteArray + // or you can use to get an object of type Data + let bufData = ByteBuffer(data: builder.data) + // or + let buf = builder.sizedBuffer + ``` + +=== "TypeScript" + + ```ts + // This must be called after `finish()`. + let buf = builder.asUint8Array(); // Of type `Uint8Array`. + ``` + + +Now you can write the bytes to a file or send them over the network. The buffer +stays valid until the Builder is cleared or destroyed. + +Make sure your file mode (or transfer protocol) is set to BINARY, and not TEXT. +If you try to transfer a flatbuffer in TEXT mode, the buffer will be corrupted +and be hard to diagnose. + +## Deserialization + +Deserialization is a bit of a misnomer, since FlatBuffers doesn't deserialize +the whole buffer when accessed. It just "decodes" the data that is requested, +leaving all the other data untouched. It is up to the application to decide if +the data is copied out or even read in the first place. However, we continue to +use the word `deserialize` to mean accessing data from a binary flatbuffer. + +Now that we have successfully create an orc FlatBuffer, the data can be saved, +sent over a network, etc. At some point, the buffer will be accessed to obtain +the underlying data. + +The same application setup used for serialization is needed for deserialization +(see [application integration](#application-integration)). + +### Root Access + +All access to the data in the flatbuffer must first go through the root object. +There is only one root object per flatbuffer. The generated code provides +functions to get the root object given the buffer. + +=== "C++" + + ```c++ + uint8_t *buffer_pointer = /* the data you just read */; + + // Get an view to the root object inside the buffer. + Monster monster = GetMonster(buffer_pointer); + ``` + +=== "C" + + ```c + // Note that we use the `table_t` suffix when reading a table object + // as opposed to the `ref_t` suffix used during the construction of + // the buffer. + ns(Monster_table_t) monster = ns(Monster_as_root(buffer)); + + // Note: root object pointers are NOT the same as the `buffer` pointer. + ``` + +=== "C#" + + ```c# + byte[] bytes = /* the data you just read */ + + // Get an view to the root object inside the buffer. + Monster monster = Monster.GetRootAsMonster(new ByteBuffer(bytes)); + ``` + +=== "Dart" + + ```dart + List data = ... // the data, e.g. from file or network + // A generated factory constructor that will read the data. + myGame.Monster monster = new myGame.Monster(data); + ``` + +=== "Go" + + ```go + var buf []byte = /* the data you just read */ + + // Get an accessor to the root object inside the buffer. + monster := sample.GetRootAsMonster(buf, 0) + + // Note: We use `0` for the offset here, which is typical for most buffers + // you would read. If you wanted to read from `builder.Bytes` directly, you + // would need to pass in the offset of `builder.Head()`, as the builder + // constructs the buffer backwards, so may not start at offset 0. + ``` + +=== "Java" + + ```java + byte[] bytes = /* the data you just read */ + java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(bytes); + + // Get an accessor to the root object inside the buffer. + Monster monster = Monster.getRootAsMonster(buf); + ``` + +=== "JavaScript" + + ```javascript + // the data you just read, as a `Uint8Array` + // Note that the example here uses `readFileSync` from the built-in `fs` + // module, but other methods for accessing the file contents will also work. + var bytes = new Uint8Array(readFileSync('./monsterdata.bin')); + + var buf = new flatbuffers.ByteBuffer(bytes); + + // Get an accessor to the root object inside the buffer. + var monster = MyGame.Sample.Monster.getRootAsMonster(buf); + ``` + +=== "Kotlin" + + ```kotlin + val bytes = /* the data you just read */ + val buf = java.nio.ByteBuffer.wrap(bytes) + + // Get an accessor to the root object inside the buffer. + Monster monster = Monster.getRootAsMonster(buf) + ``` + +=== "Lobster" + + ```lobster + buf = /* the data you just read, in a string */ + + // Get an accessor to the root object inside the buffer. + let monster = MyGame_Sample_GetRootAsMonster(buf) + ``` + +=== "Lua" + + ```lua + local bufAsString = -- The data you just read in + + -- Convert the string representation into binary array Lua structure + local buf = flatbuffers.binaryArray.New(bufAsString) + + -- Get an accessor to the root object insert the buffer + local mon = monster.GetRootAsMonster(buf, 0) + ``` + +=== "PHP" + + ```php + $bytes = /* the data you just read, in a string */ + $buf = Google\FlatBuffers\ByteBuffer::wrap($bytes); + + // Get an accessor to the root object inside the buffer. + $monster = \MyGame\Sample\Monster::GetRootAsMonster($buf); + ``` + +=== "Python" + + ```py + buf = /* the data you just read, in an object of type "bytearray" */ + + # Get an accessor to the root object inside the buffer. + monster = MyGame.Sample.Monster.Monster.GetRootAs(buf, 0) + + # Note: We use `0` for the offset here, which is typical for most buffers + # you would read. If you wanted to read from the `builder.Bytes` directly, + # you would need to pass in the offset of `builder.Head()`, as the builder + # constructs the buffer backwards, so may not start at offset 0. + ``` + +=== "Rust" + + ```rust + let buf = /* the data you just read, in a &[u8] */ + + // Get an accessor to the root object inside the buffer. + let monster = root_as_monster(buf).unwrap(); + ``` + +=== "Swift" + + ```swift + // create a ByteBuffer(:) from an [UInt8] or Data() + var buf = // Get your data + // Get an accessor to the root object inside the buffer. + let monster: Monster = try! getCheckedRoot(byteBuffer: &byteBuffer) + // let monster: Monster = getRoot(byteBuffer: &byteBuffer) + ``` + +=== "TypeScript" + + ```ts + // the data you just read, as a `Uint8Array`. + // Note that the example here uses `readFileSync` from the built-in `fs` + // module, but other methods for accessing the file contents will also work. + let bytes = new Uint8Array(readFileSync('./monsterdata.bin')); + + let buf = new flatbuffers.ByteBuffer(bytes); + + // Get an accessor to the root object inside the buffer. + let monster = MyGame.Sample.Monster.getRootAsMonster(buf); + ``` + + +Again, make sure you read the bytes in BINARY mode, otherwise the buffer may be +corrupted. + +In most languages, the returned object is just a "view" of the data with helpful +accessors. Data is typically not copied out of the backing buffer. This also +means the backing buffer must remain alive for the duration of the views. + +### Table Access + +If you look in the generated files emitted by `flatc`, you will see it generated +, for each `table`, accessors of all its non-`deprecated` fields. For example, +some of the accessors of the `Monster` root table would look like: + +=== "C++" + + ```c++ + auto hp = monster->hp(); + auto mana = monster->mana(); + auto name = monster->name()->c_str(); + ``` + +=== "C" + + ```c + uint16_t hp = ns(Monster_hp(monster)); + uint16_t mana = ns(Monster_mana(monster)); + flatbuffers_string_t name = ns(Monster_name(monster)); + ``` + +=== "C#" + + ```c# + // For C#, unlike most other languages support by FlatBuffers, most values + // (except for vectors and unions) are available as properties instead of + // accessor methods. + var hp = monster.Hp; + var mana = monster.Mana; + var name = monster.Name; + ``` + +=== "Dart" + + ```dart + // For Dart, unlike other languages support by FlatBuffers, most values + // are available as properties instead of accessor methods. + var hp = monster.hp; + var mana = monster.mana; + var name = monster.name; + ``` + +=== "Go" + + ```go + hp := monster.Hp() + mana := monster.Mana() + name := string(monster.Name()) // Note: `monster.Name()` returns a byte[]. + ``` + +=== "Java" + + ```java + short hp = monster.hp(); + short mana = monster.mana(); + String name = monster.name(); + ``` + +=== "JavaScript" + + ```javascript + var hp = monster.hp(); + var mana = monster.mana(); + var name = monster.name(); + ``` + +=== "Kotlin" + + ```kotlin + val hp = monster.hp + val mana = monster.mana + val name = monster.name + ``` + +=== "Lobster" + + ```lobster + let hp = monster.hp + let mana = monster.mana + let name = monster.name + ``` + +=== "Lua" + + ```lua + local hp = mon:Hp() + local mana = mon:Mana() + local name = mon:Name() + ``` + +=== "PHP" + + ```php + $hp = $monster->getHp(); + $mana = $monster->getMana(); + $name = monster->getName(); + ``` + +=== "Python" + + ```py + hp = monster.Hp() + mana = monster.Mana() + name = monster.Name() + ``` + +=== "Rust" + + ```rust + // Get and test some scalar types from the FlatBuffer. + let hp = monster.hp(); + let mana = monster.mana(); + let name = monster.name(); + ``` + +=== "Swift" + + ```swift + let hp = monster.hp + let mana = monster.mana + let name = monster.name // returns an optional string + ``` + +=== "TypeScript" + + ```ts + let hp = monster.hp(); + let mana = monster.mana(); + let name = monster.name(); + ``` + + +These accessors should hold the values `300`, `150`, and `"Orc"` respectively. + +The default value of `150` wasn't stored in the `mana` field, but we are still +able to retrieve it. That is because the generated accessors return a hard-coded +default value when it doesn't find the value in the buffer. + +#### Nested Object Access + +Accessing nested objects is very similar, with the nested field pointing to +another object type. Be careful, the field could be `null` if not present. + +For example, accessing the `pos` `struct`, which is type `Vec3` you would do: + +=== "C++" + + ```c++ + auto pos = monster->pos(); + auto x = pos->x(); + auto y = pos->y(); + auto z = pos->z(); + ``` + +=== "C" + + ```c + ns(Vec3_struct_t) pos = ns(Monster_pos(monster)); + float x = ns(Vec3_x(pos)); + float y = ns(Vec3_y(pos)); + float z = ns(Vec3_z(pos)); + ``` + +=== "C#" + + ```c# + var pos = monster.Pos.Value; + var x = pos.X; + var y = pos.Y; + var z = pos.Z; + ``` + +=== "Dart" + + ```dart + myGame.Vec3 pos = monster.pos; + double x = pos.x; + double y = pos.y; + double z = pos.z; + ``` + +=== "Go" + + ```go + pos := monster.Pos(nil) + x := pos.X() + y := pos.Y() + z := pos.Z() + + // Note: Whenever you access a new object, like in `Pos()`, a new temporary + // accessor object gets created. If your code is very performance sensitive, + // you can pass in a pointer to an existing `Vec3` instead of `nil`. This + // allows you to reuse it across many calls to reduce the amount of object + // allocation/garbage collection. + ``` + +=== "Java" + + ```java + Vec3 pos = monster.pos(); + float x = pos.x(); + float y = pos.y(); + float z = pos.z(); + ``` + +=== "JavaScript" + + ```javascript + var pos = monster.pos(); + var x = pos.x(); + var y = pos.y(); + var z = pos.z(); + ``` + +=== "Kotlin" + + ```kotlin + val pos = monster.pos!! + val x = pos.x + val y = pos.y + val z = pos.z + ``` + +=== "Lobster" + + ```lobster + let pos = monster.pos + let x = pos.x + let y = pos.y + let z = pos.z + ``` + +=== "Lua" + + ```lua + local pos = mon:Pos() + local x = pos:X() + local y = pos:Y() + local z = pos:Z() + ``` + +=== "PHP" + + ```php + $pos = $monster->getPos(); + $x = $pos->getX(); + $y = $pos->getY(); + $z = $pos->getZ(); + ``` + +=== "Python" + + ```py + pos = monster.Pos() + x = pos.X() + y = pos.Y() + z = pos.Z() + ``` + +=== "Rust" + + ```rust + let pos = monster.pos().unwrap(); + let x = pos.x(); + let y = pos.y(); + let z = pos.z(); + ``` + +=== "Swift" + + ```swift + let pos = monster.pos + let x = pos.x + let y = pos.y + let z = pos.z + ``` + +=== "TypeScript" + + ```ts + let pos = monster.pos(); + let x = pos.x(); + let y = pos.y(); + let z = pos.z(); + ``` + + +Where `x`, `y`, and `z` will contain `1.0`, `2.0`, and `3.0` respectively. + +### Vector Access + +Similarly, we can access elements of the `inventory` `vector` by indexing it. +You can also iterate over the length of the vector. + +=== "C++" + + ```c++ + flatbuffers::Vector inv = monster->inventory(); + auto inv_len = inv->size(); + auto third_item = inv->Get(2); + ``` + +=== "C" + + ```c + // If `inv` hasn't been set, it will be null. It is valid get + // the length of null which will be 0, useful for iteration. + flatbuffers_uint8_vec_t inv = ns(Monster_inventory(monster)); + size_t inv_len = flatbuffers_uint8_vec_len(inv); + ``` + +=== "C#" + + ```c# + int invLength = monster.InventoryLength; + var thirdItem = monster.Inventory(2); + ``` + +=== "Dart" + + ```dart + int invLength = monster.inventory.length; + var thirdItem = monster.inventory[2]; + ``` + +=== "Go" + + ```go + invLength := monster.InventoryLength() + thirdItem := monster.Inventory(2) + ``` + +=== "Java" + + ```java + int invLength = monster.inventoryLength(); + byte thirdItem = monster.inventory(2); + ``` + +=== "JavaScript" + + ```javascript + var invLength = monster.inventoryLength(); + var thirdItem = monster.inventory(2); + ``` + +=== "Kotlin" + + ```kotlin + val invLength = monster.inventoryLength + val thirdItem = monster.inventory(2)!! + ``` + +=== "Lobster" + + ```lobster + let inv_len = monster.inventory_length + let third_item = monster.inventory(2) + ``` + +=== "Lua" + + ```lua + local invLength = mon:InventoryLength() + local thirdItem = mon:Inventory(3) -- Lua is 1-based + ``` + +=== "PHP" + + ```php + $inv_len = $monster->getInventoryLength(); + $third_item = $monster->getInventory(2); + ``` + +=== "Python" + + ```py + inv_len = monster.InventoryLength() + third_item = monster.Inventory(2) + ``` + +=== "Rust" + + ```rust + // Get and test an element from the `inventory` FlatBuffer's `vector`. + let inv = monster.inventory().unwrap(); + + // Note that this vector is returned as a slice, because direct access for + // this type, a `u8` vector, is safe on all platforms: + let third_item = inv[2]; + ``` + +=== "Swift" + + ```swift + // Get a the count of objects in the vector + let count = monster.inventoryCount + + // get item at index 4 + let object = monster.inventory(at: 4) + + // or you can fetch the entire array + let inv = monster.inventory + // inv[4] should equal object + ``` + +=== "TypeScript" + + ```ts + let invLength = monster.inventoryLength(); + let thirdItem = monster.inventory(2); + ``` + + +For vectors of tables, you can access the elements like any other vector, except +you need to handle the result as a FlatBuffer table. Here we iterate over the +`weapons` vector that is houses `Weapon` `tables`. + +=== "C++" + + ```c++ + flatbuffers::Vector weapons = monster->weapons(); + auto weapon_len = weapons->size(); + auto second_weapon_name = weapons->Get(1)->name()->str(); + auto second_weapon_damage = weapons->Get(1)->damage() + ``` + +=== "C" + + ```c + ns(Weapon_vec_t) weapons = ns(Monster_weapons(monster)); + size_t weapons_len = ns(Weapon_vec_len(weapons)); + // We can use `const char *` instead of `flatbuffers_string_t`. + const char *second_weapon_name = + ns(Weapon_name(ns(Weapon_vec_at(weapons, 1)))); + uint16_t second_weapon_damage = + ns(Weapon_damage(ns(Weapon_vec_at(weapons, 1)))); + ``` + +=== "C#" + + ```c# + int weaponsLength = monster.WeaponsLength; + var secondWeaponName = monster.Weapons(1).Name; + var secondWeaponDamage = monster.Weapons(1).Damage; + ``` + +=== "Dart" + + ```dart + int weaponsLength = monster.weapons.length; + var secondWeaponName = monster.weapons[1].name; + var secondWeaponDamage = monster.Weapons[1].damage; + ``` + +=== "Go" + + ```go + weaponLength := monster.WeaponsLength() + // We need a `sample.Weapon` to pass into `monster.Weapons()` + // to capture the output of the function.k + weapon := new(sample.Weapon) + if monster.Weapons(weapon, 1) { + secondWeaponName := weapon.Name() + secondWeaponDamage := weapon.Damage() + } + ``` + +=== "Java" + + ```java + int weaponsLength = monster.weaponsLength(); + String secondWeaponName = monster.weapons(1).name(); + short secondWeaponDamage = monster.weapons(1).damage(); + ``` + +=== "JavaScript" + + ```javascript + var weaponsLength = monster.weaponsLength(); + var secondWeaponName = monster.weapons(1).name(); + var secondWeaponDamage = monster.weapons(1).damage(); + ``` + +=== "Kotlin" + + ```kotlin + val weaponsLength = monster.weaponsLength + val secondWeaponName = monster.weapons(1)!!.name + val secondWeaponDamage = monster.weapons(1)!!.damage + ``` + +=== "Lobster" + + ```lobster + let weapons_length = monster.weapons_length + let second_weapon_name = monster.weapons(1).name + let second_weapon_damage = monster.weapons(1).damage + ``` + +=== "Lua" + + ```lua + local weaponsLength = mon:WeaponsLength() + local secondWeaponName = mon:Weapon(2):Name() + local secondWeaponDamage = mon:Weapon(2):Damage() + ``` + +=== "PHP" + + ```php + $weapons_len = $monster->getWeaponsLength(); + $second_weapon_name = $monster->getWeapons(1)->getName(); + $second_weapon_damage = $monster->getWeapons(1)->getDamage(); + ``` + +=== "Python" + + ```py + weapons_length = monster.WeaponsLength() + second_weapon_name = monster.Weapons(1).Name() + second_weapon_damage = monster.Weapons(1).Damage() + ``` + +=== "Rust" + + ```rust + // Get and test the `weapons` FlatBuffers's `vector`. + let weps = monster.weapons().unwrap(); + let weps_len = weps.len(); + + let wep2 = weps.get(1); + let second_weapon_name = wep2.name(); + let second_weapon_damage = wep2.damage(); + ``` + +=== "Swift" + + ```swift + // Get the count of weapon objects + let wepsCount = monster.weaponsCount + + let weapon2 = monster.weapons(at: 1) + let weaponName = weapon2.name + let weaponDmg = weapon2.damage + ``` + +=== "TypeScript" + + ```ts + let weaponsLength = monster.weaponsLength(); + let secondWeaponName = monster.weapons(1).name(); + let secondWeaponDamage = monster.weapons(1).damage(); + ``` + + +### Union Access + +Lastly , we can access our `equipped` `union` field. Just like when we created +the union, we need to get both parts of the union: the type and the data. + +We can access the type to dynamically cast the data as needed (since the union +only stores a FlatBuffer `table`). + +=== "C++" + + ```c++ + auto union_type = monster.equipped_type(); + + if (union_type == Equipment_Weapon) { + // Requires `static_cast` to type `const Weapon*`. + auto weapon = static_cast(monster->equipped()); + + auto weapon_name = weapon->name()->str(); // "Axe" + auto weapon_damage = weapon->damage(); // 5 + } + ``` + +=== "C" + + ```c + // Access union type field. + if (ns(Monster_equipped_type(monster)) == ns(Equipment_Weapon)) { + // Cast to appropriate type: + // C allows for silent void pointer assignment, so we need no + // explicit cast. + ns(Weapon_table_t) weapon = ns(Monster_equipped(monster)); + const char *weapon_name = ns(Weapon_name(weapon)); // "Axe" + uint16_t weapon_damage = ns(Weapon_damage(weapon)); // 5 + } + ``` + +=== "C#" + + ```c# + var unionType = monster.EquippedType; + + if (unionType == Equipment.Weapon) { + var weapon = monster.Equipped().Value; + + var weaponName = weapon.Name; // "Axe" + var weaponDamage = weapon.Damage; // 5 + } + ``` + +=== "Dart" + + ```dart + var unionType = monster.equippedType.value; + + if (unionType == myGame.EquipmentTypeId.Weapon.value) { + myGame.Weapon weapon = mon.equipped as myGame.Weapon; + + var weaponName = weapon.name; // "Axe" + var weaponDamage = weapon.damage; // 5 + } + ``` + +=== "Go" + + ```go + // We need a `flatbuffers.Table` to capture the output of the + // `monster.Equipped()` function. + unionTable := new(flatbuffers.Table) + + if monster.Equipped(unionTable) { + unionType := monster.EquippedType() + + if unionType == sample.EquipmentWeapon { + // Create a `sample.Weapon` object that can be initialized with the + // contents of the `flatbuffers.Table` (`unionTable`), which was + // populated by `monster.Equipped()`. + unionWeapon = new(sample.Weapon) + unionWeapon.Init(unionTable.Bytes, unionTable.Pos) + + weaponName = unionWeapon.Name() + weaponDamage = unionWeapon.Damage() + } + } + ``` + +=== "Java" + + ```java + int unionType = monster.EquippedType(); + + if (unionType == Equipment.Weapon) { + // Requires an explicit cast to `Weapon`. + Weapon weapon = (Weapon)monster.equipped(new Weapon()); + + String weaponName = weapon.name(); // "Axe" + short weaponDamage = weapon.damage(); // 5 + } + ``` + +=== "JavaScript" + + ```javascript + var unionType = monster.equippedType(); + + if (unionType == MyGame.Sample.Equipment.Weapon) { + // 'Axe' + var weaponName = monster.equipped(new MyGame.Sample.Weapon()).name(); + // 5 + var weaponDamage = + monster.equipped(new MyGame.Sample.Weapon()).damage(); + } + ``` + +=== "Kotlin" + + ```kotlin + val unionType = monster.EquippedType + + if (unionType == Equipment.Weapon) { + // Requires an explicit cast to `Weapon`. + val weapon = monster.equipped(Weapon()) as Weapon + + val weaponName = weapon.name // "Axe" + val weaponDamage = weapon.damage // 5 + } + ``` + +=== "Lobster" + + ```lobster + union_type = monster.equipped_type + + if union_type == MyGame_Sample_Equipment_Weapon: + // `monster.equipped_as_Weapon` returns a FlatBuffer handle much like + // normal table fields, but this is only valid to call if we already + // know it is the correct type. + let union_weapon = monster.equipped_as_Weapon + + let weapon_name = union_weapon.name // "Axe" + let weapon_damage = union_weapon.damage // 5 + ``` + +=== "Lua" + + ```lua + local unionType = mon:EquippedType() + + if unionType == equipment.Weapon then + local unionWeapon = weapon.New() + unionWeapon:Init(mon:Equipped().bytes, mon:Equipped().pos) + + local weaponName = unionWeapon:Name() -- 'Axe' + local weaponDamage = unionWeapon:Damage() -- 5 + end + ``` + +=== "PHP" + + ```php + $union_type = $monster->getEquippedType(); + + if ($union_type == \MyGame\Sample\Equipment::Weapon) { + // "Axe" + $weapon_name = + $monster->getEquipped(new \MyGame\Sample\Weapon())->getName(); + // 5 + $weapon_damage = + $monster->getEquipped(new \MyGame\Sample\Weapon())->getDamage(); + } + ``` + +=== "Python" + + ```py + union_type = monster.EquippedType() + + if union_type == MyGame.Sample.Equipment.Equipment().Weapon: + # `monster.Equipped()` returns a `flatbuffers.Table`, which can be used + # to initialize a `MyGame.Sample.Weapon.Weapon()`. + union_weapon = MyGame.Sample.Weapon.Weapon() + union_weapon.Init(monster.Equipped().Bytes, monster.Equipped().Pos) + + weapon_name = union_weapon.Name() // 'Axe' + weapon_damage = union_weapon.Damage() // 5 + ``` + +=== "Rust" + + ```rust + // Get and test the `Equipment` union (`equipped` field). + // `equipped_as_weapon` returns a FlatBuffer handle much like normal table + // fields, but this will return `None` if the union is not actually of that + // type. + if monster.equipped_type() == Equipment::Weapon { + let equipped = monster.equipped_as_weapon().unwrap(); + let weapon_name = equipped.name(); + let weapon_damage = equipped.damage(); + ``` + +=== "Swift" + + ```swift + // Get and check if the monster has an equipped item + if monster.equippedType == .weapon { + let _weapon = monster.equipped(type: Weapon.self) + let name = _weapon.name // should return "Axe" + let dmg = _weapon.damage // should return 5 + } + ``` + +=== "TypeScript" + + ```ts + let unionType = monster.equippedType(); + + if (unionType == MyGame.Sample.Equipment.Weapon) { + // 'Axe' + let weaponName = monster.equipped(new MyGame.Sample.Weapon()).name(); + // 5 + let weaponDamage = monster.equipped(new MyGame.Sample.Weapon()).damage(); + } + ``` diff --git a/third_party/flatbuffers/docs/source/white_paper.md b/third_party/flatbuffers/docs/source/white_paper.md new file mode 100644 index 00000000000..dbad2cb35a0 --- /dev/null +++ b/third_party/flatbuffers/docs/source/white_paper.md @@ -0,0 +1,128 @@ +FlatBuffers white paper {#flatbuffers_white_paper} +======================= + +This document tries to shed some light on to the "why" of FlatBuffers, a +new serialization library. + +## Motivation + +Back in the good old days, performance was all about instructions and +cycles. Nowadays, processing units have run so far ahead of the memory +subsystem, that making an efficient application should start and finish +with thinking about memory. How much you use of it. How you lay it out +and access it. How you allocate it. When you copy it. + +Serialization is a pervasive activity in a lot programs, and a common +source of memory inefficiency, with lots of temporary data structures +needed to parse and represent data, and inefficient allocation patterns +and locality. + +If it would be possible to do serialization with no temporary objects, +no additional allocation, no copying, and good locality, this could be +of great value. The reason serialization systems usually don't manage +this is because it goes counter to forwards/backwards compatibility, and +platform specifics like endianness and alignment. + +FlatBuffers is what you get if you try anyway. + +In particular, FlatBuffers focus is on mobile hardware (where memory +size and memory bandwidth is even more constrained than on desktop +hardware), and applications that have the highest performance needs: +games. + +## FlatBuffers + +*This is a summary of FlatBuffers functionality, with some rationale. +A more detailed description can be found in the FlatBuffers +documentation.* + +### Summary + +A FlatBuffer is a binary buffer containing nested objects (structs, +tables, vectors,..) organized using offsets so that the data can be +traversed in-place just like any pointer-based data structure. Unlike +most in-memory data structures however, it uses strict rules of +alignment and endianness (always little) to ensure these buffers are +cross platform. Additionally, for objects that are tables, FlatBuffers +provides forwards/backwards compatibility and general optionality of +fields, to support most forms of format evolution. + +You define your object types in a schema, which can then be compiled to +C++ or Java for low to zero overhead reading & writing. +Optionally, JSON data can be dynamically parsed into buffers. + +### Tables + +Tables are the cornerstone of FlatBuffers, since format evolution is +essential for most applications of serialization. Typically, dealing +with format changes is something that can be done transparently during +the parsing process of most serialization solutions out there. +But a FlatBuffer isn't parsed before it is accessed. + +Tables get around this by using an extra indirection to access fields, +through a *vtable*. Each table comes with a vtable (which may be shared +between multiple tables with the same layout), and contains information +where fields for this particular kind of instance of vtable are stored. +The vtable may also indicate that the field is not present (because this +FlatBuffer was written with an older version of the software, or simply +because the information was not necessary for this instance, or deemed +deprecated), in which case a default value is returned. + +Tables have a low overhead in memory (since vtables are small and +shared) and in access cost (an extra indirection), but provide great +flexibility. Tables may even cost less memory than the equivalent +struct, since fields do not need to be stored when they are equal to +their default. + +FlatBuffers additionally offers "naked" structs, which do not offer +forwards/backwards compatibility, but can be even smaller (useful for +very small objects that are unlikely to change, like e.g. a coordinate +pair or a RGBA color). + +### Schemas + +While schemas reduce some generality (you can't just read any data +without having its schema), they have a lot of upsides: + +- Most information about the format can be factored into the generated + code, reducing memory needed to store data, and time to access it. + +- The strong typing of the data definitions means less error + checking/handling at runtime (less can go wrong). + +- A schema enables us to access a buffer without parsing. + +FlatBuffer schemas are fairly similar to those of the incumbent, +Protocol Buffers, and generally should be readable to those familiar +with the C family of languages. We chose to improve upon the features +offered by .proto files in the following ways: + +- Deprecation of fields instead of manual field id assignment. + Extending an object in a .proto means hunting for a free slot among + the numbers (preferring lower numbers since they have a more compact + representation). Besides being inconvenient, it also makes removing + fields problematic: you either have to keep them, not making it + obvious that this field shouldn't be read/written anymore, and still + generating accessors. Or you remove it, but now you risk that + there's still old data around that uses that field by the time + someone reuses that field id, with nasty consequences. + +- Differentiating between tables and structs (see above). Effectively + all table fields are `optional`, and all struct fields are + `required`. + +- Having a native vector type instead of `repeated`. This gives you a + length without having to collect all items, and in the case of + scalars provides for a more compact representation, and one that + guarantees adjacency. + +- Having a native `union` type instead of using a series of `optional` + fields, all of which must be checked individually. + +- Being able to define defaults for all scalars, instead of having to + deal with their optionality at each access. + +- A parser that can deal with both schemas and data definitions (JSON + compatible) uniformly. + +
diff --git a/third_party/flatbuffers/eslint.config.mjs b/third_party/flatbuffers/eslint.config.mjs new file mode 100644 index 00000000000..4cba923cfdf --- /dev/null +++ b/third_party/flatbuffers/eslint.config.mjs @@ -0,0 +1,10 @@ +import globals from "globals"; +import pluginJs from "@eslint/js"; +import tseslint from "typescript-eslint"; + +export default [ + {files: ["**/*.{js,mjs,cjs,ts}"]}, + {languageOptions: { globals: {...globals.browser, ...globals.node} }}, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, +]; diff --git a/third_party/flatbuffers/examples/go-echo/README.md b/third_party/flatbuffers/examples/go-echo/README.md new file mode 100644 index 00000000000..acecee7e42e --- /dev/null +++ b/third_party/flatbuffers/examples/go-echo/README.md @@ -0,0 +1,27 @@ +# Go Echo Example + +A simple example demonstrating how to send flatbuffers over the network in Go. + +## Generate flatbuffer code + +``` +flatc -g --gen-object-api --go-module-name echo hero.fbs net.fbs +``` + +## Running example + +1. Run go mod tidy to get dependencies +``` +go mod tidy +``` + +2. Start a server +``` +go run server/server.go +``` + +3. Run the client in another terminal +``` +go run client/client.go +``` + diff --git a/third_party/flatbuffers/examples/go-echo/client/client.go b/third_party/flatbuffers/examples/go-echo/client/client.go new file mode 100644 index 00000000000..c6c1a3926d2 --- /dev/null +++ b/third_party/flatbuffers/examples/go-echo/client/client.go @@ -0,0 +1,51 @@ +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "net/http" + + "echo/hero" + "echo/net" + + flatbuffers "github.com/google/flatbuffers/go" +) + +func RequestBody() *bytes.Reader { + b := flatbuffers.NewBuilder(0) + r := net.RequestT{Player: &hero.WarriorT{Name: "Krull", Hp: 100}} + b.Finish(r.Pack(b)) + return bytes.NewReader(b.FinishedBytes()) +} + +func ReadResponse(r *http.Response) { + body, err := ioutil.ReadAll(r.Body) + if err != nil { + fmt.Printf("Unable to read request body: %v\n", err) + return + } + + res := net.GetRootAsResponse(body, 0) + player := res.Player(nil) + + fmt.Printf("Got response (name: %v, hp: %v)\n", string(player.Name()), player.Hp()) +} + +func main() { + body := RequestBody() + req, err := http.NewRequest("POST", "http://localhost:8080/echo", body) + if err != nil { + fmt.Println(err) + return + } + + client := http.DefaultClient + resp, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + + ReadResponse(resp) +} diff --git a/third_party/flatbuffers/examples/go-echo/go.mod b/third_party/flatbuffers/examples/go-echo/go.mod new file mode 100644 index 00000000000..81abc9b5b39 --- /dev/null +++ b/third_party/flatbuffers/examples/go-echo/go.mod @@ -0,0 +1,5 @@ +module echo + +go 1.19 + +require github.com/google/flatbuffers v22.10.26+incompatible diff --git a/third_party/flatbuffers/examples/go-echo/hero.fbs b/third_party/flatbuffers/examples/go-echo/hero.fbs new file mode 100644 index 00000000000..91b9dcaaf46 --- /dev/null +++ b/third_party/flatbuffers/examples/go-echo/hero.fbs @@ -0,0 +1,6 @@ +namespace hero; + +table Warrior { + name: string; + hp: uint32; +} diff --git a/third_party/flatbuffers/examples/go-echo/hero/Warrior.go b/third_party/flatbuffers/examples/go-echo/hero/Warrior.go new file mode 100644 index 00000000000..a369043f0bc --- /dev/null +++ b/third_party/flatbuffers/examples/go-echo/hero/Warrior.go @@ -0,0 +1,100 @@ +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package hero + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type WarriorT struct { + Name string `json:"name"` + Hp uint32 `json:"hp"` +} + +func (t *WarriorT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + if t == nil { + return 0 + } + nameOffset := flatbuffers.UOffsetT(0) + if t.Name != "" { + nameOffset = builder.CreateString(t.Name) + } + WarriorStart(builder) + WarriorAddName(builder, nameOffset) + WarriorAddHp(builder, t.Hp) + return WarriorEnd(builder) +} + +func (rcv *Warrior) UnPackTo(t *WarriorT) { + t.Name = string(rcv.Name()) + t.Hp = rcv.Hp() +} + +func (rcv *Warrior) UnPack() *WarriorT { + if rcv == nil { + return nil + } + t := &WarriorT{} + rcv.UnPackTo(t) + return t +} + +type Warrior struct { + _tab flatbuffers.Table +} + +func GetRootAsWarrior(buf []byte, offset flatbuffers.UOffsetT) *Warrior { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Warrior{} + x.Init(buf, n+offset) + return x +} + +func GetSizePrefixedRootAsWarrior(buf []byte, offset flatbuffers.UOffsetT) *Warrior { + n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:]) + x := &Warrior{} + x.Init(buf, n+offset+flatbuffers.SizeUint32) + return x +} + +func (rcv *Warrior) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Warrior) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Warrior) Name() []byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return rcv._tab.ByteVector(o + rcv._tab.Pos) + } + return nil +} + +func (rcv *Warrior) Hp() uint32 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return rcv._tab.GetUint32(o + rcv._tab.Pos) + } + return 0 +} + +func (rcv *Warrior) MutateHp(n uint32) bool { + return rcv._tab.MutateUint32Slot(6, n) +} + +func WarriorStart(builder *flatbuffers.Builder) { + builder.StartObject(2) +} +func WarriorAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(name), 0) +} +func WarriorAddHp(builder *flatbuffers.Builder, hp uint32) { + builder.PrependUint32Slot(1, hp, 0) +} +func WarriorEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/third_party/flatbuffers/examples/go-echo/net.fbs b/third_party/flatbuffers/examples/go-echo/net.fbs new file mode 100644 index 00000000000..7293bb699d1 --- /dev/null +++ b/third_party/flatbuffers/examples/go-echo/net.fbs @@ -0,0 +1,11 @@ +include "hero.fbs"; + +namespace net; + +table Request { + player: hero.Warrior; +} + +table Response { + player: hero.Warrior; +} diff --git a/third_party/flatbuffers/examples/go-echo/net/Request.go b/third_party/flatbuffers/examples/go-echo/net/Request.go new file mode 100644 index 00000000000..4c833626540 --- /dev/null +++ b/third_party/flatbuffers/examples/go-echo/net/Request.go @@ -0,0 +1,86 @@ +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package net + +import ( + flatbuffers "github.com/google/flatbuffers/go" + + hero "echo/hero" +) + +type RequestT struct { + Player *hero.WarriorT `json:"player"` +} + +func (t *RequestT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + if t == nil { + return 0 + } + playerOffset := t.Player.Pack(builder) + RequestStart(builder) + RequestAddPlayer(builder, playerOffset) + return RequestEnd(builder) +} + +func (rcv *Request) UnPackTo(t *RequestT) { + t.Player = rcv.Player(nil).UnPack() +} + +func (rcv *Request) UnPack() *RequestT { + if rcv == nil { + return nil + } + t := &RequestT{} + rcv.UnPackTo(t) + return t +} + +type Request struct { + _tab flatbuffers.Table +} + +func GetRootAsRequest(buf []byte, offset flatbuffers.UOffsetT) *Request { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Request{} + x.Init(buf, n+offset) + return x +} + +func GetSizePrefixedRootAsRequest(buf []byte, offset flatbuffers.UOffsetT) *Request { + n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:]) + x := &Request{} + x.Init(buf, n+offset+flatbuffers.SizeUint32) + return x +} + +func (rcv *Request) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Request) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Request) Player(obj *hero.Warrior) *hero.Warrior { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(hero.Warrior) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +func RequestStart(builder *flatbuffers.Builder) { + builder.StartObject(1) +} +func RequestAddPlayer(builder *flatbuffers.Builder, player flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(player), 0) +} +func RequestEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/third_party/flatbuffers/examples/go-echo/net/Response.go b/third_party/flatbuffers/examples/go-echo/net/Response.go new file mode 100644 index 00000000000..a9d1f43783e --- /dev/null +++ b/third_party/flatbuffers/examples/go-echo/net/Response.go @@ -0,0 +1,86 @@ +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package net + +import ( + flatbuffers "github.com/google/flatbuffers/go" + + hero "echo/hero" +) + +type ResponseT struct { + Player *hero.WarriorT `json:"player"` +} + +func (t *ResponseT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + if t == nil { + return 0 + } + playerOffset := t.Player.Pack(builder) + ResponseStart(builder) + ResponseAddPlayer(builder, playerOffset) + return ResponseEnd(builder) +} + +func (rcv *Response) UnPackTo(t *ResponseT) { + t.Player = rcv.Player(nil).UnPack() +} + +func (rcv *Response) UnPack() *ResponseT { + if rcv == nil { + return nil + } + t := &ResponseT{} + rcv.UnPackTo(t) + return t +} + +type Response struct { + _tab flatbuffers.Table +} + +func GetRootAsResponse(buf []byte, offset flatbuffers.UOffsetT) *Response { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Response{} + x.Init(buf, n+offset) + return x +} + +func GetSizePrefixedRootAsResponse(buf []byte, offset flatbuffers.UOffsetT) *Response { + n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:]) + x := &Response{} + x.Init(buf, n+offset+flatbuffers.SizeUint32) + return x +} + +func (rcv *Response) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Response) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Response) Player(obj *hero.Warrior) *hero.Warrior { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(hero.Warrior) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +func ResponseStart(builder *flatbuffers.Builder) { + builder.StartObject(1) +} +func ResponseAddPlayer(builder *flatbuffers.Builder, player flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(player), 0) +} +func ResponseEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/third_party/flatbuffers/examples/go-echo/server/server.go b/third_party/flatbuffers/examples/go-echo/server/server.go new file mode 100644 index 00000000000..c9885b899d3 --- /dev/null +++ b/third_party/flatbuffers/examples/go-echo/server/server.go @@ -0,0 +1,29 @@ +package main + +import ( + "echo/net" + "fmt" + "io/ioutil" + "net/http" +) + +func echo(w http.ResponseWriter, r *http.Request) { + body, err := ioutil.ReadAll(r.Body) + if err != nil { + fmt.Printf("Unable to read request body: %v\n", err) + return + } + + req := net.GetRootAsRequest(body, 0) + player := req.Player(nil) + + fmt.Printf("Got request (name: %v, hp: %v)\n", string(player.Name()), player.Hp()) + w.Write(body) +} + +func main() { + http.HandleFunc("/echo", echo) + + fmt.Println("Listening on port :8080") + http.ListenAndServe(":8080", nil) +} diff --git a/third_party/flatbuffers/extensions.bzl b/third_party/flatbuffers/extensions.bzl new file mode 100644 index 00000000000..c5865af2909 --- /dev/null +++ b/third_party/flatbuffers/extensions.bzl @@ -0,0 +1,19 @@ +"""Bzlmod extensions""" + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file") + +def _non_module_dependencies_impl(_ctx): + """Non module dependencies""" + http_file( + name = "bazel_linux_x86_64", + downloaded_file_path = "bazel", + executable = True, + sha256 = "e78fc3394deae5408d6f49a15c7b1e615901969ecf6e50d55ef899996b0b8458", + urls = [ + "https://github.com/bazelbuild/bazel/releases/download/6.3.2/bazel-6.3.2-linux-x86_64", + ], + ) + +non_module_dependencies = module_extension( + implementation = _non_module_dependencies_impl, +) diff --git a/third_party/flatbuffers/go/BUILD.bazel b/third_party/flatbuffers/go/BUILD.bazel new file mode 100644 index 00000000000..78bd8d81ada --- /dev/null +++ b/third_party/flatbuffers/go/BUILD.bazel @@ -0,0 +1,23 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +alias( + name = "go_default_library", + actual = ":go", + visibility = ["//visibility:public"], +) + +go_library( + name = "go", + srcs = [ + "builder.go", + "doc.go", + "encode.go", + "grpc.go", + "lib.go", + "sizes.go", + "struct.go", + "table.go", + ], + importpath = "github.com/google/flatbuffers/go", + visibility = ["//visibility:public"], +) diff --git a/third_party/flatbuffers/go/builder.go b/third_party/flatbuffers/go/builder.go new file mode 100644 index 00000000000..b76e8f9c0ab --- /dev/null +++ b/third_party/flatbuffers/go/builder.go @@ -0,0 +1,860 @@ +package flatbuffers + +import "sort" + +// Builder is a state machine for creating FlatBuffer objects. +// Use a Builder to construct object(s) starting from leaf nodes. +// +// A Builder constructs byte buffers in a last-first manner for simplicity and +// performance. +type Builder struct { + // `Bytes` gives raw access to the buffer. Most users will want to use + // FinishedBytes() instead. + Bytes []byte + + minalign int + vtable []UOffsetT + objectEnd UOffsetT + vtables []UOffsetT + head UOffsetT + nested bool + finished bool + + sharedStrings map[string]UOffsetT +} + +const fileIdentifierLength = 4 +const sizePrefixLength = 4 + +// NewBuilder initializes a Builder of size `initial_size`. +// The internal buffer is grown as needed. +func NewBuilder(initialSize int) *Builder { + if initialSize <= 0 { + initialSize = 0 + } + + b := &Builder{} + b.Bytes = make([]byte, initialSize) + b.head = UOffsetT(initialSize) + b.minalign = 1 + b.vtables = make([]UOffsetT, 0, 16) // sensible default capacity + return b +} + +// Reset truncates the underlying Builder buffer, facilitating alloc-free +// reuse of a Builder. It also resets bookkeeping data. +func (b *Builder) Reset() { + if b.Bytes != nil { + b.Bytes = b.Bytes[:cap(b.Bytes)] + } + + if b.vtables != nil { + b.vtables = b.vtables[:0] + } + + if b.vtable != nil { + b.vtable = b.vtable[:0] + } + + if b.sharedStrings != nil { + for key := range b.sharedStrings { + delete(b.sharedStrings, key) + } + } + + b.head = UOffsetT(len(b.Bytes)) + b.minalign = 1 + b.nested = false + b.finished = false +} + +// FinishedBytes returns a pointer to the written data in the byte buffer. +// Panics if the builder is not in a finished state (which is caused by calling +// `Finish()`). +func (b *Builder) FinishedBytes() []byte { + b.assertFinished() + return b.Bytes[b.Head():] +} + +// StartObject initializes bookkeeping for writing a new object. +func (b *Builder) StartObject(numfields int) { + b.assertNotNested() + b.nested = true + + // use 32-bit offsets so that arithmetic doesn't overflow. + if cap(b.vtable) < numfields || b.vtable == nil { + b.vtable = make([]UOffsetT, numfields) + } else { + b.vtable = b.vtable[:numfields] + for i := 0; i < len(b.vtable); i++ { + b.vtable[i] = 0 + } + } + + b.objectEnd = b.Offset() +} + +// WriteVtable serializes the vtable for the current object, if applicable. +// +// Before writing out the vtable, this checks pre-existing vtables for equality +// to this one. If an equal vtable is found, point the object to the existing +// vtable and return. +// +// Because vtable values are sensitive to alignment of object data, not all +// logically-equal vtables will be deduplicated. +// +// A vtable has the following format: +// +// +// +// * N, where N is the number of fields in +// the schema for this type. Includes deprecated fields. +// +// Thus, a vtable is made of 2 + N elements, each SizeVOffsetT bytes wide. +// +// An object has the following format: +// +// +// + +func (b *Builder) WriteVtable() (n UOffsetT) { + // Prepend a zero scalar to the object. Later in this function we'll + // write an offset here that points to the object's vtable: + b.PrependSOffsetT(0) + + objectOffset := b.Offset() + existingVtable := UOffsetT(0) + + // Trim vtable of trailing zeroes. + i := len(b.vtable) - 1 + for ; i >= 0 && b.vtable[i] == 0; i-- { + } + b.vtable = b.vtable[:i+1] + + // Search backwards through existing vtables, because similar vtables + // are likely to have been recently appended. See + // BenchmarkVtableDeduplication for a case in which this heuristic + // saves about 30% of the time used in writing objects with duplicate + // tables. + for i := len(b.vtables) - 1; i >= 0; i-- { + // Find the other vtable, which is associated with `i`: + vt2Offset := b.vtables[i] + vt2Start := len(b.Bytes) - int(vt2Offset) + vt2Len := GetVOffsetT(b.Bytes[vt2Start:]) + + metadata := VtableMetadataFields * SizeVOffsetT + vt2End := vt2Start + int(vt2Len) + vt2 := b.Bytes[vt2Start+metadata : vt2End] + + // Compare the other vtable to the one under consideration. + // If they are equal, store the offset and break: + if vtableEqual(b.vtable, objectOffset, vt2) { + existingVtable = vt2Offset + break + } + } + + if existingVtable == 0 { + // Did not find a vtable, so write this one to the buffer. + + // Write out the current vtable in reverse , because + // serialization occurs in last-first order: + for i := len(b.vtable) - 1; i >= 0; i-- { + var off UOffsetT + if b.vtable[i] != 0 { + // Forward reference to field; + // use 32bit number to assert no overflow: + off = objectOffset - b.vtable[i] + } + + b.PrependVOffsetT(VOffsetT(off)) + } + + // The two metadata fields are written last. + + // First, store the object bytesize: + objectSize := objectOffset - b.objectEnd + b.PrependVOffsetT(VOffsetT(objectSize)) + + // Second, store the vtable bytesize: + vBytes := (len(b.vtable) + VtableMetadataFields) * SizeVOffsetT + b.PrependVOffsetT(VOffsetT(vBytes)) + + // Next, write the offset to the new vtable in the + // already-allocated SOffsetT at the beginning of this object: + objectStart := SOffsetT(len(b.Bytes)) - SOffsetT(objectOffset) + WriteSOffsetT(b.Bytes[objectStart:], + SOffsetT(b.Offset())-SOffsetT(objectOffset)) + + // Finally, store this vtable in memory for future + // deduplication: + b.vtables = append(b.vtables, b.Offset()) + } else { + // Found a duplicate vtable. + + objectStart := SOffsetT(len(b.Bytes)) - SOffsetT(objectOffset) + b.head = UOffsetT(objectStart) + + // Write the offset to the found vtable in the + // already-allocated SOffsetT at the beginning of this object: + WriteSOffsetT(b.Bytes[b.head:], + SOffsetT(existingVtable)-SOffsetT(objectOffset)) + } + + b.vtable = b.vtable[:0] + return objectOffset +} + +// EndObject writes data necessary to finish object construction. +func (b *Builder) EndObject() UOffsetT { + b.assertNested() + n := b.WriteVtable() + b.nested = false + return n +} + +// Doubles the size of the byteslice, and copies the old data towards the +// end of the new byteslice (since we build the buffer backwards). +func (b *Builder) growByteBuffer() { + if (int64(len(b.Bytes)) & int64(0xC0000000)) != 0 { + panic("cannot grow buffer beyond 2 gigabytes") + } + newLen := len(b.Bytes) * 2 + if newLen == 0 { + newLen = 1 + } + + if cap(b.Bytes) >= newLen { + b.Bytes = b.Bytes[:newLen] + } else { + extension := make([]byte, newLen-len(b.Bytes)) + b.Bytes = append(b.Bytes, extension...) + } + + middle := newLen / 2 + copy(b.Bytes[middle:], b.Bytes[:middle]) +} + +// Head gives the start of useful data in the underlying byte buffer. +// Note: unlike other functions, this value is interpreted as from the left. +func (b *Builder) Head() UOffsetT { + return b.head +} + +// Offset relative to the end of the buffer. +func (b *Builder) Offset() UOffsetT { + return UOffsetT(len(b.Bytes)) - b.head +} + +// Pad places zeros at the current offset. +func (b *Builder) Pad(n int) { + for i := 0; i < n; i++ { + b.PlaceByte(0) + } +} + +// Prep prepares to write an element of `size` after `additional_bytes` +// have been written, e.g. if you write a string, you need to align such +// the int length field is aligned to SizeInt32, and the string data follows it +// directly. +// If all you need to do is align, `additionalBytes` will be 0. +func (b *Builder) Prep(size, additionalBytes int) { + // Track the biggest thing we've ever aligned to. + if size > b.minalign { + b.minalign = size + } + // Find the amount of alignment needed such that `size` is properly + // aligned after `additionalBytes`: + alignSize := (^(len(b.Bytes) - int(b.Head()) + additionalBytes)) + 1 + alignSize &= (size - 1) + + // Reallocate the buffer if needed: + for int(b.head) <= alignSize+size+additionalBytes { + oldBufSize := len(b.Bytes) + b.growByteBuffer() + b.head += UOffsetT(len(b.Bytes) - oldBufSize) + } + b.Pad(alignSize) +} + +// PrependSOffsetT prepends an SOffsetT, relative to where it will be written. +func (b *Builder) PrependSOffsetT(off SOffsetT) { + b.Prep(SizeSOffsetT, 0) // Ensure alignment is already done. + if !(UOffsetT(off) <= b.Offset()) { + panic("unreachable: off <= b.Offset()") + } + off2 := SOffsetT(b.Offset()) - off + SOffsetT(SizeSOffsetT) + b.PlaceSOffsetT(off2) +} + +// PrependUOffsetT prepends an UOffsetT, relative to where it will be written. +func (b *Builder) PrependUOffsetT(off UOffsetT) { + b.Prep(SizeUOffsetT, 0) // Ensure alignment is already done. + if !(off <= b.Offset()) { + panic("unreachable: off <= b.Offset()") + } + off2 := b.Offset() - off + UOffsetT(SizeUOffsetT) + b.PlaceUOffsetT(off2) +} + +// StartVector initializes bookkeeping for writing a new vector. +// +// A vector has the following format: +// +// +// +, where T is the type of elements of this vector. +func (b *Builder) StartVector(elemSize, numElems, alignment int) UOffsetT { + b.assertNotNested() + b.nested = true + b.Prep(SizeUint32, elemSize*numElems) + b.Prep(alignment, elemSize*numElems) // Just in case alignment > int. + return b.Offset() +} + +// EndVector writes data necessary to finish vector construction. +func (b *Builder) EndVector(vectorNumElems int) UOffsetT { + b.assertNested() + + // we already made space for this, so write without PrependUint32 + b.PlaceUOffsetT(UOffsetT(vectorNumElems)) + + b.nested = false + return b.Offset() +} + +// CreateVectorOfTables serializes slice of table offsets into a vector. +func (b *Builder) CreateVectorOfTables(offsets []UOffsetT) UOffsetT { + b.assertNotNested() + b.StartVector(4, len(offsets), 4) + for i := len(offsets) - 1; i >= 0; i-- { + b.PrependUOffsetT(offsets[i]) + } + return b.EndVector(len(offsets)) +} + +type KeyCompare func(o1, o2 UOffsetT, buf []byte) bool + +func (b *Builder) CreateVectorOfSortedTables(offsets []UOffsetT, keyCompare KeyCompare) UOffsetT { + sort.Slice(offsets, func(i, j int) bool { + return keyCompare(offsets[i], offsets[j], b.Bytes) + }) + return b.CreateVectorOfTables(offsets) +} + +// CreateSharedString Checks if the string is already written +// to the buffer before calling CreateString +func (b *Builder) CreateSharedString(s string) UOffsetT { + if b.sharedStrings == nil { + b.sharedStrings = make(map[string]UOffsetT) + } + if v, ok := b.sharedStrings[s]; ok { + return v + } + off := b.CreateString(s) + b.sharedStrings[s] = off + return off +} + +// CreateString writes a null-terminated string as a vector. +func (b *Builder) CreateString(s string) UOffsetT { + b.assertNotNested() + b.nested = true + + b.Prep(int(SizeUOffsetT), (len(s)+1)*SizeByte) + b.PlaceByte(0) + + l := UOffsetT(len(s)) + + b.head -= l + copy(b.Bytes[b.head:b.head+l], s) + + return b.EndVector(len(s)) +} + +// CreateByteString writes a byte slice as a string (null-terminated). +func (b *Builder) CreateByteString(s []byte) UOffsetT { + b.assertNotNested() + b.nested = true + + b.Prep(int(SizeUOffsetT), (len(s)+1)*SizeByte) + b.PlaceByte(0) + + l := UOffsetT(len(s)) + + b.head -= l + copy(b.Bytes[b.head:b.head+l], s) + + return b.EndVector(len(s)) +} + +// CreateByteVector writes a ubyte vector +func (b *Builder) CreateByteVector(v []byte) UOffsetT { + b.assertNotNested() + b.nested = true + + b.Prep(int(SizeUOffsetT), len(v)*SizeByte) + + l := UOffsetT(len(v)) + + b.head -= l + copy(b.Bytes[b.head:b.head+l], v) + + return b.EndVector(len(v)) +} + +func (b *Builder) assertNested() { + // If you get this assert, you're in an object while trying to write + // data that belongs outside of an object. + // To fix this, write non-inline data (like vectors) before creating + // objects. + if !b.nested { + panic("Incorrect creation order: must be inside object.") + } +} + +func (b *Builder) assertNotNested() { + // If you hit this, you're trying to construct a Table/Vector/String + // during the construction of its parent table (between the MyTableBuilder + // and builder.Finish()). + // Move the creation of these sub-objects to above the MyTableBuilder to + // not get this assert. + // Ignoring this assert may appear to work in simple cases, but the reason + // it is here is that storing objects in-line may cause vtable offsets + // to not fit anymore. It also leads to vtable duplication. + if b.nested { + panic("Incorrect creation order: object must not be nested.") + } +} + +func (b *Builder) assertFinished() { + // If you get this assert, you're attempting to get access a buffer + // which hasn't been finished yet. Be sure to call builder.Finish() + // with your root table. + // If you really need to access an unfinished buffer, use the Bytes + // buffer directly. + if !b.finished { + panic("Incorrect use of FinishedBytes(): must call 'Finish' first.") + } +} + +// PrependBoolSlot prepends a bool onto the object at vtable slot `o`. +// If value `x` equals default `d`, then the slot will be set to zero and no +// other data will be written. +func (b *Builder) PrependBoolSlot(o int, x, d bool) { + val := byte(0) + if x { + val = 1 + } + def := byte(0) + if d { + def = 1 + } + b.PrependByteSlot(o, val, def) +} + +// PrependByteSlot prepends a byte onto the object at vtable slot `o`. +// If value `x` equals default `d`, then the slot will be set to zero and no +// other data will be written. +func (b *Builder) PrependByteSlot(o int, x, d byte) { + if x != d { + b.PrependByte(x) + b.Slot(o) + } +} + +// PrependUint8Slot prepends a uint8 onto the object at vtable slot `o`. +// If value `x` equals default `d`, then the slot will be set to zero and no +// other data will be written. +func (b *Builder) PrependUint8Slot(o int, x, d uint8) { + if x != d { + b.PrependUint8(x) + b.Slot(o) + } +} + +// PrependUint16Slot prepends a uint16 onto the object at vtable slot `o`. +// If value `x` equals default `d`, then the slot will be set to zero and no +// other data will be written. +func (b *Builder) PrependUint16Slot(o int, x, d uint16) { + if x != d { + b.PrependUint16(x) + b.Slot(o) + } +} + +// PrependUint32Slot prepends a uint32 onto the object at vtable slot `o`. +// If value `x` equals default `d`, then the slot will be set to zero and no +// other data will be written. +func (b *Builder) PrependUint32Slot(o int, x, d uint32) { + if x != d { + b.PrependUint32(x) + b.Slot(o) + } +} + +// PrependUint64Slot prepends a uint64 onto the object at vtable slot `o`. +// If value `x` equals default `d`, then the slot will be set to zero and no +// other data will be written. +func (b *Builder) PrependUint64Slot(o int, x, d uint64) { + if x != d { + b.PrependUint64(x) + b.Slot(o) + } +} + +// PrependInt8Slot prepends a int8 onto the object at vtable slot `o`. +// If value `x` equals default `d`, then the slot will be set to zero and no +// other data will be written. +func (b *Builder) PrependInt8Slot(o int, x, d int8) { + if x != d { + b.PrependInt8(x) + b.Slot(o) + } +} + +// PrependInt16Slot prepends a int16 onto the object at vtable slot `o`. +// If value `x` equals default `d`, then the slot will be set to zero and no +// other data will be written. +func (b *Builder) PrependInt16Slot(o int, x, d int16) { + if x != d { + b.PrependInt16(x) + b.Slot(o) + } +} + +// PrependInt32Slot prepends a int32 onto the object at vtable slot `o`. +// If value `x` equals default `d`, then the slot will be set to zero and no +// other data will be written. +func (b *Builder) PrependInt32Slot(o int, x, d int32) { + if x != d { + b.PrependInt32(x) + b.Slot(o) + } +} + +// PrependInt64Slot prepends a int64 onto the object at vtable slot `o`. +// If value `x` equals default `d`, then the slot will be set to zero and no +// other data will be written. +func (b *Builder) PrependInt64Slot(o int, x, d int64) { + if x != d { + b.PrependInt64(x) + b.Slot(o) + } +} + +// PrependFloat32Slot prepends a float32 onto the object at vtable slot `o`. +// If value `x` equals default `d`, then the slot will be set to zero and no +// other data will be written. +func (b *Builder) PrependFloat32Slot(o int, x, d float32) { + if x != d { + b.PrependFloat32(x) + b.Slot(o) + } +} + +// PrependFloat64Slot prepends a float64 onto the object at vtable slot `o`. +// If value `x` equals default `d`, then the slot will be set to zero and no +// other data will be written. +func (b *Builder) PrependFloat64Slot(o int, x, d float64) { + if x != d { + b.PrependFloat64(x) + b.Slot(o) + } +} + +// PrependUOffsetTSlot prepends an UOffsetT onto the object at vtable slot `o`. +// If value `x` equals default `d`, then the slot will be set to zero and no +// other data will be written. +func (b *Builder) PrependUOffsetTSlot(o int, x, d UOffsetT) { + if x != d { + b.PrependUOffsetT(x) + b.Slot(o) + } +} + +// PrependStructSlot prepends a struct onto the object at vtable slot `o`. +// Structs are stored inline, so nothing additional is being added. +// In generated code, `d` is always 0. +func (b *Builder) PrependStructSlot(voffset int, x, d UOffsetT) { + if x != d { + b.assertNested() + if x != b.Offset() { + panic("inline data write outside of object") + } + b.Slot(voffset) + } +} + +// Slot sets the vtable key `voffset` to the current location in the buffer. +func (b *Builder) Slot(slotnum int) { + b.vtable[slotnum] = UOffsetT(b.Offset()) +} + +// FinishWithFileIdentifier finalizes a buffer, pointing to the given `rootTable`. +// as well as applys a file identifier +func (b *Builder) FinishWithFileIdentifier(rootTable UOffsetT, fid []byte) { + if fid == nil || len(fid) != fileIdentifierLength { + panic("incorrect file identifier length") + } + // In order to add a file identifier to the flatbuffer message, we need + // to prepare an alignment and file identifier length + b.Prep(b.minalign, SizeInt32+fileIdentifierLength) + for i := fileIdentifierLength - 1; i >= 0; i-- { + // place the file identifier + b.PlaceByte(fid[i]) + } + // finish + b.Finish(rootTable) +} + +// FinishSizePrefixed finalizes a buffer, pointing to the given `rootTable`. +// The buffer is prefixed with the size of the buffer, excluding the size +// of the prefix itself. +func (b *Builder) FinishSizePrefixed(rootTable UOffsetT) { + b.finish(rootTable, true) +} + +// FinishSizePrefixedWithFileIdentifier finalizes a buffer, pointing to the given `rootTable` +// and applies a file identifier. The buffer is prefixed with the size of the buffer, +// excluding the size of the prefix itself. +func (b *Builder) FinishSizePrefixedWithFileIdentifier(rootTable UOffsetT, fid []byte) { + if fid == nil || len(fid) != fileIdentifierLength { + panic("incorrect file identifier length") + } + // In order to add a file identifier and size prefix to the flatbuffer message, + // we need to prepare an alignment, a size prefix length, and file identifier length + b.Prep(b.minalign, SizeInt32+fileIdentifierLength+sizePrefixLength) + for i := fileIdentifierLength - 1; i >= 0; i-- { + // place the file identifier + b.PlaceByte(fid[i]) + } + // finish + b.finish(rootTable, true) +} + +// Finish finalizes a buffer, pointing to the given `rootTable`. +func (b *Builder) Finish(rootTable UOffsetT) { + b.finish(rootTable, false) +} + +// finish finalizes a buffer, pointing to the given `rootTable` +// with an optional size prefix. +func (b *Builder) finish(rootTable UOffsetT, sizePrefix bool) { + b.assertNotNested() + + if sizePrefix { + b.Prep(b.minalign, SizeUOffsetT+sizePrefixLength) + } else { + b.Prep(b.minalign, SizeUOffsetT) + } + + b.PrependUOffsetT(rootTable) + + if sizePrefix { + b.PlaceUint32(uint32(b.Offset())) + } + + b.finished = true +} + +// vtableEqual compares an unwritten vtable to a written vtable. +func vtableEqual(a []UOffsetT, objectStart UOffsetT, b []byte) bool { + if len(a)*SizeVOffsetT != len(b) { + return false + } + + for i := 0; i < len(a); i++ { + x := GetVOffsetT(b[i*SizeVOffsetT : (i+1)*SizeVOffsetT]) + + // Skip vtable entries that indicate a default value. + if x == 0 && a[i] == 0 { + continue + } + + y := SOffsetT(objectStart) - SOffsetT(a[i]) + if SOffsetT(x) != y { + return false + } + } + return true +} + +// PrependBool prepends a bool to the Builder buffer. +// Aligns and checks for space. +func (b *Builder) PrependBool(x bool) { + b.Prep(SizeBool, 0) + b.PlaceBool(x) +} + +// PrependUint8 prepends a uint8 to the Builder buffer. +// Aligns and checks for space. +func (b *Builder) PrependUint8(x uint8) { + b.Prep(SizeUint8, 0) + b.PlaceUint8(x) +} + +// PrependUint16 prepends a uint16 to the Builder buffer. +// Aligns and checks for space. +func (b *Builder) PrependUint16(x uint16) { + b.Prep(SizeUint16, 0) + b.PlaceUint16(x) +} + +// PrependUint32 prepends a uint32 to the Builder buffer. +// Aligns and checks for space. +func (b *Builder) PrependUint32(x uint32) { + b.Prep(SizeUint32, 0) + b.PlaceUint32(x) +} + +// PrependUint64 prepends a uint64 to the Builder buffer. +// Aligns and checks for space. +func (b *Builder) PrependUint64(x uint64) { + b.Prep(SizeUint64, 0) + b.PlaceUint64(x) +} + +// PrependInt8 prepends a int8 to the Builder buffer. +// Aligns and checks for space. +func (b *Builder) PrependInt8(x int8) { + b.Prep(SizeInt8, 0) + b.PlaceInt8(x) +} + +// PrependInt16 prepends a int16 to the Builder buffer. +// Aligns and checks for space. +func (b *Builder) PrependInt16(x int16) { + b.Prep(SizeInt16, 0) + b.PlaceInt16(x) +} + +// PrependInt32 prepends a int32 to the Builder buffer. +// Aligns and checks for space. +func (b *Builder) PrependInt32(x int32) { + b.Prep(SizeInt32, 0) + b.PlaceInt32(x) +} + +// PrependInt64 prepends a int64 to the Builder buffer. +// Aligns and checks for space. +func (b *Builder) PrependInt64(x int64) { + b.Prep(SizeInt64, 0) + b.PlaceInt64(x) +} + +// PrependFloat32 prepends a float32 to the Builder buffer. +// Aligns and checks for space. +func (b *Builder) PrependFloat32(x float32) { + b.Prep(SizeFloat32, 0) + b.PlaceFloat32(x) +} + +// PrependFloat64 prepends a float64 to the Builder buffer. +// Aligns and checks for space. +func (b *Builder) PrependFloat64(x float64) { + b.Prep(SizeFloat64, 0) + b.PlaceFloat64(x) +} + +// PrependByte prepends a byte to the Builder buffer. +// Aligns and checks for space. +func (b *Builder) PrependByte(x byte) { + b.Prep(SizeByte, 0) + b.PlaceByte(x) +} + +// PrependVOffsetT prepends a VOffsetT to the Builder buffer. +// Aligns and checks for space. +func (b *Builder) PrependVOffsetT(x VOffsetT) { + b.Prep(SizeVOffsetT, 0) + b.PlaceVOffsetT(x) +} + +// PlaceBool prepends a bool to the Builder, without checking for space. +func (b *Builder) PlaceBool(x bool) { + b.head -= UOffsetT(SizeBool) + WriteBool(b.Bytes[b.head:], x) +} + +// PlaceUint8 prepends a uint8 to the Builder, without checking for space. +func (b *Builder) PlaceUint8(x uint8) { + b.head -= UOffsetT(SizeUint8) + WriteUint8(b.Bytes[b.head:], x) +} + +// PlaceUint16 prepends a uint16 to the Builder, without checking for space. +func (b *Builder) PlaceUint16(x uint16) { + b.head -= UOffsetT(SizeUint16) + WriteUint16(b.Bytes[b.head:], x) +} + +// PlaceUint32 prepends a uint32 to the Builder, without checking for space. +func (b *Builder) PlaceUint32(x uint32) { + b.head -= UOffsetT(SizeUint32) + WriteUint32(b.Bytes[b.head:], x) +} + +// PlaceUint64 prepends a uint64 to the Builder, without checking for space. +func (b *Builder) PlaceUint64(x uint64) { + b.head -= UOffsetT(SizeUint64) + WriteUint64(b.Bytes[b.head:], x) +} + +// PlaceInt8 prepends a int8 to the Builder, without checking for space. +func (b *Builder) PlaceInt8(x int8) { + b.head -= UOffsetT(SizeInt8) + WriteInt8(b.Bytes[b.head:], x) +} + +// PlaceInt16 prepends a int16 to the Builder, without checking for space. +func (b *Builder) PlaceInt16(x int16) { + b.head -= UOffsetT(SizeInt16) + WriteInt16(b.Bytes[b.head:], x) +} + +// PlaceInt32 prepends a int32 to the Builder, without checking for space. +func (b *Builder) PlaceInt32(x int32) { + b.head -= UOffsetT(SizeInt32) + WriteInt32(b.Bytes[b.head:], x) +} + +// PlaceInt64 prepends a int64 to the Builder, without checking for space. +func (b *Builder) PlaceInt64(x int64) { + b.head -= UOffsetT(SizeInt64) + WriteInt64(b.Bytes[b.head:], x) +} + +// PlaceFloat32 prepends a float32 to the Builder, without checking for space. +func (b *Builder) PlaceFloat32(x float32) { + b.head -= UOffsetT(SizeFloat32) + WriteFloat32(b.Bytes[b.head:], x) +} + +// PlaceFloat64 prepends a float64 to the Builder, without checking for space. +func (b *Builder) PlaceFloat64(x float64) { + b.head -= UOffsetT(SizeFloat64) + WriteFloat64(b.Bytes[b.head:], x) +} + +// PlaceByte prepends a byte to the Builder, without checking for space. +func (b *Builder) PlaceByte(x byte) { + b.head -= UOffsetT(SizeByte) + WriteByte(b.Bytes[b.head:], x) +} + +// PlaceVOffsetT prepends a VOffsetT to the Builder, without checking for space. +func (b *Builder) PlaceVOffsetT(x VOffsetT) { + b.head -= UOffsetT(SizeVOffsetT) + WriteVOffsetT(b.Bytes[b.head:], x) +} + +// PlaceSOffsetT prepends a SOffsetT to the Builder, without checking for space. +func (b *Builder) PlaceSOffsetT(x SOffsetT) { + b.head -= UOffsetT(SizeSOffsetT) + WriteSOffsetT(b.Bytes[b.head:], x) +} + +// PlaceUOffsetT prepends a UOffsetT to the Builder, without checking for space. +func (b *Builder) PlaceUOffsetT(x UOffsetT) { + b.head -= UOffsetT(SizeUOffsetT) + WriteUOffsetT(b.Bytes[b.head:], x) +} diff --git a/third_party/flatbuffers/go/doc.go b/third_party/flatbuffers/go/doc.go new file mode 100644 index 00000000000..694edc763d8 --- /dev/null +++ b/third_party/flatbuffers/go/doc.go @@ -0,0 +1,3 @@ +// Package flatbuffers provides facilities to read and write flatbuffers +// objects. +package flatbuffers diff --git a/third_party/flatbuffers/go/encode.go b/third_party/flatbuffers/go/encode.go new file mode 100644 index 00000000000..a2a57981255 --- /dev/null +++ b/third_party/flatbuffers/go/encode.go @@ -0,0 +1,238 @@ +package flatbuffers + +import ( + "math" +) + +type ( + // A SOffsetT stores a signed offset into arbitrary data. + SOffsetT int32 + // A UOffsetT stores an unsigned offset into vector data. + UOffsetT uint32 + // A VOffsetT stores an unsigned offset in a vtable. + VOffsetT uint16 +) + +const ( + // VtableMetadataFields is the count of metadata fields in each vtable. + VtableMetadataFields = 2 +) + +// GetByte decodes a little-endian byte from a byte slice. +func GetByte(buf []byte) byte { + return byte(GetUint8(buf)) +} + +// GetBool decodes a little-endian bool from a byte slice. +func GetBool(buf []byte) bool { + return buf[0] == 1 +} + +// GetUint8 decodes a little-endian uint8 from a byte slice. +func GetUint8(buf []byte) (n uint8) { + n = uint8(buf[0]) + return +} + +// GetUint16 decodes a little-endian uint16 from a byte slice. +func GetUint16(buf []byte) (n uint16) { + _ = buf[1] // Force one bounds check. See: golang.org/issue/14808 + n |= uint16(buf[0]) + n |= uint16(buf[1]) << 8 + return +} + +// GetUint32 decodes a little-endian uint32 from a byte slice. +func GetUint32(buf []byte) (n uint32) { + _ = buf[3] // Force one bounds check. See: golang.org/issue/14808 + n |= uint32(buf[0]) + n |= uint32(buf[1]) << 8 + n |= uint32(buf[2]) << 16 + n |= uint32(buf[3]) << 24 + return +} + +// GetUint64 decodes a little-endian uint64 from a byte slice. +func GetUint64(buf []byte) (n uint64) { + _ = buf[7] // Force one bounds check. See: golang.org/issue/14808 + n |= uint64(buf[0]) + n |= uint64(buf[1]) << 8 + n |= uint64(buf[2]) << 16 + n |= uint64(buf[3]) << 24 + n |= uint64(buf[4]) << 32 + n |= uint64(buf[5]) << 40 + n |= uint64(buf[6]) << 48 + n |= uint64(buf[7]) << 56 + return +} + +// GetInt8 decodes a little-endian int8 from a byte slice. +func GetInt8(buf []byte) (n int8) { + n = int8(buf[0]) + return +} + +// GetInt16 decodes a little-endian int16 from a byte slice. +func GetInt16(buf []byte) (n int16) { + _ = buf[1] // Force one bounds check. See: golang.org/issue/14808 + n |= int16(buf[0]) + n |= int16(buf[1]) << 8 + return +} + +// GetInt32 decodes a little-endian int32 from a byte slice. +func GetInt32(buf []byte) (n int32) { + _ = buf[3] // Force one bounds check. See: golang.org/issue/14808 + n |= int32(buf[0]) + n |= int32(buf[1]) << 8 + n |= int32(buf[2]) << 16 + n |= int32(buf[3]) << 24 + return +} + +// GetInt64 decodes a little-endian int64 from a byte slice. +func GetInt64(buf []byte) (n int64) { + _ = buf[7] // Force one bounds check. See: golang.org/issue/14808 + n |= int64(buf[0]) + n |= int64(buf[1]) << 8 + n |= int64(buf[2]) << 16 + n |= int64(buf[3]) << 24 + n |= int64(buf[4]) << 32 + n |= int64(buf[5]) << 40 + n |= int64(buf[6]) << 48 + n |= int64(buf[7]) << 56 + return +} + +// GetFloat32 decodes a little-endian float32 from a byte slice. +func GetFloat32(buf []byte) float32 { + x := GetUint32(buf) + return math.Float32frombits(x) +} + +// GetFloat64 decodes a little-endian float64 from a byte slice. +func GetFloat64(buf []byte) float64 { + x := GetUint64(buf) + return math.Float64frombits(x) +} + +// GetUOffsetT decodes a little-endian UOffsetT from a byte slice. +func GetUOffsetT(buf []byte) UOffsetT { + return UOffsetT(GetUint32(buf)) +} + +// GetSOffsetT decodes a little-endian SOffsetT from a byte slice. +func GetSOffsetT(buf []byte) SOffsetT { + return SOffsetT(GetInt32(buf)) +} + +// GetVOffsetT decodes a little-endian VOffsetT from a byte slice. +func GetVOffsetT(buf []byte) VOffsetT { + return VOffsetT(GetUint16(buf)) +} + +// WriteByte encodes a little-endian uint8 into a byte slice. +func WriteByte(buf []byte, n byte) { + WriteUint8(buf, uint8(n)) +} + +// WriteBool encodes a little-endian bool into a byte slice. +func WriteBool(buf []byte, b bool) { + buf[0] = 0 + if b { + buf[0] = 1 + } +} + +// WriteUint8 encodes a little-endian uint8 into a byte slice. +func WriteUint8(buf []byte, n uint8) { + buf[0] = byte(n) +} + +// WriteUint16 encodes a little-endian uint16 into a byte slice. +func WriteUint16(buf []byte, n uint16) { + _ = buf[1] // Force one bounds check. See: golang.org/issue/14808 + buf[0] = byte(n) + buf[1] = byte(n >> 8) +} + +// WriteUint32 encodes a little-endian uint32 into a byte slice. +func WriteUint32(buf []byte, n uint32) { + _ = buf[3] // Force one bounds check. See: golang.org/issue/14808 + buf[0] = byte(n) + buf[1] = byte(n >> 8) + buf[2] = byte(n >> 16) + buf[3] = byte(n >> 24) +} + +// WriteUint64 encodes a little-endian uint64 into a byte slice. +func WriteUint64(buf []byte, n uint64) { + _ = buf[7] // Force one bounds check. See: golang.org/issue/14808 + buf[0] = byte(n) + buf[1] = byte(n >> 8) + buf[2] = byte(n >> 16) + buf[3] = byte(n >> 24) + buf[4] = byte(n >> 32) + buf[5] = byte(n >> 40) + buf[6] = byte(n >> 48) + buf[7] = byte(n >> 56) +} + +// WriteInt8 encodes a little-endian int8 into a byte slice. +func WriteInt8(buf []byte, n int8) { + buf[0] = byte(n) +} + +// WriteInt16 encodes a little-endian int16 into a byte slice. +func WriteInt16(buf []byte, n int16) { + _ = buf[1] // Force one bounds check. See: golang.org/issue/14808 + buf[0] = byte(n) + buf[1] = byte(n >> 8) +} + +// WriteInt32 encodes a little-endian int32 into a byte slice. +func WriteInt32(buf []byte, n int32) { + _ = buf[3] // Force one bounds check. See: golang.org/issue/14808 + buf[0] = byte(n) + buf[1] = byte(n >> 8) + buf[2] = byte(n >> 16) + buf[3] = byte(n >> 24) +} + +// WriteInt64 encodes a little-endian int64 into a byte slice. +func WriteInt64(buf []byte, n int64) { + _ = buf[7] // Force one bounds check. See: golang.org/issue/14808 + buf[0] = byte(n) + buf[1] = byte(n >> 8) + buf[2] = byte(n >> 16) + buf[3] = byte(n >> 24) + buf[4] = byte(n >> 32) + buf[5] = byte(n >> 40) + buf[6] = byte(n >> 48) + buf[7] = byte(n >> 56) +} + +// WriteFloat32 encodes a little-endian float32 into a byte slice. +func WriteFloat32(buf []byte, n float32) { + WriteUint32(buf, math.Float32bits(n)) +} + +// WriteFloat64 encodes a little-endian float64 into a byte slice. +func WriteFloat64(buf []byte, n float64) { + WriteUint64(buf, math.Float64bits(n)) +} + +// WriteVOffsetT encodes a little-endian VOffsetT into a byte slice. +func WriteVOffsetT(buf []byte, n VOffsetT) { + WriteUint16(buf, uint16(n)) +} + +// WriteSOffsetT encodes a little-endian SOffsetT into a byte slice. +func WriteSOffsetT(buf []byte, n SOffsetT) { + WriteInt32(buf, int32(n)) +} + +// WriteUOffsetT encodes a little-endian UOffsetT into a byte slice. +func WriteUOffsetT(buf []byte, n UOffsetT) { + WriteUint32(buf, uint32(n)) +} diff --git a/third_party/flatbuffers/go/grpc.go b/third_party/flatbuffers/go/grpc.go new file mode 100644 index 00000000000..56d7e9f2ef0 --- /dev/null +++ b/third_party/flatbuffers/go/grpc.go @@ -0,0 +1,62 @@ +package flatbuffers + +import "errors" + +var ( + // Codec implements gRPC-go Codec which is used to encode and decode messages. + Codec = "flatbuffers" + + // ErrInsufficientData is returned when the data is too short to read the root UOffsetT. + ErrInsufficientData = errors.New("insufficient data") + + // ErrInvalidRootOffset is returned when the root UOffsetT is out of bounds. + ErrInvalidRootOffset = errors.New("invalid root offset") +) + +// FlatbuffersCodec defines the interface gRPC uses to encode and decode messages. Note +// that implementations of this interface must be thread safe; a Codec's +// methods can be called from concurrent goroutines. +type FlatbuffersCodec struct{} + +// Marshal returns the wire format of v. +func (FlatbuffersCodec) Marshal(v interface{}) ([]byte, error) { + return v.(*Builder).FinishedBytes(), nil +} + +// Unmarshal parses the wire format into v. +func (FlatbuffersCodec) Unmarshal(data []byte, v interface{}) error { + // Need at least 4 bytes to read the root table offset (UOffsetT). + // Vtable soffset_t and metadata are read later during field access. + if len(data) < SizeUOffsetT { + return ErrInsufficientData + } + + off := GetUOffsetT(data) + + // The root UOffsetT must be within the data buffer + // Compare in the unsigned domain to avoid signedness pitfalls + if off > UOffsetT(len(data)-SizeUOffsetT) { + return ErrInvalidRootOffset + } + + v.(flatbuffersInit).Init(data, off) + return nil +} + +// String old gRPC Codec interface func +func (FlatbuffersCodec) String() string { + return Codec +} + +// Name returns the name of the Codec implementation. The returned string +// will be used as part of content type in transmission. The result must be +// static; the result cannot change between calls. +// +// add Name() for ForceCodec interface +func (FlatbuffersCodec) Name() string { + return Codec +} + +type flatbuffersInit interface { + Init(data []byte, i UOffsetT) +} diff --git a/third_party/flatbuffers/go/lib.go b/third_party/flatbuffers/go/lib.go new file mode 100644 index 00000000000..a4e99de1019 --- /dev/null +++ b/third_party/flatbuffers/go/lib.go @@ -0,0 +1,50 @@ +package flatbuffers + +// FlatBuffer is the interface that represents a flatbuffer. +type FlatBuffer interface { + Table() Table + Init(buf []byte, i UOffsetT) +} + +// GetRootAs is a generic helper to initialize a FlatBuffer with the provided buffer bytes and its data offset. +func GetRootAs(buf []byte, offset UOffsetT, fb FlatBuffer) { + n := GetUOffsetT(buf[offset:]) + fb.Init(buf, n+offset) +} + +// GetSizePrefixedRootAs is a generic helper to initialize a FlatBuffer with the provided size-prefixed buffer +// bytes and its data offset +func GetSizePrefixedRootAs(buf []byte, offset UOffsetT, fb FlatBuffer) { + n := GetUOffsetT(buf[offset+sizePrefixLength:]) + fb.Init(buf, n+offset+sizePrefixLength) +} + +// GetSizePrefix reads the size from a size-prefixed flatbuffer +func GetSizePrefix(buf []byte, offset UOffsetT) uint32 { + return GetUint32(buf[offset:]) +} + +// GetIndirectOffset retrives the relative offset in the provided buffer stored at `offset`. +func GetIndirectOffset(buf []byte, offset UOffsetT) UOffsetT { + return offset + GetUOffsetT(buf[offset:]) +} + +// GetBufferIdentifier returns the file identifier as string +func GetBufferIdentifier(buf []byte) string { + return string(buf[SizeUOffsetT:][:fileIdentifierLength]) +} + +// GetBufferIdentifier returns the file identifier as string for a size-prefixed buffer +func GetSizePrefixedBufferIdentifier(buf []byte) string { + return string(buf[SizeUOffsetT+sizePrefixLength:][:fileIdentifierLength]) +} + +// BufferHasIdentifier checks if the identifier in a buffer has the expected value +func BufferHasIdentifier(buf []byte, identifier string) bool { + return GetBufferIdentifier(buf) == identifier +} + +// BufferHasIdentifier checks if the identifier in a buffer has the expected value for a size-prefixed buffer +func SizePrefixedBufferHasIdentifier(buf []byte, identifier string) bool { + return GetSizePrefixedBufferIdentifier(buf) == identifier +} diff --git a/third_party/flatbuffers/go/sizes.go b/third_party/flatbuffers/go/sizes.go new file mode 100644 index 00000000000..ba221698455 --- /dev/null +++ b/third_party/flatbuffers/go/sizes.go @@ -0,0 +1,55 @@ +package flatbuffers + +import ( + "unsafe" +) + +const ( + // See http://golang.org/ref/spec#Numeric_types + + // SizeUint8 is the byte size of a uint8. + SizeUint8 = 1 + // SizeUint16 is the byte size of a uint16. + SizeUint16 = 2 + // SizeUint32 is the byte size of a uint32. + SizeUint32 = 4 + // SizeUint64 is the byte size of a uint64. + SizeUint64 = 8 + + // SizeInt8 is the byte size of a int8. + SizeInt8 = 1 + // SizeInt16 is the byte size of a int16. + SizeInt16 = 2 + // SizeInt32 is the byte size of a int32. + SizeInt32 = 4 + // SizeInt64 is the byte size of a int64. + SizeInt64 = 8 + + // SizeFloat32 is the byte size of a float32. + SizeFloat32 = 4 + // SizeFloat64 is the byte size of a float64. + SizeFloat64 = 8 + + // SizeByte is the byte size of a byte. + // The `byte` type is aliased (by Go definition) to uint8. + SizeByte = 1 + + // SizeBool is the byte size of a bool. + // The `bool` type is aliased (by flatbuffers convention) to uint8. + SizeBool = 1 + + // SizeSOffsetT is the byte size of an SOffsetT. + // The `SOffsetT` type is aliased (by flatbuffers convention) to int32. + SizeSOffsetT = 4 + // SizeUOffsetT is the byte size of an UOffsetT. + // The `UOffsetT` type is aliased (by flatbuffers convention) to uint32. + SizeUOffsetT = 4 + // SizeVOffsetT is the byte size of an VOffsetT. + // The `VOffsetT` type is aliased (by flatbuffers convention) to uint16. + SizeVOffsetT = 2 +) + +// byteSliceToString converts a []byte to string without a heap allocation. +func byteSliceToString(b []byte) string { + return *(*string)(unsafe.Pointer(&b)) +} diff --git a/third_party/flatbuffers/go/struct.go b/third_party/flatbuffers/go/struct.go new file mode 100644 index 00000000000..11258f715d4 --- /dev/null +++ b/third_party/flatbuffers/go/struct.go @@ -0,0 +1,8 @@ +package flatbuffers + +// Struct wraps a byte slice and provides read access to its data. +// +// Structs do not have a vtable. +type Struct struct { + Table +} diff --git a/third_party/flatbuffers/go/table.go b/third_party/flatbuffers/go/table.go new file mode 100644 index 00000000000..b273146fad4 --- /dev/null +++ b/third_party/flatbuffers/go/table.go @@ -0,0 +1,505 @@ +package flatbuffers + +// Table wraps a byte slice and provides read access to its data. +// +// The variable `Pos` indicates the root of the FlatBuffers object therein. +type Table struct { + Bytes []byte + Pos UOffsetT // Always < 1<<31. +} + +// Offset provides access into the Table's vtable. +// +// Fields which are deprecated are ignored by checking against the vtable's length. +func (t *Table) Offset(vtableOffset VOffsetT) VOffsetT { + vtable := UOffsetT(SOffsetT(t.Pos) - t.GetSOffsetT(t.Pos)) + if vtableOffset < t.GetVOffsetT(vtable) { + return t.GetVOffsetT(vtable + UOffsetT(vtableOffset)) + } + return 0 +} + +// Indirect retrieves the relative offset stored at `offset`. +func (t *Table) Indirect(off UOffsetT) UOffsetT { + return off + GetUOffsetT(t.Bytes[off:]) +} + +// String gets a string from data stored inside the flatbuffer. +func (t *Table) String(off UOffsetT) string { + b := t.ByteVector(off) + return byteSliceToString(b) +} + +// ByteVector gets a byte slice from data stored inside the flatbuffer. +func (t *Table) ByteVector(off UOffsetT) []byte { + off += GetUOffsetT(t.Bytes[off:]) + start := off + UOffsetT(SizeUOffsetT) + length := GetUOffsetT(t.Bytes[off:]) + return t.Bytes[start : start+length] +} + +// VectorLen retrieves the length of the vector whose offset is stored at +// "off" in this object. +func (t *Table) VectorLen(off UOffsetT) int { + off += t.Pos + off += GetUOffsetT(t.Bytes[off:]) + return int(GetUOffsetT(t.Bytes[off:])) +} + +// Vector retrieves the start of data of the vector whose offset is stored +// at "off" in this object. +func (t *Table) Vector(off UOffsetT) UOffsetT { + off += t.Pos + x := off + GetUOffsetT(t.Bytes[off:]) + // data starts after metadata containing the vector length + x += UOffsetT(SizeUOffsetT) + return x +} + +// Union initializes any Table-derived type to point to the union at the given +// offset. +func (t *Table) Union(t2 *Table, off UOffsetT) { + off += t.Pos + t2.Pos = off + t.GetUOffsetT(off) + t2.Bytes = t.Bytes +} + +// GetBool retrieves a bool at the given offset. +func (t *Table) GetBool(off UOffsetT) bool { + return GetBool(t.Bytes[off:]) +} + +// GetByte retrieves a byte at the given offset. +func (t *Table) GetByte(off UOffsetT) byte { + return GetByte(t.Bytes[off:]) +} + +// GetUint8 retrieves a uint8 at the given offset. +func (t *Table) GetUint8(off UOffsetT) uint8 { + return GetUint8(t.Bytes[off:]) +} + +// GetUint16 retrieves a uint16 at the given offset. +func (t *Table) GetUint16(off UOffsetT) uint16 { + return GetUint16(t.Bytes[off:]) +} + +// GetUint32 retrieves a uint32 at the given offset. +func (t *Table) GetUint32(off UOffsetT) uint32 { + return GetUint32(t.Bytes[off:]) +} + +// GetUint64 retrieves a uint64 at the given offset. +func (t *Table) GetUint64(off UOffsetT) uint64 { + return GetUint64(t.Bytes[off:]) +} + +// GetInt8 retrieves a int8 at the given offset. +func (t *Table) GetInt8(off UOffsetT) int8 { + return GetInt8(t.Bytes[off:]) +} + +// GetInt16 retrieves a int16 at the given offset. +func (t *Table) GetInt16(off UOffsetT) int16 { + return GetInt16(t.Bytes[off:]) +} + +// GetInt32 retrieves a int32 at the given offset. +func (t *Table) GetInt32(off UOffsetT) int32 { + return GetInt32(t.Bytes[off:]) +} + +// GetInt64 retrieves a int64 at the given offset. +func (t *Table) GetInt64(off UOffsetT) int64 { + return GetInt64(t.Bytes[off:]) +} + +// GetFloat32 retrieves a float32 at the given offset. +func (t *Table) GetFloat32(off UOffsetT) float32 { + return GetFloat32(t.Bytes[off:]) +} + +// GetFloat64 retrieves a float64 at the given offset. +func (t *Table) GetFloat64(off UOffsetT) float64 { + return GetFloat64(t.Bytes[off:]) +} + +// GetUOffsetT retrieves a UOffsetT at the given offset. +func (t *Table) GetUOffsetT(off UOffsetT) UOffsetT { + return GetUOffsetT(t.Bytes[off:]) +} + +// GetVOffsetT retrieves a VOffsetT at the given offset. +func (t *Table) GetVOffsetT(off UOffsetT) VOffsetT { + return GetVOffsetT(t.Bytes[off:]) +} + +// GetSOffsetT retrieves a SOffsetT at the given offset. +func (t *Table) GetSOffsetT(off UOffsetT) SOffsetT { + return GetSOffsetT(t.Bytes[off:]) +} + +// GetBoolSlot retrieves the bool that the given vtable location +// points to. If the vtable value is zero, the default value `d` +// will be returned. +func (t *Table) GetBoolSlot(slot VOffsetT, d bool) bool { + off := t.Offset(slot) + if off == 0 { + return d + } + + return t.GetBool(t.Pos + UOffsetT(off)) +} + +// GetByteSlot retrieves the byte that the given vtable location +// points to. If the vtable value is zero, the default value `d` +// will be returned. +func (t *Table) GetByteSlot(slot VOffsetT, d byte) byte { + off := t.Offset(slot) + if off == 0 { + return d + } + + return t.GetByte(t.Pos + UOffsetT(off)) +} + +// GetInt8Slot retrieves the int8 that the given vtable location +// points to. If the vtable value is zero, the default value `d` +// will be returned. +func (t *Table) GetInt8Slot(slot VOffsetT, d int8) int8 { + off := t.Offset(slot) + if off == 0 { + return d + } + + return t.GetInt8(t.Pos + UOffsetT(off)) +} + +// GetUint8Slot retrieves the uint8 that the given vtable location +// points to. If the vtable value is zero, the default value `d` +// will be returned. +func (t *Table) GetUint8Slot(slot VOffsetT, d uint8) uint8 { + off := t.Offset(slot) + if off == 0 { + return d + } + + return t.GetUint8(t.Pos + UOffsetT(off)) +} + +// GetInt16Slot retrieves the int16 that the given vtable location +// points to. If the vtable value is zero, the default value `d` +// will be returned. +func (t *Table) GetInt16Slot(slot VOffsetT, d int16) int16 { + off := t.Offset(slot) + if off == 0 { + return d + } + + return t.GetInt16(t.Pos + UOffsetT(off)) +} + +// GetUint16Slot retrieves the uint16 that the given vtable location +// points to. If the vtable value is zero, the default value `d` +// will be returned. +func (t *Table) GetUint16Slot(slot VOffsetT, d uint16) uint16 { + off := t.Offset(slot) + if off == 0 { + return d + } + + return t.GetUint16(t.Pos + UOffsetT(off)) +} + +// GetInt32Slot retrieves the int32 that the given vtable location +// points to. If the vtable value is zero, the default value `d` +// will be returned. +func (t *Table) GetInt32Slot(slot VOffsetT, d int32) int32 { + off := t.Offset(slot) + if off == 0 { + return d + } + + return t.GetInt32(t.Pos + UOffsetT(off)) +} + +// GetUint32Slot retrieves the uint32 that the given vtable location +// points to. If the vtable value is zero, the default value `d` +// will be returned. +func (t *Table) GetUint32Slot(slot VOffsetT, d uint32) uint32 { + off := t.Offset(slot) + if off == 0 { + return d + } + + return t.GetUint32(t.Pos + UOffsetT(off)) +} + +// GetInt64Slot retrieves the int64 that the given vtable location +// points to. If the vtable value is zero, the default value `d` +// will be returned. +func (t *Table) GetInt64Slot(slot VOffsetT, d int64) int64 { + off := t.Offset(slot) + if off == 0 { + return d + } + + return t.GetInt64(t.Pos + UOffsetT(off)) +} + +// GetUint64Slot retrieves the uint64 that the given vtable location +// points to. If the vtable value is zero, the default value `d` +// will be returned. +func (t *Table) GetUint64Slot(slot VOffsetT, d uint64) uint64 { + off := t.Offset(slot) + if off == 0 { + return d + } + + return t.GetUint64(t.Pos + UOffsetT(off)) +} + +// GetFloat32Slot retrieves the float32 that the given vtable location +// points to. If the vtable value is zero, the default value `d` +// will be returned. +func (t *Table) GetFloat32Slot(slot VOffsetT, d float32) float32 { + off := t.Offset(slot) + if off == 0 { + return d + } + + return t.GetFloat32(t.Pos + UOffsetT(off)) +} + +// GetFloat64Slot retrieves the float64 that the given vtable location +// points to. If the vtable value is zero, the default value `d` +// will be returned. +func (t *Table) GetFloat64Slot(slot VOffsetT, d float64) float64 { + off := t.Offset(slot) + if off == 0 { + return d + } + + return t.GetFloat64(t.Pos + UOffsetT(off)) +} + +// GetVOffsetTSlot retrieves the VOffsetT that the given vtable location +// points to. If the vtable value is zero, the default value `d` +// will be returned. +func (t *Table) GetVOffsetTSlot(slot VOffsetT, d VOffsetT) VOffsetT { + off := t.Offset(slot) + if off == 0 { + return d + } + return VOffsetT(off) +} + +// MutateBool updates a bool at the given offset. +func (t *Table) MutateBool(off UOffsetT, n bool) bool { + WriteBool(t.Bytes[off:], n) + return true +} + +// MutateByte updates a Byte at the given offset. +func (t *Table) MutateByte(off UOffsetT, n byte) bool { + WriteByte(t.Bytes[off:], n) + return true +} + +// MutateUint8 updates a Uint8 at the given offset. +func (t *Table) MutateUint8(off UOffsetT, n uint8) bool { + WriteUint8(t.Bytes[off:], n) + return true +} + +// MutateUint16 updates a Uint16 at the given offset. +func (t *Table) MutateUint16(off UOffsetT, n uint16) bool { + WriteUint16(t.Bytes[off:], n) + return true +} + +// MutateUint32 updates a Uint32 at the given offset. +func (t *Table) MutateUint32(off UOffsetT, n uint32) bool { + WriteUint32(t.Bytes[off:], n) + return true +} + +// MutateUint64 updates a Uint64 at the given offset. +func (t *Table) MutateUint64(off UOffsetT, n uint64) bool { + WriteUint64(t.Bytes[off:], n) + return true +} + +// MutateInt8 updates a Int8 at the given offset. +func (t *Table) MutateInt8(off UOffsetT, n int8) bool { + WriteInt8(t.Bytes[off:], n) + return true +} + +// MutateInt16 updates a Int16 at the given offset. +func (t *Table) MutateInt16(off UOffsetT, n int16) bool { + WriteInt16(t.Bytes[off:], n) + return true +} + +// MutateInt32 updates a Int32 at the given offset. +func (t *Table) MutateInt32(off UOffsetT, n int32) bool { + WriteInt32(t.Bytes[off:], n) + return true +} + +// MutateInt64 updates a Int64 at the given offset. +func (t *Table) MutateInt64(off UOffsetT, n int64) bool { + WriteInt64(t.Bytes[off:], n) + return true +} + +// MutateFloat32 updates a Float32 at the given offset. +func (t *Table) MutateFloat32(off UOffsetT, n float32) bool { + WriteFloat32(t.Bytes[off:], n) + return true +} + +// MutateFloat64 updates a Float64 at the given offset. +func (t *Table) MutateFloat64(off UOffsetT, n float64) bool { + WriteFloat64(t.Bytes[off:], n) + return true +} + +// MutateUOffsetT updates a UOffsetT at the given offset. +func (t *Table) MutateUOffsetT(off UOffsetT, n UOffsetT) bool { + WriteUOffsetT(t.Bytes[off:], n) + return true +} + +// MutateVOffsetT updates a VOffsetT at the given offset. +func (t *Table) MutateVOffsetT(off UOffsetT, n VOffsetT) bool { + WriteVOffsetT(t.Bytes[off:], n) + return true +} + +// MutateSOffsetT updates a SOffsetT at the given offset. +func (t *Table) MutateSOffsetT(off UOffsetT, n SOffsetT) bool { + WriteSOffsetT(t.Bytes[off:], n) + return true +} + +// MutateBoolSlot updates the bool at given vtable location +func (t *Table) MutateBoolSlot(slot VOffsetT, n bool) bool { + if off := t.Offset(slot); off != 0 { + t.MutateBool(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateByteSlot updates the byte at given vtable location +func (t *Table) MutateByteSlot(slot VOffsetT, n byte) bool { + if off := t.Offset(slot); off != 0 { + t.MutateByte(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateInt8Slot updates the int8 at given vtable location +func (t *Table) MutateInt8Slot(slot VOffsetT, n int8) bool { + if off := t.Offset(slot); off != 0 { + t.MutateInt8(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateUint8Slot updates the uint8 at given vtable location +func (t *Table) MutateUint8Slot(slot VOffsetT, n uint8) bool { + if off := t.Offset(slot); off != 0 { + t.MutateUint8(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateInt16Slot updates the int16 at given vtable location +func (t *Table) MutateInt16Slot(slot VOffsetT, n int16) bool { + if off := t.Offset(slot); off != 0 { + t.MutateInt16(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateUint16Slot updates the uint16 at given vtable location +func (t *Table) MutateUint16Slot(slot VOffsetT, n uint16) bool { + if off := t.Offset(slot); off != 0 { + t.MutateUint16(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateInt32Slot updates the int32 at given vtable location +func (t *Table) MutateInt32Slot(slot VOffsetT, n int32) bool { + if off := t.Offset(slot); off != 0 { + t.MutateInt32(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateUint32Slot updates the uint32 at given vtable location +func (t *Table) MutateUint32Slot(slot VOffsetT, n uint32) bool { + if off := t.Offset(slot); off != 0 { + t.MutateUint32(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateInt64Slot updates the int64 at given vtable location +func (t *Table) MutateInt64Slot(slot VOffsetT, n int64) bool { + if off := t.Offset(slot); off != 0 { + t.MutateInt64(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateUint64Slot updates the uint64 at given vtable location +func (t *Table) MutateUint64Slot(slot VOffsetT, n uint64) bool { + if off := t.Offset(slot); off != 0 { + t.MutateUint64(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateFloat32Slot updates the float32 at given vtable location +func (t *Table) MutateFloat32Slot(slot VOffsetT, n float32) bool { + if off := t.Offset(slot); off != 0 { + t.MutateFloat32(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateFloat64Slot updates the float64 at given vtable location +func (t *Table) MutateFloat64Slot(slot VOffsetT, n float64) bool { + if off := t.Offset(slot); off != 0 { + t.MutateFloat64(t.Pos+UOffsetT(off), n) + return true + } + + return false +} diff --git a/third_party/flatbuffers/goldens/README.md b/third_party/flatbuffers/goldens/README.md new file mode 100644 index 00000000000..856c0efceed --- /dev/null +++ b/third_party/flatbuffers/goldens/README.md @@ -0,0 +1,26 @@ +# Golden Generated Files + +This directory is a repository for the generated files of `flatc`. + +We check in the generated code so we can see, during a PR review, how the +changes affect the generated output. It's also useful as a reference to show +how things work across various languages. + +These files are **NOT** intended to be depended on by any code, such as tests or +or compiled examples. + +## Languages Specifics + +Each language should keep their generated code in their respective directories. +However, the parent schemas can, and should, be shared so we have a consistent +view of things across languages. These are kept in the `schema/` directory. + +Some languages may not support every generation feature, so each language is +required to specify the `flatc` arguments individually. + +* Try to avoid includes and nested directories, preferring it as flat as +possible. + +## Updating + +Just run the `generate_goldens.py` script and it should generate them all. diff --git a/third_party/flatbuffers/goldens/cpp/basic_generated.h b/third_party/flatbuffers/goldens/cpp/basic_generated.h new file mode 100644 index 00000000000..2c5391fd848 --- /dev/null +++ b/third_party/flatbuffers/goldens/cpp/basic_generated.h @@ -0,0 +1,163 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_BASIC_FLATBUFFERS_GOLDENS_H_ +#define FLATBUFFERS_GENERATED_BASIC_FLATBUFFERS_GOLDENS_H_ + +#include "flatbuffers/flatbuffers.h" + +// Ensure the included flatbuffers.h is the same version as when this file was +// generated, otherwise it may not be compatible. +static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && + FLATBUFFERS_VERSION_MINOR == 9 && + FLATBUFFERS_VERSION_REVISION == 23, + "Non-compatible flatbuffers version included"); + +namespace flatbuffers { +namespace goldens { + +struct Galaxy; +struct GalaxyBuilder; + +struct Universe; +struct UniverseBuilder; + +struct Galaxy FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef GalaxyBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NUM_STARS = 4 + }; + int64_t num_stars() const { + return GetField(VT_NUM_STARS, 0); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_NUM_STARS, 8) && + verifier.EndTable(); + } +}; + +struct GalaxyBuilder { + typedef Galaxy Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_num_stars(int64_t num_stars) { + fbb_.AddElement(Galaxy::VT_NUM_STARS, num_stars, 0); + } + explicit GalaxyBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateGalaxy( + ::flatbuffers::FlatBufferBuilder &_fbb, + int64_t num_stars = 0) { + GalaxyBuilder builder_(_fbb); + builder_.add_num_stars(num_stars); + return builder_.Finish(); +} + +struct Universe FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef UniverseBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_AGE = 4, + VT_GALAXIES = 6 + }; + double age() const { + return GetField(VT_AGE, 0.0); + } + const ::flatbuffers::Vector<::flatbuffers::Offset> *galaxies() const { + return GetPointer> *>(VT_GALAXIES); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_AGE, 8) && + VerifyOffset(verifier, VT_GALAXIES) && + verifier.VerifyVector(galaxies()) && + verifier.VerifyVectorOfTables(galaxies()) && + verifier.EndTable(); + } +}; + +struct UniverseBuilder { + typedef Universe Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_age(double age) { + fbb_.AddElement(Universe::VT_AGE, age, 0.0); + } + void add_galaxies(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> galaxies) { + fbb_.AddOffset(Universe::VT_GALAXIES, galaxies); + } + explicit UniverseBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateUniverse( + ::flatbuffers::FlatBufferBuilder &_fbb, + double age = 0.0, + ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> galaxies = 0) { + UniverseBuilder builder_(_fbb); + builder_.add_age(age); + builder_.add_galaxies(galaxies); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateUniverseDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + double age = 0.0, + const std::vector<::flatbuffers::Offset> *galaxies = nullptr) { + auto galaxies__ = galaxies ? _fbb.CreateVector<::flatbuffers::Offset>(*galaxies) : 0; + return flatbuffers::goldens::CreateUniverse( + _fbb, + age, + galaxies__); +} + +inline const flatbuffers::goldens::Universe *GetUniverse(const void *buf) { + return ::flatbuffers::GetRoot(buf); +} + +inline const flatbuffers::goldens::Universe *GetSizePrefixedUniverse(const void *buf) { + return ::flatbuffers::GetSizePrefixedRoot(buf); +} + +inline bool VerifyUniverseBuffer( + ::flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer(nullptr); +} + +inline bool VerifySizePrefixedUniverseBuffer( + ::flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer(nullptr); +} + +inline void FinishUniverseBuffer( + ::flatbuffers::FlatBufferBuilder &fbb, + ::flatbuffers::Offset root) { + fbb.Finish(root); +} + +inline void FinishSizePrefixedUniverseBuffer( + ::flatbuffers::FlatBufferBuilder &fbb, + ::flatbuffers::Offset root) { + fbb.FinishSizePrefixed(root); +} + +} // namespace goldens +} // namespace flatbuffers + +#endif // FLATBUFFERS_GENERATED_BASIC_FLATBUFFERS_GOLDENS_H_ diff --git a/third_party/flatbuffers/goldens/cpp/generate.py b/third_party/flatbuffers/goldens/cpp/generate.py new file mode 100644 index 00000000000..c71dbc61080 --- /dev/null +++ b/third_party/flatbuffers/goldens/cpp/generate.py @@ -0,0 +1,10 @@ +from golden_utils import flatc_golden + + +def flatc(options, schema): + # Wrap the golden flatc generator with C++ specifics + flatc_golden(options=["--cpp"] + options, schema=schema, prefix="cpp") + + +def GenerateCpp(): + flatc([], "basic.fbs") diff --git a/third_party/flatbuffers/goldens/csharp/flatbuffers/goldens/Galaxy.cs b/third_party/flatbuffers/goldens/csharp/flatbuffers/goldens/Galaxy.cs new file mode 100644 index 00000000000..471e9b3df7d --- /dev/null +++ b/third_party/flatbuffers/goldens/csharp/flatbuffers/goldens/Galaxy.cs @@ -0,0 +1,50 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace flatbuffers.goldens +{ + +using global::System; +using global::System.Collections.Generic; +using global::Google.FlatBuffers; + +public struct Galaxy : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_9_23(); } + public static Galaxy GetRootAsGalaxy(ByteBuffer _bb) { return GetRootAsGalaxy(_bb, new Galaxy()); } + public static Galaxy GetRootAsGalaxy(ByteBuffer _bb, Galaxy obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Galaxy __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public long NumStars { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetLong(o + __p.bb_pos) : (long)0; } } + + public static Offset CreateGalaxy(FlatBufferBuilder builder, + long num_stars = 0) { + builder.StartTable(1); + Galaxy.AddNumStars(builder, num_stars); + return Galaxy.EndGalaxy(builder); + } + + public static void StartGalaxy(FlatBufferBuilder builder) { builder.StartTable(1); } + public static void AddNumStars(FlatBufferBuilder builder, long numStars) { builder.AddLong(0, numStars, 0); } + public static Offset EndGalaxy(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } +} + + +static public class GalaxyVerify +{ + static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*NumStars*/, 8 /*long*/, 8, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/third_party/flatbuffers/goldens/csharp/flatbuffers/goldens/Universe.cs b/third_party/flatbuffers/goldens/csharp/flatbuffers/goldens/Universe.cs new file mode 100644 index 00000000000..9f74a1daedd --- /dev/null +++ b/third_party/flatbuffers/goldens/csharp/flatbuffers/goldens/Universe.cs @@ -0,0 +1,64 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace flatbuffers.goldens +{ + +using global::System; +using global::System.Collections.Generic; +using global::Google.FlatBuffers; + +public struct Universe : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_9_23(); } + public static Universe GetRootAsUniverse(ByteBuffer _bb) { return GetRootAsUniverse(_bb, new Universe()); } + public static Universe GetRootAsUniverse(ByteBuffer _bb, Universe obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public static bool VerifyUniverse(ByteBuffer _bb) {Google.FlatBuffers.Verifier verifier = new Google.FlatBuffers.Verifier(_bb); return verifier.VerifyBuffer("", false, UniverseVerify.Verify); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Universe __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public double Age { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetDouble(o + __p.bb_pos) : (double)0.0; } } + public flatbuffers.goldens.Galaxy? Galaxies(int j) { int o = __p.__offset(6); return o != 0 ? (flatbuffers.goldens.Galaxy?)(new flatbuffers.goldens.Galaxy()).__assign(__p.__indirect(__p.__vector(o) + j * 4), __p.bb) : null; } + public int GalaxiesLength { get { int o = __p.__offset(6); return o != 0 ? __p.__vector_len(o) : 0; } } + + public static Offset CreateUniverse(FlatBufferBuilder builder, + double age = 0.0, + VectorOffset galaxiesOffset = default(VectorOffset)) { + builder.StartTable(2); + Universe.AddAge(builder, age); + Universe.AddGalaxies(builder, galaxiesOffset); + return Universe.EndUniverse(builder); + } + + public static void StartUniverse(FlatBufferBuilder builder) { builder.StartTable(2); } + public static void AddAge(FlatBufferBuilder builder, double age) { builder.AddDouble(0, age, 0.0); } + public static void AddGalaxies(FlatBufferBuilder builder, VectorOffset galaxiesOffset) { builder.AddOffset(1, galaxiesOffset.Value, 0); } + public static VectorOffset CreateGalaxiesVector(FlatBufferBuilder builder, Offset[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); } + public static VectorOffset CreateGalaxiesVectorBlock(FlatBufferBuilder builder, Offset[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateGalaxiesVectorBlock(FlatBufferBuilder builder, ArraySegment> data) { builder.StartVector(4, data.Count, 4); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateGalaxiesVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add>(dataPtr, sizeInBytes); return builder.EndVector(); } + public static void StartGalaxiesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static Offset EndUniverse(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishUniverseBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value); } + public static void FinishSizePrefixedUniverseBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value); } +} + + +static public class UniverseVerify +{ + static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*Age*/, 8 /*double*/, 8, false) + && verifier.VerifyVectorOfTables(tablePos, 6 /*Galaxies*/, flatbuffers.goldens.GalaxyVerify.Verify, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/third_party/flatbuffers/goldens/csharp/generate.py b/third_party/flatbuffers/goldens/csharp/generate.py new file mode 100644 index 00000000000..11f5b0572f1 --- /dev/null +++ b/third_party/flatbuffers/goldens/csharp/generate.py @@ -0,0 +1,10 @@ +from golden_utils import flatc_golden + + +def flatc(options, schema): + # Wrap the golden flatc generator with C# specifics + flatc_golden(options=["--csharp"] + options, schema=schema, prefix="csharp") + + +def GenerateCSharp(): + flatc([], "basic.fbs") diff --git a/third_party/flatbuffers/goldens/dart/basic_flatbuffers.goldens_generated.dart b/third_party/flatbuffers/goldens/dart/basic_flatbuffers.goldens_generated.dart new file mode 100644 index 00000000000..0f6c6087ca0 --- /dev/null +++ b/third_party/flatbuffers/goldens/dart/basic_flatbuffers.goldens_generated.dart @@ -0,0 +1,162 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable, constant_identifier_names + +library flatbuffers.goldens; + +import 'dart:typed_data' show Uint8List; +import 'package:flat_buffers/flat_buffers.dart' as fb; + + +class Galaxy { + Galaxy._(this._bc, this._bcOffset); + factory Galaxy(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _GalaxyReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + int get numStars => const fb.Int64Reader().vTableGet(_bc, _bcOffset, 4, 0); + + @override + String toString() { + return 'Galaxy{numStars: ${numStars}}'; + } +} + +class _GalaxyReader extends fb.TableReader { + const _GalaxyReader(); + + @override + Galaxy createObject(fb.BufferContext bc, int offset) => + Galaxy._(bc, offset); +} + +class GalaxyBuilder { + GalaxyBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(1); + } + + int addNumStars(int? numStars) { + fbBuilder.addInt64(0, numStars); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class GalaxyObjectBuilder extends fb.ObjectBuilder { + final int? _numStars; + + GalaxyObjectBuilder({ + int? numStars, + }) + : _numStars = numStars; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + fbBuilder.startTable(1); + fbBuilder.addInt64(0, _numStars); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} +class Universe { + Universe._(this._bc, this._bcOffset); + factory Universe(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _UniverseReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + double get age => const fb.Float64Reader().vTableGet(_bc, _bcOffset, 4, 0.0); + List? get galaxies => const fb.ListReader(Galaxy.reader).vTableGetNullable(_bc, _bcOffset, 6); + + @override + String toString() { + return 'Universe{age: ${age}, galaxies: ${galaxies}}'; + } +} + +class _UniverseReader extends fb.TableReader { + const _UniverseReader(); + + @override + Universe createObject(fb.BufferContext bc, int offset) => + Universe._(bc, offset); +} + +class UniverseBuilder { + UniverseBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(2); + } + + int addAge(double? age) { + fbBuilder.addFloat64(0, age); + return fbBuilder.offset; + } + int addGalaxiesOffset(int? offset) { + fbBuilder.addOffset(1, offset); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class UniverseObjectBuilder extends fb.ObjectBuilder { + final double? _age; + final List? _galaxies; + + UniverseObjectBuilder({ + double? age, + List? galaxies, + }) + : _age = age, + _galaxies = galaxies; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? galaxiesOffset = _galaxies == null ? null + : fbBuilder.writeList(_galaxies!.map((b) => b.getOrCreateOffset(fbBuilder)).toList()); + fbBuilder.startTable(2); + fbBuilder.addFloat64(0, _age); + fbBuilder.addOffset(1, galaxiesOffset); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} diff --git a/third_party/flatbuffers/goldens/dart/generate.py b/third_party/flatbuffers/goldens/dart/generate.py new file mode 100644 index 00000000000..4d667c01b59 --- /dev/null +++ b/third_party/flatbuffers/goldens/dart/generate.py @@ -0,0 +1,10 @@ +from golden_utils import flatc_golden + + +def flatc(options, schema): + # Wrap the golden flatc generator with Dart specifics + flatc_golden(options=["--dart"] + options, schema=schema, prefix="dart") + + +def GenerateDart(): + flatc([], "basic.fbs") diff --git a/third_party/flatbuffers/goldens/generate_goldens.py b/third_party/flatbuffers/goldens/generate_goldens.py new file mode 100755 index 00000000000..d521b812dc6 --- /dev/null +++ b/third_party/flatbuffers/goldens/generate_goldens.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +from cpp.generate import GenerateCpp +from csharp.generate import GenerateCSharp +from dart.generate import GenerateDart +from go.generate import GenerateGo +from java.generate import GenerateJava +from kotlin.generate import GenerateKotlin +from lobster.generate import GenerateLobster +from lua.generate import GenerateLua +from nim.generate import GenerateNim +from php.generate import GeneratePhp +from py.generate import GeneratePython +from rust.generate import GenerateRust +from swift.generate import GenerateSwift +from ts.generate import GenerateTs + +# Run each language generation logic +GenerateCpp() +GenerateCSharp() +GenerateDart() +GenerateGo() +GenerateJava() +GenerateKotlin() +GenerateLobster() +GenerateLua() +GenerateNim() +GeneratePhp() +GeneratePython() +GenerateRust() +GenerateSwift() +GenerateTs() diff --git a/third_party/flatbuffers/goldens/go/flatbuffers/goldens/Galaxy.go b/third_party/flatbuffers/goldens/go/flatbuffers/goldens/Galaxy.go new file mode 100644 index 00000000000..a0cd0ae719f --- /dev/null +++ b/third_party/flatbuffers/goldens/go/flatbuffers/goldens/Galaxy.go @@ -0,0 +1,64 @@ +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package goldens + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type Galaxy struct { + _tab flatbuffers.Table +} + +func GetRootAsGalaxy(buf []byte, offset flatbuffers.UOffsetT) *Galaxy { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Galaxy{} + x.Init(buf, n+offset) + return x +} + +func FinishGalaxyBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.Finish(offset) +} + +func GetSizePrefixedRootAsGalaxy(buf []byte, offset flatbuffers.UOffsetT) *Galaxy { + n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:]) + x := &Galaxy{} + x.Init(buf, n+offset+flatbuffers.SizeUint32) + return x +} + +func FinishSizePrefixedGalaxyBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.FinishSizePrefixed(offset) +} + +func (rcv *Galaxy) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Galaxy) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Galaxy) NumStars() int64 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return rcv._tab.GetInt64(o + rcv._tab.Pos) + } + return 0 +} + +func (rcv *Galaxy) MutateNumStars(n int64) bool { + return rcv._tab.MutateInt64Slot(4, n) +} + +func GalaxyStart(builder *flatbuffers.Builder) { + builder.StartObject(1) +} +func GalaxyAddNumStars(builder *flatbuffers.Builder, numStars int64) { + builder.PrependInt64Slot(0, numStars, 0) +} +func GalaxyEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/third_party/flatbuffers/goldens/go/flatbuffers/goldens/Universe.go b/third_party/flatbuffers/goldens/go/flatbuffers/goldens/Universe.go new file mode 100644 index 00000000000..d8fd83327af --- /dev/null +++ b/third_party/flatbuffers/goldens/go/flatbuffers/goldens/Universe.go @@ -0,0 +1,90 @@ +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package goldens + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type Universe struct { + _tab flatbuffers.Table +} + +func GetRootAsUniverse(buf []byte, offset flatbuffers.UOffsetT) *Universe { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Universe{} + x.Init(buf, n+offset) + return x +} + +func FinishUniverseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.Finish(offset) +} + +func GetSizePrefixedRootAsUniverse(buf []byte, offset flatbuffers.UOffsetT) *Universe { + n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:]) + x := &Universe{} + x.Init(buf, n+offset+flatbuffers.SizeUint32) + return x +} + +func FinishSizePrefixedUniverseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.FinishSizePrefixed(offset) +} + +func (rcv *Universe) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Universe) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Universe) Age() float64 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return rcv._tab.GetFloat64(o + rcv._tab.Pos) + } + return 0.0 +} + +func (rcv *Universe) MutateAge(n float64) bool { + return rcv._tab.MutateFloat64Slot(4, n) +} + +func (rcv *Universe) Galaxies(obj *Galaxy, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 4 + x = rcv._tab.Indirect(x) + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *Universe) GalaxiesLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +func UniverseStart(builder *flatbuffers.Builder) { + builder.StartObject(2) +} +func UniverseAddAge(builder *flatbuffers.Builder, age float64) { + builder.PrependFloat64Slot(0, age, 0.0) +} +func UniverseAddGalaxies(builder *flatbuffers.Builder, galaxies flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(galaxies), 0) +} +func UniverseStartGalaxiesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(4, numElems, 4) +} +func UniverseEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/third_party/flatbuffers/goldens/go/generate.py b/third_party/flatbuffers/goldens/go/generate.py new file mode 100644 index 00000000000..1f809aa64d3 --- /dev/null +++ b/third_party/flatbuffers/goldens/go/generate.py @@ -0,0 +1,10 @@ +from golden_utils import flatc_golden + + +def flatc(options, schema): + # Wrap the golden flatc generator with Go specifics + flatc_golden(options=["--go"] + options, schema=schema, prefix="go") + + +def GenerateGo(): + flatc([], "basic.fbs") diff --git a/third_party/flatbuffers/goldens/golden_utils.py b/third_party/flatbuffers/goldens/golden_utils.py new file mode 100644 index 00000000000..576178e510b --- /dev/null +++ b/third_party/flatbuffers/goldens/golden_utils.py @@ -0,0 +1,30 @@ +from pathlib import Path +import sys + +# Get the path where this script is located so we can invoke the script from +# any directory and have the paths work correctly. +script_path = Path(__file__).parent.resolve() + +# Get the root path as an absolute path, so all derived paths are absolute. +root_path = script_path.parent.absolute() + +# Get the location of the schema +schema_path = Path(script_path, "schema") + +# Too add the util package in /scripts/util.py +sys.path.append(str(root_path.absolute())) + +from scripts.util import flatc + + +def flatc_golden(options, schema, prefix): + # wrap the generic flatc call with specifis for these goldens. + flatc( + options=options, + # where the files are generated, typically the language (e.g. "cpp"). + prefix=prefix, + # The schema are relative to the schema directory. + schema=str(Path(schema_path, schema)), + # Run flatc from this location. + cwd=script_path, + ) diff --git a/third_party/flatbuffers/goldens/java/flatbuffers/goldens/Galaxy.java b/third_party/flatbuffers/goldens/java/flatbuffers/goldens/Galaxy.java new file mode 100644 index 00000000000..c387318e2b3 --- /dev/null +++ b/third_party/flatbuffers/goldens/java/flatbuffers/goldens/Galaxy.java @@ -0,0 +1,53 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package flatbuffers.goldens; + +import com.google.flatbuffers.BaseVector; +import com.google.flatbuffers.BooleanVector; +import com.google.flatbuffers.ByteVector; +import com.google.flatbuffers.Constants; +import com.google.flatbuffers.DoubleVector; +import com.google.flatbuffers.FlatBufferBuilder; +import com.google.flatbuffers.FloatVector; +import com.google.flatbuffers.IntVector; +import com.google.flatbuffers.LongVector; +import com.google.flatbuffers.ShortVector; +import com.google.flatbuffers.StringVector; +import com.google.flatbuffers.Struct; +import com.google.flatbuffers.Table; +import com.google.flatbuffers.UnionVector; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +@SuppressWarnings("unused") +public final class Galaxy extends Table { + public static void ValidateVersion() { Constants.FLATBUFFERS_25_9_23(); } + public static Galaxy getRootAsGalaxy(ByteBuffer _bb) { return getRootAsGalaxy(_bb, new Galaxy()); } + public static Galaxy getRootAsGalaxy(ByteBuffer _bb, Galaxy obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public Galaxy __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public long numStars() { int o = __offset(4); return o != 0 ? bb.getLong(o + bb_pos) : 0L; } + + public static int createGalaxy(FlatBufferBuilder builder, + long numStars) { + builder.startTable(1); + Galaxy.addNumStars(builder, numStars); + return Galaxy.endGalaxy(builder); + } + + public static void startGalaxy(FlatBufferBuilder builder) { builder.startTable(1); } + public static void addNumStars(FlatBufferBuilder builder, long numStars) { builder.addLong(0, numStars, 0L); } + public static int endGalaxy(FlatBufferBuilder builder) { + int o = builder.endTable(); + return o; + } + + public static final class Vector extends BaseVector { + public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } + + public Galaxy get(int j) { return get(new Galaxy(), j); } + public Galaxy get(Galaxy obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } + } +} + diff --git a/third_party/flatbuffers/goldens/java/flatbuffers/goldens/Universe.java b/third_party/flatbuffers/goldens/java/flatbuffers/goldens/Universe.java new file mode 100644 index 00000000000..c94db618ea9 --- /dev/null +++ b/third_party/flatbuffers/goldens/java/flatbuffers/goldens/Universe.java @@ -0,0 +1,65 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package flatbuffers.goldens; + +import com.google.flatbuffers.BaseVector; +import com.google.flatbuffers.BooleanVector; +import com.google.flatbuffers.ByteVector; +import com.google.flatbuffers.Constants; +import com.google.flatbuffers.DoubleVector; +import com.google.flatbuffers.FlatBufferBuilder; +import com.google.flatbuffers.FloatVector; +import com.google.flatbuffers.IntVector; +import com.google.flatbuffers.LongVector; +import com.google.flatbuffers.ShortVector; +import com.google.flatbuffers.StringVector; +import com.google.flatbuffers.Struct; +import com.google.flatbuffers.Table; +import com.google.flatbuffers.UnionVector; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +@SuppressWarnings("unused") +public final class Universe extends Table { + public static void ValidateVersion() { Constants.FLATBUFFERS_25_9_23(); } + public static Universe getRootAsUniverse(ByteBuffer _bb) { return getRootAsUniverse(_bb, new Universe()); } + public static Universe getRootAsUniverse(ByteBuffer _bb, Universe obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public Universe __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public double age() { int o = __offset(4); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } + public flatbuffers.goldens.Galaxy galaxies(int j) { return galaxies(new flatbuffers.goldens.Galaxy(), j); } + public flatbuffers.goldens.Galaxy galaxies(flatbuffers.goldens.Galaxy obj, int j) { int o = __offset(6); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public int galaxiesLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } + public flatbuffers.goldens.Galaxy.Vector galaxiesVector() { return galaxiesVector(new flatbuffers.goldens.Galaxy.Vector()); } + public flatbuffers.goldens.Galaxy.Vector galaxiesVector(flatbuffers.goldens.Galaxy.Vector obj) { int o = __offset(6); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } + + public static int createUniverse(FlatBufferBuilder builder, + double age, + int galaxiesOffset) { + builder.startTable(2); + Universe.addAge(builder, age); + Universe.addGalaxies(builder, galaxiesOffset); + return Universe.endUniverse(builder); + } + + public static void startUniverse(FlatBufferBuilder builder) { builder.startTable(2); } + public static void addAge(FlatBufferBuilder builder, double age) { builder.addDouble(0, age, 0.0); } + public static void addGalaxies(FlatBufferBuilder builder, int galaxiesOffset) { builder.addOffset(1, galaxiesOffset, 0); } + public static int createGalaxiesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } + public static void startGalaxiesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static int endUniverse(FlatBufferBuilder builder) { + int o = builder.endTable(); + return o; + } + public static void finishUniverseBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset); } + public static void finishSizePrefixedUniverseBuffer(FlatBufferBuilder builder, int offset) { builder.finishSizePrefixed(offset); } + + public static final class Vector extends BaseVector { + public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } + + public Universe get(int j) { return get(new Universe(), j); } + public Universe get(Universe obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } + } +} + diff --git a/third_party/flatbuffers/goldens/java/generate.py b/third_party/flatbuffers/goldens/java/generate.py new file mode 100644 index 00000000000..369ceb022be --- /dev/null +++ b/third_party/flatbuffers/goldens/java/generate.py @@ -0,0 +1,10 @@ +from golden_utils import flatc_golden + + +def flatc(options, schema): + # Wrap the golden flatc generator with Java specifics + flatc_golden(options=["--java"] + options, schema=schema, prefix="java") + + +def GenerateJava(): + flatc([], "basic.fbs") diff --git a/third_party/flatbuffers/goldens/kotlin/flatbuffers/goldens/Galaxy.kt b/third_party/flatbuffers/goldens/kotlin/flatbuffers/goldens/Galaxy.kt new file mode 100644 index 00000000000..4d3035b54f6 --- /dev/null +++ b/third_party/flatbuffers/goldens/kotlin/flatbuffers/goldens/Galaxy.kt @@ -0,0 +1,55 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package flatbuffers.goldens + +import com.google.flatbuffers.BaseVector +import com.google.flatbuffers.BooleanVector +import com.google.flatbuffers.ByteVector +import com.google.flatbuffers.Constants +import com.google.flatbuffers.DoubleVector +import com.google.flatbuffers.FlatBufferBuilder +import com.google.flatbuffers.FloatVector +import com.google.flatbuffers.LongVector +import com.google.flatbuffers.StringVector +import com.google.flatbuffers.Struct +import com.google.flatbuffers.Table +import com.google.flatbuffers.UnionVector +import java.nio.ByteBuffer +import java.nio.ByteOrder +import kotlin.math.sign + +@Suppress("unused") +class Galaxy : Table() { + + fun __init(_i: Int, _bb: ByteBuffer) { + __reset(_i, _bb) + } + fun __assign(_i: Int, _bb: ByteBuffer) : Galaxy { + __init(_i, _bb) + return this + } + val numStars : Long + get() { + val o = __offset(4) + return if(o != 0) bb.getLong(o + bb_pos) else 0L + } + companion object { + fun validateVersion() = Constants.FLATBUFFERS_25_9_23() + fun getRootAsGalaxy(_bb: ByteBuffer): Galaxy = getRootAsGalaxy(_bb, Galaxy()) + fun getRootAsGalaxy(_bb: ByteBuffer, obj: Galaxy): Galaxy { + _bb.order(ByteOrder.LITTLE_ENDIAN) + return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)) + } + fun createGalaxy(builder: FlatBufferBuilder, numStars: Long) : Int { + builder.startTable(1) + addNumStars(builder, numStars) + return endGalaxy(builder) + } + fun startGalaxy(builder: FlatBufferBuilder) = builder.startTable(1) + fun addNumStars(builder: FlatBufferBuilder, numStars: Long) = builder.addLong(0, numStars, 0L) + fun endGalaxy(builder: FlatBufferBuilder) : Int { + val o = builder.endTable() + return o + } + } +} diff --git a/third_party/flatbuffers/goldens/kotlin/flatbuffers/goldens/Universe.kt b/third_party/flatbuffers/goldens/kotlin/flatbuffers/goldens/Universe.kt new file mode 100644 index 00000000000..b14127a016f --- /dev/null +++ b/third_party/flatbuffers/goldens/kotlin/flatbuffers/goldens/Universe.kt @@ -0,0 +1,80 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package flatbuffers.goldens + +import com.google.flatbuffers.BaseVector +import com.google.flatbuffers.BooleanVector +import com.google.flatbuffers.ByteVector +import com.google.flatbuffers.Constants +import com.google.flatbuffers.DoubleVector +import com.google.flatbuffers.FlatBufferBuilder +import com.google.flatbuffers.FloatVector +import com.google.flatbuffers.LongVector +import com.google.flatbuffers.StringVector +import com.google.flatbuffers.Struct +import com.google.flatbuffers.Table +import com.google.flatbuffers.UnionVector +import java.nio.ByteBuffer +import java.nio.ByteOrder +import kotlin.math.sign + +@Suppress("unused") +class Universe : Table() { + + fun __init(_i: Int, _bb: ByteBuffer) { + __reset(_i, _bb) + } + fun __assign(_i: Int, _bb: ByteBuffer) : Universe { + __init(_i, _bb) + return this + } + val age : Double + get() { + val o = __offset(4) + return if(o != 0) bb.getDouble(o + bb_pos) else 0.0 + } + fun galaxies(j: Int) : flatbuffers.goldens.Galaxy? = galaxies(flatbuffers.goldens.Galaxy(), j) + fun galaxies(obj: flatbuffers.goldens.Galaxy, j: Int) : flatbuffers.goldens.Galaxy? { + val o = __offset(6) + return if (o != 0) { + obj.__assign(__indirect(__vector(o) + j * 4), bb) + } else { + null + } + } + val galaxiesLength : Int + get() { + val o = __offset(6); return if (o != 0) __vector_len(o) else 0 + } + companion object { + fun validateVersion() = Constants.FLATBUFFERS_25_9_23() + fun getRootAsUniverse(_bb: ByteBuffer): Universe = getRootAsUniverse(_bb, Universe()) + fun getRootAsUniverse(_bb: ByteBuffer, obj: Universe): Universe { + _bb.order(ByteOrder.LITTLE_ENDIAN) + return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)) + } + fun createUniverse(builder: FlatBufferBuilder, age: Double, galaxiesOffset: Int) : Int { + builder.startTable(2) + addAge(builder, age) + addGalaxies(builder, galaxiesOffset) + return endUniverse(builder) + } + fun startUniverse(builder: FlatBufferBuilder) = builder.startTable(2) + fun addAge(builder: FlatBufferBuilder, age: Double) = builder.addDouble(0, age, 0.0) + fun addGalaxies(builder: FlatBufferBuilder, galaxies: Int) = builder.addOffset(1, galaxies, 0) + fun createGalaxiesVector(builder: FlatBufferBuilder, data: IntArray) : Int { + builder.startVector(4, data.size, 4) + for (i in data.size - 1 downTo 0) { + builder.addOffset(data[i]) + } + return builder.endVector() + } + fun startGalaxiesVector(builder: FlatBufferBuilder, numElems: Int) = builder.startVector(4, numElems, 4) + fun endUniverse(builder: FlatBufferBuilder) : Int { + val o = builder.endTable() + return o + } + fun finishUniverseBuffer(builder: FlatBufferBuilder, offset: Int) = builder.finish(offset) + fun finishSizePrefixedUniverseBuffer(builder: FlatBufferBuilder, offset: Int) = builder.finishSizePrefixed(offset) + } +} diff --git a/third_party/flatbuffers/goldens/kotlin/generate.py b/third_party/flatbuffers/goldens/kotlin/generate.py new file mode 100644 index 00000000000..bab81ae8b17 --- /dev/null +++ b/third_party/flatbuffers/goldens/kotlin/generate.py @@ -0,0 +1,10 @@ +from golden_utils import flatc_golden + + +def flatc(options, schema): + # Wrap the golden flatc generator with Kotlin specifics + flatc_golden(options=["--kotlin"] + options, schema=schema, prefix="kotlin") + + +def GenerateKotlin(): + flatc([], "basic.fbs") diff --git a/third_party/flatbuffers/goldens/lobster/basic_generated.lobster b/third_party/flatbuffers/goldens/lobster/basic_generated.lobster new file mode 100644 index 00000000000..ade4b824d49 --- /dev/null +++ b/third_party/flatbuffers/goldens/lobster/basic_generated.lobster @@ -0,0 +1,57 @@ +// automatically generated by the FlatBuffers compiler, do not modify +import flatbuffers + +namespace flatbuffers.goldens + +class Galaxy + +class Universe + +class Galaxy : flatbuffers.handle + def num_stars() -> int: + return flatbuffers.field_int64(buf_, pos_, 4, 0) + +def GetRootAsGalaxy(buf:string): return Galaxy { buf, flatbuffers.indirect(buf, 0) } + +struct GalaxyBuilder: + b_:flatbuffers.builder + def start(): + b_.StartObject(1) + return this + def add_num_stars(num_stars:int): + b_.PrependInt64Slot(0, num_stars, 0) + return this + def end(): + return b_.EndObject() + +class Universe : flatbuffers.handle + def age() -> float: + return flatbuffers.field_float64(buf_, pos_, 4, 0.0) + def galaxies(i:int) -> flatbuffers.goldens.Galaxy: + return flatbuffers.goldens.Galaxy { buf_, flatbuffers.indirect(buf_, flatbuffers.field_vector(buf_, pos_, 6) + i * 4) } + def galaxies_length() -> int: + return flatbuffers.field_vector_len(buf_, pos_, 6) + +def GetRootAsUniverse(buf:string): return Universe { buf, flatbuffers.indirect(buf, 0) } + +struct UniverseBuilder: + b_:flatbuffers.builder + def start(): + b_.StartObject(2) + return this + def add_age(age:float): + b_.PrependFloat64Slot(0, age, 0.0) + return this + def add_galaxies(galaxies:flatbuffers.offset): + b_.PrependUOffsetTRelativeSlot(1, galaxies) + return this + def end(): + return b_.EndObject() + +def UniverseStartGalaxiesVector(b_:flatbuffers.builder, n_:int): + b_.StartVector(4, n_, 4) +def UniverseCreateGalaxiesVector(b_:flatbuffers.builder, v_:[flatbuffers.offset]): + b_.StartVector(4, v_.length, 4) + reverse(v_) e_: b_.PrependUOffsetTRelative(e_) + return b_.EndVector(v_.length) + diff --git a/third_party/flatbuffers/goldens/lobster/generate.py b/third_party/flatbuffers/goldens/lobster/generate.py new file mode 100644 index 00000000000..bcd51509b55 --- /dev/null +++ b/third_party/flatbuffers/goldens/lobster/generate.py @@ -0,0 +1,10 @@ +from golden_utils import flatc_golden + + +def flatc(options, schema): + # Wrap the golden flatc generator with Lobster specifics + flatc_golden(options=["--lobster"] + options, schema=schema, prefix="lobster") + + +def GenerateLobster(): + flatc([], "basic.fbs") diff --git a/third_party/flatbuffers/goldens/lua/Galaxy.lua b/third_party/flatbuffers/goldens/lua/Galaxy.lua new file mode 100644 index 00000000000..fd346081921 --- /dev/null +++ b/third_party/flatbuffers/goldens/lua/Galaxy.lua @@ -0,0 +1,48 @@ +--[[ Galaxy + + Automatically generated by the FlatBuffers compiler, do not modify. + Or modify. I'm a message, not a cop. + + flatc version: 23.5.26 + + Declared by : //basic.fbs + Rooting type : Universe (//basic.fbs) + +--]] + +local flatbuffers = require('flatbuffers') + +local Galaxy = {} +local mt = {} + +function Galaxy.New() + local o = {} + setmetatable(o, {__index = mt}) + return o +end + +function mt:Init(buf, pos) + self.view = flatbuffers.view.New(buf, pos) +end + +function mt:NumStars() + local o = self.view:Offset(4) + if o ~= 0 then + return self.view:Get(flatbuffers.N.Int64, self.view.pos + o) + end + return 0 +end + +function Galaxy.Start(builder) + builder:StartObject(1) +end + +function Galaxy.AddNumStars(builder, numStars) + builder:PrependInt64Slot(0, numStars, 0) +end + +function Galaxy.End(builder) + return builder:EndObject() +end + +return Galaxy \ No newline at end of file diff --git a/third_party/flatbuffers/goldens/lua/Universe.lua b/third_party/flatbuffers/goldens/lua/Universe.lua new file mode 100644 index 00000000000..74a7761e0fd --- /dev/null +++ b/third_party/flatbuffers/goldens/lua/Universe.lua @@ -0,0 +1,88 @@ +--[[ Universe + + Automatically generated by the FlatBuffers compiler, do not modify. + Or modify. I'm a message, not a cop. + + flatc version: 23.5.26 + + Declared by : //basic.fbs + Rooting type : Universe (//basic.fbs) + +--]] + +local __Galaxy = require('Galaxy') +local flatbuffers = require('flatbuffers') + +local Universe = {} +local mt = {} + +function Universe.New() + local o = {} + setmetatable(o, {__index = mt}) + return o +end + +function Universe.GetRootAsUniverse(buf, offset) + if type(buf) == "string" then + buf = flatbuffers.binaryArray.New(buf) + end + + local n = flatbuffers.N.UOffsetT:Unpack(buf, offset) + local o = Universe.New() + o:Init(buf, n + offset) + return o +end + +function mt:Init(buf, pos) + self.view = flatbuffers.view.New(buf, pos) +end + +function mt:Age() + local o = self.view:Offset(4) + if o ~= 0 then + return self.view:Get(flatbuffers.N.Float64, self.view.pos + o) + end + return 0.0 +end + +function mt:Galaxies(j) + local o = self.view:Offset(6) + if o ~= 0 then + local x = self.view:Vector(o) + x = x + ((j-1) * 4) + x = self.view:Indirect(x) + local obj = __Galaxy.New() + obj:Init(self.view.bytes, x) + return obj + end +end + +function mt:GalaxiesLength() + local o = self.view:Offset(6) + if o ~= 0 then + return self.view:VectorLen(o) + end + return 0 +end + +function Universe.Start(builder) + builder:StartObject(2) +end + +function Universe.AddAge(builder, age) + builder:PrependFloat64Slot(0, age, 0.0) +end + +function Universe.AddGalaxies(builder, galaxies) + builder:PrependUOffsetTRelativeSlot(1, galaxies, 0) +end + +function Universe.StartGalaxiesVector(builder, numElems) + return builder:StartVector(4, numElems, 4) +end + +function Universe.End(builder) + return builder:EndObject() +end + +return Universe \ No newline at end of file diff --git a/third_party/flatbuffers/goldens/lua/generate.py b/third_party/flatbuffers/goldens/lua/generate.py new file mode 100644 index 00000000000..108a4d580ed --- /dev/null +++ b/third_party/flatbuffers/goldens/lua/generate.py @@ -0,0 +1,10 @@ +from golden_utils import flatc_golden + + +def flatc(options, schema): + # Wrap the golden flatc generator with Lua specifics + flatc_golden(options=["--lua"] + options, schema=schema, prefix="lua") + + +def GenerateLua(): + flatc([], "basic.fbs") diff --git a/third_party/flatbuffers/goldens/nim/Galaxy.nim b/third_party/flatbuffers/goldens/nim/Galaxy.nim new file mode 100644 index 00000000000..76b1e4a2e03 --- /dev/null +++ b/third_party/flatbuffers/goldens/nim/Galaxy.nim @@ -0,0 +1,26 @@ +#[ Galaxy + Automatically generated by the FlatBuffers compiler, do not modify. + Or modify. I'm a message, not a cop. + + flatc version: 23.5.26 + + Declared by : //basic.fbs + Rooting type : Universe (//basic.fbs) +]# + +import flatbuffers + +type Galaxy* = object of FlatObj +func numStars*(self: Galaxy): int64 = + let o = self.tab.Offset(4) + if o != 0: + return Get[int64](self.tab, self.tab.Pos + o) + return 0 +func `numStars=`*(self: var Galaxy, n: int64): bool = + return self.tab.MutateSlot(4, n) +proc GalaxyStart*(builder: var Builder) = + builder.StartObject(1) +proc GalaxyAddnumStars*(builder: var Builder, numStars: int64) = + builder.PrependSlot(0, numStars, default(int64)) +proc GalaxyEnd*(builder: var Builder): uoffset = + return builder.EndObject() diff --git a/third_party/flatbuffers/goldens/nim/Universe.nim b/third_party/flatbuffers/goldens/nim/Universe.nim new file mode 100644 index 00000000000..a3e8a9114f8 --- /dev/null +++ b/third_party/flatbuffers/goldens/nim/Universe.nim @@ -0,0 +1,46 @@ +#[ Universe + Automatically generated by the FlatBuffers compiler, do not modify. + Or modify. I'm a message, not a cop. + + flatc version: 23.5.26 + + Declared by : //basic.fbs + Rooting type : Universe (//basic.fbs) +]# + +import Galaxy as Galaxy +import flatbuffers +import std/options + +type Universe* = object of FlatObj +func age*(self: Universe): float64 = + let o = self.tab.Offset(4) + if o != 0: + return Get[float64](self.tab, self.tab.Pos + o) + return 0.0 +func `age=`*(self: var Universe, n: float64): bool = + return self.tab.MutateSlot(4, n) +func galaxiesLength*(self: Universe): int = + let o = self.tab.Offset(6) + if o != 0: + return self.tab.VectorLen(o) +func galaxies*(self: Universe, j: int): Galaxy.Galaxy = + let o = self.tab.Offset(6) + if o != 0: + var x = self.tab.Vector(o) + x += j.uoffset * 4.uoffset + return Galaxy.Galaxy(tab: Vtable(Bytes: self.tab.Bytes, Pos: x)) +func galaxies*(self: Universe): seq[Galaxy.Galaxy] = + let len = self.galaxiesLength + for i in countup(0, len - 1): + result.add(self.galaxies(i)) +proc UniverseStart*(builder: var Builder) = + builder.StartObject(2) +proc UniverseAddage*(builder: var Builder, age: float64) = + builder.PrependSlot(0, age, default(float64)) +proc UniverseAddgalaxies*(builder: var Builder, galaxies: uoffset) = + builder.PrependSlot(1, galaxies, default(uoffset)) +proc UniverseStartgalaxiesVector*(builder: var Builder, numElems: uoffset) = + builder.StartVector(4, numElems, 4) +proc UniverseEnd*(builder: var Builder): uoffset = + return builder.EndObject() diff --git a/third_party/flatbuffers/goldens/nim/generate.py b/third_party/flatbuffers/goldens/nim/generate.py new file mode 100644 index 00000000000..5aef75b1bec --- /dev/null +++ b/third_party/flatbuffers/goldens/nim/generate.py @@ -0,0 +1,10 @@ +from golden_utils import flatc_golden + + +def flatc(options, schema): + # Wrap the golden flatc generator with Nim specifics + flatc_golden(options=["--nim"] + options, schema=schema, prefix="nim") + + +def GenerateNim(): + flatc([], "basic.fbs") diff --git a/third_party/flatbuffers/goldens/php/flatbuffers/goldens/Galaxy.php b/third_party/flatbuffers/goldens/php/flatbuffers/goldens/Galaxy.php new file mode 100644 index 00000000000..d29a09a7665 --- /dev/null +++ b/third_party/flatbuffers/goldens/php/flatbuffers/goldens/Galaxy.php @@ -0,0 +1,84 @@ +init($bb->getInt($bb->getPosition()) + $bb->getPosition(), $bb)); + } + + /** + * @param int $_i offset + * @param ByteBuffer $_bb + * @return Galaxy + **/ + public function init($_i, ByteBuffer $_bb) + { + $this->bb_pos = $_i; + $this->bb = $_bb; + return $this; + } + + /** + * @return long + */ + public function getNumStars() + { + $o = $this->__offset(4); + return $o != 0 ? $this->bb->getLong($o + $this->bb_pos) : 0; + } + + /** + * @param FlatBufferBuilder $builder + * @return void + */ + public static function startGalaxy(FlatBufferBuilder $builder) + { + $builder->StartObject(1); + } + + /** + * @param FlatBufferBuilder $builder + * @return Galaxy + */ + public static function createGalaxy(FlatBufferBuilder $builder, $num_stars) + { + $builder->startObject(1); + self::addNumStars($builder, $num_stars); + $o = $builder->endObject(); + return $o; + } + + /** + * @param FlatBufferBuilder $builder + * @param long + * @return void + */ + public static function addNumStars(FlatBufferBuilder $builder, $numStars) + { + $builder->addLongX(0, $numStars, 0); + } + + /** + * @param FlatBufferBuilder $builder + * @return int table offset + */ + public static function endGalaxy(FlatBufferBuilder $builder) + { + $o = $builder->endObject(); + return $o; + } +} diff --git a/third_party/flatbuffers/goldens/php/flatbuffers/goldens/Universe.php b/third_party/flatbuffers/goldens/php/flatbuffers/goldens/Universe.php new file mode 100644 index 00000000000..9d705614e91 --- /dev/null +++ b/third_party/flatbuffers/goldens/php/flatbuffers/goldens/Universe.php @@ -0,0 +1,143 @@ +init($bb->getInt($bb->getPosition()) + $bb->getPosition(), $bb)); + } + + /** + * @param int $_i offset + * @param ByteBuffer $_bb + * @return Universe + **/ + public function init($_i, ByteBuffer $_bb) + { + $this->bb_pos = $_i; + $this->bb = $_bb; + return $this; + } + + /** + * @return double + */ + public function getAge() + { + $o = $this->__offset(4); + return $o != 0 ? $this->bb->getDouble($o + $this->bb_pos) : 0.0; + } + + /** + * @returnVectorOffset + */ + public function getGalaxies($j) + { + $o = $this->__offset(6); + $obj = new Galaxy(); + return $o != 0 ? $obj->init($this->__indirect($this->__vector($o) + $j * 4), $this->bb) : null; + } + + /** + * @return int + */ + public function getGalaxiesLength() + { + $o = $this->__offset(6); + return $o != 0 ? $this->__vector_len($o) : 0; + } + + /** + * @param FlatBufferBuilder $builder + * @return void + */ + public static function startUniverse(FlatBufferBuilder $builder) + { + $builder->StartObject(2); + } + + /** + * @param FlatBufferBuilder $builder + * @return Universe + */ + public static function createUniverse(FlatBufferBuilder $builder, $age, $galaxies) + { + $builder->startObject(2); + self::addAge($builder, $age); + self::addGalaxies($builder, $galaxies); + $o = $builder->endObject(); + return $o; + } + + /** + * @param FlatBufferBuilder $builder + * @param double + * @return void + */ + public static function addAge(FlatBufferBuilder $builder, $age) + { + $builder->addDoubleX(0, $age, 0.0); + } + + /** + * @param FlatBufferBuilder $builder + * @param VectorOffset + * @return void + */ + public static function addGalaxies(FlatBufferBuilder $builder, $galaxies) + { + $builder->addOffsetX(1, $galaxies, 0); + } + + /** + * @param FlatBufferBuilder $builder + * @param array offset array + * @return int vector offset + */ + public static function createGalaxiesVector(FlatBufferBuilder $builder, array $data) + { + $builder->startVector(4, count($data), 4); + for ($i = count($data) - 1; $i >= 0; $i--) { + $builder->putOffset($data[$i]); + } + return $builder->endVector(); + } + + /** + * @param FlatBufferBuilder $builder + * @param int $numElems + * @return void + */ + public static function startGalaxiesVector(FlatBufferBuilder $builder, $numElems) + { + $builder->startVector(4, $numElems, 4); + } + + /** + * @param FlatBufferBuilder $builder + * @return int table offset + */ + public static function endUniverse(FlatBufferBuilder $builder) + { + $o = $builder->endObject(); + return $o; + } + + public static function finishUniverseBuffer(FlatBufferBuilder $builder, $offset) + { + $builder->finish($offset); + } +} diff --git a/third_party/flatbuffers/goldens/php/generate.py b/third_party/flatbuffers/goldens/php/generate.py new file mode 100644 index 00000000000..e167b7c8dbb --- /dev/null +++ b/third_party/flatbuffers/goldens/php/generate.py @@ -0,0 +1,10 @@ +from golden_utils import flatc_golden + + +def flatc(options, schema): + # Wrap the golden flatc generator with PHP specifics + flatc_golden(options=["--php"] + options, schema=schema, prefix="php") + + +def GeneratePhp(): + flatc([], "basic.fbs") diff --git a/third_party/flatbuffers/goldens/py/__init__.py b/third_party/flatbuffers/goldens/py/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/third_party/flatbuffers/goldens/py/flatbuffers/__init__.py b/third_party/flatbuffers/goldens/py/flatbuffers/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/third_party/flatbuffers/goldens/py/flatbuffers/goldens/Galaxy.py b/third_party/flatbuffers/goldens/py/flatbuffers/goldens/Galaxy.py new file mode 100644 index 00000000000..5f3fb0f6eb9 --- /dev/null +++ b/third_party/flatbuffers/goldens/py/flatbuffers/goldens/Galaxy.py @@ -0,0 +1,50 @@ +# automatically generated by the FlatBuffers compiler, do not modify + +# namespace: goldens + +import flatbuffers +from flatbuffers.compat import import_numpy +np = import_numpy() + +class Galaxy(object): + __slots__ = ['_tab'] + + @classmethod + def GetRootAs(cls, buf, offset=0): + n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset) + x = Galaxy() + x.Init(buf, n + offset) + return x + + @classmethod + def GetRootAsGalaxy(cls, buf, offset=0): + """This method is deprecated. Please switch to GetRootAs.""" + return cls.GetRootAs(buf, offset) + # Galaxy + def Init(self, buf, pos): + self._tab = flatbuffers.table.Table(buf, pos) + + # Galaxy + def NumStars(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos) + return 0 + +def GalaxyStart(builder): + builder.StartObject(1) + +def Start(builder): + GalaxyStart(builder) + +def GalaxyAddNumStars(builder, numStars): + builder.PrependInt64Slot(0, numStars, 0) + +def AddNumStars(builder, numStars): + GalaxyAddNumStars(builder, numStars) + +def GalaxyEnd(builder): + return builder.EndObject() + +def End(builder): + return GalaxyEnd(builder) diff --git a/third_party/flatbuffers/goldens/py/flatbuffers/goldens/Universe.py b/third_party/flatbuffers/goldens/py/flatbuffers/goldens/Universe.py new file mode 100644 index 00000000000..feec6d96c06 --- /dev/null +++ b/third_party/flatbuffers/goldens/py/flatbuffers/goldens/Universe.py @@ -0,0 +1,87 @@ +# automatically generated by the FlatBuffers compiler, do not modify + +# namespace: goldens + +import flatbuffers +from flatbuffers.compat import import_numpy +np = import_numpy() + +class Universe(object): + __slots__ = ['_tab'] + + @classmethod + def GetRootAs(cls, buf, offset=0): + n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset) + x = Universe() + x.Init(buf, n + offset) + return x + + @classmethod + def GetRootAsUniverse(cls, buf, offset=0): + """This method is deprecated. Please switch to GetRootAs.""" + return cls.GetRootAs(buf, offset) + # Universe + def Init(self, buf, pos): + self._tab = flatbuffers.table.Table(buf, pos) + + # Universe + def Age(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos) + return 0.0 + + # Universe + def Galaxies(self, j): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6)) + if o != 0: + x = self._tab.Vector(o) + x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4 + x = self._tab.Indirect(x) + from flatbuffers.goldens.Galaxy import Galaxy + obj = Galaxy() + obj.Init(self._tab.Bytes, x) + return obj + return None + + # Universe + def GalaxiesLength(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6)) + if o != 0: + return self._tab.VectorLen(o) + return 0 + + # Universe + def GalaxiesIsNone(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6)) + return o == 0 + +def UniverseStart(builder): + builder.StartObject(2) + +def Start(builder): + UniverseStart(builder) + +def UniverseAddAge(builder, age): + builder.PrependFloat64Slot(0, age, 0.0) + +def AddAge(builder, age): + UniverseAddAge(builder, age) + +def UniverseAddGalaxies(builder, galaxies): + builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(galaxies), 0) + +def AddGalaxies(builder, galaxies): + UniverseAddGalaxies(builder, galaxies) + +def UniverseStartGalaxiesVector(builder, numElems): + return builder.StartVector(4, numElems, 4) + +def StartGalaxiesVector(builder, numElems): + return UniverseStartGalaxiesVector(builder, numElems) + +def UniverseEnd(builder): + return builder.EndObject() + +def End(builder): + return UniverseEnd(builder) diff --git a/third_party/flatbuffers/goldens/py/flatbuffers/goldens/__init__.py b/third_party/flatbuffers/goldens/py/flatbuffers/goldens/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/third_party/flatbuffers/goldens/py/generate.py b/third_party/flatbuffers/goldens/py/generate.py new file mode 100644 index 00000000000..9ba58ea9ea3 --- /dev/null +++ b/third_party/flatbuffers/goldens/py/generate.py @@ -0,0 +1,10 @@ +from golden_utils import flatc_golden + + +def flatc(options, schema): + # Wrap the golden flatc generator with Python specifics + flatc_golden(options=["--python"] + options, schema=schema, prefix="py") + + +def GeneratePython(): + flatc([], "basic.fbs") diff --git a/third_party/flatbuffers/goldens/rust/basic_generated.rs b/third_party/flatbuffers/goldens/rust/basic_generated.rs new file mode 100644 index 00000000000..2ed0ad8822c --- /dev/null +++ b/third_party/flatbuffers/goldens/rust/basic_generated.rs @@ -0,0 +1,313 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +// @generated + +use core::mem; +use core::cmp::Ordering; + +extern crate flatbuffers; +use self::flatbuffers::{EndianScalar, Follow}; + +#[allow(unused_imports, dead_code)] +pub mod flatbuffers { + + use core::mem; + use core::cmp::Ordering; + + extern crate flatbuffers; + use self::flatbuffers::{EndianScalar, Follow}; +#[allow(unused_imports, dead_code)] +pub mod goldens { + + use core::mem; + use core::cmp::Ordering; + + extern crate flatbuffers; + use self::flatbuffers::{EndianScalar, Follow}; + +pub enum GalaxyOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct Galaxy<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for Galaxy<'a> { + type Inner = Galaxy<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> Galaxy<'a> { + pub const VT_NUM_STARS: flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + Galaxy { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args GalaxyArgs + ) -> flatbuffers::WIPOffset> { + let mut builder = GalaxyBuilder::new(_fbb); + builder.add_num_stars(args.num_stars); + builder.finish() + } + + + #[inline] + pub fn num_stars(&self) -> i64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Galaxy::VT_NUM_STARS, Some(0)).unwrap()} + } +} + +impl flatbuffers::Verifiable for Galaxy<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::("num_stars", Self::VT_NUM_STARS, false)? + .finish(); + Ok(()) + } +} +pub struct GalaxyArgs { + pub num_stars: i64, +} +impl<'a> Default for GalaxyArgs { + #[inline] + fn default() -> Self { + GalaxyArgs { + num_stars: 0, + } + } +} + +pub struct GalaxyBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> GalaxyBuilder<'a, 'b, A> { + #[inline] + pub fn add_num_stars(&mut self, num_stars: i64) { + self.fbb_.push_slot::(Galaxy::VT_NUM_STARS, num_stars, 0); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> GalaxyBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + GalaxyBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for Galaxy<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("Galaxy"); + ds.field("num_stars", &self.num_stars()); + ds.finish() + } +} +pub enum UniverseOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct Universe<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for Universe<'a> { + type Inner = Universe<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: unsafe { flatbuffers::Table::new(buf, loc) } } + } +} + +impl<'a> Universe<'a> { + pub const VT_AGE: flatbuffers::VOffsetT = 4; + pub const VT_GALAXIES: flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + Universe { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args UniverseArgs<'args> + ) -> flatbuffers::WIPOffset> { + let mut builder = UniverseBuilder::new(_fbb); + builder.add_age(args.age); + if let Some(x) = args.galaxies { builder.add_galaxies(x); } + builder.finish() + } + + + #[inline] + pub fn age(&self) -> f64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Universe::VT_AGE, Some(0.0)).unwrap()} + } + #[inline] + pub fn galaxies(&self) -> Option>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Universe::VT_GALAXIES, None)} + } +} + +impl flatbuffers::Verifiable for Universe<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::("age", Self::VT_AGE, false)? + .visit_field::>>>("galaxies", Self::VT_GALAXIES, false)? + .finish(); + Ok(()) + } +} +pub struct UniverseArgs<'a> { + pub age: f64, + pub galaxies: Option>>>>, +} +impl<'a> Default for UniverseArgs<'a> { + #[inline] + fn default() -> Self { + UniverseArgs { + age: 0.0, + galaxies: None, + } + } +} + +pub struct UniverseBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> UniverseBuilder<'a, 'b, A> { + #[inline] + pub fn add_age(&mut self, age: f64) { + self.fbb_.push_slot::(Universe::VT_AGE, age, 0.0); + } + #[inline] + pub fn add_galaxies(&mut self, galaxies: flatbuffers::WIPOffset>>>) { + self.fbb_.push_slot_always::>(Universe::VT_GALAXIES, galaxies); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> UniverseBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + UniverseBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for Universe<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("Universe"); + ds.field("age", &self.age()); + ds.field("galaxies", &self.galaxies()); + ds.finish() + } +} +#[inline] +/// Verifies that a buffer of bytes contains a `Universe` +/// and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_universe_unchecked`. +pub fn root_as_universe(buf: &[u8]) -> Result { + flatbuffers::root::(buf) +} +#[inline] +/// Verifies that a buffer of bytes contains a size prefixed +/// `Universe` and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `size_prefixed_root_as_universe_unchecked`. +pub fn size_prefixed_root_as_universe(buf: &[u8]) -> Result { + flatbuffers::size_prefixed_root::(buf) +} +#[inline] +/// Verifies, with the given options, that a buffer of bytes +/// contains a `Universe` and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_universe_unchecked`. +pub fn root_as_universe_with_opts<'b, 'o>( + opts: &'o flatbuffers::VerifierOptions, + buf: &'b [u8], +) -> Result, flatbuffers::InvalidFlatbuffer> { + flatbuffers::root_with_opts::>(opts, buf) +} +#[inline] +/// Verifies, with the given verifier options, that a buffer of +/// bytes contains a size prefixed `Universe` and returns +/// it. Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_universe_unchecked`. +pub fn size_prefixed_root_as_universe_with_opts<'b, 'o>( + opts: &'o flatbuffers::VerifierOptions, + buf: &'b [u8], +) -> Result, flatbuffers::InvalidFlatbuffer> { + flatbuffers::size_prefixed_root_with_opts::>(opts, buf) +} +#[inline] +/// Assumes, without verification, that a buffer of bytes contains a Universe and returns it. +/// # Safety +/// Callers must trust the given bytes do indeed contain a valid `Universe`. +pub unsafe fn root_as_universe_unchecked(buf: &[u8]) -> Universe { + unsafe { flatbuffers::root_unchecked::(buf) } +} +#[inline] +/// Assumes, without verification, that a buffer of bytes contains a size prefixed Universe and returns it. +/// # Safety +/// Callers must trust the given bytes do indeed contain a valid size prefixed `Universe`. +pub unsafe fn size_prefixed_root_as_universe_unchecked(buf: &[u8]) -> Universe { + unsafe { flatbuffers::size_prefixed_root_unchecked::(buf) } +} +#[inline] +pub fn finish_universe_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>( + fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + root: flatbuffers::WIPOffset>) { + fbb.finish(root, None); +} + +#[inline] +pub fn finish_size_prefixed_universe_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>(fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, root: flatbuffers::WIPOffset>) { + fbb.finish_size_prefixed(root, None); +} +} // pub mod goldens +} // pub mod flatbuffers + diff --git a/third_party/flatbuffers/goldens/rust/generate.py b/third_party/flatbuffers/goldens/rust/generate.py new file mode 100644 index 00000000000..9d3d874daf1 --- /dev/null +++ b/third_party/flatbuffers/goldens/rust/generate.py @@ -0,0 +1,10 @@ +from golden_utils import flatc_golden + + +def flatc(options, schema): + # Wrap the golden flatc generator with Rust specifics + flatc_golden(options=["--rust"] + options, schema=schema, prefix="rust") + + +def GenerateRust(): + flatc([], "basic.fbs") diff --git a/third_party/flatbuffers/goldens/schema/basic.fbs b/third_party/flatbuffers/goldens/schema/basic.fbs new file mode 100644 index 00000000000..b4574a1c1f3 --- /dev/null +++ b/third_party/flatbuffers/goldens/schema/basic.fbs @@ -0,0 +1,15 @@ +// This file should contain the basics of flatbuffers that all languages should +// support. + +namespace flatbuffers.goldens; + +table Galaxy { + num_stars:long; +} + +table Universe { + age:double; + galaxies:[Galaxy]; +} + +root_type Universe; \ No newline at end of file diff --git a/third_party/flatbuffers/goldens/swift/__init__.py b/third_party/flatbuffers/goldens/swift/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/third_party/flatbuffers/goldens/swift/basic_generated.swift b/third_party/flatbuffers/goldens/swift/basic_generated.swift new file mode 100644 index 00000000000..852868bfe7b --- /dev/null +++ b/third_party/flatbuffers/goldens/swift/basic_generated.swift @@ -0,0 +1,88 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// swiftlint:disable all +// swiftformat:disable all + +#if canImport(Common) +import Common +#endif + +import FlatBuffers + +public struct flatbuffers_goldens_Galaxy: FlatBufferObject, Verifiable { + + static func validateVersion() { FlatBuffersVersion_25_9_23() } + public var __buffer: ByteBuffer! { return _accessor.bb } + private var _accessor: Table + + private init(_ t: Table) { _accessor = t } + public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) } + + private enum VTOFFSET: VOffset { + case numStars = 4 + var v: Int32 { Int32(self.rawValue) } + var p: VOffset { self.rawValue } + } + + public var numStars: Int64 { let o = _accessor.offset(VTOFFSET.numStars.v); return o == 0 ? 0 : _accessor.readBuffer(of: Int64.self, at: o) } + public static func startGalaxy(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 1) } + public static func add(numStars: Int64, _ fbb: inout FlatBufferBuilder) { fbb.add(element: numStars, def: 0, at: VTOFFSET.numStars.p) } + public static func endGalaxy(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end } + public static func createGalaxy( + _ fbb: inout FlatBufferBuilder, + numStars: Int64 = 0 + ) -> Offset { + let __start = flatbuffers_goldens_Galaxy.startGalaxy(&fbb) + flatbuffers_goldens_Galaxy.add(numStars: numStars, &fbb) + return flatbuffers_goldens_Galaxy.endGalaxy(&fbb, start: __start) + } + + public static func verify(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable { + var _v = try verifier.visitTable(at: position) + try _v.visit(field: VTOFFSET.numStars.p, fieldName: "numStars", required: false, type: Int64.self) + _v.finish() + } +} + +public struct flatbuffers_goldens_Universe: FlatBufferObject, Verifiable { + + static func validateVersion() { FlatBuffersVersion_25_9_23() } + public var __buffer: ByteBuffer! { return _accessor.bb } + private var _accessor: Table + + private init(_ t: Table) { _accessor = t } + public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) } + + private enum VTOFFSET: VOffset { + case age = 4 + case galaxies = 6 + var v: Int32 { Int32(self.rawValue) } + var p: VOffset { self.rawValue } + } + + public var age: Double { let o = _accessor.offset(VTOFFSET.age.v); return o == 0 ? 0.0 : _accessor.readBuffer(of: Double.self, at: o) } + public var hasGalaxies: Bool { let o = _accessor.offset(VTOFFSET.galaxies.v); return o == 0 ? false : true } + public var galaxiesCount: Int32 { let o = _accessor.offset(VTOFFSET.galaxies.v); return o == 0 ? 0 : _accessor.vector(count: o) } + public func galaxies(at index: Int32) -> flatbuffers_goldens_Galaxy? { let o = _accessor.offset(VTOFFSET.galaxies.v); return o == 0 ? nil : flatbuffers_goldens_Galaxy(_accessor.bb, o: _accessor.indirect(_accessor.vector(at: o) + index * 4)) } + public static func startUniverse(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 2) } + public static func add(age: Double, _ fbb: inout FlatBufferBuilder) { fbb.add(element: age, def: 0.0, at: VTOFFSET.age.p) } + public static func addVectorOf(galaxies: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: galaxies, at: VTOFFSET.galaxies.p) } + public static func endUniverse(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end } + public static func createUniverse( + _ fbb: inout FlatBufferBuilder, + age: Double = 0.0, + galaxiesVectorOffset galaxies: Offset = Offset() + ) -> Offset { + let __start = flatbuffers_goldens_Universe.startUniverse(&fbb) + flatbuffers_goldens_Universe.add(age: age, &fbb) + flatbuffers_goldens_Universe.addVectorOf(galaxies: galaxies, &fbb) + return flatbuffers_goldens_Universe.endUniverse(&fbb, start: __start) + } + + public static func verify(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable { + var _v = try verifier.visitTable(at: position) + try _v.visit(field: VTOFFSET.age.p, fieldName: "age", required: false, type: Double.self) + try _v.visit(field: VTOFFSET.galaxies.p, fieldName: "galaxies", required: false, type: ForwardOffset, flatbuffers_goldens_Galaxy>>.self) + _v.finish() + } +} + diff --git a/third_party/flatbuffers/goldens/swift/generate.py b/third_party/flatbuffers/goldens/swift/generate.py new file mode 100644 index 00000000000..b16d83d514b --- /dev/null +++ b/third_party/flatbuffers/goldens/swift/generate.py @@ -0,0 +1,10 @@ +from golden_utils import flatc_golden + + +def flatc(options, schema): + # Wrap the golden flatc generator with Swift specifics + flatc_golden(options=["--swift"] + options, schema=schema, prefix="swift") + + +def GenerateSwift(): + flatc([], "basic.fbs") diff --git a/third_party/flatbuffers/goldens/ts/basic.ts b/third_party/flatbuffers/goldens/ts/basic.ts new file mode 100644 index 00000000000..ee62cf2d185 --- /dev/null +++ b/third_party/flatbuffers/goldens/ts/basic.ts @@ -0,0 +1,6 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +export {Galaxy} from './galaxy.js'; +export {Universe} from './universe.js'; diff --git a/third_party/flatbuffers/goldens/ts/flatbuffers/goldens.ts b/third_party/flatbuffers/goldens/ts/flatbuffers/goldens.ts new file mode 100644 index 00000000000..0d2097f7816 --- /dev/null +++ b/third_party/flatbuffers/goldens/ts/flatbuffers/goldens.ts @@ -0,0 +1,6 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +export { Galaxy } from './goldens/galaxy.js'; +export { Universe } from './goldens/universe.js'; diff --git a/third_party/flatbuffers/goldens/ts/flatbuffers/goldens/galaxy.ts b/third_party/flatbuffers/goldens/ts/flatbuffers/goldens/galaxy.ts new file mode 100644 index 00000000000..1d3c50d68bd --- /dev/null +++ b/third_party/flatbuffers/goldens/ts/flatbuffers/goldens/galaxy.ts @@ -0,0 +1,48 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +export class Galaxy { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):Galaxy { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsGalaxy(bb:flatbuffers.ByteBuffer, obj?:Galaxy):Galaxy { + return (obj || new Galaxy()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsGalaxy(bb:flatbuffers.ByteBuffer, obj?:Galaxy):Galaxy { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Galaxy()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +numStars():bigint { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0'); +} + +static startGalaxy(builder:flatbuffers.Builder) { + builder.startObject(1); +} + +static addNumStars(builder:flatbuffers.Builder, numStars:bigint) { + builder.addFieldInt64(0, numStars, BigInt('0')); +} + +static endGalaxy(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createGalaxy(builder:flatbuffers.Builder, numStars:bigint):flatbuffers.Offset { + Galaxy.startGalaxy(builder); + Galaxy.addNumStars(builder, numStars); + return Galaxy.endGalaxy(builder); +} +} diff --git a/third_party/flatbuffers/goldens/ts/flatbuffers/goldens/universe.ts b/third_party/flatbuffers/goldens/ts/flatbuffers/goldens/universe.ts new file mode 100644 index 00000000000..5634d78314a --- /dev/null +++ b/third_party/flatbuffers/goldens/ts/flatbuffers/goldens/universe.ts @@ -0,0 +1,86 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +import { Galaxy } from '../../flatbuffers/goldens/galaxy.js'; + + +export class Universe { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):Universe { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsUniverse(bb:flatbuffers.ByteBuffer, obj?:Universe):Universe { + return (obj || new Universe()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsUniverse(bb:flatbuffers.ByteBuffer, obj?:Universe):Universe { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new Universe()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +age():number { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readFloat64(this.bb_pos + offset) : 0.0; +} + +galaxies(index: number, obj?:Galaxy):Galaxy|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? (obj || new Galaxy()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null; +} + +galaxiesLength():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +static startUniverse(builder:flatbuffers.Builder) { + builder.startObject(2); +} + +static addAge(builder:flatbuffers.Builder, age:number) { + builder.addFieldFloat64(0, age, 0.0); +} + +static addGalaxies(builder:flatbuffers.Builder, galaxiesOffset:flatbuffers.Offset) { + builder.addFieldOffset(1, galaxiesOffset, 0); +} + +static createGalaxiesVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (let i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]!); + } + return builder.endVector(); +} + +static startGalaxiesVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +} + +static endUniverse(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static finishUniverseBuffer(builder:flatbuffers.Builder, offset:flatbuffers.Offset) { + builder.finish(offset); +} + +static finishSizePrefixedUniverseBuffer(builder:flatbuffers.Builder, offset:flatbuffers.Offset) { + builder.finish(offset, undefined, true); +} + +static createUniverse(builder:flatbuffers.Builder, age:number, galaxiesOffset:flatbuffers.Offset):flatbuffers.Offset { + Universe.startUniverse(builder); + Universe.addAge(builder, age); + Universe.addGalaxies(builder, galaxiesOffset); + return Universe.endUniverse(builder); +} +} diff --git a/third_party/flatbuffers/goldens/ts/generate.py b/third_party/flatbuffers/goldens/ts/generate.py new file mode 100644 index 00000000000..64106388a7f --- /dev/null +++ b/third_party/flatbuffers/goldens/ts/generate.py @@ -0,0 +1,10 @@ +from golden_utils import flatc_golden + + +def flatc(options, schema): + # Wrap the golden flatc generator with Swift specifics + flatc_golden(options=["--ts"] + options, schema=schema, prefix="ts") + + +def GenerateTs(): + flatc([], "basic.fbs") diff --git a/third_party/flatbuffers/grpc/README.md b/third_party/flatbuffers/grpc/README.md index f46258fcb16..74aa86b46de 100644 --- a/third_party/flatbuffers/grpc/README.md +++ b/third_party/flatbuffers/grpc/README.md @@ -1,5 +1,4 @@ GRPC implementation and test -============================ NOTE: files in `src/` are shared with the GRPC project, and maintained there (any changes should be submitted to GRPC instead). These files are copied @@ -39,4 +38,64 @@ For Bazel users: ```shell $bazel test tests/... -``` \ No newline at end of file +``` + +## C++ Callback API Generation + +FlatBuffers gRPC C++ code generation now optionally supports the modern gRPC Callback API. + +To enable generation of a `CallbackService` skeleton alongside the existing `Service` and async mixins, invoke `flatc` with both `--grpc` and `--grpc-callback-api`: + +```shell +flatc --cpp --grpc --grpc-callback-api your_service.fbs +``` + +This adds (guarded by `#if defined(GRPC_CALLBACK_API_NONEXPERIMENTAL)`) a class: + +```cpp +class YourService::CallbackService : public ::grpc::Service { /* reactor virtuals */ }; +``` + +Each RPC shape maps to the appropriate reactor return type: + +- Unary -> `::grpc::ServerUnaryReactor*` Method(...) +- Client streaming -> `::grpc::ServerReadReactor*` +- Server streaming -> `::grpc::ServerWriteReactor*` +- Bidi streaming -> `::grpc::ServerBidiReactor*` + +Default generated implementations return `nullptr`; override in your derived class and return a reactor instance you manage (see gRPC docs for lifecycle patterns). + +If your gRPC library predates the stable callback API macro, the code inside the guard will be skipped (no breaking changes). Ensure you build against a recent gRPC (1.38+; verify current minimum in grpc repo) to use this feature. + +### Client Callback Stubs + +When `--grpc-callback-api` is supplied, the generated C++ client stub gains native callback / reactor based async methods in addition to the existing synchronous / generic async flavors, guarded by the same macro. For each RPC named `Foo`: + +Unary: + +``` +void async_Foo(::grpc::ClientContext*, const Request&, Response*, std::function); +void async_Foo(::grpc::ClientContext*, const Request&, Response*, ::grpc::ClientUnaryReactor*); +``` + +Client streaming: + +``` +::grpc::ClientWriteReactor* async_Foo(::grpc::ClientContext*, Response*, ::grpc::ClientWriteReactor*); +``` + +Server streaming: + +``` +::grpc::ClientReadReactor* async_Foo(::grpc::ClientContext*, const Request&, ::grpc::ClientReadReactor*); +``` + +Bidirectional streaming: + +``` +::grpc::ClientBidiReactor* async_Foo(::grpc::ClientContext*, ::grpc::ClientBidiReactor*); +``` + +These map directly onto the native gRPC callback API factories (e.g. `CallbackUnaryCall`, `ClientCallbackWriterFactory::Create`, etc.) and do not spawn threads. Override the appropriate reactor callbacks per gRPC's documentation to drive I/O. + +If your build uses an older gRPC lacking the non-experimental macro, these symbols will not be emitted, preserving backwards compatibility. diff --git a/third_party/flatbuffers/grpc/boringssl.patch b/third_party/flatbuffers/grpc/boringssl.patch index 632499e2804..a8768927ac1 100644 --- a/third_party/flatbuffers/grpc/boringssl.patch +++ b/third_party/flatbuffers/grpc/boringssl.patch @@ -11,3 +11,31 @@ index 1645a264a..12f8ca999 100644 add_executable( bssl +diff --git a/src/crypto/x509/t_x509.c b/src/crypto/x509/t_x509.c +index 7c32a8798..6e50d040e 100644 +--- a/src/crypto/x509/t_x509.c ++++ b/src/crypto/x509/t_x509.c +@@ -318,9 +318,7 @@ int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg, + int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase) + { + char *s, *c, *b; +- int ret = 0, l, i; +- +- l = 80 - 2 - obase; ++ int ret = 0, i; + + b = X509_NAME_oneline(name, NULL, 0); + if (!b) +@@ -347,12 +345,10 @@ int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase) + if (BIO_write(bp, ", ", 2) != 2) + goto err; + } +- l--; + } + if (*s == '\0') + break; + s++; +- l--; + } + + ret = 1; diff --git a/third_party/flatbuffers/grpc/build_grpc_with_cxx14.patch b/third_party/flatbuffers/grpc/build_grpc_with_cxx14.patch index 38cdfe9931b..b5900af5b34 100644 --- a/third_party/flatbuffers/grpc/build_grpc_with_cxx14.patch +++ b/third_party/flatbuffers/grpc/build_grpc_with_cxx14.patch @@ -2,9 +2,12 @@ diff --git a/bazel/copts.bzl b/bazel/copts.bzl index 10be944f25..879518b92f 100644 --- a/bazel/copts.bzl +++ b/bazel/copts.bzl -@@ -59,4 +59,4 @@ GRPC_LLVM_WARNING_FLAGS = [ +@@ -59,4 +59,7 @@ GRPC_LLVM_WARNING_FLAGS = [ GRPC_DEFAULT_COPTS = select({ "//:use_strict_warning": GRPC_LLVM_WARNING_FLAGS + ["-DUSE_STRICT_WARNING=1"], "//conditions:default": [], -}) -+}) + ["-std=c++14"] ++}) + select({ ++ "@bazel_tools//src/conditions:windows": ["/std:c++14"], ++ "//conditions:default": ["-std=c++14"], ++}) diff --git a/third_party/flatbuffers/grpc/examples/python/greeter/client.py b/third_party/flatbuffers/grpc/examples/python/greeter/client.py index d2d718452f1..a373c5a311a 100644 --- a/third_party/flatbuffers/grpc/examples/python/greeter/client.py +++ b/third_party/flatbuffers/grpc/examples/python/greeter/client.py @@ -1,40 +1,46 @@ -import sys import argparse +import sys import grpc -sys.path.insert(0, '../../../../../flatbuffers/python') +sys.path.insert(0, "../../../../../flatbuffers/python") import flatbuffers from models import HelloReply, HelloRequest, greeter_grpc_fb parser = argparse.ArgumentParser() parser.add_argument("port", help="server port to connect to", default=3000) -parser.add_argument("name", help="name to be sent to server", default="flatbuffers") +parser.add_argument( + "name", help="name to be sent to server", default="flatbuffers" +) + def say_hello(stub, hello_request): - reply = stub.SayHello(hello_request) - r = HelloReply.HelloReply.GetRootAs(reply) - print(r.Message()) + reply = stub.SayHello(hello_request) + r = HelloReply.HelloReply.GetRootAs(reply) + print(r.Message()) + def say_many_hellos(stub, hello_request): - greetings = stub.SayManyHellos(hello_request) - for greeting in greetings: - r = HelloReply.HelloReply.GetRootAs(greeting) - print(r.Message()) + greetings = stub.SayManyHellos(hello_request) + for greeting in greetings: + r = HelloReply.HelloReply.GetRootAs(greeting) + print(r.Message()) + def main(): - args = parser.parse_args() - - with grpc.insecure_channel('localhost:' + args.port) as channel: - builder = flatbuffers.Builder() - ind = builder.CreateString(args.name) - HelloRequest.HelloRequestStart(builder) - HelloRequest.HelloRequestAddName(builder, ind) - root = HelloRequest.HelloRequestEnd(builder) - builder.Finish(root) - output = bytes(builder.Output()) - stub = greeter_grpc_fb.GreeterStub(channel) - say_hello(stub, output) - say_many_hellos(stub, output) - -main() \ No newline at end of file + args = parser.parse_args() + + with grpc.insecure_channel("localhost:" + args.port) as channel: + builder = flatbuffers.Builder() + ind = builder.CreateString(args.name) + HelloRequest.HelloRequestStart(builder) + HelloRequest.HelloRequestAddName(builder, ind) + root = HelloRequest.HelloRequestEnd(builder) + builder.Finish(root) + output = bytes(builder.Output()) + stub = greeter_grpc_fb.GreeterStub(channel) + say_hello(stub, output) + say_many_hellos(stub, output) + + +main() diff --git a/third_party/flatbuffers/grpc/examples/python/greeter/greeter_grpc.fb.py b/third_party/flatbuffers/grpc/examples/python/greeter/greeter_grpc.fb.py new file mode 100644 index 00000000000..8c9f13a4544 --- /dev/null +++ b/third_party/flatbuffers/grpc/examples/python/greeter/greeter_grpc.fb.py @@ -0,0 +1,52 @@ +# Generated by the gRPC FlatBuffers compiler. DO NOT EDIT! + +import flatbuffers +import grpc +from models.HelloReply import HelloReply +from models.HelloRequest import HelloRequest + + +class GreeterStub(object): + """Interface exported by the server.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + + self.SayHello = channel.unary_unary(method='/models.Greeter/SayHello') + + self.SayManyHellos = channel.unary_stream( + method='/models.Greeter/SayManyHellos' + ) + + +class GreeterServicer(object): + """Interface exported by the server.""" + + def SayHello(self, request, context): + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def SayManyHellos(self, request, context): + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_GreeterServicer_to_server(servicer, server): + rpc_method_handlers = { + 'SayHello': grpc.unary_unary_rpc_method_handler(servicer.SayHello), + 'SayManyHellos': grpc.unary_stream_rpc_method_handler( + servicer.SayManyHellos + ), + } + + generic_handler = grpc.method_handlers_generic_handler( + 'models.Greeter', rpc_method_handlers + ) + + server.add_generic_rpc_handlers((generic_handler,)) diff --git a/third_party/flatbuffers/grpc/examples/python/greeter/models/greeter_grpc_fb.py b/third_party/flatbuffers/grpc/examples/python/greeter/models/greeter_grpc_fb.py index b9f8a4ed233..7d1fec44f8f 100644 --- a/third_party/flatbuffers/grpc/examples/python/greeter/models/greeter_grpc_fb.py +++ b/third_party/flatbuffers/grpc/examples/python/greeter/models/greeter_grpc_fb.py @@ -1,52 +1,54 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +# Generated by the gRPC FlatBuffers compiler. DO NOT EDIT! +import flatbuffers import grpc +from models.HelloReply import HelloReply +from models.HelloRequest import HelloRequest + + class GreeterStub(object): - """ Interface exported by the server. """ - + '''Interface exported by the server.''' + def __init__(self, channel): - """ Constructor. - - Args: - channel: A grpc.Channel. - """ - + '''Constructor. + + Args: + channel: A grpc.Channel. + ''' + self.SayHello = channel.unary_unary( - "/models.Greeter/SayHello" - ) - + method='/models.Greeter/SayHello') + self.SayManyHellos = channel.unary_stream( - "/models.Greeter/SayManyHellos" - ) - + method='/models.Greeter/SayManyHellos') + class GreeterServicer(object): - """ Interface exported by the server. """ - + '''Interface exported by the server.''' + def SayHello(self, request, context): context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - - + def SayManyHellos(self, request, context): context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - - + def add_GreeterServicer_to_server(servicer, server): rpc_method_handlers = { 'SayHello': grpc.unary_unary_rpc_method_handler( - servicer.SayHello - ), + servicer.SayHello), 'SayManyHellos': grpc.unary_stream_rpc_method_handler( - servicer.SayManyHellos - ), + servicer.SayManyHellos), } + generic_handler = grpc.method_handlers_generic_handler( 'models.Greeter', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + diff --git a/third_party/flatbuffers/grpc/examples/python/greeter/server.py b/third_party/flatbuffers/grpc/examples/python/greeter/server.py index acca880b562..55b0789724e 100644 --- a/third_party/flatbuffers/grpc/examples/python/greeter/server.py +++ b/third_party/flatbuffers/grpc/examples/python/greeter/server.py @@ -1,9 +1,9 @@ -from concurrent import futures -import sys import argparse +from concurrent import futures +import sys import grpc -sys.path.insert(0, '../../../../../flatbuffers/python') +sys.path.insert(0, "../../../../../flatbuffers/python") import flatbuffers from models import HelloReply, HelloRequest, greeter_grpc_fb @@ -11,47 +11,48 @@ parser = argparse.ArgumentParser() parser.add_argument("port", help="server on port", default=3000) + def build_reply(message): - builder = flatbuffers.Builder() - ind = builder.CreateString(message) - HelloReply.HelloReplyStart(builder) - HelloReply.HelloReplyAddMessage(builder, ind) - root = HelloReply.HelloReplyEnd(builder) - builder.Finish(root) - return bytes(builder.Output()) + builder = flatbuffers.Builder() + ind = builder.CreateString(message) + HelloReply.HelloReplyStart(builder) + HelloReply.HelloReplyAddMessage(builder, ind) + root = HelloReply.HelloReplyEnd(builder) + builder.Finish(root) + return bytes(builder.Output()) + class GreeterServicer(greeter_grpc_fb.GreeterServicer): - def __init__(self): - self.greetings = ["Hi", "Hallo", "Ciao"] + def __init__(self): + self.greetings = ["Hi", "Hallo", "Ciao"] - def SayHello(self, request, context): - r = HelloRequest.HelloRequest().GetRootAs(request, 0) - reply = "Unknown" - if r.Name(): - reply = r.Name() - return build_reply("welcome " + reply.decode('UTF-8')) + def SayHello(self, request, context): + r = HelloRequest.HelloRequest().GetRootAs(request, 0) + reply = "Unknown" + if r.Name(): + reply = r.Name() + return build_reply("welcome " + reply.decode("UTF-8")) - def SayManyHellos(self, request, context): - r = HelloRequest.HelloRequest().GetRootAs(request, 0) - reply = "Unknown" - if r.Name(): - reply = r.Name() + def SayManyHellos(self, request, context): + r = HelloRequest.HelloRequest().GetRootAs(request, 0) + reply = "Unknown" + if r.Name(): + reply = r.Name() + + for greeting in self.greetings: + print(type(reply)) + yield build_reply(greeting + " " + reply.decode("UTF-8")) - for greeting in self.greetings: - print(type(reply)) - yield build_reply(greeting + " " + reply.decode('UTF-8')) - def serve(): - args = parser.parse_args() - server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) - greeter_grpc_fb.add_GreeterServicer_to_server( - GreeterServicer(), server - ) - server.add_insecure_port('[::]:' + args.port) - server.start() - server.wait_for_termination() - -if __name__ == '__main__': - serve() \ No newline at end of file + args = parser.parse_args() + server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + greeter_grpc_fb.add_GreeterServicer_to_server(GreeterServicer(), server) + server.add_insecure_port("[::]:" + args.port) + server.start() + server.wait_for_termination() + + +if __name__ == "__main__": + serve() diff --git a/third_party/flatbuffers/grpc/examples/swift/Greeter/Package.swift b/third_party/flatbuffers/grpc/examples/swift/Greeter/Package.swift index 5e6fb68cde3..9fd6cab834d 100644 --- a/third_party/flatbuffers/grpc/examples/swift/Greeter/Package.swift +++ b/third_party/flatbuffers/grpc/examples/swift/Greeter/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.1 +// swift-tools-version:5.9 /* * Copyright 2020 Google Inc. All rights reserved. * @@ -20,7 +20,7 @@ import PackageDescription let package = Package( name: "Greeter", platforms: [ - .iOS(.v11), + .iOS(.v12), .macOS(.v10_14), ], dependencies: [ diff --git a/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/Model/greeter.grpc.swift b/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/Model/greeter.grpc.swift index 0f29f1958a1..700c5cd5952 100644 --- a/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/Model/greeter.grpc.swift +++ b/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/Model/greeter.grpc.swift @@ -5,6 +5,7 @@ // swiftlint:disable all // swiftformat:disable all +#if !os(Windows) import Foundation import GRPC import NIO @@ -17,8 +18,7 @@ public extension GRPCFlatBufPayload { self.init(byteBuffer: FlatBuffers.ByteBuffer(contiguousBytes: serializedByteBuffer.readableBytesView, count: serializedByteBuffer.readableBytes)) } func serialize(into buffer: inout NIO.ByteBuffer) throws { - let buf = UnsafeRawBufferPointer(start: self.rawPointer, count: Int(self.size)) - buffer.writeBytes(buf) + withUnsafeReadableBytes { buffer.writeBytes($0) } } } extension Message: GRPCFlatBufPayload {} @@ -143,3 +143,5 @@ public protocol models_GreeterServerInterceptorFactoryProtocol { func makeSayManyHellosInterceptors() -> [ServerInterceptor, Message>] } +#endif + diff --git a/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/Model/greeter_generated.swift b/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/Model/greeter_generated.swift index 81ffe48f857..160ea747159 100644 --- a/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/Model/greeter_generated.swift +++ b/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/Model/greeter_generated.swift @@ -2,11 +2,15 @@ // swiftlint:disable all // swiftformat:disable all +#if canImport(Common) +import Common +#endif + import FlatBuffers public struct models_HelloReply: FlatBufferObject, Verifiable { - static func validateVersion() { FlatBuffersVersion_24_3_25() } + static func validateVersion() { FlatBuffersVersion_25_9_23() } public var __buffer: ByteBuffer! { return _accessor.bb } private var _accessor: Table @@ -53,7 +57,7 @@ extension models_HelloReply: Encodable { public struct models_HelloRequest: FlatBufferObject, Verifiable { - static func validateVersion() { FlatBuffersVersion_24_3_25() } + static func validateVersion() { FlatBuffersVersion_25_9_23() } public var __buffer: ByteBuffer! { return _accessor.bb } private var _accessor: Table diff --git a/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/client/main.swift b/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/client/main.swift index a4b2a675c70..61c809aa87a 100644 --- a/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/client/main.swift +++ b/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/client/main.swift @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google Inc. All rights reserved. + * Copyright 2024 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,7 +37,8 @@ func greet(name: String, client greeter: models_GreeterServiceClient) { builder.finish(offset: root) // Make the RPC call to the server. - let sayHello = greeter + let sayHello = + greeter .SayHello(Message(builder: &builder)) // wait() on the response to stop the program from exiting before the response is received. @@ -76,7 +77,7 @@ func main(args: [String]) { print("Usage: PORT [NAME]") exit(1) - case let (.some(port), name): + case (.some(let port), let name): // Setup an `EventLoopGroup` for the connection to run on. // // See: https://github.com/apple/swift-nio#eventloops-and-eventloopgroups diff --git a/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/server/main.swift b/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/server/main.swift index 62286c4759f..5eedd95fc75 100644 --- a/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/server/main.swift +++ b/third_party/flatbuffers/grpc/examples/swift/Greeter/Sources/server/main.swift @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google Inc. All rights reserved. + * Copyright 2024 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,8 @@ class Greeter: models_GreeterProvider { func SayHello( request: Message, - context: StatusOnlyCallContext) + context: StatusOnlyCallContext + ) -> EventLoopFuture> { let recipient = request.object.name ?? "Stranger" @@ -47,12 +48,14 @@ class Greeter: models_GreeterProvider { func SayManyHellos( request: Message, - context: StreamingResponseCallContext>) + context: StreamingResponseCallContext> + ) -> EventLoopFuture { for name in greetings { var builder = FlatBufferBuilder() - let off = builder + let off = + builder .create(string: "\(name) \(request.object.name ?? "Unknown")") let root = models_HelloReply.createHelloReply( &builder, diff --git a/third_party/flatbuffers/grpc/examples/ts/greeter/src/client.ts b/third_party/flatbuffers/grpc/examples/ts/greeter/src/client.ts index 62444f1ebc3..c1bc5bc20c0 100644 --- a/third_party/flatbuffers/grpc/examples/ts/greeter/src/client.ts +++ b/third_party/flatbuffers/grpc/examples/ts/greeter/src/client.ts @@ -1,34 +1,39 @@ import * as grpc from '@grpc/grpc-js'; import * as flatbuffers from 'flatbuffers'; -import { HelloReply } from './models/hello-reply'; -import { HelloRequest } from './models/hello-request'; -import { GreeterClient } from './greeter_grpc'; +import {GreeterClient} from './greeter_grpc'; +import {HelloReply} from './models/hello-reply'; +import {HelloRequest} from './models/hello-request'; async function main(PORT: Number, name: string) { - const client = new GreeterClient(`localhost:${PORT}`, grpc.credentials.createInsecure()); - const builder = new flatbuffers.Builder(); - const offset = builder.createString(name); - const root = HelloRequest.createHelloRequest(builder, offset); - builder.finish(root); - const buffer = HelloRequest.getRootAsHelloRequest(new flatbuffers.ByteBuffer(builder.asUint8Array())); + const client = new GreeterClient( + `localhost:${PORT}`, + grpc.credentials.createInsecure(), + ); + const builder = new flatbuffers.Builder(); + const offset = builder.createString(name); + const root = HelloRequest.createHelloRequest(builder, offset); + builder.finish(root); + const buffer = HelloRequest.getRootAsHelloRequest( + new flatbuffers.ByteBuffer(builder.asUint8Array()), + ); - client.SayHello(buffer, (err, response) => { - console.log(response.message()); - }); + client.SayHello(buffer, (err, response) => { + console.log(response.message()); + }); - const data = client.SayManyHellos(buffer, null); + const data = client.SayManyHellos(buffer, null); - data.on('data', (data) => { - console.log(data.message()); - }); + data.on('data', (data) => { + console.log(data.message()); + }); } -const args = process.argv.slice(2) +const args = process.argv.slice(2); const PORT = Number(args[0]); -const name: string = args[1] ?? "flatbuffers"; +const name: string = args[1] ?? 'flatbuffers'; if (PORT) { - main(PORT, name); + main(PORT, name); } else { - throw new Error("Requires a valid port number.") -} \ No newline at end of file + throw new Error('Requires a valid port number.'); +} diff --git a/third_party/flatbuffers/grpc/examples/ts/greeter/src/greeter_generated.ts b/third_party/flatbuffers/grpc/examples/ts/greeter/src/greeter_generated.ts index c48afe53845..1d54f718436 100644 --- a/third_party/flatbuffers/grpc/examples/ts/greeter/src/greeter_generated.ts +++ b/third_party/flatbuffers/grpc/examples/ts/greeter/src/greeter_generated.ts @@ -1,4 +1,4 @@ // automatically generated by the FlatBuffers compiler, do not modify -export { HelloReply } from './models/hello-reply.js'; -export { HelloRequest } from './models/hello-request.js'; +export {HelloReply} from './models/hello-reply.js'; +export {HelloRequest} from './models/hello-request.js'; diff --git a/third_party/flatbuffers/grpc/examples/ts/greeter/src/server.ts b/third_party/flatbuffers/grpc/examples/ts/greeter/src/server.ts index a3f2eeec2ec..b4b360e404c 100644 --- a/third_party/flatbuffers/grpc/examples/ts/greeter/src/server.ts +++ b/third_party/flatbuffers/grpc/examples/ts/greeter/src/server.ts @@ -1,49 +1,63 @@ import * as grpc from '@grpc/grpc-js'; import * as flatbuffers from 'flatbuffers'; -import { HelloReply } from './models/hello-reply'; -import { HelloRequest } from './models/hello-request'; -import { IGreeterServer, GreeterService } from './greeter_grpc'; +import {GreeterService, IGreeterServer} from './greeter_grpc'; +import {HelloReply} from './models/hello-reply'; +import {HelloRequest} from './models/hello-request'; const greeter: IGreeterServer = { - SayHello(call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData): void { - console.log(`SayHello ${call.request.name()}`); - const builder = new flatbuffers.Builder(); - const offset = builder.createString(`welcome ${call.request.name()}`); - const root = HelloReply.createHelloReply(builder, offset); - builder.finish(root); - callback(null, HelloReply.getRootAsHelloReply(new flatbuffers.ByteBuffer(builder.asUint8Array()))); - }, - async SayManyHellos(call: grpc.ServerWritableStream): Promise { - const name = call.request.name(); - console.log(`${call.request.name()} saying hi in different langagues`); - ['Hi', 'Hallo', 'Ciao'].forEach(element => { - const builder = new flatbuffers.Builder(); - const offset = builder.createString(`${element} ${name}`); - const root = HelloReply.createHelloReply(builder, offset); - builder.finish(root); - call.write(HelloReply.getRootAsHelloReply(new flatbuffers.ByteBuffer(builder.asUint8Array()))) - }); - call.end(); - } -} + SayHello( + call: grpc.ServerUnaryCall, + callback: grpc.sendUnaryData, + ): void { + console.log(`SayHello ${call.request.name()}`); + const builder = new flatbuffers.Builder(); + const offset = builder.createString(`welcome ${call.request.name()}`); + const root = HelloReply.createHelloReply(builder, offset); + builder.finish(root); + callback( + null, + HelloReply.getRootAsHelloReply( + new flatbuffers.ByteBuffer(builder.asUint8Array()), + ), + ); + }, + async SayManyHellos( + call: grpc.ServerWritableStream, + ): Promise { + const name = call.request.name(); + console.log(`${call.request.name()} saying hi in different langagues`); + ['Hi', 'Hallo', 'Ciao'].forEach((element) => { + const builder = new flatbuffers.Builder(); + const offset = builder.createString(`${element} ${name}`); + const root = HelloReply.createHelloReply(builder, offset); + builder.finish(root); + call.write( + HelloReply.getRootAsHelloReply( + new flatbuffers.ByteBuffer(builder.asUint8Array()), + ), + ); + }); + call.end(); + }, +}; function serve(): void { - const PORT = 3000; - const server = new grpc.Server(); - server.addService(GreeterService, greeter); - console.log(`Listening on ${PORT}`); - server.bindAsync( - `localhost:${PORT}`, - grpc.ServerCredentials.createInsecure(), - (err: Error | null, port: number) => { - if (err) { - console.error(`Server error: ${err.message}`); - } else { - console.log(`Server bound on port: ${port}`); - server.start(); - } - } - ); + const PORT = 3000; + const server = new grpc.Server(); + server.addService(GreeterService, greeter); + console.log(`Listening on ${PORT}`); + server.bindAsync( + `localhost:${PORT}`, + grpc.ServerCredentials.createInsecure(), + (err: Error | null, port: number) => { + if (err) { + console.error(`Server error: ${err.message}`); + } else { + console.log(`Server bound on port: ${port}`); + server.start(); + } + }, + ); } -serve(); \ No newline at end of file +serve(); diff --git a/third_party/flatbuffers/grpc/flatbuffers-java-grpc/pom.xml b/third_party/flatbuffers/grpc/flatbuffers-java-grpc/pom.xml index f7d41763747..dee931344d4 100644 --- a/third_party/flatbuffers/grpc/flatbuffers-java-grpc/pom.xml +++ b/third_party/flatbuffers/grpc/flatbuffers-java-grpc/pom.xml @@ -24,7 +24,7 @@ - 1.36.0 + 1.67.1 diff --git a/third_party/flatbuffers/grpc/flatbuffers-java-grpc/src/main/java/com/google/flatbuffers/grpc/FlatbuffersUtils.java b/third_party/flatbuffers/grpc/flatbuffers-java-grpc/src/main/java/com/google/flatbuffers/grpc/FlatbuffersUtils.java index 768708b111e..bd2b91a2b80 100644 --- a/third_party/flatbuffers/grpc/flatbuffers-java-grpc/src/main/java/com/google/flatbuffers/grpc/FlatbuffersUtils.java +++ b/third_party/flatbuffers/grpc/flatbuffers-java-grpc/src/main/java/com/google/flatbuffers/grpc/FlatbuffersUtils.java @@ -19,99 +19,99 @@ import io.grpc.Drainable; import io.grpc.KnownLength; import io.grpc.MethodDescriptor; - -import javax.annotation.Nullable; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; +import javax.annotation.Nullable; public class FlatbuffersUtils { - abstract public static class FBExtactor { - T extract (InputStream stream) throws IOException { - if (stream instanceof KnownLength) { - int size = stream.available(); - ByteBuffer buffer = ByteBuffer.allocate(size); - stream.read(buffer.array()); - return extract(buffer); - } else - throw new RuntimeException("The class " + stream.getClass().getCanonicalName() + " does not extend from KnownLength "); - } - - public abstract T extract(ByteBuffer buffer); - + public abstract static class FBExtactor { + T extract(InputStream stream) throws IOException { + if (stream instanceof KnownLength) { + int size = stream.available(); + ByteBuffer buffer = ByteBuffer.allocate(size); + stream.read(buffer.array()); + return extract(buffer); + } else + throw new RuntimeException( + "The class " + + stream.getClass().getCanonicalName() + + " does not extend from KnownLength "); } - static class FBInputStream extends InputStream implements Drainable, KnownLength { - private final ByteBuffer buffer; - private final int size; - @Nullable private ByteArrayInputStream inputStream; + public abstract T extract(ByteBuffer buffer); + } - FBInputStream(ByteBuffer buffer) { - this.buffer = buffer; - this.size = buffer.remaining(); - } + static class FBInputStream extends InputStream implements Drainable, KnownLength { + private final ByteBuffer buffer; + private final int size; + @Nullable private ByteArrayInputStream inputStream; - private void makeStreamIfNotAlready() { - if (inputStream == null) - inputStream = new ByteArrayInputStream(buffer.array(), buffer.position(), size); - } + FBInputStream(ByteBuffer buffer) { + this.buffer = buffer; + this.size = buffer.remaining(); + } - @Override - public int drainTo(OutputStream target) throws IOException { - target.write(buffer.array(), buffer.position(), size); - return size; - } + private void makeStreamIfNotAlready() { + if (inputStream == null) + inputStream = new ByteArrayInputStream(buffer.array(), buffer.position(), size); + } - @Override - public int read() throws IOException { - makeStreamIfNotAlready(); - return inputStream.read(); - } + @Override + public int drainTo(OutputStream target) throws IOException { + target.write(buffer.array(), buffer.position(), size); + return size; + } - @Override - public int read(byte[] b, int off, int len) throws IOException { - makeStreamIfNotAlready(); - if (inputStream == null) { - if (len >= size) { - System.arraycopy(buffer.array(), buffer.position(), b, off, size); - return size; - } else { - makeStreamIfNotAlready(); - return inputStream.read(b, off, len); - } - } else - return inputStream.read(b, off, len); - } + @Override + public int read() throws IOException { + makeStreamIfNotAlready(); + return inputStream.read(); + } - @Override - public int available() throws IOException { - return inputStream == null ? size : inputStream.available(); + @Override + public int read(byte[] b, int off, int len) throws IOException { + makeStreamIfNotAlready(); + if (inputStream == null) { + if (len >= size) { + System.arraycopy(buffer.array(), buffer.position(), b, off, size); + return size; + } else { + makeStreamIfNotAlready(); + return inputStream.read(b, off, len); } - + } else return inputStream.read(b, off, len); } - public static MethodDescriptor.Marshaller marshaller(final Class clazz, final FBExtactor extractor) { - return new MethodDescriptor.ReflectableMarshaller() { - @Override - public Class getMessageClass() { - return clazz; - } - - @Override - public InputStream stream(T value) { - return new FBInputStream (value.getByteBuffer()); - } - - @Override - public T parse(InputStream stream) { - try { - return extractor.extract(stream); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }; + @Override + public int available() throws IOException { + return inputStream == null ? size : inputStream.available(); } + } + + public static MethodDescriptor.Marshaller marshaller( + final Class clazz, final FBExtactor extractor) { + return new MethodDescriptor.ReflectableMarshaller() { + @Override + public Class getMessageClass() { + return clazz; + } + + @Override + public InputStream stream(T value) { + return new FBInputStream(value.getByteBuffer()); + } + + @Override + public T parse(InputStream stream) { + try { + return extractor.extract(stream); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }; + } } diff --git a/third_party/flatbuffers/grpc/src/compiler/BUILD.bazel b/third_party/flatbuffers/grpc/src/compiler/BUILD.bazel index 0efa9560c2d..a73a79ba45d 100644 --- a/third_party/flatbuffers/grpc/src/compiler/BUILD.bazel +++ b/third_party/flatbuffers/grpc/src/compiler/BUILD.bazel @@ -95,6 +95,8 @@ cc_library( visibility = ["//visibility:private"], deps = [ "//:flatbuffers", + "//include/codegen:namer", + "//include/codegen:python", ], ) diff --git a/third_party/flatbuffers/grpc/src/compiler/cpp_generator.cc b/third_party/flatbuffers/grpc/src/compiler/cpp_generator.cc index fd635f2fa5e..58cef4f4bd7 100644 --- a/third_party/flatbuffers/grpc/src/compiler/cpp_generator.cc +++ b/third_party/flatbuffers/grpc/src/compiler/cpp_generator.cc @@ -8,24 +8,22 @@ namespace grpc_cpp_generator { namespace { -static grpc::string service_header_ext() { return ".grpc.fb.h"; } - -template +template static grpc::string as_string(T x) { std::ostringstream out; out << x; return out.str(); } -static inline bool ClientOnlyStreaming(const grpc_generator::Method *method) { +static inline bool ClientOnlyStreaming(const grpc_generator::Method* method) { return method->ClientStreaming() && !method->ServerStreaming(); } -static inline bool ServerOnlyStreaming(const grpc_generator::Method *method) { +static inline bool ServerOnlyStreaming(const grpc_generator::Method* method) { return !method->ClientStreaming() && method->ServerStreaming(); } -static grpc::string FilenameIdentifier(const grpc::string &filename) { +static grpc::string FilenameIdentifier(const grpc::string& filename) { grpc::string result; for (unsigned i = 0; i < filename.size(); i++) { char c = filename[i]; @@ -41,33 +39,48 @@ static grpc::string FilenameIdentifier(const grpc::string &filename) { return result; } -template -static T *array_end(T (&array)[N]) { return array + N; } +template +static T* array_end(T (&array)[N]) { + return array + N; +} -static void PrintIncludes(grpc_generator::Printer *printer, - const std::vector &headers, - const Parameters ¶ms) { +static void PrintIncludes(grpc_generator::Printer* printer, + const std::vector& headers, + const Parameters& params) { std::map vars; vars["l"] = params.use_system_headers ? '<' : '"'; vars["r"] = params.use_system_headers ? '>' : '"'; - auto &s = params.grpc_search_path; + auto& s = params.grpc_search_path; if (!s.empty()) { vars["l"] += s; - if (s[s.size() - 1] != '/') { vars["l"] += '/'; } + if (s[s.size() - 1] != '/') { + vars["l"] += '/'; + } } for (auto i = headers.begin(); i != headers.end(); i++) { vars["h"] = *i; printer->Print(vars, "#include $l$$h$$r$\n"); } + if (params.generate_callback_api) { + // Callback API headers (guarded later by feature macro in emitted code). + static const char* cb_headers[] = { + "grpcpp/impl/codegen/callback_common.h", + "grpcpp/impl/codegen/server_callback_handlers.h", + "grpcpp/support/client_callback.h"}; + for (auto& h : cb_headers) { + vars["h"] = h; + printer->Print(vars, "#include $l$$h$$r$\n"); + } + } } } // namespace -grpc::string GetHeaderPrologue(grpc_generator::File *file, - const Parameters ¶ms) { +grpc::string GetHeaderPrologue(grpc_generator::File* file, + const Parameters& params) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. @@ -98,25 +111,24 @@ grpc::string GetHeaderPrologue(grpc_generator::File *file, return output; } -grpc::string GetHeaderIncludes(grpc_generator::File *file, - const Parameters ¶ms) { +grpc::string GetHeaderIncludes(grpc_generator::File* file, + const Parameters& params) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. auto printer = file->CreatePrinter(&output); std::map vars; - static const char *headers_strs[] = { - "grpcpp/impl/codegen/async_stream.h", - "grpcpp/impl/codegen/async_unary_call.h", - "grpcpp/impl/codegen/method_handler.h", - "grpcpp/impl/codegen/proto_utils.h", - "grpcpp/impl/codegen/rpc_method.h", - "grpcpp/impl/codegen/service_type.h", - "grpcpp/impl/codegen/status.h", - "grpcpp/impl/codegen/stub_options.h", - "grpcpp/impl/codegen/sync_stream.h" - }; + static const char* headers_strs[] = { + "grpcpp/impl/codegen/async_stream.h", + "grpcpp/impl/codegen/async_unary_call.h", + "grpcpp/impl/codegen/method_handler.h", + "grpcpp/impl/codegen/proto_utils.h", + "grpcpp/impl/codegen/rpc_method.h", + "grpcpp/impl/codegen/service_type.h", + "grpcpp/impl/codegen/status.h", + "grpcpp/impl/codegen/stub_options.h", + "grpcpp/impl/codegen/sync_stream.h"}; std::vector headers(headers_strs, array_end(headers_strs)); PrintIncludes(printer.get(), headers, params); printer->Print(vars, "\n"); @@ -140,12 +152,11 @@ grpc::string GetHeaderIncludes(grpc_generator::File *file, return output; } - namespace { static void PrintHeaderClientMethodInterfaces( - grpc_generator::Printer *printer, const grpc_generator::Method *method, - std::map *vars, bool is_public) { + grpc_generator::Printer* printer, const grpc_generator::Method* method, + std::map* vars, bool is_public) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); @@ -154,8 +165,8 @@ static void PrintHeaderClientMethodInterfaces( grpc::string prefix; grpc::string method_params; // extra arguments to method grpc::string raw_args; // extra arguments to raw version of method - } async_prefixes[] = { { "Async", ", void* tag", ", tag" }, - { "PrepareAsync", "", "" } }; + } async_prefixes[] = {{"Async", ", void* tag", ", tag"}, + {"PrepareAsync", "", ""}}; if (is_public) { if (method->NoStreaming()) { @@ -165,7 +176,7 @@ static void PrintHeaderClientMethodInterfaces( "const $Request$& request, $Response$* response) = 0;\n"); for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; printer->Print( *vars, @@ -198,7 +209,7 @@ static void PrintHeaderClientMethodInterfaces( printer->Print("}\n"); for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; (*vars)["AsyncRawArgs"] = async_prefix.raw_args; @@ -233,7 +244,7 @@ static void PrintHeaderClientMethodInterfaces( printer->Print("}\n"); for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; (*vars)["AsyncRawArgs"] = async_prefix.raw_args; @@ -267,7 +278,7 @@ static void PrintHeaderClientMethodInterfaces( printer->Print("}\n"); for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; (*vars)["AsyncRawArgs"] = async_prefix.raw_args; @@ -291,7 +302,7 @@ static void PrintHeaderClientMethodInterfaces( if (method->NoStreaming()) { for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; printer->Print( *vars, @@ -308,7 +319,7 @@ static void PrintHeaderClientMethodInterfaces( "::grpc::ClientContext* context, $Response$* response) = 0;\n"); for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; printer->Print( @@ -326,7 +337,7 @@ static void PrintHeaderClientMethodInterfaces( "::grpc::ClientContext* context, const $Request$& request) = 0;\n"); for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; printer->Print( @@ -343,7 +354,7 @@ static void PrintHeaderClientMethodInterfaces( "$Method$Raw(::grpc::ClientContext* context) = 0;\n"); for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; printer->Print( @@ -357,12 +368,10 @@ static void PrintHeaderClientMethodInterfaces( } } - - -static void PrintHeaderClientMethod(grpc_generator::Printer *printer, - const grpc_generator::Method *method, - std::map *vars, - bool is_public) { +static void PrintHeaderClientMethod(grpc_generator::Printer* printer, + const grpc_generator::Method* method, + std::map* vars, + bool is_public) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); @@ -370,8 +379,8 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer, grpc::string prefix; grpc::string method_params; // extra arguments to method grpc::string raw_args; // extra arguments to raw version of method - } async_prefixes[] = { { "Async", ", void* tag", ", tag" }, - { "PrepareAsync", "", "" } }; + } async_prefixes[] = {{"Async", ", void* tag", ", tag"}, + {"PrepareAsync", "", ""}}; if (is_public) { if (method->NoStreaming()) { @@ -379,9 +388,25 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer, *vars, "::grpc::Status $Method$(::grpc::ClientContext* context, " "const $Request$& request, $Response$* response) override;\n"); + if ((*vars)["generate_callback_api"] == "1") { + // Native gRPC callback unary wrappers (function callback & reactor + // variants). + printer->Print(*vars, + "// Callback unary (function form). Request/response " + "must outlive callback.\n"); + printer->Print(*vars, + "void async_$Method$(::grpc::ClientContext* context, " + "const $Request$& request, $Response$* response, " + "std::function on_done);\n"); + printer->Print(*vars, "// Callback unary (reactor form).\n"); + printer->Print(*vars, + "void async_$Method$(::grpc::ClientContext* context, " + "const $Request$& request, $Response$* response, " + "::grpc::ClientUnaryReactor* reactor);\n"); + } for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; printer->Print( *vars, @@ -409,9 +434,16 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer, "($Method$Raw(context, response));\n"); printer->Outdent(); printer->Print("}\n"); + if ((*vars)["generate_callback_api"] == "1") { + printer->Print(*vars, "// Client streaming callback reactor entry.\n"); + printer->Print( + *vars, + "void async_$Method$(::grpc::ClientContext* context, $Response$* " + "response, ::grpc::ClientWriteReactor< $Request$ >* reactor);\n"); + } for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; (*vars)["AsyncRawArgs"] = async_prefix.raw_args; @@ -442,9 +474,16 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer, "($Method$Raw(context, request));\n"); printer->Outdent(); printer->Print("}\n"); + if ((*vars)["generate_callback_api"] == "1") { + printer->Print(*vars, "// Server streaming callback reactor entry.\n"); + printer->Print(*vars, + "void async_$Method$(::grpc::ClientContext* context, " + "const $Request$& request, ::grpc::ClientReadReactor< " + "$Response$ >* reactor);\n"); + } for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; (*vars)["AsyncRawArgs"] = async_prefix.raw_args; @@ -474,9 +513,17 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer, "$Method$Raw(context));\n"); printer->Outdent(); printer->Print("}\n"); + if ((*vars)["generate_callback_api"] == "1") { + printer->Print(*vars, + "// Bidirectional streaming callback reactor entry.\n"); + printer->Print( + *vars, + "void async_$Method$(::grpc::ClientContext* context, " + "::grpc::ClientBidiReactor< $Request$, $Response$ >* reactor);\n"); + } for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; (*vars)["AsyncRawArgs"] = async_prefix.raw_args; @@ -499,7 +546,7 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer, if (method->NoStreaming()) { for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; printer->Print( *vars, @@ -508,6 +555,10 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer, "const $Request$& request, " "::grpc::CompletionQueue* cq) override;\n"); } + if ((*vars)["generate_callback_api"] == "1") { + // Native callback unary forms declared earlier (no private sync helper + // needed). + } } else if (ClientOnlyStreaming(method)) { printer->Print(*vars, "::grpc::ClientWriter< $Request$>* $Method$Raw(" @@ -515,7 +566,7 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer, "override;\n"); for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; (*vars)["AsyncRawArgs"] = async_prefix.raw_args; @@ -532,7 +583,7 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer, " override;\n"); for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; (*vars)["AsyncRawArgs"] = async_prefix.raw_args; @@ -548,7 +599,7 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer, "$Method$Raw(::grpc::ClientContext* context) override;\n"); for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; (*vars)["AsyncRawArgs"] = async_prefix.raw_args; @@ -562,17 +613,17 @@ static void PrintHeaderClientMethod(grpc_generator::Printer *printer, } } -static void PrintHeaderClientMethodData(grpc_generator::Printer *printer, - const grpc_generator::Method *method, - std::map *vars) { +static void PrintHeaderClientMethodData( + grpc_generator::Printer* printer, const grpc_generator::Method* method, + std::map* vars) { (*vars)["Method"] = method->name(); printer->Print(*vars, "const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n"); } -static void PrintHeaderServerMethodSync(grpc_generator::Printer *printer, - const grpc_generator::Method *method, - std::map *vars) { +static void PrintHeaderServerMethodSync( + grpc_generator::Printer* printer, const grpc_generator::Method* method, + std::map* vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); @@ -604,9 +655,9 @@ static void PrintHeaderServerMethodSync(grpc_generator::Printer *printer, printer->Print(method->GetTrailingComments("//").c_str()); } -static void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer, - const grpc_generator::Method *method, - std::map *vars) { +static void PrintHeaderServerMethodAsync( + grpc_generator::Printer* printer, const grpc_generator::Method* method, + std::map* vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); @@ -721,8 +772,8 @@ static void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer, } static void PrintHeaderServerMethodStreamedUnary( - grpc_generator::Printer *printer, const grpc_generator::Method *method, - std::map *vars) { + grpc_generator::Printer* printer, const grpc_generator::Method* method, + std::map* vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); @@ -772,8 +823,8 @@ static void PrintHeaderServerMethodStreamedUnary( } static void PrintHeaderServerMethodSplitStreaming( - grpc_generator::Printer *printer, const grpc_generator::Method *method, - std::map *vars) { + grpc_generator::Printer* printer, const grpc_generator::Method* method, + std::map* vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); @@ -825,8 +876,8 @@ static void PrintHeaderServerMethodSplitStreaming( } static void PrintHeaderServerMethodGeneric( - grpc_generator::Printer *printer, const grpc_generator::Method *method, - std::map *vars) { + grpc_generator::Printer* printer, const grpc_generator::Method* method, + std::map* vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); @@ -895,9 +946,9 @@ static void PrintHeaderServerMethodGeneric( printer->Print(*vars, "};\n"); } -static void PrintHeaderService(grpc_generator::Printer *printer, - const grpc_generator::Service *service, - std::map *vars) { +static void PrintHeaderService(grpc_generator::Printer* printer, + const grpc_generator::Service* service, + std::map* vars) { (*vars)["Service"] = service->name(); printer->Print(service->GetLeadingComments("//").c_str()); @@ -932,6 +983,10 @@ static void PrintHeaderService(grpc_generator::Printer *printer, false); } printer->Outdent(); + // Forward declaration of nested CallbackService if callback API enabled. + if ((*vars)["generate_callback_api"] == "1") { + printer->Print("class CallbackService;\n"); + } printer->Print("};\n"); printer->Print( "class Stub final : public StubInterface" @@ -988,7 +1043,9 @@ static void PrintHeaderService(grpc_generator::Printer *printer, printer->Print(*vars, "WithAsyncMethod_$method_name$<"); } printer->Print("Service"); - for (int i = 0; i < service->method_count(); ++i) { printer->Print(" >"); } + for (int i = 0; i < service->method_count(); ++i) { + printer->Print(" >"); + } printer->Print(" AsyncService;\n"); // Server side - Generic @@ -1013,7 +1070,9 @@ static void PrintHeaderService(grpc_generator::Printer *printer, } printer->Print("Service"); for (int i = 0; i < service->method_count(); ++i) { - if (service->method(i)->NoStreaming()) { printer->Print(" >"); } + if (service->method(i)->NoStreaming()) { + printer->Print(" >"); + } } printer->Print(" StreamedUnaryService;\n"); @@ -1035,7 +1094,9 @@ static void PrintHeaderService(grpc_generator::Printer *printer, printer->Print("Service"); for (int i = 0; i < service->method_count(); ++i) { auto method = service->method(i); - if (ServerOnlyStreaming(method.get())) { printer->Print(" >"); } + if (ServerOnlyStreaming(method.get())) { + printer->Print(" >"); + } } printer->Print(" SplitStreamedService;\n"); @@ -1064,12 +1125,54 @@ static void PrintHeaderService(grpc_generator::Printer *printer, printer->Outdent(); printer->Print("};\n"); printer->Print(service->GetTrailingComments("//").c_str()); + + // Optional CallbackService (modern async API) + if ((*vars)["generate_callback_api"] == "1") { + (*vars)["Service"] = service->name(); + printer->Print("\n#if defined(GRPC_CALLBACK_API_NONEXPERIMENTAL)\n"); + printer->Print(*vars, + "class $Service$::CallbackService : public ::grpc::Service " + "{\n public:\n CallbackService();\n virtual " + "~CallbackService();\n"); + printer->Indent(); + for (int i = 0; i < service->method_count(); ++i) { + auto m = service->method(i); + (*vars)["Method"] = m->name(); + (*vars)["Request"] = m->input_type_name(); + (*vars)["Response"] = m->output_type_name(); + if (m->NoStreaming()) { + printer->Print(*vars, + "virtual ::grpc::ServerUnaryReactor* " + "$Method$(::grpc::CallbackServerContext* context, const " + "$Request$* request, $Response$* response);\n"); + } else if (ClientOnlyStreaming(m.get())) { + printer->Print(*vars, + "virtual ::grpc::ServerReadReactor<$Request$>* " + "$Method$(::grpc::CallbackServerContext* context, " + "$Response$* response);\n"); + } else if (ServerOnlyStreaming(m.get())) { + printer->Print(*vars, + "virtual ::grpc::ServerWriteReactor<$Response$>* " + "$Method$(::grpc::CallbackServerContext* context, const " + "$Request$* request);\n"); + } else if (m->BidiStreaming()) { + printer->Print( + *vars, + "virtual ::grpc::ServerBidiReactor<$Request$, $Response$>* " + "$Method$(::grpc::CallbackServerContext* context);\n"); + } + } + printer->Outdent(); + printer->Print( + "};\n#else\n// Callback API requested but not available in this gRPC " + "version.\n#endif // GRPC_CALLBACK_API_NONEXPERIMENTAL\n"); + } } -} // namespace +} // namespace -grpc::string GetHeaderServices(grpc_generator::File *file, - const Parameters ¶ms) { +grpc::string GetHeaderServices(grpc_generator::File* file, + const Parameters& params) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. @@ -1078,7 +1181,9 @@ grpc::string GetHeaderServices(grpc_generator::File *file, // Package string is empty or ends with a dot. It is used to fully qualify // method names. vars["Package"] = file->package(); - if (!file->package().empty()) { vars["Package"].append("."); } + if (!file->package().empty()) { + vars["Package"].append("."); + } if (!params.services_namespace.empty()) { vars["services_namespace"] = params.services_namespace; @@ -1086,9 +1191,14 @@ grpc::string GetHeaderServices(grpc_generator::File *file, } for (int i = 0; i < file->service_count(); ++i) { + vars["generate_callback_api"] = params.generate_callback_api ? "1" : "0"; PrintHeaderService(printer.get(), file->service(i).get(), &vars); printer->Print("\n"); } + if (params.generate_callback_api) { + printer->Print("// FlatBuffers: Callback API code generated.\n"); + printer->Print("#define FLATBUFFERS_GENERATED_GRPC_CALLBACK_API 1\n\n"); + } if (!params.services_namespace.empty()) { printer->Print(vars, "} // namespace $services_namespace$\n\n"); @@ -1097,8 +1207,8 @@ grpc::string GetHeaderServices(grpc_generator::File *file, return output; } -grpc::string GetHeaderEpilogue(grpc_generator::File *file, - const Parameters & /*params*/) { +grpc::string GetHeaderEpilogue(grpc_generator::File* file, + const Parameters& /*params*/) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. @@ -1126,8 +1236,8 @@ grpc::string GetHeaderEpilogue(grpc_generator::File *file, return output; } -grpc::string GetSourcePrologue(grpc_generator::File *file, - const Parameters ¶ms) { +grpc::string GetSourcePrologue(grpc_generator::File* file, + const Parameters& params) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. @@ -1137,11 +1247,12 @@ grpc::string GetSourcePrologue(grpc_generator::File *file, vars["filename"] = file->filename(); vars["filename_base"] = file->filename_without_ext(); vars["message_header_ext"] = params.message_header_extension; - vars["service_header_ext"] = service_header_ext(); + vars["service_header_ext"] = params.service_header_extension; printer->Print(vars, "// Generated by the gRPC C++ plugin.\n"); printer->Print(vars, - "// If you make any local change, they will be lost.\n"); + "// FlatBuffers modified generator: native gRPC callback " + "client API enabled when --grpc-callback-api.\n"); printer->Print(vars, "// source: $filename$\n\n"); printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n"); @@ -1151,24 +1262,23 @@ grpc::string GetSourcePrologue(grpc_generator::File *file, return output; } -grpc::string GetSourceIncludes(grpc_generator::File *file, - const Parameters ¶ms) { +grpc::string GetSourceIncludes(grpc_generator::File* file, + const Parameters& params) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. auto printer = file->CreatePrinter(&output); std::map vars; - static const char *headers_strs[] = { - "grpcpp/impl/codegen/async_stream.h", - "grpcpp/impl/codegen/async_unary_call.h", - "grpcpp/impl/codegen/channel_interface.h", - "grpcpp/impl/codegen/client_unary_call.h", - "grpcpp/impl/codegen/method_handler.h", - "grpcpp/impl/codegen/rpc_service_method.h", - "grpcpp/impl/codegen/service_type.h", - "grpcpp/impl/codegen/sync_stream.h" - }; + static const char* headers_strs[] = { + "grpcpp/impl/codegen/async_stream.h", + "grpcpp/impl/codegen/async_unary_call.h", + "grpcpp/impl/codegen/channel_interface.h", + "grpcpp/impl/codegen/client_unary_call.h", + "grpcpp/impl/codegen/method_handler.h", + "grpcpp/impl/codegen/rpc_service_method.h", + "grpcpp/impl/codegen/service_type.h", + "grpcpp/impl/codegen/sync_stream.h"}; std::vector headers(headers_strs, array_end(headers_strs)); PrintIncludes(printer.get(), headers, params); @@ -1186,12 +1296,11 @@ grpc::string GetSourceIncludes(grpc_generator::File *file, return output; } - namespace { -static void PrintSourceClientMethod(grpc_generator::Printer *printer, - const grpc_generator::Method *method, - std::map *vars) { +static void PrintSourceClientMethod( + grpc_generator::Printer* printer, const grpc_generator::Method* method, + std::map* vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); @@ -1200,8 +1309,8 @@ static void PrintSourceClientMethod(grpc_generator::Printer *printer, grpc::string start; // bool literal expressed as string grpc::string method_params; // extra arguments to method grpc::string create_args; // extra arguments to creator - } async_prefixes[] = { { "Async", "true", ", void* tag", ", tag" }, - { "PrepareAsync", "false", "", ", nullptr" } }; + } async_prefixes[] = {{"Async", "true", ", void* tag", ", tag"}, + {"PrepareAsync", "false", "", ", nullptr"}}; if (method->NoStreaming()) { printer->Print(*vars, "::grpc::Status $ns$$Service$::Stub::$Method$(" @@ -1211,9 +1320,31 @@ static void PrintSourceClientMethod(grpc_generator::Printer *printer, " return ::grpc::internal::BlockingUnaryCall" "(channel_.get(), rpcmethod_$Method$_, " "context, request, response);\n}\n\n"); + if ((*vars)["generate_callback_api"] == "1") { + printer->Print( + *vars, + "void $ns$$Service$::Stub::async_$Method$(::grpc::ClientContext* " + "context, const $Request$& request, $Response$* response, " + "std::function on_done) {\n"); + printer->Print(*vars, + " ::grpc::internal::CallbackUnaryCall(channel_.get(), " + "rpcmethod_$Method$_, context, &request, response, " + "std::move(on_done));\n}\n\n"); + printer->Print( + *vars, + "void $ns$$Service$::Stub::async_$Method$(::grpc::ClientContext* " + "context, const $Request$& request, $Response$* response, " + "::grpc::ClientUnaryReactor* reactor) {\n"); + printer->Print( + *vars, + " " + "::grpc::internal::ClientCallbackUnaryFactory::Create(channel_.get()," + " rpcmethod_$Method$_, context, &request, response, " + "reactor);\n}\n\n"); + } for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncStart"] = async_prefix.start; printer->Print(*vars, @@ -1243,9 +1374,20 @@ static void PrintSourceClientMethod(grpc_generator::Printer *printer, "rpcmethod_$Method$_, " "context, response);\n" "}\n\n"); + if ((*vars)["generate_callback_api"] == "1") { + printer->Print( + *vars, + "void $ns$$Service$::Stub::async_$Method$(::grpc::ClientContext* " + "context, $Response$* response, ::grpc::ClientWriteReactor< " + "$Request$ >* reactor) {\n"); + printer->Print(*vars, + " ::grpc::internal::ClientCallbackWriterFactory< " + "$Request$ >::Create(channel_.get(), rpcmethod_$Method$_, " + "context, response, reactor);\n}\n\n"); + } for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncStart"] = async_prefix.start; (*vars)["AsyncMethodParams"] = async_prefix.method_params; @@ -1276,9 +1418,21 @@ static void PrintSourceClientMethod(grpc_generator::Printer *printer, "rpcmethod_$Method$_, " "context, request);\n" "}\n\n"); + if ((*vars)["generate_callback_api"] == "1") { + printer->Print( + *vars, + "void $ns$$Service$::Stub::async_$Method$(::grpc::ClientContext* " + "context, const $Request$& request, ::grpc::ClientReadReactor< " + "$Response$ >* reactor) {\n"); + printer->Print( + *vars, + " ::grpc::internal::ClientCallbackReaderFactory< " + "$Response$ >::Create(channel_.get(), " + "rpcmethod_$Method$_, context, &request, reactor);\n}\n\n"); + } for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncStart"] = async_prefix.start; (*vars)["AsyncMethodParams"] = async_prefix.method_params; @@ -1309,9 +1463,20 @@ static void PrintSourceClientMethod(grpc_generator::Printer *printer, "rpcmethod_$Method$_, " "context);\n" "}\n\n"); + if ((*vars)["generate_callback_api"] == "1") { + printer->Print( + *vars, + "void $ns$$Service$::Stub::async_$Method$(::grpc::ClientContext* " + "context, ::grpc::ClientBidiReactor< $Request$, $Response$ >* " + "reactor) {\n"); + printer->Print(*vars, + " ::grpc::internal::ClientCallbackReaderWriterFactory< " + "$Request$, $Response$ >::Create(channel_.get(), " + "rpcmethod_$Method$_, context, reactor);\n}\n\n"); + } for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncStart"] = async_prefix.start; (*vars)["AsyncMethodParams"] = async_prefix.method_params; @@ -1333,9 +1498,9 @@ static void PrintSourceClientMethod(grpc_generator::Printer *printer, } } -static void PrintSourceServerMethod(grpc_generator::Printer *printer, - const grpc_generator::Method *method, - std::map *vars) { +static void PrintSourceServerMethod( + grpc_generator::Printer* printer, const grpc_generator::Method* method, + std::map* vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); @@ -1382,9 +1547,9 @@ static void PrintSourceServerMethod(grpc_generator::Printer *printer, } } -static void PrintSourceService(grpc_generator::Printer *printer, - const grpc_generator::Service *service, - std::map *vars) { +static void PrintSourceService(grpc_generator::Printer* printer, + const grpc_generator::Service* service, + std::map* vars) { (*vars)["Service"] = service->name(); if (service->method_count() > 0) { @@ -1497,12 +1662,120 @@ static void PrintSourceService(grpc_generator::Printer *printer, (*vars)["Idx"] = as_string(i); PrintSourceServerMethod(printer, service->method(i).get(), vars); } + + // CallbackService implementation (if enabled) + if ((*vars)["generate_callback_api"] == "1") { + (*vars)["Service"] = service->name(); + printer->Print("#if defined(GRPC_CALLBACK_API_NONEXPERIMENTAL)\n"); + printer->Print(*vars, + "$ns$$Service$::CallbackService::CallbackService() {\n"); + printer->Indent(); + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + (*vars)["Idx"] = as_string(i); + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + if (method->NoStreaming()) { + printer->Print( + *vars, + "AddMethod(new ::grpc::internal::RpcServiceMethod(\n" + " $prefix$$Service$_method_names[$Idx$],\n" + " ::grpc::internal::RpcMethod::NORMAL_RPC,\n" + " new ::grpc::internal::CallbackUnaryHandler<$Request$, " + "$Response$>(\n" + " [this](::grpc::CallbackServerContext* ctx, const $Request$* " + "req, $Response$* resp) {\n" + " return this->$Method$(ctx, req, resp);\n" + " })));\n"); + } else if (ClientOnlyStreaming(method.get())) { + printer->Print(*vars, + "AddMethod(new ::grpc::internal::RpcServiceMethod(\n" + " $prefix$$Service$_method_names[$Idx$],\n" + " ::grpc::internal::RpcMethod::CLIENT_STREAMING,\n" + " new " + "::grpc::internal::CallbackClientStreamingHandler<$" + "Request$, $Response$>(\n" + " [this](::grpc::CallbackServerContext* ctx, " + "$Response$* resp) {\n" + " return this->$Method$(ctx, resp);\n" + " })));\n"); + } else if (ServerOnlyStreaming(method.get())) { + printer->Print(*vars, + "AddMethod(new ::grpc::internal::RpcServiceMethod(\n" + " $prefix$$Service$_method_names[$Idx$],\n" + " ::grpc::internal::RpcMethod::SERVER_STREAMING,\n" + " new " + "::grpc::internal::CallbackServerStreamingHandler<$" + "Request$, $Response$>(\n" + " [this](::grpc::CallbackServerContext* ctx, const " + "$Request$* req) {\n" + " return this->$Method$(ctx, req);\n" + " })));\n"); + } else if (method->BidiStreaming()) { + printer->Print( + *vars, + "AddMethod(new ::grpc::internal::RpcServiceMethod(\n" + " $prefix$$Service$_method_names[$Idx$],\n" + " ::grpc::internal::RpcMethod::BIDI_STREAMING,\n" + " new ::grpc::internal::CallbackBidiHandler<$Request$, " + "$Response$>(\n" + " [this](::grpc::CallbackServerContext* ctx) {\n" + " return this->$Method$(ctx);\n" + " })));\n"); + } + } + printer->Outdent(); + printer->Print("}\n\n"); + printer->Print(*vars, + "$ns$$Service$::CallbackService::~CallbackService() {}\n\n"); + // Default method bodies returning UNIMPLEMENTED reactors. + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + if (method->NoStreaming()) { + printer->Print(*vars, + "::grpc::ServerUnaryReactor* " + "$ns$$Service$::CallbackService::$Method$(::grpc::" + "CallbackServerContext* /*context*/, const $Request$* " + "/*request*/, $Response$* /*response*/) {\n" + " return nullptr; // user must override\n" + "}\n\n"); + } else if (ClientOnlyStreaming(method.get())) { + printer->Print( + *vars, + "::grpc::ServerReadReactor<$Request$>* " + "$ns$$Service$::CallbackService::$Method$(::grpc::" + "CallbackServerContext* /*context*/, $Response$* /*response*/) {\n" + " return nullptr; // user must override\n" + "}\n\n"); + } else if (ServerOnlyStreaming(method.get())) { + printer->Print(*vars, + "::grpc::ServerWriteReactor<$Response$>* " + "$ns$$Service$::CallbackService::$Method$(::grpc::" + "CallbackServerContext* /*context*/, const $Request$* " + "/*request*/) {\n" + " return nullptr; // user must override\n" + "}\n\n"); + } else if (method->BidiStreaming()) { + printer->Print(*vars, + "::grpc::ServerBidiReactor<$Request$, $Response$>* " + "$ns$$Service$::CallbackService::$Method$(::grpc::" + "CallbackServerContext* /*context*/) {\n" + " return nullptr; // user must override\n" + "}\n\n"); + } + } + printer->Print("#endif // GRPC_CALLBACK_API_NONEXPERIMENTAL\n"); + } } -} // namespace +} // namespace -grpc::string GetSourceServices(grpc_generator::File *file, - const Parameters ¶ms) { +grpc::string GetSourceServices(grpc_generator::File* file, + const Parameters& params) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. @@ -1511,7 +1784,9 @@ grpc::string GetSourceServices(grpc_generator::File *file, // Package string is empty or ends with a dot. It is used to fully qualify // method names. vars["Package"] = file->package(); - if (!file->package().empty()) { vars["Package"].append("."); } + if (!file->package().empty()) { + vars["Package"].append("."); + } if (!params.services_namespace.empty()) { vars["ns"] = params.services_namespace + "::"; vars["prefix"] = params.services_namespace; @@ -1521,6 +1796,7 @@ grpc::string GetSourceServices(grpc_generator::File *file, } for (int i = 0; i < file->service_count(); ++i) { + vars["generate_callback_api"] = params.generate_callback_api ? "1" : "0"; PrintSourceService(printer.get(), file->service(i).get(), &vars); printer->Print("\n"); } @@ -1528,8 +1804,8 @@ grpc::string GetSourceServices(grpc_generator::File *file, return output; } -grpc::string GetSourceEpilogue(grpc_generator::File *file, - const Parameters & /*params*/) { +grpc::string GetSourceEpilogue(grpc_generator::File* file, + const Parameters& /*params*/) { grpc::string temp; if (!file->package().empty()) { @@ -1546,8 +1822,8 @@ grpc::string GetSourceEpilogue(grpc_generator::File *file, return temp; } -grpc::string GetMockPrologue(grpc_generator::File *file, - const Parameters ¶ms) { +grpc::string GetMockPrologue(grpc_generator::File* file, + const Parameters& params) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. @@ -1557,7 +1833,7 @@ grpc::string GetMockPrologue(grpc_generator::File *file, vars["filename"] = file->filename(); vars["filename_base"] = file->filename_without_ext(); vars["message_header_ext"] = params.message_header_extension; - vars["service_header_ext"] = service_header_ext(); + vars["service_header_ext"] = params.service_header_extension; printer->Print(vars, "// Generated by the gRPC C++ plugin.\n"); printer->Print(vars, @@ -1573,18 +1849,18 @@ grpc::string GetMockPrologue(grpc_generator::File *file, } // TODO(mmukhi): Add client-stream and completion-queue headers. -grpc::string GetMockIncludes(grpc_generator::File *file, - const Parameters ¶ms) { +grpc::string GetMockIncludes(grpc_generator::File* file, + const Parameters& params) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. auto printer = file->CreatePrinter(&output); std::map vars; - static const char *headers_strs[] = { - "grpcpp/impl/codegen/async_stream.h", - "grpcpp/impl/codegen/sync_stream.h", - "gmock/gmock.h", + static const char* headers_strs[] = { + "grpcpp/impl/codegen/async_stream.h", + "grpcpp/impl/codegen/sync_stream.h", + "gmock/gmock.h", }; std::vector headers(headers_strs, array_end(headers_strs)); PrintIncludes(printer.get(), headers, params); @@ -1603,12 +1879,11 @@ grpc::string GetMockIncludes(grpc_generator::File *file, return output; } - namespace { -static void PrintMockClientMethods(grpc_generator::Printer *printer, - const grpc_generator::Method *method, - std::map *vars) { +static void PrintMockClientMethods(grpc_generator::Printer* printer, + const grpc_generator::Method* method, + std::map* vars) { (*vars)["Method"] = method->name(); (*vars)["Request"] = method->input_type_name(); (*vars)["Response"] = method->output_type_name(); @@ -1617,8 +1892,7 @@ static void PrintMockClientMethods(grpc_generator::Printer *printer, grpc::string prefix; grpc::string method_params; // extra arguments to method int extra_method_param_count; - } async_prefixes[] = { { "Async", ", void* tag", 1 }, - { "PrepareAsync", "", 0 } }; + } async_prefixes[] = {{"Async", ", void* tag", 1}, {"PrepareAsync", "", 0}}; if (method->NoStreaming()) { printer->Print( @@ -1627,7 +1901,7 @@ static void PrintMockClientMethods(grpc_generator::Printer *printer, "const $Request$& request, $Response$* response));\n"); for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; printer->Print( *vars, @@ -1644,7 +1918,7 @@ static void PrintMockClientMethods(grpc_generator::Printer *printer, "(::grpc::ClientContext* context, $Response$* response));\n"); for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; (*vars)["MockArgs"] = @@ -1663,7 +1937,7 @@ static void PrintMockClientMethods(grpc_generator::Printer *printer, "(::grpc::ClientContext* context, const $Request$& request));\n"); for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; (*vars)["MockArgs"] = @@ -1683,7 +1957,7 @@ static void PrintMockClientMethods(grpc_generator::Printer *printer, "(::grpc::ClientContext* context));\n"); for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]); i++) { - auto &async_prefix = async_prefixes[i]; + auto& async_prefix = async_prefixes[i]; (*vars)["AsyncPrefix"] = async_prefix.prefix; (*vars)["AsyncMethodParams"] = async_prefix.method_params; (*vars)["MockArgs"] = @@ -1698,9 +1972,9 @@ static void PrintMockClientMethods(grpc_generator::Printer *printer, } } -static void PrintMockService(grpc_generator::Printer *printer, - const grpc_generator::Service *service, - std::map *vars) { +static void PrintMockService(grpc_generator::Printer* printer, + const grpc_generator::Service* service, + std::map* vars) { (*vars)["Service"] = service->name(); printer->Print(*vars, @@ -1714,10 +1988,10 @@ static void PrintMockService(grpc_generator::Printer *printer, printer->Print("};\n"); } -} // namespace +} // namespace -grpc::string GetMockServices(grpc_generator::File *file, - const Parameters ¶ms) { +grpc::string GetMockServices(grpc_generator::File* file, + const Parameters& params) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. @@ -1726,7 +2000,9 @@ grpc::string GetMockServices(grpc_generator::File *file, // Package string is empty or ends with a dot. It is used to fully qualify // method names. vars["Package"] = file->package(); - if (!file->package().empty()) { vars["Package"].append("."); } + if (!file->package().empty()) { + vars["Package"].append("."); + } if (!params.services_namespace.empty()) { vars["services_namespace"] = params.services_namespace; @@ -1745,8 +2021,8 @@ grpc::string GetMockServices(grpc_generator::File *file, return output; } -grpc::string GetMockEpilogue(grpc_generator::File *file, - const Parameters & /*params*/) { +grpc::string GetMockEpilogue(grpc_generator::File* file, + const Parameters& /*params*/) { grpc::string temp; if (!file->package().empty()) { diff --git a/third_party/flatbuffers/grpc/src/compiler/cpp_generator.h b/third_party/flatbuffers/grpc/src/compiler/cpp_generator.h index a9af1a6794f..c7bfbe81d66 100644 --- a/third_party/flatbuffers/grpc/src/compiler/cpp_generator.h +++ b/third_party/flatbuffers/grpc/src/compiler/cpp_generator.h @@ -11,8 +11,8 @@ #include "src/compiler/schema_interface.h" #ifndef GRPC_CUSTOM_STRING -# include -# define GRPC_CUSTOM_STRING std::string +#include +#define GRPC_CUSTOM_STRING std::string #endif namespace grpc { @@ -35,71 +35,75 @@ struct Parameters { bool generate_mock_code; // By default, use "_generated.h" std::string message_header_extension; + // Default: ".grpc.fb.h" + std::string service_header_extension; + // Generate modern callback-based async API service code (CallbackService) + bool generate_callback_api = false; }; // Return the prologue of the generated header file. -grpc::string GetHeaderPrologue(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetHeaderPrologue(grpc_generator::File* file, + const Parameters& params); // Return the includes needed for generated header file. -grpc::string GetHeaderIncludes(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetHeaderIncludes(grpc_generator::File* file, + const Parameters& params); // Return the includes needed for generated source file. -grpc::string GetSourceIncludes(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetSourceIncludes(grpc_generator::File* file, + const Parameters& params); // Return the epilogue of the generated header file. -grpc::string GetHeaderEpilogue(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetHeaderEpilogue(grpc_generator::File* file, + const Parameters& params); // Return the prologue of the generated source file. -grpc::string GetSourcePrologue(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetSourcePrologue(grpc_generator::File* file, + const Parameters& params); // Return the services for generated header file. -grpc::string GetHeaderServices(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetHeaderServices(grpc_generator::File* file, + const Parameters& params); // Return the services for generated source file. -grpc::string GetSourceServices(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetSourceServices(grpc_generator::File* file, + const Parameters& params); // Return the epilogue of the generated source file. -grpc::string GetSourceEpilogue(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetSourceEpilogue(grpc_generator::File* file, + const Parameters& params); // Return the prologue of the generated mock file. -grpc::string GetMockPrologue(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetMockPrologue(grpc_generator::File* file, + const Parameters& params); // Return the includes needed for generated mock file. -grpc::string GetMockIncludes(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetMockIncludes(grpc_generator::File* file, + const Parameters& params); // Return the services for generated mock file. -grpc::string GetMockServices(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetMockServices(grpc_generator::File* file, + const Parameters& params); // Return the epilogue of generated mock file. -grpc::string GetMockEpilogue(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetMockEpilogue(grpc_generator::File* file, + const Parameters& params); // Return the prologue of the generated mock file. -grpc::string GetMockPrologue(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetMockPrologue(grpc_generator::File* file, + const Parameters& params); // Return the includes needed for generated mock file. -grpc::string GetMockIncludes(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetMockIncludes(grpc_generator::File* file, + const Parameters& params); // Return the services for generated mock file. -grpc::string GetMockServices(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetMockServices(grpc_generator::File* file, + const Parameters& params); // Return the epilogue of generated mock file. -grpc::string GetMockEpilogue(grpc_generator::File *file, - const Parameters ¶ms); +grpc::string GetMockEpilogue(grpc_generator::File* file, + const Parameters& params); } // namespace grpc_cpp_generator diff --git a/third_party/flatbuffers/grpc/src/compiler/go_generator.cc b/third_party/flatbuffers/grpc/src/compiler/go_generator.cc index ad4694b107f..8cc8951e893 100644 --- a/third_party/flatbuffers/grpc/src/compiler/go_generator.cc +++ b/third_party/flatbuffers/grpc/src/compiler/go_generator.cc @@ -4,17 +4,18 @@ #include #include -template grpc::string as_string(T x) { +template +grpc::string as_string(T x) { std::ostringstream out; out << x; return out.str(); } -inline bool ClientOnlyStreaming(const grpc_generator::Method *method) { +inline bool ClientOnlyStreaming(const grpc_generator::Method* method) { return method->ClientStreaming() && !method->ServerStreaming(); } -inline bool ServerOnlyStreaming(const grpc_generator::Method *method) { +inline bool ServerOnlyStreaming(const grpc_generator::Method* method) { return !method->ClientStreaming() && method->ServerStreaming(); } @@ -35,9 +36,9 @@ static grpc::string exportName(grpc::string s) { return s; } -static void GenerateError(grpc_generator::Printer *printer, - std::map vars, - const bool multiple_return = true) { +static void GenerateError(grpc_generator::Printer* printer, + std::map vars, + const bool multiple_return = true) { printer->Print(vars, "if $Error_Check$ {\n"); printer->Indent(); vars["Return"] = multiple_return ? "nil, err" : "err"; @@ -47,9 +48,9 @@ static void GenerateError(grpc_generator::Printer *printer, } // Generates imports for the service -static void GenerateImports(grpc_generator::File *file, - grpc_generator::Printer *printer, - std::map vars) { +static void GenerateImports(grpc_generator::File* file, + grpc_generator::Printer* printer, + std::map vars) { vars["filename"] = file->filename(); printer->Print("//Generated by gRPC Go plugin\n"); printer->Print("//If you make any local changes, they will be lost\n"); @@ -67,9 +68,9 @@ static void GenerateImports(grpc_generator::File *file, } // Generates Server method signature source -static void GenerateServerMethodSignature(const grpc_generator::Method *method, - grpc_generator::Printer *printer, - std::map vars) { +static void GenerateServerMethodSignature( + const grpc_generator::Method* method, grpc_generator::Printer* printer, + std::map vars) { vars["Method"] = exportName(method->name()); vars["Request"] = method->get_input_type_name(); vars["Response"] = (vars["CustomMethodIO"] == "") @@ -87,9 +88,9 @@ static void GenerateServerMethodSignature(const grpc_generator::Method *method, } } -static void GenerateServerMethod(const grpc_generator::Method *method, - grpc_generator::Printer *printer, - std::map vars) { +static void GenerateServerMethod(const grpc_generator::Method* method, + grpc_generator::Printer* printer, + std::map vars) { vars["Method"] = exportName(method->name()); vars["Request"] = method->get_input_type_name(); vars["Response"] = (vars["CustomMethodIO"] == "") @@ -160,8 +161,12 @@ static void GenerateServerMethod(const grpc_generator::Method *method, printer->Print(vars, "type $Service$_$Method$Server interface {\n"); printer->Indent(); - if (genSend) { printer->Print(vars, "Send(*$Response$) error\n"); } - if (genRecv) { printer->Print(vars, "Recv() (*$Request$, error)\n"); } + if (genSend) { + printer->Print(vars, "Send(*$Response$) error\n"); + } + if (genRecv) { + printer->Print(vars, "Recv() (*$Request$, error)\n"); + } if (genSendAndClose) { printer->Print(vars, "SendAndClose(*$Response$) error\n"); } @@ -205,9 +210,9 @@ static void GenerateServerMethod(const grpc_generator::Method *method, } // Generates Client method signature source -static void GenerateClientMethodSignature(const grpc_generator::Method *method, - grpc_generator::Printer *printer, - std::map vars) { +static void GenerateClientMethodSignature( + const grpc_generator::Method* method, grpc_generator::Printer* printer, + std::map vars) { vars["Method"] = exportName(method->name()); vars["Request"] = ", in *" + ((vars["CustomMethodIO"] == "") ? method->get_input_type_name() @@ -226,9 +231,9 @@ static void GenerateClientMethodSignature(const grpc_generator::Method *method, } // Generates Client method source -static void GenerateClientMethod(const grpc_generator::Method *method, - grpc_generator::Printer *printer, - std::map vars) { +static void GenerateClientMethod(const grpc_generator::Method* method, + grpc_generator::Printer* printer, + std::map vars) { printer->Print(vars, "func (c *$ServiceUnexported$Client) "); vars["Ending"] = " {\n"; GenerateClientMethodSignature(method, printer, vars); @@ -277,8 +282,12 @@ static void GenerateClientMethod(const grpc_generator::Method *method, // Stream interface printer->Print(vars, "type $Service$_$Method$Client interface {\n"); printer->Indent(); - if (genSend) { printer->Print(vars, "Send(*$Request$) error\n"); } - if (genRecv) { printer->Print(vars, "Recv() (*$Response$, error)\n"); } + if (genSend) { + printer->Print(vars, "Send(*$Request$) error\n"); + } + if (genRecv) { + printer->Print(vars, "Recv() (*$Response$, error)\n"); + } if (genCloseAndRecv) { printer->Print(vars, "CloseAndRecv() (*$Response$, error)\n"); } @@ -329,8 +338,8 @@ static void GenerateClientMethod(const grpc_generator::Method *method, } // Generates client API for the service -void GenerateService(const grpc_generator::Service *service, - grpc_generator::Printer *printer, +void GenerateService(const grpc_generator::Service* service, + grpc_generator::Printer* printer, std::map vars) { vars["Service"] = exportName(service->name()); // Client Interface @@ -484,9 +493,9 @@ void GenerateService(const grpc_generator::Service *service, } // namespace // Returns source for the service -grpc::string GenerateServiceSource(grpc_generator::File *file, - const grpc_generator::Service *service, - grpc_go_generator::Parameters *parameters) { +grpc::string GenerateServiceSource(grpc_generator::File* file, + const grpc_generator::Service* service, + grpc_go_generator::Parameters* parameters) { grpc::string out; auto p = file->CreatePrinter(&out, '\t'); p->SetIndentationSize(1); diff --git a/third_party/flatbuffers/grpc/src/compiler/go_generator.h b/third_party/flatbuffers/grpc/src/compiler/go_generator.h index 766e100c584..f1ced289367 100644 --- a/third_party/flatbuffers/grpc/src/compiler/go_generator.h +++ b/third_party/flatbuffers/grpc/src/compiler/go_generator.h @@ -24,9 +24,9 @@ struct Parameters { }; // Return the source of the generated service file. -grpc::string GenerateServiceSource(grpc_generator::File *file, - const grpc_generator::Service *service, - grpc_go_generator::Parameters *parameters); +grpc::string GenerateServiceSource(grpc_generator::File* file, + const grpc_generator::Service* service, + grpc_go_generator::Parameters* parameters); } // namespace grpc_go_generator diff --git a/third_party/flatbuffers/grpc/src/compiler/java_generator.cc b/third_party/flatbuffers/grpc/src/compiler/java_generator.cc index bfe2b111dbb..00d3350f3de 100644 --- a/third_party/flatbuffers/grpc/src/compiler/java_generator.cc +++ b/third_party/flatbuffers/grpc/src/compiler/java_generator.cc @@ -28,11 +28,11 @@ // Stringify helpers used solely to cast GRPC_VERSION #ifndef STR -# define STR(s) # s +#define STR(s) #s #endif #ifndef XSTR -# define XSTR(s) STR(s) +#define XSTR(s) STR(s) #endif typedef grpc_generator::Printer Printer; @@ -46,8 +46,8 @@ namespace grpc_java_generator { typedef std::string string; namespace { // Generates imports for the service -static void GenerateImports(grpc_generator::File *file, - grpc_generator::Printer *printer, VARS &vars) { +static void GenerateImports(grpc_generator::File* file, + grpc_generator::Printer* printer, VARS& vars) { vars["filename"] = file->filename(); printer->Print(vars, "//Generated by flatc compiler (version $flatc_version$)\n"); @@ -64,7 +64,7 @@ static void GenerateImports(grpc_generator::File *file, // Adjust a method name prefix identifier to follow the JavaBean spec: // - decapitalize the first letter // - remove embedded underscores & capitalize the following letter -static string MixedLower(const string &word) { +static string MixedLower(const string& word) { string w; w += static_cast(tolower(word[0])); bool after_underscore = false; @@ -84,7 +84,7 @@ static string MixedLower(const string &word) { // - An underscore is inserted where a lower case letter is followed by an // upper case letter. // - All letters are converted to upper case -static string ToAllUpperCase(const string &word) { +static string ToAllUpperCase(const string& word) { string w; for (size_t i = 0; i < word.length(); ++i) { w += static_cast(toupper(word[i])); @@ -95,49 +95,48 @@ static string ToAllUpperCase(const string &word) { return w; } -static inline string LowerMethodName(const MethodDescriptor *method) { +static inline string LowerMethodName(const MethodDescriptor* method) { return MixedLower(method->name()); } -static inline string MethodPropertiesFieldName(const MethodDescriptor *method) { +static inline string MethodPropertiesFieldName(const MethodDescriptor* method) { return "METHOD_" + ToAllUpperCase(method->name()); } static inline string MethodPropertiesGetterName( - const MethodDescriptor *method) { + const MethodDescriptor* method) { return MixedLower("get_" + method->name() + "_method"); } -static inline string MethodIdFieldName(const MethodDescriptor *method) { +static inline string MethodIdFieldName(const MethodDescriptor* method) { return "METHODID_" + ToAllUpperCase(method->name()); } -static inline string JavaClassName(VARS &vars, const string &name) { +static inline string JavaClassName(VARS& vars, const string& name) { // string name = google::protobuf::compiler::java::ClassName(desc); return vars["Package"] + name; } -static inline string ServiceClassName(const string &service_name) { +static inline string ServiceClassName(const string& service_name) { return service_name + "Grpc"; } // TODO(nmittler): Remove once protobuf includes javadoc methods in // distribution. -template -static void GrpcSplitStringToIteratorUsing(const string &full, - const char *delim, ITR &result) { +template +static void GrpcSplitStringToIteratorUsing(const string& full, + const char* delim, ITR& result) { // Optimize the common case where delim is a single character. if (delim[0] != '\0' && delim[1] == '\0') { char c = delim[0]; - const char *p = full.data(); - const char *end = p + full.size(); + const char* p = full.data(); + const char* end = p + full.size(); while (p != end) { if (*p == c) { ++p; } else { - const char *start = p; - while (++p != end && *p != c) - ; + const char* start = p; + while (++p != end && *p != c); *result++ = string(start, p - start); } } @@ -157,13 +156,13 @@ static void GrpcSplitStringToIteratorUsing(const string &full, } } -static void GrpcSplitStringUsing(const string &full, const char *delim, - std::vector *result) { +static void GrpcSplitStringUsing(const string& full, const char* delim, + std::vector* result) { std::back_insert_iterator> it(*result); GrpcSplitStringToIteratorUsing(full, delim, it); } -static std::vector GrpcSplit(const string &full, const char *delim) { +static std::vector GrpcSplit(const string& full, const char* delim) { std::vector result; GrpcSplitStringUsing(full, delim, &result); return result; @@ -171,7 +170,7 @@ static std::vector GrpcSplit(const string &full, const char *delim) { // TODO(nmittler): Remove once protobuf includes javadoc methods in // distribution. -static string GrpcEscapeJavadoc(const string &input) { +static string GrpcEscapeJavadoc(const string& input) { string result; result.reserve(input.size() * 2); @@ -218,7 +217,9 @@ static string GrpcEscapeJavadoc(const string &input) { // Java interprets Unicode escape sequences anywhere! result.append("\"); break; - default: result.push_back(c); break; + default: + result.push_back(c); + break; } prev = c; @@ -227,7 +228,7 @@ static string GrpcEscapeJavadoc(const string &input) { return result; } -static std::vector GrpcGetDocLines(const string &comments) { +static std::vector GrpcGetDocLines(const string& comments) { if (!comments.empty()) { // TODO(kenton): Ideally we should parse the comment text as Markdown and // write it back as HTML, but this requires a Markdown parser. For now @@ -238,23 +239,27 @@ static std::vector GrpcGetDocLines(const string &comments) { string escapedComments = GrpcEscapeJavadoc(comments); std::vector lines = GrpcSplit(escapedComments, "\n"); - while (!lines.empty() && lines.back().empty()) { lines.pop_back(); } + while (!lines.empty() && lines.back().empty()) { + lines.pop_back(); + } return lines; } return std::vector(); } static std::vector GrpcGetDocLinesForDescriptor( - const DescriptorType *descriptor) { + const DescriptorType* descriptor) { return descriptor->GetAllComments(); // return GrpcGetDocLines(descriptor->GetLeadingComments("///")); } -static void GrpcWriteDocCommentBody(Printer *printer, VARS &vars, - const std::vector &lines, +static void GrpcWriteDocCommentBody(Printer* printer, VARS& vars, + const std::vector& lines, bool surroundWithPreTag) { if (!lines.empty()) { - if (surroundWithPreTag) { printer->Print(" *
\n"); }
+    if (surroundWithPreTag) {
+      printer->Print(" * 
\n");
+    }
 
     for (size_t i = 0; i < lines.size(); i++) {
       // Most lines should start with a space.  Watch out for lines that start
@@ -268,28 +273,30 @@ static void GrpcWriteDocCommentBody(Printer *printer, VARS &vars,
       }
     }
 
-    if (surroundWithPreTag) { printer->Print(" * 
\n"); } + if (surroundWithPreTag) { + printer->Print(" *
\n"); + } } } -static void GrpcWriteDocComment(Printer *printer, VARS &vars, - const string &comments) { +static void GrpcWriteDocComment(Printer* printer, VARS& vars, + const string& comments) { printer->Print("/**\n"); std::vector lines = GrpcGetDocLines(comments); GrpcWriteDocCommentBody(printer, vars, lines, false); printer->Print(" */\n"); } -static void GrpcWriteServiceDocComment(Printer *printer, VARS &vars, - const ServiceDescriptor *service) { +static void GrpcWriteServiceDocComment(Printer* printer, VARS& vars, + const ServiceDescriptor* service) { printer->Print("/**\n"); std::vector lines = GrpcGetDocLinesForDescriptor(service); GrpcWriteDocCommentBody(printer, vars, lines, true); printer->Print(" */\n"); } -static void GrpcWriteMethodDocComment(Printer *printer, VARS &vars, - const MethodDescriptor *method) { +static void GrpcWriteMethodDocComment(Printer* printer, VARS& vars, + const MethodDescriptor* method) { printer->Print("/**\n"); std::vector lines = GrpcGetDocLinesForDescriptor(method); GrpcWriteDocCommentBody(printer, vars, lines, true); @@ -298,7 +305,7 @@ static void GrpcWriteMethodDocComment(Printer *printer, VARS &vars, // outputs static singleton extractor for type stored in "extr_type" and // "extr_type_name" vars -static void PrintTypeExtractor(Printer *p, VARS &vars) { +static void PrintTypeExtractor(Printer* p, VARS& vars) { p->Print(vars, "private static volatile FlatbuffersUtils.FBExtactor<$extr_type$> " "extractorOf$extr_type_name$;\n" @@ -320,8 +327,8 @@ static void PrintTypeExtractor(Printer *p, VARS &vars) { " }\n" "}\n\n"); } -static void PrintMethodFields(Printer *p, VARS &vars, - const ServiceDescriptor *service) { +static void PrintMethodFields(Printer* p, VARS& vars, + const ServiceDescriptor* service) { p->Print("// Static method descriptors that strictly reflect the proto.\n"); vars["service_name"] = service->name(); @@ -443,11 +450,11 @@ enum StubType { enum CallType { ASYNC_CALL = 0, BLOCKING_CALL = 1, FUTURE_CALL = 2 }; -static void PrintBindServiceMethodBody(Printer *p, VARS &vars, - const ServiceDescriptor *service); +static void PrintBindServiceMethodBody(Printer* p, VARS& vars, + const ServiceDescriptor* service); // Prints a client interface or implementation class, or a server interface. -static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service, +static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service, StubType type) { const string service_name = service->name(); vars["service_name"] = service_name; @@ -493,7 +500,9 @@ static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service, vars["client_name"] = client_name; // Class head - if (!interface) { GrpcWriteServiceDocComment(p, vars, service); } + if (!interface) { + GrpcWriteServiceDocComment(p, vars, service); + } if (impl_base) { p->Print(vars, "public static abstract class $abstract_name$ implements " @@ -555,7 +564,9 @@ static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service, p->Print("\n"); // TODO(nmittler): Replace with WriteMethodDocComment once included by the // protobuf distro. - if (!interface) { GrpcWriteMethodDocComment(p, vars, &*method); } + if (!interface) { + GrpcWriteMethodDocComment(p, vars, &*method); + } p->Print("public "); switch (call_type) { case BLOCKING_CALL: @@ -620,7 +631,8 @@ static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service, "responseObserver);\n"); } break; - default: break; + default: + break; } } else if (!interface) { switch (call_type) { @@ -695,15 +707,15 @@ static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service, } static bool CompareMethodClientStreaming( - const std::unique_ptr &method1, - const std::unique_ptr &method2) { + const std::unique_ptr& method1, + const std::unique_ptr& method2) { return method1->ClientStreaming() < method2->ClientStreaming(); } // Place all method invocations into a single class to reduce memory footprint // on Android. -static void PrintMethodHandlerClass(Printer *p, VARS &vars, - const ServiceDescriptor *service) { +static void PrintMethodHandlerClass(Printer* p, VARS& vars, + const ServiceDescriptor* service) { // Sort method ids based on ClientStreaming() so switch tables are compact. std::vector> sorted_methods( service->method_count()); @@ -713,7 +725,7 @@ static void PrintMethodHandlerClass(Printer *p, VARS &vars, stable_sort(sorted_methods.begin(), sorted_methods.end(), CompareMethodClientStreaming); for (size_t i = 0; i < sorted_methods.size(); i++) { - auto &method = sorted_methods[i]; + auto& method = sorted_methods[i]; vars["method_id"] = to_string(i); vars["method_id_name"] = MethodIdFieldName(&*method); p->Print(vars, @@ -746,7 +758,9 @@ static void PrintMethodHandlerClass(Printer *p, VARS &vars, for (int i = 0; i < service->method_count(); ++i) { auto method = service->method(i); - if (method->ClientStreaming() || method->BidiStreaming()) { continue; } + if (method->ClientStreaming() || method->BidiStreaming()) { + continue; + } vars["method_id_name"] = MethodIdFieldName(&*method); vars["lower_method_name"] = LowerMethodName(&*method); vars["input_type"] = JavaClassName(vars, method->get_input_type_name()); @@ -778,7 +792,9 @@ static void PrintMethodHandlerClass(Printer *p, VARS &vars, for (int i = 0; i < service->method_count(); ++i) { auto method = service->method(i); - if (!(method->ClientStreaming() || method->BidiStreaming())) { continue; } + if (!(method->ClientStreaming() || method->BidiStreaming())) { + continue; + } vars["method_id_name"] = MethodIdFieldName(&*method); vars["lower_method_name"] = LowerMethodName(&*method); vars["input_type"] = JavaClassName(vars, method->get_input_type_name()); @@ -803,8 +819,8 @@ static void PrintMethodHandlerClass(Printer *p, VARS &vars, p->Print("}\n\n"); } -static void PrintGetServiceDescriptorMethod(Printer *p, VARS &vars, - const ServiceDescriptor *service) { +static void PrintGetServiceDescriptorMethod(Printer* p, VARS& vars, + const ServiceDescriptor* service) { vars["service_name"] = service->name(); // vars["proto_base_descriptor_supplier"] = service->name() + // "BaseDescriptorSupplier"; vars["proto_file_descriptor_supplier"] = @@ -896,8 +912,8 @@ static void PrintGetServiceDescriptorMethod(Printer *p, VARS &vars, p->Print("}\n"); } -static void PrintBindServiceMethodBody(Printer *p, VARS &vars, - const ServiceDescriptor *service) { +static void PrintBindServiceMethodBody(Printer* p, VARS& vars, + const ServiceDescriptor* service) { vars["service_name"] = service->name(); p->Indent(); p->Print(vars, @@ -949,8 +965,8 @@ static void PrintBindServiceMethodBody(Printer *p, VARS &vars, p->Outdent(); } -static void PrintService(Printer *p, VARS &vars, - const ServiceDescriptor *service, +static void PrintService(Printer* p, VARS& vars, + const ServiceDescriptor* service, bool disable_version) { vars["service_name"] = service->name(); vars["service_class_name"] = ServiceClassName(service->name()); @@ -1030,7 +1046,7 @@ static void PrintService(Printer *p, VARS &vars, p->Print("}\n"); } -static void PrintStaticImports(Printer *p) { +static void PrintStaticImports(Printer* p) { p->Print( "import java.nio.ByteBuffer;\n" "import static " @@ -1063,9 +1079,9 @@ static void PrintStaticImports(Printer *p) { "io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;\n\n"); } -static void GenerateService(const grpc_generator::Service *service, - grpc_generator::Printer *printer, VARS &vars, - bool disable_version) { +static void GenerateService(const grpc_generator::Service* service, + grpc_generator::Printer* printer, VARS& vars, + bool disable_version) { // All non-generated classes must be referred by fully qualified names to // avoid collision with generated classes. vars["String"] = "java.lang.String"; @@ -1098,11 +1114,11 @@ static void GenerateService(const grpc_generator::Service *service, PrintService(printer, vars, service, disable_version); } -} // namespace +} // namespace grpc::string GenerateServiceSource( - grpc_generator::File *file, const grpc_generator::Service *service, - grpc_java_generator::Parameters *parameters) { + grpc_generator::File* file, const grpc_generator::Service* service, + grpc_java_generator::Parameters* parameters) { grpc::string out; auto printer = file->CreatePrinter(&out); VARS vars; diff --git a/third_party/flatbuffers/grpc/src/compiler/java_generator.h b/third_party/flatbuffers/grpc/src/compiler/java_generator.h index b101fbf565e..00fe3feeb57 100644 --- a/third_party/flatbuffers/grpc/src/compiler/java_generator.h +++ b/third_party/flatbuffers/grpc/src/compiler/java_generator.h @@ -18,6 +18,7 @@ #define NET_GRPC_COMPILER_JAVA_GENERATOR_H_ #include // for abort() + #include #include #include @@ -39,8 +40,8 @@ class LogHelper { LogHelper(std::ostream* os) : os_(os) {} #if defined(_MSC_VER) #pragma warning(push) -#pragma warning( \ - disable : 4722) // the flow of control terminates in a destructor +#pragma warning(disable \ + : 4722) // the flow of control terminates in a destructor // (needed to compile ~LogHelper where destructor emits abort intentionally - // inherited from grpc/java code generator). #endif diff --git a/third_party/flatbuffers/grpc/src/compiler/python_generator.cc b/third_party/flatbuffers/grpc/src/compiler/python_generator.cc index d5f69e20e71..f217c9d5e00 100644 --- a/third_party/flatbuffers/grpc/src/compiler/python_generator.cc +++ b/third_party/flatbuffers/grpc/src/compiler/python_generator.cc @@ -16,136 +16,396 @@ * */ +#include "src/compiler/python_generator.h" + +#include +#include #include +#include #include +#include +#include "codegen/idl_namer.h" +#include "codegen/namer.h" +#include "codegen/python.h" +#include "flatbuffers/idl.h" #include "flatbuffers/util.h" -#include "src/compiler/python_generator.h" -namespace grpc_python_generator { +namespace flatbuffers { +namespace python { +namespace grpc { namespace { +bool ClientStreaming(const RPCCall* method) { + const Value* val = method->attributes.Lookup("streaming"); + return val != nullptr && + (val->constant == "client" || val->constant == "bidi"); +} -static grpc::string GenerateMethodType(const grpc_generator::Method *method) { +bool ServerStreaming(const RPCCall* method) { + const Value* val = method->attributes.Lookup("streaming"); + return val != nullptr && + (val->constant == "server" || val->constant == "bidi"); +} - if (method->NoStreaming()) - return "unary_unary"; +void FormatImports(std::stringstream& ss, const Imports& imports) { + std::set modules; + std::map> names_by_module; + for (const Import& import : imports.imports) { + if (import.IsLocal()) continue; // skip all local imports + if (import.name == "") { + modules.insert(import.module); + } else { + names_by_module[import.module].insert(import.name); + } + } - if (method->ServerStreaming()) - return "unary_stream"; + for (const std::string& module : modules) { + ss << "import " << module << '\n'; + } + ss << '\n'; + for (const auto& import : names_by_module) { + ss << "from " << import.first << " import "; + size_t i = 0; + for (const std::string& name : import.second) { + if (i > 0) ss << ", "; + ss << name; + ++i; + } + ss << '\n'; + } + ss << "\n\n"; +} - if (method->ClientStreaming()) - return "stream_unary"; +bool SaveStub(const std::string& filename, const Imports& imports, + const std::string& content) { + std::stringstream ss; + ss << "# Generated by the gRPC FlatBuffers compiler. DO NOT EDIT!\n" + << '\n' + << "from __future__ import annotations\n" + << '\n'; + FormatImports(ss, imports); + ss << content << '\n'; - return "stream_stream"; + EnsureDirExists(StripFileName(filename)); + return flatbuffers::SaveFile(filename.c_str(), ss.str(), false); } -grpc::string GenerateMethodInput(const grpc_generator::Method *method) { - - if (method->NoStreaming() || method->ServerStreaming()) - return "self, request, context"; +bool SaveService(const std::string& filename, const Imports& imports, + const std::string& content) { + std::stringstream ss; + ss << "# Generated by the gRPC FlatBuffers compiler. DO NOT EDIT!\n" << '\n'; + FormatImports(ss, imports); + ss << content << '\n'; - return "self, request_iterator, context"; + EnsureDirExists(StripFileName(filename)); + return flatbuffers::SaveFile(filename.c_str(), ss.str(), false); } -void GenerateStub(const grpc_generator::Service *service, - grpc_generator::Printer *printer, - std::map *dictonary) { - auto vars = *dictonary; - printer->Print(vars, "class $ServiceName$Stub(object):\n"); - printer->Indent(); - printer->Print("\"\"\" Interface exported by the server. \"\"\""); - printer->Print("\n\n"); - printer->Print("def __init__(self, channel):\n"); - printer->Indent(); - printer->Print("\"\"\" Constructor. \n\n"); - printer->Print("Args: \n"); - printer->Print("channel: A grpc.Channel. \n"); - printer->Print("\"\"\"\n\n"); - - for (int j = 0; j < service->method_count(); j++) { - auto method = service->method(j); - vars["MethodName"] = method->name(); - vars["MethodType"] = GenerateMethodType(&*method); - printer->Print(vars, "self.$MethodName$ = channel.$MethodType$(\n"); - printer->Indent(); - printer->Print(vars, "\"/$PATH$$ServiceName$/$MethodName$\"\n"); - printer->Print(")\n"); - printer->Outdent(); - printer->Print("\n"); +class BaseGenerator { + protected: + BaseGenerator(const Parser& parser, const Namer::Config& config, + const std::string& path, const Version& version) + : parser_{parser}, + namer_{WithFlagOptions(config, parser.opts, path), Keywords(version)}, + version_{version}, + path_(path) {} + + protected: + std::string ModuleForFile(const std::string& file) const { + std::string module = parser_.opts.include_prefix + StripExtension(file) + + parser_.opts.filename_suffix; + std::replace(module.begin(), module.end(), '/', '.'); + return module; } - printer->Outdent(); - printer->Outdent(); - printer->Print("\n"); -} -void GenerateServicer(const grpc_generator::Service *service, - grpc_generator::Printer *printer, - std::map *dictonary) { - auto vars = *dictonary; - printer->Print(vars, "class $ServiceName$Servicer(object):\n"); - printer->Indent(); - printer->Print("\"\"\" Interface exported by the server. \"\"\""); - printer->Print("\n\n"); - - for (int j = 0; j < service->method_count(); j++) { - auto method = service->method(j); - vars["MethodName"] = method->name(); - vars["MethodInput"] = GenerateMethodInput(&*method); - printer->Print(vars, "def $MethodName$($MethodInput$):\n"); - printer->Indent(); - printer->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n"); - printer->Print("context.set_details('Method not implemented!')\n"); - printer->Print("raise NotImplementedError('Method not implemented!')\n"); - printer->Outdent(); - printer->Print("\n\n"); + template + std::string ModuleFor(const T* def) const { + if (parser_.opts.one_file) return ModuleForFile(def->file); + return namer_.NamespacedType(*def); } - printer->Outdent(); - printer->Print("\n"); -} + std::string NamespaceDir(const Parser& parser, const std::string& path, + const Namespace& ns, const bool dasherize) { + EnsureDirExists(path); + if (parser.opts.one_file) return path; + std::string namespace_dir = path; // Either empty or ends in separator. + auto& namespaces = ns.components; + for (auto it = namespaces.begin(); it != namespaces.end(); ++it) { + namespace_dir += + !dasherize ? *it : ConvertCase(*it, Case::kDasher, Case::kUpperCamel); + namespace_dir += kPathSeparator; + EnsureDirExists(namespace_dir); + } + return namespace_dir; + } + + std::string NamespaceDir(const Namespace& ns, const bool dasherize) { + return NamespaceDir(parser_, path_, ns, dasherize); + } + + const Parser& parser_; + const IdlNamer namer_; + const Version version_; + const std::string& path_; +}; + +class StubGenerator : public BaseGenerator { + public: + StubGenerator(const Parser& parser, const std::string& path, + const Version& version) + : BaseGenerator(parser, kStubConfig, path, version) {} + + bool Generate() { + Imports imports; + std::stringstream stub; + std::string ns_name{}; + for (const ServiceDef* service : parser_.services_.vec) { + Generate(stub, service, &imports); + ns_name = NamespaceDir(*service->defined_namespace, false); + } + + std::string sanitized_suffix{parser_.opts.grpc_filename_suffix}; + std::replace(sanitized_suffix.begin(), sanitized_suffix.end(), '.', '_'); + std::string filename = + ns_name + kPathSeparator + + StripPath(StripExtension(parser_.file_being_parsed_)) + "_grpc" + + sanitized_suffix + namer_.config_.filename_extension; + + return SaveStub(filename, imports, stub.str()); + } + + private: + void Generate(std::stringstream& ss, const ServiceDef* service, + Imports* imports) { + imports->Import("grpc"); + + ss << "class " << service->name << "Stub(object):\n" + << " def __init__(self, channel: grpc.Channel) -> None: ...\n"; + + for (const RPCCall* method : service->calls.vec) { + std::string request = "bytes"; + std::string response = "bytes"; + + if (parser_.opts.grpc_python_typed_handlers) { + request = namer_.Type(*method->request); + response = namer_.Type(*method->response); + + imports->Import(ModuleFor(method->request), request); + imports->Import(ModuleFor(method->response), response); + } + + ss << " def " << method->name << "(self, "; + if (ClientStreaming(method)) { + imports->Import("typing"); + ss << "request_iterator: typing.Iterator[" << request << "]"; + } else { + ss << "request: " << request; + } + ss << ") -> "; + if (ServerStreaming(method)) { + imports->Import("typing"); + ss << "typing.Iterator[" << response << "]"; + } else { + ss << response; + } + ss << ": ...\n"; + } + + ss << "\n\n"; + ss << "class " << service->name << "Servicer(object):\n"; + + for (const RPCCall* method : service->calls.vec) { + std::string request = "bytes"; + std::string response = "bytes"; + + if (parser_.opts.grpc_python_typed_handlers) { + request = namer_.Type(*method->request); + response = namer_.Type(*method->response); -void GenerateRegister(const grpc_generator::Service *service, - grpc_generator::Printer *printer, - std::map *dictonary) { - auto vars = *dictonary; - printer->Print(vars, "def add_$ServiceName$Servicer_to_server(servicer, server):\n"); - printer->Indent(); - printer->Print("rpc_method_handlers = {\n"); - printer->Indent(); - for (int j = 0; j < service->method_count(); j++) { - auto method = service->method(j); - vars["MethodName"] = method->name(); - vars["MethodType"] = GenerateMethodType(&*method); - printer->Print(vars, "'$MethodName$': grpc.$MethodType$_rpc_method_handler(\n"); - printer->Indent(); - printer->Print(vars, "servicer.$MethodName$\n"); - printer->Outdent(); - printer->Print("),\n"); + imports->Import(ModuleFor(method->request), request); + imports->Import(ModuleFor(method->response), response); + } + + ss << " def " << method->name << "(self, "; + if (ClientStreaming(method)) { + imports->Import("typing"); + ss << "request_iterator: typing.Iterator[" << request << "]"; + } else { + ss << "request: " << request; + } + ss << ", context: grpc.ServicerContext) -> "; + if (ServerStreaming(method)) { + imports->Import("typing"); + ss << "typing.Iterator[" << response << "]"; + } else { + ss << response; + } + ss << ": ...\n"; + } + + ss << '\n' + << '\n' + << "def add_" << service->name + << "Servicer_to_server(servicer: " << service->name + << "Servicer, server: grpc.Server) -> None: ...\n"; + } +}; + +class ServiceGenerator : public BaseGenerator { + public: + ServiceGenerator(const Parser& parser, const std::string& path, + const Version& version) + : BaseGenerator(parser, kConfig, path, version) {} + + bool Generate() { + Imports imports; + std::stringstream ss; + + imports.Import("flatbuffers"); + + if (parser_.opts.grpc_python_typed_handlers) { + ss << "def _serialize_to_bytes(table):\n" + << " buf = table._tab.Bytes\n" + << " n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, 0)\n" + << " if table._tab.Pos != n:\n" + << " raise ValueError('must be a top-level table')\n" + << " return bytes(buf)\n" + << '\n' + << '\n'; + } + + std::string ns_name{}; + for (const ServiceDef* service : parser_.services_.vec) { + GenerateStub(ss, service, &imports); + GenerateServicer(ss, service, &imports); + GenerateRegister(ss, service, &imports); + ns_name = NamespaceDir(*service->defined_namespace, false); + } + + std::string sanitized_suffix{parser_.opts.grpc_filename_suffix}; + std::replace(sanitized_suffix.begin(), sanitized_suffix.end(), '.', '_'); + std::string filename = + ns_name + kPathSeparator + + StripPath(StripExtension(parser_.file_being_parsed_)) + "_grpc" + + sanitized_suffix + namer_.config_.filename_extension; + + return SaveService(filename, imports, ss.str()); } - printer->Outdent(); - printer->Print("}\n"); - printer->Print(vars, "generic_handler = grpc.method_handlers_generic_handler(\n"); - printer->Indent(); - printer->Print(vars, "'$PATH$$ServiceName$', rpc_method_handlers)\n"); - printer->Outdent(); - printer->Print("server.add_generic_rpc_handlers((generic_handler,))"); - printer->Outdent(); - printer->Print("\n"); + + private: + void GenerateStub(std::stringstream& ss, const ServiceDef* service, + Imports* imports) { + ss << "class " << service->name << "Stub"; + if (version_.major != 3) ss << "(object)"; + ss << ":\n" + << " '''Interface exported by the server.'''\n" + << '\n' + << " def __init__(self, channel):\n" + << " '''Constructor.\n" + << '\n' + << " Args:\n" + << " channel: A grpc.Channel.\n" + << " '''\n" + << '\n'; + + for (const RPCCall* method : service->calls.vec) { + std::string response = namer_.Type(*method->response); + + imports->Import(ModuleFor(method->response), response); + + ss << " self." << method->name << " = channel." + << (ClientStreaming(method) ? "stream" : "unary") << "_" + << (ServerStreaming(method) ? "stream" : "unary") << "(\n" + << " method='/" + << service->defined_namespace->GetFullyQualifiedName(service->name) + << "/" << method->name << "'"; + + if (parser_.opts.grpc_python_typed_handlers) { + ss << ",\n" + << " request_serializer=_serialize_to_bytes,\n" + << " response_deserializer=" << response << ".GetRootAs"; + } + ss << ")\n\n"; + } + + ss << '\n'; + } + + void GenerateServicer(std::stringstream& ss, const ServiceDef* service, + Imports* imports) { + imports->Import("grpc"); + + ss << "class " << service->name << "Servicer"; + if (version_.major != 3) ss << "(object)"; + ss << ":\n" + << " '''Interface exported by the server.'''\n" + << '\n'; + + for (const RPCCall* method : service->calls.vec) { + const std::string request_param = + ClientStreaming(method) ? "request_iterator" : "request"; + ss << " def " << method->name << "(self, " << request_param + << ", context):\n" + << " context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n" + << " context.set_details('Method not implemented!')\n" + << " raise NotImplementedError('Method not implemented!')\n" + << '\n'; + } + + ss << '\n'; + } + + void GenerateRegister(std::stringstream& ss, const ServiceDef* service, + Imports* imports) { + imports->Import("grpc"); + + ss << "def add_" << service->name + << "Servicer_to_server(servicer, server):\n" + << " rpc_method_handlers = {\n"; + + for (const RPCCall* method : service->calls.vec) { + std::string request = namer_.Type(*method->request); + + imports->Import(ModuleFor(method->request), request); + + ss << " '" << method->name << "': grpc." + << (ClientStreaming(method) ? "stream" : "unary") << "_" + << (ServerStreaming(method) ? "stream" : "unary") + << "_rpc_method_handler(\n" + << " servicer." << method->name; + + if (parser_.opts.grpc_python_typed_handlers) { + ss << ",\n" + << " request_deserializer=" << request << ".GetRootAs,\n" + << " response_serializer=_serialize_to_bytes"; + } + ss << "),\n"; + } + ss << " }\n" + << '\n' + << " generic_handler = grpc.method_handlers_generic_handler(\n" + << " '" + << service->defined_namespace->GetFullyQualifiedName(service->name) + << "', rpc_method_handlers)\n" + << '\n' + << " server.add_generic_rpc_handlers((generic_handler,))\n" + << '\n'; + } +}; +} // namespace + +bool Generate(const Parser& parser, const std::string& path, + const Version& version) { + ServiceGenerator generator{parser, path, version}; + return generator.Generate(); } -} // namespace - -grpc::string Generate(grpc_generator::File *file, - const grpc_generator::Service *service) { - grpc::string output; - std::map vars; - vars["PATH"] = file->package(); - if (!file->package().empty()) { vars["PATH"].append("."); } - vars["ServiceName"] = service->name(); - auto printer = file->CreatePrinter(&output); - GenerateStub(service, &*printer, &vars); - GenerateServicer(service, &*printer, &vars); - GenerateRegister(service, &*printer, &vars); - return output; + +bool GenerateStub(const Parser& parser, const std::string& path, + const Version& version) { + StubGenerator generator{parser, path, version}; + return generator.Generate(); } -} // namespace grpc_python_generator +} // namespace grpc +} // namespace python +} // namespace flatbuffers diff --git a/third_party/flatbuffers/grpc/src/compiler/python_generator.h b/third_party/flatbuffers/grpc/src/compiler/python_generator.h index 40d29aada55..5967e1f84c3 100644 --- a/third_party/flatbuffers/grpc/src/compiler/python_generator.h +++ b/third_party/flatbuffers/grpc/src/compiler/python_generator.h @@ -19,14 +19,21 @@ #ifndef GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H #define GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H -#include +#include -#include "src/compiler/schema_interface.h" +#include "codegen/python.h" +#include "flatbuffers/idl.h" -namespace grpc_python_generator { +namespace flatbuffers { +namespace python { +namespace grpc { +bool Generate(const Parser& parser, const std::string& path, + const Version& version); -grpc::string Generate(grpc_generator::File *file, - const grpc_generator::Service *service); -} // namespace grpc_python_generator +bool GenerateStub(const Parser& parser, const std::string& path, + const Version& version); +} // namespace grpc +} // namespace python +} // namespace flatbuffers #endif // GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H diff --git a/third_party/flatbuffers/grpc/src/compiler/schema_interface.h b/third_party/flatbuffers/grpc/src/compiler/schema_interface.h index f89288d7560..483d5ac6af3 100644 --- a/third_party/flatbuffers/grpc/src/compiler/schema_interface.h +++ b/third_party/flatbuffers/grpc/src/compiler/schema_interface.h @@ -24,8 +24,8 @@ #include #ifndef GRPC_CUSTOM_STRING -# include -# define GRPC_CUSTOM_STRING std::string +#include +#define GRPC_CUSTOM_STRING std::string #endif namespace grpc { @@ -55,10 +55,10 @@ struct Method : public CommentHolder { virtual grpc::string output_type_name() const = 0; virtual bool get_module_and_message_path_input( - grpc::string *str, grpc::string generator_file_name, + grpc::string* str, grpc::string generator_file_name, bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0; virtual bool get_module_and_message_path_output( - grpc::string *str, grpc::string generator_file_name, + grpc::string* str, grpc::string generator_file_name, bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0; virtual std::vector get_input_namespace_parts() const = 0; @@ -89,9 +89,9 @@ struct Service : public CommentHolder { struct Printer { virtual ~Printer() {} - virtual void Print(const std::map &vars, - const char *template_string) = 0; - virtual void Print(const char *string) = 0; + virtual void Print(const std::map& vars, + const char* template_string) = 0; + virtual void Print(const char* string) = 0; virtual void SetIndentationSize(const size_t size) = 0; virtual void Indent() = 0; virtual void Outdent() = 0; @@ -112,7 +112,7 @@ struct File : public CommentHolder { virtual std::unique_ptr service(int i) const = 0; virtual std::unique_ptr CreatePrinter( - grpc::string *str, const char indentation_type = ' ') const = 0; + grpc::string* str, const char indentation_type = ' ') const = 0; }; } // namespace grpc_generator diff --git a/third_party/flatbuffers/grpc/src/compiler/swift_generator.cc b/third_party/flatbuffers/grpc/src/compiler/swift_generator.cc index b0a96d869ac..b741415393f 100644 --- a/third_party/flatbuffers/grpc/src/compiler/swift_generator.cc +++ b/third_party/flatbuffers/grpc/src/compiler/swift_generator.cc @@ -20,34 +20,35 @@ * please open an issue in the flatbuffers repository. This file should always * be maintained according to the Swift-grpc repository */ +#include "src/compiler/swift_generator.h" + #include #include #include "flatbuffers/util.h" #include "src/compiler/schema_interface.h" -#include "src/compiler/swift_generator.h" namespace grpc_swift_generator { namespace { -static std::string WrapInNameSpace(const std::vector &components, - const grpc::string &name) { +static std::string WrapInNameSpace(const std::vector& components, + const grpc::string& name) { std::string qualified_name; for (auto it = components.begin(); it != components.end(); ++it) qualified_name += *it + "_"; return qualified_name + name; } -static grpc::string GenerateMessage(const std::vector &components, - const grpc::string &name) { +static grpc::string GenerateMessage(const std::vector& components, + const grpc::string& name) { return "Message<" + WrapInNameSpace(components, name) + ">"; } // MARK: - Client -static void GenerateClientFuncName(const grpc_generator::Method *method, - grpc_generator::Printer *printer, - std::map *dictonary) { +static void GenerateClientFuncName( + const grpc_generator::Method* method, grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; if (method->NoStreaming()) { printer->Print(vars, @@ -83,9 +84,9 @@ static void GenerateClientFuncName(const grpc_generator::Method *method, " ) -> BidirectionalStreamingCall<$Input$, $Output$>"); } -static void GenerateClientFuncBody(const grpc_generator::Method *method, - grpc_generator::Printer *printer, - std::map *dictonary) { +static void GenerateClientFuncBody( + const grpc_generator::Method* method, grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; vars["Interceptor"] = "interceptors: self.interceptors?.make$MethodName$Interceptors() ?? []"; @@ -133,9 +134,9 @@ static void GenerateClientFuncBody(const grpc_generator::Method *method, " )\n"); } -void GenerateClientProtocol(const grpc_generator::Service *service, - grpc_generator::Printer *printer, - std::map *dictonary) { +void GenerateClientProtocol(const grpc_generator::Service* service, + grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; printer->Print( vars, @@ -207,8 +208,8 @@ void GenerateClientProtocol(const grpc_generator::Service *service, printer->Print("}\n\n"); } -void GenerateClientClass(grpc_generator::Printer *printer, - std::map *dictonary) { +void GenerateClientClass(grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; printer->Print(vars, "$ACCESS$ final class $ServiceQualifiedName$ServiceClient: " @@ -237,7 +238,7 @@ void GenerateClientClass(grpc_generator::Printer *printer, // MARK: - Server -grpc::string GenerateServerFuncName(const grpc_generator::Method *method) { +grpc::string GenerateServerFuncName(const grpc_generator::Method* method) { if (method->NoStreaming()) { return "func $MethodName$(request: $Input$" ", context: StatusOnlyCallContext) -> EventLoopFuture<$Output$>"; @@ -258,7 +259,7 @@ grpc::string GenerateServerFuncName(const grpc_generator::Method *method) { "-> EventLoopFuture<(StreamEvent<$Input$>) -> Void>"; } -grpc::string GenerateServerExtensionBody(const grpc_generator::Method *method) { +grpc::string GenerateServerExtensionBody(const grpc_generator::Method* method) { grpc::string start = " case \"$MethodName$\":\n "; grpc::string interceptors = " interceptors: self.interceptors?.make$MethodName$Interceptors() " @@ -302,9 +303,9 @@ grpc::string GenerateServerExtensionBody(const grpc_generator::Method *method) { return ""; } -void GenerateServerProtocol(const grpc_generator::Service *service, - grpc_generator::Printer *printer, - std::map *dictonary) { +void GenerateServerProtocol(const grpc_generator::Service* service, + grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; printer->Print(vars, "$ACCESS$ protocol $ServiceQualifiedName$Provider: " @@ -373,14 +374,16 @@ void GenerateServerProtocol(const grpc_generator::Service *service, } printer->Print("}"); } -} // namespace +} // namespace -grpc::string Generate(grpc_generator::File *file, - const grpc_generator::Service *service) { +grpc::string Generate(grpc_generator::File* file, + const grpc_generator::Service* service) { grpc::string output; std::map vars; vars["PATH"] = file->package(); - if (!file->package().empty()) { vars["PATH"].append("."); } + if (!file->package().empty()) { + vars["PATH"].append("."); + } vars["ServiceQualifiedName"] = WrapInNameSpace(service->namespace_parts(), service->name()); vars["ServiceName"] = service->name(); @@ -394,6 +397,8 @@ grpc::string Generate(grpc_generator::File *file, GenerateClientClass(&*printer, &vars); printer->Print("\n"); GenerateServerProtocol(service, &*printer, &vars); + printer->Print("\n"); + printer->Print("#endif\n"); return output; } @@ -409,6 +414,7 @@ grpc::string GenerateHeader() { code += "// swiftlint:disable all\n"; code += "// swiftformat:disable all\n"; code += "\n"; + code += "#if !os(Windows)\n"; code += "import Foundation\n"; code += "import GRPC\n"; code += "import NIO\n"; @@ -428,10 +434,7 @@ grpc::string GenerateHeader() { code += " }\n"; code += " func serialize(into buffer: inout NIO.ByteBuffer) throws {\n"; - code += - " let buf = UnsafeRawBufferPointer(start: self.rawPointer, count: " - "Int(self.size))\n"; - code += " buffer.writeBytes(buf)\n"; + code += " withUnsafeReadableBytes { buffer.writeBytes($0) }\n"; code += " }\n"; code += "}\n"; code += "extension Message: GRPCFlatBufPayload {}\n"; diff --git a/third_party/flatbuffers/grpc/src/compiler/swift_generator.h b/third_party/flatbuffers/grpc/src/compiler/swift_generator.h index 2a226fa9409..fea1a311c16 100644 --- a/third_party/flatbuffers/grpc/src/compiler/swift_generator.h +++ b/third_party/flatbuffers/grpc/src/compiler/swift_generator.h @@ -20,8 +20,8 @@ #include "src/compiler/schema_interface.h" #ifndef GRPC_CUSTOM_STRING -# include -# define GRPC_CUSTOM_STRING std::string +#include +#define GRPC_CUSTOM_STRING std::string #endif namespace grpc { @@ -31,7 +31,7 @@ typedef GRPC_CUSTOM_STRING string; } // namespace grpc namespace grpc_swift_generator { -grpc::string Generate(grpc_generator::File *file, - const grpc_generator::Service *service); +grpc::string Generate(grpc_generator::File* file, + const grpc_generator::Service* service); grpc::string GenerateHeader(); } // namespace grpc_swift_generator diff --git a/third_party/flatbuffers/grpc/src/compiler/ts_generator.cc b/third_party/flatbuffers/grpc/src/compiler/ts_generator.cc index ff362b774a1..a5789887e80 100644 --- a/third_party/flatbuffers/grpc/src/compiler/ts_generator.cc +++ b/third_party/flatbuffers/grpc/src/compiler/ts_generator.cc @@ -33,8 +33,8 @@ namespace grpc_ts_generator { namespace { static grpc::string GenerateNamespace(const std::vector ns, - const std::string filename, - const bool include_separator) { + const std::string filename, + const bool include_separator) { grpc::string path = ""; if (include_separator) path += "."; @@ -56,10 +56,10 @@ static grpc::string GenerateNamespace(const std::vector ns, // MARK: - Shared code -static void GenerateImports(const grpc_generator::Service *service, - grpc_generator::Printer *printer, - std::map *dictonary, - const bool grpc_var_import) { +static void GenerateImports(const grpc_generator::Service* service, + grpc_generator::Printer* printer, + std::map* dictonary, + const bool grpc_var_import) { auto vars = *dictonary; printer->Print( "// Generated GRPC code for FlatBuffers TS *** DO NOT EDIT ***\n"); @@ -105,9 +105,9 @@ static void GenerateImports(const grpc_generator::Service *service, // MARK: - Generate Main GRPC Code -static void GetStreamType(grpc_generator::Printer *printer, - const grpc_generator::Method *method, - std::map *dictonary) { +static void GetStreamType(grpc_generator::Printer* printer, + const grpc_generator::Method* method, + std::map* dictonary) { auto vars = *dictonary; auto client_streaming = method->ClientStreaming() || method->BidiStreaming(); auto server_streaming = method->ServerStreaming() || method->BidiStreaming(); @@ -117,8 +117,9 @@ static void GetStreamType(grpc_generator::Printer *printer, printer->Print(vars, "responseStream: $ServerStreaming$,\n"); } -static void GenerateSerializeMethod(grpc_generator::Printer *printer, - std::map *dictonary) { +static void GenerateSerializeMethod( + grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; printer->Print(vars, "function serialize_$Type$(buffer_args) {\n"); printer->Indent(); @@ -134,8 +135,8 @@ static void GenerateSerializeMethod(grpc_generator::Printer *printer, } static void GenerateDeserializeMethod( - grpc_generator::Printer *printer, - std::map *dictonary) { + grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; printer->Print(vars, "function deserialize_$Type$(buffer) {\n"); printer->Indent(); @@ -146,9 +147,9 @@ static void GenerateDeserializeMethod( printer->Print("}\n\n"); } -static void GenerateMethods(const grpc_generator::Service *service, - grpc_generator::Printer *printer, - std::map *dictonary) { +static void GenerateMethods(const grpc_generator::Service* service, + grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; std::set generated_functions; @@ -178,9 +179,9 @@ static void GenerateMethods(const grpc_generator::Service *service, } } -static void GenerateService(const grpc_generator::Service *service, - grpc_generator::Printer *printer, - std::map *dictonary) { +static void GenerateService(const grpc_generator::Service* service, + grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; vars["NAME"] = service->name() + "Service"; @@ -213,17 +214,19 @@ static void GenerateService(const grpc_generator::Service *service, "grpc.makeGenericClientConstructor($NAME$);"); } -} // namespace +} // namespace -grpc::string Generate(grpc_generator::File *file, - const grpc_generator::Service *service, - const grpc::string &filename) { +grpc::string Generate(grpc_generator::File* file, + const grpc_generator::Service* service, + const grpc::string& filename) { grpc::string output; std::map vars; vars["PATH"] = file->package(); - if (!file->package().empty()) { vars["PATH"].append("."); } + if (!file->package().empty()) { + vars["PATH"].append("."); + } vars["ServiceName"] = service->name(); vars["FBSFile"] = service->name() + "_fbs"; @@ -240,8 +243,8 @@ namespace { // MARK: - Generate Interface -static void FillInterface(grpc_generator::Printer *printer, - std::map *dictonary) { +static void FillInterface(grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; printer->Print(vars, "interface I$ServiceName$Service_I$MethodName$ extends " @@ -258,9 +261,9 @@ static void FillInterface(grpc_generator::Printer *printer, printer->Print("}\n"); } -static void GenerateInterfaces(const grpc_generator::Service *service, - grpc_generator::Printer *printer, - std::map *dictonary) { +static void GenerateInterfaces( + const grpc_generator::Service* service, grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; for (auto it = 0; it < service->method_count(); it++) { auto method = service->method(it); @@ -281,8 +284,8 @@ static void GenerateInterfaces(const grpc_generator::Service *service, } static void GenerateExportedInterface( - const grpc_generator::Service *service, grpc_generator::Printer *printer, - std::map *dictonary) { + const grpc_generator::Service* service, grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; printer->Print(vars, "export interface I$ServiceName$Server extends " @@ -324,9 +327,9 @@ static void GenerateExportedInterface( printer->Print("}\n"); } -static void GenerateMainInterface(const grpc_generator::Service *service, - grpc_generator::Printer *printer, - std::map *dictonary) { +static void GenerateMainInterface( + const grpc_generator::Service* service, grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; printer->Print( vars, @@ -351,11 +354,13 @@ static void GenerateMainInterface(const grpc_generator::Service *service, static grpc::string GenerateMetaData() { return "metadata: grpc.Metadata"; } -static grpc::string GenerateOptions() { return "options: Partial"; } +static grpc::string GenerateOptions() { + return "options: Partial"; +} static void GenerateUnaryClientInterface( - grpc_generator::Printer *printer, - std::map *dictonary) { + grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; grpc::string main = "$ISPUBLIC$$MethodName$(request: $INPUT$, "; grpc::string callback = @@ -369,8 +374,8 @@ static void GenerateUnaryClientInterface( } static void GenerateClientWriteStreamInterface( - grpc_generator::Printer *printer, - std::map *dictonary) { + grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; grpc::string main = "$ISPUBLIC$$MethodName$("; grpc::string callback = @@ -386,8 +391,8 @@ static void GenerateClientWriteStreamInterface( } static void GenerateClientReadableStreamInterface( - grpc_generator::Printer *printer, - std::map *dictonary) { + grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; grpc::string main = "$ISPUBLIC$$MethodName$(request: $INPUT$, "; grpc::string end_function = "): grpc.ClientReadableStream<$OUTPUT$>;\n"; @@ -398,8 +403,8 @@ static void GenerateClientReadableStreamInterface( } static void GenerateDepluxStreamInterface( - grpc_generator::Printer *printer, - std::map *dictonary) { + grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; grpc::string main = "$ISPUBLIC$$MethodName$("; grpc::string end_function = @@ -413,9 +418,9 @@ static void GenerateDepluxStreamInterface( .c_str()); } -static void GenerateClientInterface(const grpc_generator::Service *service, - grpc_generator::Printer *printer, - std::map *dictonary) { +static void GenerateClientInterface( + const grpc_generator::Service* service, grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; printer->Print(vars, "export interface I$ServiceName$Client {\n"); printer->Indent(); @@ -452,8 +457,8 @@ static void GenerateClientInterface(const grpc_generator::Service *service, } static void GenerateClientClassInterface( - const grpc_generator::Service *service, grpc_generator::Printer *printer, - std::map *dictonary) { + const grpc_generator::Service* service, grpc_generator::Printer* printer, + std::map* dictonary) { auto vars = *dictonary; printer->Print(vars, "export class $ServiceName$Client extends grpc.Client " @@ -492,12 +497,11 @@ static void GenerateClientClassInterface( printer->Outdent(); printer->Print("}\n"); } -} // namespace +} // namespace - -grpc::string GenerateInterface(grpc_generator::File *file, - const grpc_generator::Service *service, - const grpc::string &filename) { +grpc::string GenerateInterface(grpc_generator::File* file, + const grpc_generator::Service* service, + const grpc::string& filename) { grpc::string output; std::set generated_functions; @@ -505,7 +509,9 @@ grpc::string GenerateInterface(grpc_generator::File *file, vars["PATH"] = file->package(); - if (!file->package().empty()) { vars["PATH"].append("."); } + if (!file->package().empty()) { + vars["PATH"].append("."); + } vars["ServiceName"] = service->name(); vars["FBSFile"] = service->name() + "_fbs"; diff --git a/third_party/flatbuffers/grpc/src/compiler/ts_generator.h b/third_party/flatbuffers/grpc/src/compiler/ts_generator.h index a356659daac..655fc8e34fd 100644 --- a/third_party/flatbuffers/grpc/src/compiler/ts_generator.h +++ b/third_party/flatbuffers/grpc/src/compiler/ts_generator.h @@ -5,8 +5,8 @@ #include "src/compiler/schema_interface.h" #ifndef GRPC_CUSTOM_STRING -# include -# define GRPC_CUSTOM_STRING std::string +#include +#define GRPC_CUSTOM_STRING std::string #endif namespace grpc { @@ -16,11 +16,11 @@ typedef GRPC_CUSTOM_STRING string; } // namespace grpc namespace grpc_ts_generator { -grpc::string Generate(grpc_generator::File *file, - const grpc_generator::Service *service, - const grpc::string &filename); +grpc::string Generate(grpc_generator::File* file, + const grpc_generator::Service* service, + const grpc::string& filename); -grpc::string GenerateInterface(grpc_generator::File *file, - const grpc_generator::Service *service, - const grpc::string &filename); +grpc::string GenerateInterface(grpc_generator::File* file, + const grpc_generator::Service* service, + const grpc::string& filename); } // namespace grpc_ts_generator diff --git a/third_party/flatbuffers/grpc/tests/BUILD b/third_party/flatbuffers/grpc/tests/BUILD index 5d4023ec752..4ae4e7fed94 100644 --- a/third_party/flatbuffers/grpc/tests/BUILD +++ b/third_party/flatbuffers/grpc/tests/BUILD @@ -1,3 +1,5 @@ +load("@rules_cc//cc:defs.bzl", "cc_test") + cc_test( name = "grpc_test", srcs = [ @@ -15,3 +17,27 @@ cc_test( "@com_github_grpc_grpc//:grpc++", ], ) + +cc_test( + name = "grpc_callback_compile_test", + srcs = ["grpctest_callback_compile.cpp"], + copts = ["-Itests"], + linkstatic = 1, + deps = [ + "//tests:monster_test_cc_fbs", + "//tests:monster_test_grpc", + "@com_github_grpc_grpc//:grpc++", + ], +) + +cc_test( + name = "grpc_callback_client_compile_test", + srcs = ["grpctest_callback_client_compile.cpp"], + copts = ["-Itests"], + linkstatic = 1, + deps = [ + "//tests:monster_test_cc_fbs", + "//tests:monster_test_grpc", + "@com_github_grpc_grpc//:grpc++", + ], +) diff --git a/third_party/flatbuffers/grpc/tests/GameFactory.java b/third_party/flatbuffers/grpc/tests/GameFactory.java index 520ae392090..87e792bc044 100644 --- a/third_party/flatbuffers/grpc/tests/GameFactory.java +++ b/third_party/flatbuffers/grpc/tests/GameFactory.java @@ -1,10 +1,11 @@ -import java.nio.ByteBuffer; import MyGame.Example.Monster; import MyGame.Example.Stat; import com.google.flatbuffers.FlatBufferBuilder; +import java.nio.ByteBuffer; class GameFactory { - public static Monster createMonster(String monsterName, short nestedMonsterHp, short nestedMonsterMana) { + public static Monster createMonster( + String monsterName, short nestedMonsterHp, short nestedMonsterMana) { FlatBufferBuilder builder = new FlatBufferBuilder(); int name_offset = builder.createString(monsterName); @@ -31,12 +32,11 @@ public static Monster createMonsterFromStat(Stat stat, int seqNo) { return monster; } - public static Stat createStat(String greeting, long val, int count) { + public static Stat createStat(String greeting, long val, int count) { FlatBufferBuilder builder = new FlatBufferBuilder(); int statOffset = Stat.createStat(builder, builder.createString(greeting), val, count); builder.finish(statOffset); Stat stat = Stat.getRootAsStat(builder.dataBuffer()); return stat; } - } diff --git a/third_party/flatbuffers/grpc/tests/JavaGrpcTest.java b/third_party/flatbuffers/grpc/tests/JavaGrpcTest.java index 27329116171..3bce08e6049 100644 --- a/third_party/flatbuffers/grpc/tests/JavaGrpcTest.java +++ b/third_party/flatbuffers/grpc/tests/JavaGrpcTest.java @@ -17,226 +17,236 @@ import MyGame.Example.Monster; import MyGame.Example.MonsterStorageGrpc; import MyGame.Example.Stat; -import com.google.flatbuffers.FlatBufferBuilder; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.grpc.Server; import io.grpc.ServerBuilder; import io.grpc.stub.StreamObserver; -import org.junit.Assert; - import java.io.IOException; -import java.lang.InterruptedException; -import java.nio.ByteBuffer; import java.util.Iterator; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.CountDownLatch; - +import java.util.concurrent.atomic.AtomicReference; +import org.junit.Assert; -/** - * Demonstrates basic client-server interaction using grpc-java over netty. - */ +/** Demonstrates basic client-server interaction using grpc-java over netty. */ public class JavaGrpcTest { - static final String BIG_MONSTER_NAME = "Cyberdemon"; - static final short nestedMonsterHp = 600; - static final short nestedMonsterMana = 1024; - static final int numStreamedMsgs = 10; - static final int timeoutMs = 3000; - static Server server; - static ManagedChannel channel; - static MonsterStorageGrpc.MonsterStorageBlockingStub blockingStub; - static MonsterStorageGrpc.MonsterStorageStub asyncStub; - - static class MyService extends MonsterStorageGrpc.MonsterStorageImplBase { - @Override - public void store(Monster request, io.grpc.stub.StreamObserver responseObserver) { - Assert.assertEquals(request.name(), BIG_MONSTER_NAME); - Assert.assertEquals(request.hp(), nestedMonsterHp); - Assert.assertEquals(request.mana(), nestedMonsterMana); - System.out.println("Received store request from " + request.name()); - // Create a response from the incoming request name. - Stat stat = GameFactory.createStat("Hello " + request.name(), 100, 10); - responseObserver.onNext(stat); - responseObserver.onCompleted(); - } - - @Override - public void retrieve(Stat request, io.grpc.stub.StreamObserver responseObserver) { - // Create 10 monsters for streaming response. - for (int i=0; i getMaxHitPoint(final StreamObserver responseObserver) { - return computeMinMax(responseObserver, false); - } - - @Override - public StreamObserver getMinMaxHitPoints(final StreamObserver responseObserver) { - return computeMinMax(responseObserver, true); - } - - private StreamObserver computeMinMax(final StreamObserver responseObserver, final boolean includeMin) { - final AtomicInteger maxHp = new AtomicInteger(Integer.MIN_VALUE); - final AtomicReference maxHpMonsterName = new AtomicReference(); - final AtomicInteger maxHpCount = new AtomicInteger(); - - final AtomicInteger minHp = new AtomicInteger(Integer.MAX_VALUE); - final AtomicReference minHpMonsterName = new AtomicReference(); - final AtomicInteger minHpCount = new AtomicInteger(); - - return new StreamObserver() { - public void onNext(Monster monster) { - if (monster.hp() > maxHp.get()) { - // Found a monster of higher hit points. - maxHp.set(monster.hp()); - maxHpMonsterName.set(monster.name()); - maxHpCount.set(1); - } - else if (monster.hp() == maxHp.get()) { - // Count how many times we saw a monster of current max hit points. - maxHpCount.getAndIncrement(); - } - - if (monster.hp() < minHp.get()) { - // Found a monster of a lower hit points. - minHp.set(monster.hp()); - minHpMonsterName.set(monster.name()); - minHpCount.set(1); - } - else if (monster.hp() == minHp.get()) { - // Count how many times we saw a monster of current min hit points. - minHpCount.getAndIncrement(); - } - } - public void onCompleted() { - Stat maxHpStat = GameFactory.createStat(maxHpMonsterName.get(), maxHp.get(), maxHpCount.get()); - // Send max hit points first. - responseObserver.onNext(maxHpStat); - if (includeMin) { - // Send min hit points. - Stat minHpStat = GameFactory.createStat(minHpMonsterName.get(), minHp.get(), minHpCount.get()); - responseObserver.onNext(minHpStat); - } - responseObserver.onCompleted(); - } - public void onError(Throwable t) { - // Not expected - Assert.fail(); - }; - }; - } + static final String BIG_MONSTER_NAME = "Cyberdemon"; + static final short nestedMonsterHp = 600; + static final short nestedMonsterMana = 1024; + static final int numStreamedMsgs = 10; + static final int timeoutMs = 3000; + static Server server; + static ManagedChannel channel; + static MonsterStorageGrpc.MonsterStorageBlockingStub blockingStub; + static MonsterStorageGrpc.MonsterStorageStub asyncStub; + + static class MyService extends MonsterStorageGrpc.MonsterStorageImplBase { + @Override + public void store(Monster request, io.grpc.stub.StreamObserver responseObserver) { + Assert.assertEquals(request.name(), BIG_MONSTER_NAME); + Assert.assertEquals(request.hp(), nestedMonsterHp); + Assert.assertEquals(request.mana(), nestedMonsterMana); + System.out.println("Received store request from " + request.name()); + // Create a response from the incoming request name. + Stat stat = GameFactory.createStat("Hello " + request.name(), 100, 10); + responseObserver.onNext(stat); + responseObserver.onCompleted(); } - @org.junit.BeforeClass - public static void startServer() throws IOException { - server = ServerBuilder.forPort(0).addService(new MyService()).build().start(); - int port = server.getPort(); - channel = ManagedChannelBuilder.forAddress("localhost", port) - // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid - // needing certificates. - .usePlaintext() - .directExecutor() - .build(); - blockingStub = MonsterStorageGrpc.newBlockingStub(channel); - asyncStub = MonsterStorageGrpc.newStub(channel); + @Override + public void retrieve(Stat request, io.grpc.stub.StreamObserver responseObserver) { + // Create 10 monsters for streaming response. + for (int i = 0; i < numStreamedMsgs; i++) { + Monster monster = GameFactory.createMonsterFromStat(request, i); + responseObserver.onNext(monster); + } + responseObserver.onCompleted(); } - @org.junit.Test - public void testUnary() throws IOException { - Monster monsterRequest = GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana); - Stat stat = blockingStub.store(monsterRequest); - Assert.assertEquals(stat.id(), "Hello " + BIG_MONSTER_NAME); - System.out.println("Received stat response from service: " + stat.id()); + @Override + public StreamObserver getMaxHitPoint(final StreamObserver responseObserver) { + return computeMinMax(responseObserver, false); } - @org.junit.Test - public void testServerStreaming() throws IOException { - Monster monsterRequest = GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana); - Stat stat = blockingStub.store(monsterRequest); - Iterator iterator = blockingStub.retrieve(stat); - int counter = 0; - while(iterator.hasNext()) { - Monster m = iterator.next(); - System.out.println("Received monster " + m.name()); - counter ++; - } - Assert.assertEquals(counter, numStreamedMsgs); - System.out.println("FlatBuffers GRPC client/server test: completed successfully"); + @Override + public StreamObserver getMinMaxHitPoints(final StreamObserver responseObserver) { + return computeMinMax(responseObserver, true); } - @org.junit.Test - public void testClientStreaming() throws IOException, InterruptedException { - final AtomicReference maxHitStat = new AtomicReference(); - final CountDownLatch streamAlive = new CountDownLatch(1); + private StreamObserver computeMinMax( + final StreamObserver responseObserver, final boolean includeMin) { + final AtomicInteger maxHp = new AtomicInteger(Integer.MIN_VALUE); + final AtomicReference maxHpMonsterName = new AtomicReference(); + final AtomicInteger maxHpCount = new AtomicInteger(); + + final AtomicInteger minHp = new AtomicInteger(Integer.MAX_VALUE); + final AtomicReference minHpMonsterName = new AtomicReference(); + final AtomicInteger minHpCount = new AtomicInteger(); + + return new StreamObserver() { + public void onNext(Monster monster) { + if (monster.hp() > maxHp.get()) { + // Found a monster of higher hit points. + maxHp.set(monster.hp()); + maxHpMonsterName.set(monster.name()); + maxHpCount.set(1); + } else if (monster.hp() == maxHp.get()) { + // Count how many times we saw a monster of current max hit points. + maxHpCount.getAndIncrement(); + } + + if (monster.hp() < minHp.get()) { + // Found a monster of a lower hit points. + minHp.set(monster.hp()); + minHpMonsterName.set(monster.name()); + minHpCount.set(1); + } else if (monster.hp() == minHp.get()) { + // Count how many times we saw a monster of current min hit points. + minHpCount.getAndIncrement(); + } + } - StreamObserver statObserver = new StreamObserver() { public void onCompleted() { - streamAlive.countDown(); + Stat maxHpStat = + GameFactory.createStat(maxHpMonsterName.get(), maxHp.get(), maxHpCount.get()); + // Send max hit points first. + responseObserver.onNext(maxHpStat); + if (includeMin) { + // Send min hit points. + Stat minHpStat = + GameFactory.createStat(minHpMonsterName.get(), minHp.get(), minHpCount.get()); + responseObserver.onNext(minHpStat); + } + responseObserver.onCompleted(); } - public void onError(Throwable ex) { } - public void onNext(Stat stat) { - maxHitStat.set(stat); + + public void onError(Throwable t) { + // Not expected + Assert.fail(); } + ; }; - StreamObserver monsterStream = asyncStub.getMaxHitPoint(statObserver); - short count = 10; - for (short i = 0;i < count; ++i) { - Monster monster = GameFactory.createMonster(BIG_MONSTER_NAME + i, (short) (nestedMonsterHp * i), nestedMonsterMana); - monsterStream.onNext(monster); - } - monsterStream.onCompleted(); - // Wait a little bit for the server to send the stats of the monster with the max hit-points. - streamAlive.await(timeoutMs, TimeUnit.MILLISECONDS); - Assert.assertEquals(maxHitStat.get().id(), BIG_MONSTER_NAME + (count - 1)); - Assert.assertEquals(maxHitStat.get().val(), nestedMonsterHp * (count - 1)); - Assert.assertEquals(maxHitStat.get().count(), 1); } + } + + @org.junit.BeforeClass + public static void startServer() throws IOException { + server = ServerBuilder.forPort(0).addService(new MyService()).build().start(); + int port = server.getPort(); + channel = + ManagedChannelBuilder.forAddress("localhost", port) + // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid + // needing certificates. + .usePlaintext() + .directExecutor() + .build(); + blockingStub = MonsterStorageGrpc.newBlockingStub(channel); + asyncStub = MonsterStorageGrpc.newStub(channel); + } + + @org.junit.Test + public void testUnary() throws IOException { + Monster monsterRequest = + GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana); + Stat stat = blockingStub.store(monsterRequest); + Assert.assertEquals(stat.id(), "Hello " + BIG_MONSTER_NAME); + System.out.println("Received stat response from service: " + stat.id()); + } + + @org.junit.Test + public void testServerStreaming() throws IOException { + Monster monsterRequest = + GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana); + Stat stat = blockingStub.store(monsterRequest); + Iterator iterator = blockingStub.retrieve(stat); + int counter = 0; + while (iterator.hasNext()) { + Monster m = iterator.next(); + System.out.println("Received monster " + m.name()); + counter++; + } + Assert.assertEquals(counter, numStreamedMsgs); + System.out.println("FlatBuffers GRPC client/server test: completed successfully"); + } + + @org.junit.Test + public void testClientStreaming() throws IOException, InterruptedException { + final AtomicReference maxHitStat = new AtomicReference(); + final CountDownLatch streamAlive = new CountDownLatch(1); + + StreamObserver statObserver = + new StreamObserver() { + public void onCompleted() { + streamAlive.countDown(); + } - @org.junit.Test - public void testBiDiStreaming() throws IOException, InterruptedException { - final AtomicReference maxHitStat = new AtomicReference(); - final AtomicReference minHitStat = new AtomicReference(); - final CountDownLatch streamAlive = new CountDownLatch(1); + public void onError(Throwable ex) {} - StreamObserver statObserver = new StreamObserver() { - public void onCompleted() { - streamAlive.countDown(); - } - public void onError(Throwable ex) { } - public void onNext(Stat stat) { - // We expect the server to send the max stat first and then the min stat. - if (maxHitStat.get() == null) { + public void onNext(Stat stat) { maxHitStat.set(stat); } - else { - minHitStat.set(stat); + }; + StreamObserver monsterStream = asyncStub.getMaxHitPoint(statObserver); + short count = 10; + for (short i = 0; i < count; ++i) { + Monster monster = + GameFactory.createMonster( + BIG_MONSTER_NAME + i, (short) (nestedMonsterHp * i), nestedMonsterMana); + monsterStream.onNext(monster); + } + monsterStream.onCompleted(); + // Wait a little bit for the server to send the stats of the monster with the max hit-points. + streamAlive.await(timeoutMs, TimeUnit.MILLISECONDS); + Assert.assertEquals(maxHitStat.get().id(), BIG_MONSTER_NAME + (count - 1)); + Assert.assertEquals(maxHitStat.get().val(), nestedMonsterHp * (count - 1)); + Assert.assertEquals(maxHitStat.get().count(), 1); + } + + @org.junit.Test + public void testBiDiStreaming() throws IOException, InterruptedException { + final AtomicReference maxHitStat = new AtomicReference(); + final AtomicReference minHitStat = new AtomicReference(); + final CountDownLatch streamAlive = new CountDownLatch(1); + + StreamObserver statObserver = + new StreamObserver() { + public void onCompleted() { + streamAlive.countDown(); } - } - }; - StreamObserver monsterStream = asyncStub.getMinMaxHitPoints(statObserver); - short count = 10; - for (short i = 0;i < count; ++i) { - Monster monster = GameFactory.createMonster(BIG_MONSTER_NAME + i, (short) (nestedMonsterHp * i), nestedMonsterMana); - monsterStream.onNext(monster); - } - monsterStream.onCompleted(); - - // Wait a little bit for the server to send the stats of the monster with the max and min hit-points. - streamAlive.await(timeoutMs, TimeUnit.MILLISECONDS); - Assert.assertEquals(maxHitStat.get().id(), BIG_MONSTER_NAME + (count - 1)); - Assert.assertEquals(maxHitStat.get().val(), nestedMonsterHp * (count - 1)); - Assert.assertEquals(maxHitStat.get().count(), 1); + public void onError(Throwable ex) {} - Assert.assertEquals(minHitStat.get().id(), BIG_MONSTER_NAME + 0); - Assert.assertEquals(minHitStat.get().val(), nestedMonsterHp * 0); - Assert.assertEquals(minHitStat.get().count(), 1); + public void onNext(Stat stat) { + // We expect the server to send the max stat first and then the min stat. + if (maxHitStat.get() == null) { + maxHitStat.set(stat); + } else { + minHitStat.set(stat); + } + } + }; + StreamObserver monsterStream = asyncStub.getMinMaxHitPoints(statObserver); + short count = 10; + for (short i = 0; i < count; ++i) { + Monster monster = + GameFactory.createMonster( + BIG_MONSTER_NAME + i, (short) (nestedMonsterHp * i), nestedMonsterMana); + monsterStream.onNext(monster); } + monsterStream.onCompleted(); + + // Wait a little bit for the server to send the stats of the monster with the max and min + // hit-points. + streamAlive.await(timeoutMs, TimeUnit.MILLISECONDS); + + Assert.assertEquals(maxHitStat.get().id(), BIG_MONSTER_NAME + (count - 1)); + Assert.assertEquals(maxHitStat.get().val(), nestedMonsterHp * (count - 1)); + Assert.assertEquals(maxHitStat.get().count(), 1); + + Assert.assertEquals(minHitStat.get().id(), BIG_MONSTER_NAME + 0); + Assert.assertEquals(minHitStat.get().val(), nestedMonsterHp * 0); + Assert.assertEquals(minHitStat.get().count(), 1); + } } diff --git a/third_party/flatbuffers/grpc/tests/grpctest.cpp b/third_party/flatbuffers/grpc/tests/grpctest.cpp index 6991b7ebb87..f4798c9b5f0 100644 --- a/third_party/flatbuffers/grpc/tests/grpctest.cpp +++ b/third_party/flatbuffers/grpc/tests/grpctest.cpp @@ -33,9 +33,9 @@ void message_builder_tests(); // code. It implements all rpcs specified in the FlatBuffers schema. class ServiceImpl final : public MyGame::Example::MonsterStorage::Service { virtual ::grpc::Status Store( - ::grpc::ServerContext *context, - const flatbuffers::grpc::Message *request, - flatbuffers::grpc::Message *response) override { + ::grpc::ServerContext* context, + const flatbuffers::grpc::Message* request, + flatbuffers::grpc::Message* response) override { // Create a response from the incoming request name. fbb_.Clear(); auto stat_offset = CreateStat( @@ -46,9 +46,9 @@ class ServiceImpl final : public MyGame::Example::MonsterStorage::Service { return grpc::Status::OK; } virtual ::grpc::Status Retrieve( - ::grpc::ServerContext *context, - const flatbuffers::grpc::Message *request, - ::grpc::ServerWriter> *writer) + ::grpc::ServerContext* context, + const flatbuffers::grpc::Message* request, + ::grpc::ServerWriter>* writer) override { for (int i = 0; i < 5; i++) { fbb_.Clear(); @@ -73,7 +73,7 @@ class ServiceImpl final : public MyGame::Example::MonsterStorage::Service { }; // Track the server instance, so we can terminate it later. -grpc::Server *server_instance = nullptr; +grpc::Server* server_instance = nullptr; // Mutex to protec this variable. std::mutex wait_for_server; std::condition_variable server_instance_cv; @@ -98,7 +98,8 @@ void RunServer() { server_instance->Wait(); } -template void StoreRPC(MonsterStorage::Stub *stub) { +template +void StoreRPC(MonsterStorage::Stub* stub) { Builder fbb; grpc::ClientContext context; // Build a request with the name set. @@ -119,7 +120,8 @@ template void StoreRPC(MonsterStorage::Stub *stub) { } } -template void RetrieveRPC(MonsterStorage::Stub *stub) { +template +void RetrieveRPC(MonsterStorage::Stub* stub) { Builder fbb; grpc::ClientContext context; fbb.Clear(); @@ -179,7 +181,7 @@ int grpc_server_test() { return 0; } -int main(int /*argc*/, const char * /*argv*/[]) { +int main(int /*argc*/, const char* /*argv*/[]) { message_builder_tests(); grpc_server_test(); diff --git a/third_party/flatbuffers/grpc/tests/grpctest.py b/third_party/flatbuffers/grpc/tests/grpctest.py index 9cfeda6891b..f2ff261d4dd 100644 --- a/third_party/flatbuffers/grpc/tests/grpctest.py +++ b/third_party/flatbuffers/grpc/tests/grpctest.py @@ -1,13 +1,13 @@ from __future__ import print_function +from concurrent import futures import os import sys -import grpc -import flatbuffers -from concurrent import futures +import flatbuffers +import grpc -sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'tests')) +sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "tests")) import MyGame.Example.Monster as Monster import MyGame.Example.Stat as Stat import MyGame.Example.Vec3 as Vec3 @@ -39,136 +39,138 @@ class MonsterStorage(monster_grpc_fb.MonsterStorageServicer): - def Store(self, request, context): + def Store(self, request, context): - m = Monster.Monster().GetRootAsMonster(request, 0) + m = Monster.Monster().GetRootAsMonster(request, 0) - assert m.Name().decode("utf-8") == test_monster_name1 + assert m.Name().decode("utf-8") == test_monster_name1 - assert m.Pos().X() == test_X - assert m.Pos().Y() == test_Y - assert m.Pos().Z() == test_Z - assert m.Pos().Test1() == test_test1 - assert m.Pos().Test2() == test_color - test3 = Test.Test() - assert m.Pos().Test3(test3).A() == test_a - assert m.Pos().Test3(test3).B() == test_b + assert m.Pos().X() == test_X + assert m.Pos().Y() == test_Y + assert m.Pos().Z() == test_Z + assert m.Pos().Test1() == test_test1 + assert m.Pos().Test2() == test_color + test3 = Test.Test() + assert m.Pos().Test3(test3).A() == test_a + assert m.Pos().Test3(test3).B() == test_b - assert m.Hp() == test_hp + assert m.Hp() == test_hp - assert m.Color() == test_color + assert m.Color() == test_color - assert m.InventoryLength() == len(test_inventory) - for i in range(0, len(test_inventory)): - assert m.Inventory(i) == test_inventory[len(test_inventory)-i -1] + assert m.InventoryLength() == len(test_inventory) + for i in range(0, len(test_inventory)): + assert m.Inventory(i) == test_inventory[len(test_inventory) - i - 1] - assert m.TestType() == test_testtype + assert m.TestType() == test_testtype - assert m.Test() is not None - table = m.Test() + assert m.Test() is not None + table = m.Test() - m2 = Monster.Monster() - m2.Init(table.Bytes, table.Pos) - assert m2.Name().decode("utf-8") == test_monster_name2 + m2 = Monster.Monster() + m2.Init(table.Bytes, table.Pos) + assert m2.Name().decode("utf-8") == test_monster_name2 - m3 = m.Enemy() - assert m3.Name().decode("utf-8") == test_monster_name2 + m3 = m.Enemy() + assert m3.Name().decode("utf-8") == test_monster_name2 - assert m.Testarrayofstring(0).decode("utf-8") == test_string + assert m.Testarrayofstring(0).decode("utf-8") == test_string - b = flatbuffers.Builder(0) - i = b.CreateString(test_stat_id) - Stat.StatStart(b) - Stat.StatAddId(b, i) - Stat.StatAddVal(b, test_stat_val) - Stat.StatAddCount(b, test_stat_count) - b.Finish(Stat.StatEnd(b)) - return bytes(b.Output()) + b = flatbuffers.Builder(0) + i = b.CreateString(test_stat_id) + Stat.StatStart(b) + Stat.StatAddId(b, i) + Stat.StatAddVal(b, test_stat_val) + Stat.StatAddCount(b, test_stat_count) + b.Finish(Stat.StatEnd(b)) + return bytes(b.Output()) - def Retrieve(self, request, context): + def Retrieve(self, request, context): - s = Stat.Stat().GetRootAsStat(request, 0) + s = Stat.Stat().GetRootAsStat(request, 0) - no_of_monsters = test_no_of_monsters - for i in range(0, no_of_monsters): - b = flatbuffers.Builder(0) - i = b.CreateString(test_monsters_name_retrieve[i]) - Monster.MonsterStart(b) - Monster.MonsterAddName(b, i) - b.Finish(Monster.MonsterEnd(b)) - yield bytes(b.Output()) + no_of_monsters = test_no_of_monsters + for i in range(0, no_of_monsters): + b = flatbuffers.Builder(0) + i = b.CreateString(test_monsters_name_retrieve[i]) + Monster.MonsterStart(b) + Monster.MonsterAddName(b, i) + b.Finish(Monster.MonsterEnd(b)) + yield bytes(b.Output()) def serve(): - server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) - monster_grpc_fb.add_MonsterStorageServicer_to_server(MonsterStorage(), server) - server.add_insecure_port('[::]:50051') + server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + monster_grpc_fb.add_MonsterStorageServicer_to_server(MonsterStorage(), server) + server.add_insecure_port("[::]:50051") - server.start() + server.start() - run() + run() def run(): - channel = grpc.insecure_channel('127.0.0.1:50051') - stub = monster_grpc_fb.MonsterStorageStub(channel) - - b = flatbuffers.Builder(0) - name2 = b.CreateString(test_monster_name2) - name1 = b.CreateString(test_monster_name1) - Monster.MonsterStart(b) - Monster.MonsterAddName(b, name2) - monster2 = Monster.MonsterEnd(b) - test1 = b.CreateString(test_string) - - Monster.MonsterStartInventoryVector(b, len(test_inventory)) - for i in range(0, len(test_inventory)): - b.PrependByte(test_inventory[i]) - inv = b.EndVector() - - Monster.MonsterStartTest4Vector(b, 2) - Test.CreateTest(b, 10, 20) - Test.CreateTest(b, 30, 40) - test4 = b.EndVector() - - Monster.MonsterStartTestarrayofstringVector(b, 1) - b.PrependUOffsetTRelative(test1) - test_array_of_string = b.EndVector() - - Monster.MonsterStart(b) - - Monster.MonsterAddHp(b, test_hp) - Monster.MonsterAddName(b, name1) - Monster.MonsterAddColor(b, test_color) - pos = Vec3.CreateVec3(b, test_X, test_Y, test_Z, test_test1, test_color, test_a, test_b) - Monster.MonsterAddPos(b, pos) - Monster.MonsterAddInventory(b, inv) - Monster.MonsterAddTestType(b, test_testtype) - Monster.MonsterAddTest(b, monster2) - Monster.MonsterAddTest4(b, test4) - Monster.MonsterAddEnemy(b, monster2) - Monster.MonsterAddTestarrayofstring(b, test_array_of_string) - monster = Monster.MonsterEnd(b) - - b.Finish(monster) - - stat_response = stub.Store(bytes(b.Output())) - - s = Stat.Stat().GetRootAsStat(stat_response, 0) - - assert s.Id().decode("utf-8") == test_stat_id - assert s.Val() == test_stat_val - assert s.Count() == test_stat_count - - monster_reponses = stub.Retrieve(stat_response) - count = 0 - for monster_reponse in monster_reponses: - m = Monster.Monster().GetRootAsMonster(monster_reponse, 0) - assert m.Name().decode("utf-8") == test_monsters_name_retrieve[count] - count = count + 1 - - -if __name__ == '__main__': - serve() + channel = grpc.insecure_channel("127.0.0.1:50051") + stub = monster_grpc_fb.MonsterStorageStub(channel) + + b = flatbuffers.Builder(0) + name2 = b.CreateString(test_monster_name2) + name1 = b.CreateString(test_monster_name1) + Monster.MonsterStart(b) + Monster.MonsterAddName(b, name2) + monster2 = Monster.MonsterEnd(b) + test1 = b.CreateString(test_string) + + Monster.MonsterStartInventoryVector(b, len(test_inventory)) + for i in range(0, len(test_inventory)): + b.PrependByte(test_inventory[i]) + inv = b.EndVector() + + Monster.MonsterStartTest4Vector(b, 2) + Test.CreateTest(b, 10, 20) + Test.CreateTest(b, 30, 40) + test4 = b.EndVector() + + Monster.MonsterStartTestarrayofstringVector(b, 1) + b.PrependUOffsetTRelative(test1) + test_array_of_string = b.EndVector() + + Monster.MonsterStart(b) + + Monster.MonsterAddHp(b, test_hp) + Monster.MonsterAddName(b, name1) + Monster.MonsterAddColor(b, test_color) + pos = Vec3.CreateVec3( + b, test_X, test_Y, test_Z, test_test1, test_color, test_a, test_b + ) + Monster.MonsterAddPos(b, pos) + Monster.MonsterAddInventory(b, inv) + Monster.MonsterAddTestType(b, test_testtype) + Monster.MonsterAddTest(b, monster2) + Monster.MonsterAddTest4(b, test4) + Monster.MonsterAddEnemy(b, monster2) + Monster.MonsterAddTestarrayofstring(b, test_array_of_string) + monster = Monster.MonsterEnd(b) + + b.Finish(monster) + + stat_response = stub.Store(bytes(b.Output())) + + s = Stat.Stat().GetRootAsStat(stat_response, 0) + + assert s.Id().decode("utf-8") == test_stat_id + assert s.Val() == test_stat_val + assert s.Count() == test_stat_count + + monster_reponses = stub.Retrieve(stat_response) + count = 0 + for monster_reponse in monster_reponses: + m = Monster.Monster().GetRootAsMonster(monster_reponse, 0) + assert m.Name().decode("utf-8") == test_monsters_name_retrieve[count] + count = count + 1 + + +if __name__ == "__main__": + serve() diff --git a/third_party/flatbuffers/grpc/tests/grpctest_callback_client_compile.cpp b/third_party/flatbuffers/grpc/tests/grpctest_callback_client_compile.cpp new file mode 100644 index 00000000000..b3947ee974e --- /dev/null +++ b/third_party/flatbuffers/grpc/tests/grpctest_callback_client_compile.cpp @@ -0,0 +1,60 @@ +// Verifies that the generated gRPC callback client stub methods are present. +// This is a compile-time only test: it never performs an actual RPC. +// It supplements grpctest_callback_compile.cpp (server side) by checking +// client-side async_ / reactor entry points. + +#include + +#include "monster_test.grpc.fb.h" + +#if defined(FLATBUFFERS_GENERATED_GRPC_CALLBACK_API) && \ + defined(GRPC_CALLBACK_API_NONEXPERIMENTAL) +using Stub = MyGame::Example::MonsterStorage::Stub; +using namespace MyGame::Example; // NOLINT + +// Unary async overloads +static_assert(std::is_member_function_pointer< + decltype(static_cast&, + flatbuffers::grpc::Message*, + std::function)>( + &Stub::async_Store))>::value, + "Function-form unary async_Store missing"); +static_assert( + std::is_member_function_pointer< + decltype(static_cast&, + flatbuffers::grpc::Message*, + ::grpc::ClientUnaryReactor*)>(&Stub::async_Store))>::value, + "Reactor-form unary async_Store missing"); + +// Streaming reactor entry points +static_assert( + std::is_member_function_pointer< + decltype(static_cast&, + ::grpc::ClientReadReactor >*)>(&Stub::async_Retrieve))>::value, + "Server streaming reactor async_Retrieve missing"); +static_assert( + std::is_member_function_pointer< + decltype(static_cast*, + ::grpc::ClientWriteReactor >*)>(&Stub::async_GetMaxHitPoint))>::value, + "Client streaming reactor async_GetMaxHitPoint missing"); +static_assert(std::is_member_function_pointer< + decltype(static_cast, + flatbuffers::grpc::Message >*)>( + &Stub::async_GetMinMaxHitPoints))>::value, + "Bidi streaming reactor async_GetMinMaxHitPoints missing"); +#endif // FLATBUFFERS_GENERATED_GRPC_CALLBACK_API && + // GRPC_CALLBACK_API_NONEXPERIMENTAL + +int main() { return 0; } diff --git a/third_party/flatbuffers/grpc/tests/grpctest_callback_compile.cpp b/third_party/flatbuffers/grpc/tests/grpctest_callback_compile.cpp new file mode 100644 index 00000000000..d65186a4238 --- /dev/null +++ b/third_party/flatbuffers/grpc/tests/grpctest_callback_compile.cpp @@ -0,0 +1,22 @@ +#include "monster_test.grpc.fb.h" + +// This test only verifies that the generated CallbackService compiles when the +// callback API is available. It does not run any RPCs. + +#if defined(FLATBUFFERS_GENERATED_GRPC_CALLBACK_API) && \ + defined(GRPC_CALLBACK_API_NONEXPERIMENTAL) +class CallbackServiceImpl + : public MyGame::Example::MonsterStorage::CallbackService { + public: + // For brevity we don't override methods; user code will provide reactors. +}; +#endif + +int main() { +#if defined(FLATBUFFERS_GENERATED_GRPC_CALLBACK_API) && \ + defined(GRPC_CALLBACK_API_NONEXPERIMENTAL) + CallbackServiceImpl svc; + (void)svc; // suppress unused +#endif + return 0; +} diff --git a/third_party/flatbuffers/grpc/tests/message_builder_test.cpp b/third_party/flatbuffers/grpc/tests/message_builder_test.cpp index 8af0c2141b9..cdaf7cb7da5 100644 --- a/third_party/flatbuffers/grpc/tests/message_builder_test.cpp +++ b/third_party/flatbuffers/grpc/tests/message_builder_test.cpp @@ -7,9 +7,9 @@ using MyGame::Example::Any_NONE; using MyGame::Example::CreateStat; using MyGame::Example::Vec3; -bool verify(flatbuffers::grpc::Message &msg, - const std::string &expected_name, Color expected_color) { - const Monster *monster = msg.GetRoot(); +bool verify(flatbuffers::grpc::Message& msg, + const std::string& expected_name, Color expected_color) { + const Monster* monster = msg.GetRoot(); const auto name = monster->name()->str(); const auto color = monster->color(); TEST_EQ(name, expected_name); @@ -17,8 +17,8 @@ bool verify(flatbuffers::grpc::Message &msg, return (name == expected_name) && (color == expected_color); } -bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb, - const std::string &expected_name, Color expected_color) { +bool release_n_verify(flatbuffers::grpc::MessageBuilder& mbb, + const std::string& expected_name, Color expected_color) { flatbuffers::grpc::Message msg = mbb.ReleaseMessage(); return verify(msg, expected_name, expected_color); } @@ -41,11 +41,13 @@ void builder_move_assign_after_releaseraw_test( TEST_EQ(src.GetSize(), 0); } -template +template struct BuilderReuseTests { static void builder_reusable_after_release_message_test( TestSelector selector) { - if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) { return; } + if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) { + return; + } flatbuffers::grpc::MessageBuilder mb; std::vector> buffers; @@ -58,7 +60,9 @@ struct BuilderReuseTests { } static void builder_reusable_after_release_test(TestSelector selector) { - if (!selector.count(REUSABLE_AFTER_RELEASE)) { return; } + if (!selector.count(REUSABLE_AFTER_RELEASE)) { + return; + } // FIXME: Populate-Release loop fails assert(GRPC_SLICE_IS_EMPTY(slice_)) in // SliceAllocator::allocate in the second iteration. @@ -74,7 +78,9 @@ struct BuilderReuseTests { } static void builder_reusable_after_releaseraw_test(TestSelector selector) { - if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) { return; } + if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) { + return; + } flatbuffers::grpc::MessageBuilder mb; for (int i = 0; i < 5; ++i) { @@ -82,14 +88,16 @@ struct BuilderReuseTests { mb.Finish(root_offset1); size_t size, offset; ::grpc::Slice slice; - const uint8_t *buf = mb.ReleaseRaw(size, offset, slice); + const uint8_t* buf = mb.ReleaseRaw(size, offset, slice); TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color())); } } static void builder_reusable_after_release_and_move_assign_test( TestSelector selector) { - if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) { return; } + if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) { + return; + } // FIXME: Release-move_assign loop fails assert(p == // GRPC_SLICE_START_PTR(slice_)) in DetachedBuffer destructor after all the @@ -137,7 +145,9 @@ struct BuilderReuseTests { static void builder_reusable_after_releaseraw_and_move_assign_test( TestSelector selector) { - if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) { return; } + if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) { + return; + } flatbuffers::grpc::MessageBuilder dst; for (int i = 0; i < 5; ++i) { @@ -145,7 +155,7 @@ struct BuilderReuseTests { dst.Finish(root_offset1); size_t size, offset; ::grpc::Slice slice; - const uint8_t *buf = dst.ReleaseRaw(size, offset, slice); + const uint8_t* buf = dst.ReleaseRaw(size, offset, slice); TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color())); SrcBuilder src; @@ -170,7 +180,7 @@ void slice_allocator_tests() { { size_t size = 2048; flatbuffers::grpc::SliceAllocator sa1; - uint8_t *buf = sa1.allocate(size); + uint8_t* buf = sa1.allocate(size); TEST_ASSERT_FUNC(buf != 0); buf[0] = 100; buf[size - 1] = 200; @@ -184,7 +194,7 @@ void slice_allocator_tests() { // move-assign test { flatbuffers::grpc::SliceAllocator sa1, sa2; - uint8_t *buf = sa1.allocate(2048); + uint8_t* buf = sa1.allocate(2048); sa1 = std::move(sa2); // sa1 deletes previously allocated memory in move-assign. // So buf is no longer usable here. @@ -194,7 +204,7 @@ void slice_allocator_tests() { /// This function does not populate exactly the first half of the table. But it /// could. -void populate_first_half(MyGame::Example::MonsterBuilder &wrapper, +void populate_first_half(MyGame::Example::MonsterBuilder& wrapper, flatbuffers::Offset name_offset) { wrapper.add_name(name_offset); wrapper.add_color(m1_color()); @@ -202,7 +212,7 @@ void populate_first_half(MyGame::Example::MonsterBuilder &wrapper, /// This function does not populate exactly the second half of the table. But it /// could. -void populate_second_half(MyGame::Example::MonsterBuilder &wrapper) { +void populate_second_half(MyGame::Example::MonsterBuilder& wrapper) { wrapper.add_hp(77); wrapper.add_mana(88); Vec3 vec3; @@ -216,9 +226,9 @@ void populate_second_half(MyGame::Example::MonsterBuilder &wrapper) { /// between FlatBufferBuilders. If MonsterBuilder had a fbb_ pointer, this hack /// would be unnecessary. That involves a code-generator change though. void test_only_hack_update_fbb_reference( - MyGame::Example::MonsterBuilder &monsterBuilder, - flatbuffers::grpc::MessageBuilder &mb) { - *reinterpret_cast(&monsterBuilder) = &mb; + MyGame::Example::MonsterBuilder& monsterBuilder, + flatbuffers::grpc::MessageBuilder& mb) { + *reinterpret_cast(&monsterBuilder) = &mb; } /// This test validates correctness of move conversion of FlatBufferBuilder to a @@ -351,15 +361,14 @@ void message_builder_tests() { BuilderTests::all_tests(); BuilderReuseTestSelector tests[6] = { - // REUSABLE_AFTER_RELEASE, // Assertion failed: - // (GRPC_SLICE_IS_EMPTY(slice_)) - // REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN, // Assertion failed: (p == - // GRPC_SLICE_START_PTR(slice_) - - REUSABLE_AFTER_RELEASE_RAW, REUSABLE_AFTER_RELEASE_MESSAGE, - REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN, - REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN - }; + // REUSABLE_AFTER_RELEASE, // Assertion failed: + // (GRPC_SLICE_IS_EMPTY(slice_)) + // REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN, // Assertion failed: (p == + // GRPC_SLICE_START_PTR(slice_) + + REUSABLE_AFTER_RELEASE_RAW, REUSABLE_AFTER_RELEASE_MESSAGE, + REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN, + REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN}; BuilderReuseTests::run_tests( TestSelector(tests, tests + 6)); diff --git a/third_party/flatbuffers/include/codegen/BUILD.bazel b/third_party/flatbuffers/include/codegen/BUILD.bazel new file mode 100644 index 00000000000..196181b411b --- /dev/null +++ b/third_party/flatbuffers/include/codegen/BUILD.bazel @@ -0,0 +1,39 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") + +package( + default_visibility = ["//visibility:private"], +) + +filegroup( + name = "distribution", + srcs = [ + "BUILD.bazel", + ] + glob([ + "*.cc", + "*.h", + ]), + visibility = ["//visibility:public"], +) + +cc_library( + name = "namer", + hdrs = [ + "idl_namer.h", + "namer.h", + ], + strip_include_prefix = "/include", + visibility = ["//:__subpackages__"], + deps = ["//:runtime_cc"], +) + +cc_library( + name = "python", + srcs = ["python.cc"], + hdrs = ["python.h"], + strip_include_prefix = "/include", + visibility = [ + "//grpc:__subpackages__", + "//src:__subpackages__", + ], + deps = [":namer"], +) diff --git a/third_party/flatbuffers/include/codegen/idl_namer.h b/third_party/flatbuffers/include/codegen/idl_namer.h new file mode 100644 index 00000000000..2aa716ed386 --- /dev/null +++ b/third_party/flatbuffers/include/codegen/idl_namer.h @@ -0,0 +1,181 @@ +#ifndef FLATBUFFERS_INCLUDE_CODEGEN_IDL_NAMER_H_ +#define FLATBUFFERS_INCLUDE_CODEGEN_IDL_NAMER_H_ + +#include "codegen/namer.h" +#include "flatbuffers/idl.h" + +namespace flatbuffers { + +// Provides Namer capabilities to types defined in the flatbuffers IDL. +class IdlNamer : public Namer { + public: + explicit IdlNamer(Config config, std::set keywords) + : Namer(config, std::move(keywords)) {} + + using Namer::Constant; + using Namer::Directories; + using Namer::Field; + using Namer::File; + using Namer::Function; + using Namer::Method; + using Namer::Namespace; + using Namer::NamespacedType; + using Namer::ObjectType; + using Namer::Type; + using Namer::Variable; + using Namer::Variant; + + std::string Constant(const FieldDef& d) const { return Constant(d.name); } + + // Types are always structs or enums so we can only expose these two + // overloads. + std::string Type(const StructDef& d) const { return Type(d.name); } + std::string Type(const EnumDef& d) const { return Type(d.name); } + + std::string Function(const Definition& s) const { return Function(s.name); } + std::string Function(const std::string& prefix, const Definition& s) const { + return Function(prefix + s.name); + } + + std::string Field(const FieldDef& s) const { return Field(s.name); } + std::string Field(const FieldDef& d, const std::string& s) const { + return Field(d.name + "_" + s); + } + + std::string Variable(const FieldDef& s) const { return Variable(s.name); } + + std::string Variable(const StructDef& s) const { return Variable(s.name); } + + std::string Variant(const EnumVal& s) const { return Variant(s.name); } + + std::string EnumVariant(const EnumDef& e, const EnumVal& v) const { + return Type(e) + config_.enum_variant_seperator + Variant(v); + } + + std::string ObjectType(const StructDef& d) const { + return ObjectType(d.name); + } + std::string ObjectType(const EnumDef& d) const { return ObjectType(d.name); } + + std::string Method(const FieldDef& d, const std::string& suffix) const { + return Method(d.name, suffix); + } + std::string Method(const std::string& prefix, const StructDef& d) const { + return Method(prefix, d.name); + } + std::string Method(const std::string& prefix, const FieldDef& d) const { + return Method(prefix, d.name); + } + std::string Method(const std::string& prefix, const FieldDef& d, + const std::string& suffix) const { + return Method(prefix, d.name, suffix); + } + + std::string Namespace(const struct Namespace& ns) const { + return Namespace(ns.components); + } + + std::string NamespacedEnumVariant(const EnumDef& e, const EnumVal& v) const { + return NamespacedString(e.defined_namespace, EnumVariant(e, v)); + } + + std::string NamespacedType(const Definition& def) const { + return NamespacedString(def.defined_namespace, Type(def.name)); + } + + std::string NamespacedObjectType(const Definition& def) const { + return NamespacedString(def.defined_namespace, ObjectType(def.name)); + } + + std::string Directories(const struct Namespace& ns, + SkipDir skips = SkipDir::None, + Case input_case = Case::kUpperCamel) const { + return Directories(ns.components, skips, input_case); + } + + // Legacy fields do not really follow the usual config and should be + // considered for deprecation. + + std::string LegacyRustNativeVariant(const EnumVal& v) const { + return ConvertCase(EscapeKeyword(v.name), Case::kUpperCamel); + } + + std::string LegacyRustFieldOffsetName(const FieldDef& field) const { + return "VT_" + ConvertCase(EscapeKeyword(field.name), Case::kAllUpper); + } + std::string LegacyRustUnionTypeOffsetName(const FieldDef& field) const { + return "VT_" + + ConvertCase(EscapeKeyword(field.name + "_type"), Case::kAllUpper); + } + + std::string LegacySwiftVariant(const EnumVal& ev) const { + auto name = ev.name; + if (isupper(name.front())) { + std::transform(name.begin(), name.end(), name.begin(), CharToLower); + } + return EscapeKeyword(ConvertCase(name, Case::kLowerCamel)); + } + + // Also used by Kotlin, lol. + std::string LegacyJavaMethod2(const std::string& prefix, const StructDef& sd, + const std::string& suffix) const { + return prefix + sd.name + suffix; + } + + std::string LegacyKotlinVariant(EnumVal& ev) const { + // Namer assumes the input case is snake case which is wrong... + return ConvertCase(EscapeKeyword(ev.name), Case::kLowerCamel); + } + // Kotlin methods escapes keywords after case conversion but before + // prefixing and suffixing. + std::string LegacyKotlinMethod(const std::string& prefix, const FieldDef& d, + const std::string& suffix) const { + return prefix + ConvertCase(EscapeKeyword(d.name), Case::kUpperCamel) + + suffix; + } + std::string LegacyKotlinMethod(const std::string& prefix, const StructDef& d, + const std::string& suffix) const { + return prefix + ConvertCase(EscapeKeyword(d.name), Case::kUpperCamel) + + suffix; + } + + // This is a mix of snake case and keep casing, when Ts should be using + // lower camel case. + std::string LegacyTsMutateMethod(const FieldDef& d) { + return "mutate_" + d.name; + } + + std::string LegacyRustUnionTypeMethod(const FieldDef& d) { + // assert d is a union + // d should convert case but not escape keywords due to historical reasons + return ConvertCase(d.name, config_.fields, Case::kLowerCamel) + "_type"; + } + + private: + std::string NamespacedString(const struct Namespace* ns, + const std::string& str) const { + std::string ret; + if (ns != nullptr) { + ret += Namespace(ns->components); + } + if (!ret.empty()) ret += config_.namespace_seperator; + return ret + str; + } +}; + +// This is a temporary helper function for code generators to call until all +// flag-overriding logic into flatc.cpp +inline Namer::Config WithFlagOptions(const Namer::Config& input, + const IDLOptions& opts, + const std::string& path) { + Namer::Config result = input; + result.object_prefix = opts.object_prefix; + result.object_suffix = opts.object_suffix; + result.output_path = path; + result.filename_suffix = opts.filename_suffix; + return result; +} + +} // namespace flatbuffers + +#endif // FLATBUFFERS_INCLUDE_CODEGEN_IDL_NAMER_H_ diff --git a/third_party/flatbuffers/include/codegen/namer.h b/third_party/flatbuffers/include/codegen/namer.h new file mode 100644 index 00000000000..e99bf744c39 --- /dev/null +++ b/third_party/flatbuffers/include/codegen/namer.h @@ -0,0 +1,270 @@ +#ifndef FLATBUFFERS_INCLUDE_CODEGEN_NAMER_H_ +#define FLATBUFFERS_INCLUDE_CODEGEN_NAMER_H_ + +#include "flatbuffers/util.h" + +namespace flatbuffers { + +// Options for Namer::File. +enum class SkipFile { + None = 0, + Suffix = 1, + Extension = 2, + SuffixAndExtension = 3, +}; +inline SkipFile operator&(SkipFile a, SkipFile b) { + return static_cast(static_cast(a) & static_cast(b)); +} +// Options for Namer::Directories +enum class SkipDir { + None = 0, + // Skip prefixing the -o $output_path. + OutputPath = 1, + // Skip trailing path seperator. + TrailingPathSeperator = 2, + OutputPathAndTrailingPathSeparator = 3, +}; +inline SkipDir operator&(SkipDir a, SkipDir b) { + return static_cast(static_cast(a) & static_cast(b)); +} + +// `Namer` applies style configuration to symbols in generated code. It manages +// casing, escapes keywords, and object API naming. +// TODO: Refactor all code generators to use this. +class Namer { + public: + struct Config { + // Symbols in code. + + // Case style for flatbuffers-defined types. + // e.g. `class TableA {}` + Case types; + // Case style for flatbuffers-defined constants. + // e.g. `uint64_t ENUM_A_MAX`; + Case constants; + // Case style for flatbuffers-defined methods. + // e.g. `class TableA { int field_a(); }` + Case methods; + // Case style for flatbuffers-defined functions. + // e.g. `TableA* get_table_a_root()`; + Case functions; + // Case style for flatbuffers-defined fields. + // e.g. `struct Struct { int my_field; }` + Case fields; + // Case style for flatbuffers-defined variables. + // e.g. `int my_variable = 2` + Case variables; + // Case style for flatbuffers-defined variants. + // e.g. `enum class Enum { MyVariant, }` + Case variants; + // Seperator for qualified enum names. + // e.g. `Enum::MyVariant` uses `::`. + std::string enum_variant_seperator; + + // Configures, when formatting code, whether symbols are checked against + // keywords and escaped before or after case conversion. It does not make + // sense to do so before, but its legacy behavior. :shrug: + // TODO(caspern): Deprecate. + enum class Escape { + BeforeConvertingCase, + AfterConvertingCase, + }; + Escape escape_keywords; + + // Namespaces + + // e.g. `namespace my_namespace {}` + Case namespaces; + // The seperator between namespaces in a namespace path. + std::string namespace_seperator; + + // Object API. + // Native versions flatbuffers types have this prefix. + // e.g. "" (it's usually empty string) + std::string object_prefix; + // Native versions flatbuffers types have this suffix. + // e.g. "T" + std::string object_suffix; + + // Keywords. + // Prefix used to escape keywords. It is usually empty string. + std::string keyword_prefix; + // Suffix used to escape keywords. It is usually "_". + std::string keyword_suffix; + + // Files. + + // Case style for filenames. e.g. `foo_bar_generated.rs` + Case filenames; + // Case style for directories, e.g. `output_files/foo_bar/baz/` + Case directories; + // The directory within which we will generate files. + std::string output_path; + // Suffix for generated file names, e.g. "_generated". + std::string filename_suffix; + // Extension for generated files, e.g. ".cpp" or ".rs". + std::string filename_extension; + }; + Namer(Config config, std::set keywords) + : config_(config), keywords_(std::move(keywords)) {} + + virtual ~Namer() {} + + template + std::string Method(const T& s) const { + return Method(s.name); + } + + virtual std::string Method(const std::string& pre, const std::string& mid, + const std::string& suf) const { + return Format(pre + "_" + mid + "_" + suf, config_.methods); + } + virtual std::string Method(const std::string& pre, + const std::string& suf) const { + return Format(pre + "_" + suf, config_.methods); + } + virtual std::string Method(const std::string& s) const { + return Format(s, config_.methods); + } + + virtual std::string Constant(const std::string& s) const { + return Format(s, config_.constants); + } + + virtual std::string Function(const std::string& s) const { + return Format(s, config_.functions); + } + + virtual std::string Variable(const std::string& s) const { + return Format(s, config_.variables); + } + + template + std::string Variable(const std::string& p, const T& s) const { + return Format(p + "_" + s.name, config_.variables); + } + virtual std::string Variable(const std::string& p, + const std::string& s) const { + return Format(p + "_" + s, config_.variables); + } + + virtual std::string Namespace(const std::string& s) const { + return Format(s, config_.namespaces); + } + + virtual std::string Namespace(const std::vector& ns) const { + std::string result; + for (auto it = ns.begin(); it != ns.end(); it++) { + if (it != ns.begin()) result += config_.namespace_seperator; + result += Namespace(*it); + } + return result; + } + + virtual std::string NamespacedType(const std::vector& ns, + const std::string& s) const { + return (ns.empty() ? "" : (Namespace(ns) + config_.namespace_seperator)) + + Type(s); + } + + // Returns `filename` with the right casing, suffix, and extension. + virtual std::string File(const std::string& filename, + SkipFile skips = SkipFile::None) const { + const bool skip_suffix = (skips & SkipFile::Suffix) != SkipFile::None; + const bool skip_ext = (skips & SkipFile::Extension) != SkipFile::None; + return ConvertCase(filename, config_.filenames, Case::kUpperCamel) + + (skip_suffix ? "" : config_.filename_suffix) + + (skip_ext ? "" : config_.filename_extension); + } + template + std::string File(const T& f, SkipFile skips = SkipFile::None) const { + return File(f.name, skips); + } + + // Formats `directories` prefixed with the output_path and joined with the + // right seperator. Output path prefixing and the trailing separator may be + // skiped using `skips`. + // Callers may want to use `EnsureDirExists` with the result. + // input_case is used to tell how to modify namespace. e.g. kUpperCamel will + // add a underscode between case changes, so MyGame turns into My_Game + // (depending also on the output_case). + virtual std::string Directories(const std::vector& directories, + SkipDir skips = SkipDir::None, + Case input_case = Case::kUpperCamel) const { + const bool skip_output_path = + (skips & SkipDir::OutputPath) != SkipDir::None; + const bool skip_trailing_seperator = + (skips & SkipDir::TrailingPathSeperator) != SkipDir::None; + std::string result = skip_output_path ? "" : config_.output_path; + for (auto d = directories.begin(); d != directories.end(); d++) { + result += ConvertCase(*d, config_.directories, input_case); + result.push_back(kPathSeparator); + } + if (skip_trailing_seperator && !result.empty()) result.pop_back(); + return result; + } + + virtual std::string EscapeKeyword(const std::string& name) const { + if (keywords_.find(name) == keywords_.end()) { + return name; + } else { + return config_.keyword_prefix + name + config_.keyword_suffix; + } + } + + virtual std::string Type(const std::string& s) const { + return Format(s, config_.types); + } + virtual std::string Type(const std::string& t, const std::string& s) const { + return Format(t + "_" + s, config_.types); + } + + virtual std::string ObjectType(const std::string& s) const { + return config_.object_prefix + Type(s) + config_.object_suffix; + } + + virtual std::string Field(const std::string& s) const { + return Format(s, config_.fields); + } + + virtual std::string Variant(const std::string& s) const { + return Format(s, config_.variants); + } + + virtual std::string Format(const std::string& s, Case casing) const { + if (config_.escape_keywords == Config::Escape::BeforeConvertingCase) { + return ConvertCase(EscapeKeyword(s), casing, Case::kLowerCamel); + } else { + return EscapeKeyword(ConvertCase(s, casing, Case::kLowerCamel)); + } + } + + // Denamespaces a string (e.g. The.Quick.Brown.Fox) by returning the last part + // after the `delimiter` (Fox) and placing the rest in `namespace_prefix` + // (The.Quick.Brown). + virtual std::string Denamespace(const std::string& s, + std::string& namespace_prefix, + const char delimiter = '.') const { + const size_t pos = s.find_last_of(delimiter); + if (pos == std::string::npos) { + namespace_prefix = ""; + return s; + } + namespace_prefix = s.substr(0, pos); + return s.substr(pos + 1); + } + + // Same as above, but disregards the prefix. + virtual std::string Denamespace(const std::string& s, + const char delimiter = '.') const { + std::string prefix; + return Denamespace(s, prefix, delimiter); + } + + const Config config_; + const std::set keywords_; +}; + +} // namespace flatbuffers + +#endif // FLATBUFFERS_INCLUDE_CODEGEN_NAMER_H_ diff --git a/third_party/flatbuffers/include/codegen/python.cc b/third_party/flatbuffers/include/codegen/python.cc new file mode 100644 index 00000000000..3225371766e --- /dev/null +++ b/third_party/flatbuffers/include/codegen/python.cc @@ -0,0 +1,79 @@ +#include "codegen/python.h" + +#include +#include +#include +#include + +namespace flatbuffers { +namespace python { +Version::Version(const std::string& version) { + std::stringstream ss(version); + char dot; + ss >> major >> dot >> minor >> dot >> micro; +} + +bool Version::IsValid() const { + return (major == 0 || major == 2 || major == 3) && minor >= 0 && micro >= 0; +} + +std::set Keywords(const Version& version) { + switch (version.major) { + case 2: + // https://docs.python.org/2/reference/lexical_analysis.html#keywords + return { + "and", "as", "assert", "break", "class", "continue", "def", + "del", "elif", "else", "except", "exec", "finally", "for", + "from", "global", "if", "import", "in", "is", "lambda", + "not", "or", "pass", "print", "raise", "return", "try", + "while", "with", "yield", + }; + case 0: + case 3: + // https://docs.python.org/3/reference/lexical_analysis.html#keywords + return { + "and", "as", "assert", "async", "await", "break", + "class", "continue", "def", "del", "elif", "else", + "except", "False", "finally", "for", "from", "global", + "if", "import", "in", "is", "lambda", "None", + "nonlocal", "not", "or", "pass", "raise", "return", + "True", "try", "while", "with", "yield", + }; + default: + return {}; + } +} + +const python::Import& python::Imports::Import(const std::string& module) { + python::Import import; + import.module = module; + imports.push_back(std::move(import)); + return imports.back(); +} + +const python::Import& python::Imports::Import(const std::string& module, + const std::string& name) { + python::Import import; + import.module = module; + import.name = name; + imports.push_back(std::move(import)); + return imports.back(); +} + +const python::Import& python::Imports::Export(const std::string& module) { + python::Import import; + import.module = module; + exports.push_back(std::move(import)); + return exports.back(); +} + +const python::Import& python::Imports::Export(const std::string& module, + const std::string& name) { + python::Import import; + import.module = module; + import.name = name; + exports.push_back(std::move(import)); + return exports.back(); +} +} // namespace python +} // namespace flatbuffers diff --git a/third_party/flatbuffers/include/codegen/python.h b/third_party/flatbuffers/include/codegen/python.h new file mode 100644 index 00000000000..cc6c241f2d6 --- /dev/null +++ b/third_party/flatbuffers/include/codegen/python.h @@ -0,0 +1,98 @@ +#ifndef FLATBUFFERS_INCLUDE_CODEGEN_PYTHON_H_ +#define FLATBUFFERS_INCLUDE_CODEGEN_PYTHON_H_ + +#include +#include +#include +#include + +#include "codegen/namer.h" + +namespace flatbuffers { +namespace python { +static const Namer::Config kConfig = { + /*types=*/Case::kKeep, + /*constants=*/Case::kScreamingSnake, + /*methods=*/Case::kUpperCamel, + /*functions=*/Case::kUpperCamel, + /*fields=*/Case::kLowerCamel, + /*variable=*/Case::kLowerCamel, + /*variants=*/Case::kKeep, + /*enum_variant_seperator=*/".", + /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase, + /*namespaces=*/Case::kKeep, // Packages in python. + /*namespace_seperator=*/".", + /*object_prefix=*/"", + /*object_suffix=*/"T", + /*keyword_prefix=*/"", + /*keyword_suffix=*/"_", + /*filenames=*/Case::kKeep, + /*directories=*/Case::kKeep, + /*output_path=*/"", + /*filename_suffix=*/"", + /*filename_extension=*/".py", +}; + +static const Namer::Config kStubConfig = { + /*types=*/Case::kKeep, + /*constants=*/Case::kScreamingSnake, + /*methods=*/Case::kUpperCamel, + /*functions=*/Case::kUpperCamel, + /*fields=*/Case::kLowerCamel, + /*variables=*/Case::kLowerCamel, + /*variants=*/Case::kKeep, + /*enum_variant_seperator=*/".", + /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase, + /*namespaces=*/Case::kKeep, // Packages in python. + /*namespace_seperator=*/".", + /*object_prefix=*/"", + /*object_suffix=*/"T", + /*keyword_prefix=*/"", + /*keyword_suffix=*/"_", + /*filenames=*/Case::kKeep, + /*directories=*/Case::kKeep, + /*output_path=*/"", + /*filename_suffix=*/"", + /*filename_extension=*/".pyi", +}; + +// `Version` represent a Python version. +// +// The zero value (i.e. `Version{}`) represents both Python2 and Python3. +// +// https://docs.python.org/3/faq/general.html#how-does-the-python-version-numbering-scheme-work +struct Version { + explicit Version(const std::string& version); + + bool IsValid() const; + + int16_t major = 0; + int16_t minor = 0; + int16_t micro = 0; +}; + +std::set Keywords(const Version& version); + +struct Import { + bool IsLocal() const { return module == "."; } + + std::string module; + std::string name; +}; + +struct Imports { + const python::Import& Import(const std::string& module); + const python::Import& Import(const std::string& module, + const std::string& name); + + const python::Import& Export(const std::string& module); + const python::Import& Export(const std::string& module, + const std::string& name); + + std::vector imports; + std::vector exports; +}; +} // namespace python +} // namespace flatbuffers + +#endif // FLATBUFFERS_INCLUDE_CODEGEN_PYTHON_H_ diff --git a/third_party/flatbuffers/include/flatbuffers/allocator.h b/third_party/flatbuffers/include/flatbuffers/allocator.h index 30427190b6c..d451818568a 100644 --- a/third_party/flatbuffers/include/flatbuffers/allocator.h +++ b/third_party/flatbuffers/include/flatbuffers/allocator.h @@ -28,21 +28,21 @@ class Allocator { virtual ~Allocator() {} // Allocate `size` bytes of memory. - virtual uint8_t *allocate(size_t size) = 0; + virtual uint8_t* allocate(size_t size) = 0; // Deallocate `size` bytes of memory at `p` allocated by this allocator. - virtual void deallocate(uint8_t *p, size_t size) = 0; + virtual void deallocate(uint8_t* p, size_t size) = 0; // Reallocate `new_size` bytes of memory, replacing the old region of size // `old_size` at `p`. In contrast to a normal realloc, this grows downwards, // and is intended specifcally for `vector_downward` use. // `in_use_back` and `in_use_front` indicate how much of `old_size` is // actually in use at each end, and needs to be copied. - virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size, + virtual uint8_t* reallocate_downward(uint8_t* old_p, size_t old_size, size_t new_size, size_t in_use_back, size_t in_use_front) { FLATBUFFERS_ASSERT(new_size > old_size); // vector_downward only grows - uint8_t *new_p = allocate(new_size); + uint8_t* new_p = allocate(new_size); memcpy_downward(old_p, old_size, new_p, new_size, in_use_back, in_use_front); deallocate(old_p, old_size); @@ -54,7 +54,7 @@ class Allocator { // to `new_p` of `new_size`. Only memory of size `in_use_front` and // `in_use_back` will be copied from the front and back of the old memory // allocation. - void memcpy_downward(uint8_t *old_p, size_t old_size, uint8_t *new_p, + void memcpy_downward(uint8_t* old_p, size_t old_size, uint8_t* new_p, size_t new_size, size_t in_use_back, size_t in_use_front) { memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back, diff --git a/third_party/flatbuffers/include/flatbuffers/array.h b/third_party/flatbuffers/include/flatbuffers/array.h index f4bfbf054c4..914f479aab7 100644 --- a/third_party/flatbuffers/include/flatbuffers/array.h +++ b/third_party/flatbuffers/include/flatbuffers/array.h @@ -27,17 +27,15 @@ namespace flatbuffers { // This is used as a helper type for accessing arrays. -template class Array { +template +class Array { // Array can carry only POD data types (scalars or structs). typedef typename flatbuffers::bool_constant::value> scalar_tag; - typedef - typename flatbuffers::conditional::type - IndirectHelperType; public: typedef uint16_t size_type; - typedef typename IndirectHelper::return_type return_type; + typedef typename IndirectHelper::return_type return_type; typedef VectorConstIterator const_iterator; typedef VectorReverseIterator const_reverse_iterator; @@ -50,7 +48,7 @@ template class Array { return_type Get(uoffset_t i) const { FLATBUFFERS_ASSERT(i < size()); - return IndirectHelper::Read(Data(), i); + return IndirectHelper::Read(Data(), i); } return_type operator[](uoffset_t i) const { return Get(i); } @@ -58,7 +56,8 @@ template class Array { // If this is a Vector of enums, T will be its storage type, not the enum // type. This function makes it convenient to retrieve value with enum // type E. - template E GetEnum(uoffset_t i) const { + template + E GetEnum(uoffset_t i) const { return static_cast(Get(i)); } @@ -83,28 +82,28 @@ template class Array { // operation. For primitive types use @p Mutate directly. // @warning Assignments and reads to/from the dereferenced pointer are not // automatically converted to the correct endianness. - typename flatbuffers::conditional::type + typename flatbuffers::conditional::type GetMutablePointer(uoffset_t i) const { FLATBUFFERS_ASSERT(i < size()); - return const_cast(&data()[i]); + return const_cast(&data()[i]); } // Change elements if you have a non-const pointer to this object. - void Mutate(uoffset_t i, const T &val) { MutateImpl(scalar_tag(), i, val); } + void Mutate(uoffset_t i, const T& val) { MutateImpl(scalar_tag(), i, val); } // The raw data in little endian format. Use with care. - const uint8_t *Data() const { return data_; } + const uint8_t* Data() const { return data_; } - uint8_t *Data() { return data_; } + uint8_t* Data() { return data_; } // Similarly, but typed, much like std::vector::data - const T *data() const { return reinterpret_cast(Data()); } - T *data() { return reinterpret_cast(Data()); } + const T* data() const { return reinterpret_cast(Data()); } + T* data() { return reinterpret_cast(Data()); } // Copy data from a span with endian conversion. // If this Array and the span overlap, the behavior is undefined. void CopyFromSpan(flatbuffers::span src) { - const auto p1 = reinterpret_cast(src.data()); + const auto p1 = reinterpret_cast(src.data()); const auto p2 = Data(); FLATBUFFERS_ASSERT(!(p1 >= p2 && p1 < (p2 + length)) && !(p2 >= p1 && p2 < (p1 + length))); @@ -114,12 +113,12 @@ template class Array { } protected: - void MutateImpl(flatbuffers::true_type, uoffset_t i, const T &val) { + void MutateImpl(flatbuffers::true_type, uoffset_t i, const T& val) { FLATBUFFERS_ASSERT(i < size()); WriteScalar(data() + i, val); } - void MutateImpl(flatbuffers::false_type, uoffset_t i, const T &val) { + void MutateImpl(flatbuffers::false_type, uoffset_t i, const T& val) { *(GetMutablePointer(i)) = val; } @@ -134,7 +133,9 @@ template class Array { // Copy data from flatbuffers::span with endian conversion. void CopyFromSpanImpl(flatbuffers::false_type, flatbuffers::span src) { - for (size_type k = 0; k < length; k++) { Mutate(k, src[k]); } + for (size_type k = 0; k < length; k++) { + Mutate(k, src[k]); + } } // This class is only used to access pre-existing data. Don't ever @@ -153,21 +154,21 @@ template class Array { private: // This class is a pointer. Copying will therefore create an invalid object. // Private and unimplemented copy constructor. - Array(const Array &); - Array &operator=(const Array &); + Array(const Array&); + Array& operator=(const Array&); }; // Specialization for Array[struct] with access using Offset pointer. // This specialization used by idl_gen_text.cpp. -template class OffsetT> +template class OffsetT> class Array, length> { static_assert(flatbuffers::is_same::value, "unexpected type T"); public: - typedef const void *return_type; + typedef const void* return_type; typedef uint16_t size_type; - const uint8_t *Data() const { return data_; } + const uint8_t* Data() const { return data_; } // Make idl_gen_text.cpp::PrintContainer happy. return_type operator[](uoffset_t) const { @@ -178,14 +179,14 @@ class Array, length> { private: // This class is only used to access pre-existing data. Array(); - Array(const Array &); - Array &operator=(const Array &); + Array(const Array&); + Array& operator=(const Array&); uint8_t data_[1]; }; -template -FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_span(Array &arr) +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_span(Array& arr) FLATBUFFERS_NOEXCEPT { static_assert( Array::is_span_observable, @@ -193,26 +194,26 @@ FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_span(Array &arr) return span(arr.data(), N); } -template +template FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_span( - const Array &arr) FLATBUFFERS_NOEXCEPT { + const Array& arr) FLATBUFFERS_NOEXCEPT { static_assert( Array::is_span_observable, "wrong type U, only plain struct, LE-scalar, or byte types are allowed"); return span(arr.data(), N); } -template +template FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span -make_bytes_span(Array &arr) FLATBUFFERS_NOEXCEPT { +make_bytes_span(Array& arr) FLATBUFFERS_NOEXCEPT { static_assert(Array::is_span_observable, "internal error, Array might hold only scalars or structs"); return span(arr.Data(), sizeof(U) * N); } -template +template FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span -make_bytes_span(const Array &arr) FLATBUFFERS_NOEXCEPT { +make_bytes_span(const Array& arr) FLATBUFFERS_NOEXCEPT { static_assert(Array::is_span_observable, "internal error, Array might hold only scalars or structs"); return span(arr.Data(), sizeof(U) * N); @@ -221,31 +222,31 @@ make_bytes_span(const Array &arr) FLATBUFFERS_NOEXCEPT { // Cast a raw T[length] to a raw flatbuffers::Array // without endian conversion. Use with care. // TODO: move these Cast-methods to `internal` namespace. -template -Array &CastToArray(T (&arr)[length]) { - return *reinterpret_cast *>(arr); +template +Array& CastToArray(T (&arr)[length]) { + return *reinterpret_cast*>(arr); } -template -const Array &CastToArray(const T (&arr)[length]) { - return *reinterpret_cast *>(arr); +template +const Array& CastToArray(const T (&arr)[length]) { + return *reinterpret_cast*>(arr); } -template -Array &CastToArrayOfEnum(T (&arr)[length]) { +template +Array& CastToArrayOfEnum(T (&arr)[length]) { static_assert(sizeof(E) == sizeof(T), "invalid enum type E"); - return *reinterpret_cast *>(arr); + return *reinterpret_cast*>(arr); } -template -const Array &CastToArrayOfEnum(const T (&arr)[length]) { +template +const Array& CastToArrayOfEnum(const T (&arr)[length]) { static_assert(sizeof(E) == sizeof(T), "invalid enum type E"); - return *reinterpret_cast *>(arr); + return *reinterpret_cast*>(arr); } -template -bool operator==(const Array &lhs, - const Array &rhs) noexcept { +template +bool operator==(const Array& lhs, + const Array& rhs) noexcept { return std::addressof(lhs) == std::addressof(rhs) || (lhs.size() == rhs.size() && std::memcmp(lhs.Data(), rhs.Data(), rhs.size() * sizeof(T)) == 0); diff --git a/third_party/flatbuffers/include/flatbuffers/base.h b/third_party/flatbuffers/include/flatbuffers/base.h index 1c19dde98f3..987dcbc4063 100644 --- a/third_party/flatbuffers/include/flatbuffers/base.h +++ b/third_party/flatbuffers/include/flatbuffers/base.h @@ -139,9 +139,9 @@ #endif #endif // !defined(FLATBUFFERS_LITTLEENDIAN) -#define FLATBUFFERS_VERSION_MAJOR 24 -#define FLATBUFFERS_VERSION_MINOR 3 -#define FLATBUFFERS_VERSION_REVISION 25 +#define FLATBUFFERS_VERSION_MAJOR 25 +#define FLATBUFFERS_VERSION_MINOR 9 +#define FLATBUFFERS_VERSION_REVISION 23 #define FLATBUFFERS_STRING_EXPAND(X) #X #define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X) namespace flatbuffers { @@ -339,15 +339,15 @@ typedef uint16_t voffset_t; typedef uintmax_t largest_scalar_t; // In 32bits, this evaluates to 2GB - 1 -#define FLATBUFFERS_MAX_BUFFER_SIZE std::numeric_limits<::flatbuffers::soffset_t>::max() -#define FLATBUFFERS_MAX_64_BUFFER_SIZE std::numeric_limits<::flatbuffers::soffset64_t>::max() +#define FLATBUFFERS_MAX_BUFFER_SIZE (std::numeric_limits<::flatbuffers::soffset_t>::max)() +#define FLATBUFFERS_MAX_64_BUFFER_SIZE (std::numeric_limits<::flatbuffers::soffset64_t>::max)() // The minimum size buffer that can be a valid flatbuffer. // Includes the offset to the root table (uoffset_t), the offset to the vtable // of the root table (soffset_t), the size of the vtable (uint16_t), and the // size of the referring table (uint16_t). -#define FLATBUFFERS_MIN_BUFFER_SIZE sizeof(uoffset_t) + sizeof(soffset_t) + \ - sizeof(uint16_t) + sizeof(uint16_t) +#define FLATBUFFERS_MIN_BUFFER_SIZE sizeof(::flatbuffers::uoffset_t) + \ + sizeof(::flatbuffers::soffset_t) + sizeof(uint16_t) + sizeof(uint16_t) // We support aligning the contents of buffers up to this size. #ifndef FLATBUFFERS_MAX_ALIGNMENT @@ -459,10 +459,17 @@ inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) { return ((~buf_size) + 1) & (scalar_size - 1); } +#if !defined(_MSC_VER) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif // Generic 'operator==' with conditional specialisations. // T e - new value of a scalar field. // T def - default of scalar (is known at compile-time). template inline bool IsTheSameAs(T e, T def) { return e == def; } +#if !defined(_MSC_VER) + #pragma GCC diagnostic pop +#endif #if defined(FLATBUFFERS_NAN_DEFAULTS) && \ defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0) diff --git a/third_party/flatbuffers/include/flatbuffers/buffer.h b/third_party/flatbuffers/include/flatbuffers/buffer.h index 94d4f7903be..154d187ab75 100644 --- a/third_party/flatbuffers/include/flatbuffers/buffer.h +++ b/third_party/flatbuffers/include/flatbuffers/buffer.h @@ -20,12 +20,14 @@ #include #include "flatbuffers/base.h" +#include "flatbuffers/stl_emulation.h" namespace flatbuffers { // Wrapper for uoffset_t to allow safe template specialization. // Value is allowed to be 0 to indicate a null object (see e.g. AddOffset). -template struct Offset { +template +struct Offset { // The type of offset to use. typedef uoffset_t offset_type; @@ -36,8 +38,14 @@ template struct Offset { bool IsNull() const { return !o; } }; +template +struct is_specialisation_of_Offset : false_type {}; +template +struct is_specialisation_of_Offset> : true_type {}; + // Wrapper for uoffset64_t Offsets. -template struct Offset64 { +template +struct Offset64 { // The type of offset to use. typedef uoffset64_t offset_type; @@ -48,6 +56,11 @@ template struct Offset64 { bool IsNull() const { return !o; } }; +template +struct is_specialisation_of_Offset64 : false_type {}; +template +struct is_specialisation_of_Offset64> : true_type {}; + // Litmus check for ensuring the Offsets are the expected size. static_assert(sizeof(Offset<>) == 4, "Offset has wrong size"); static_assert(sizeof(Offset64<>) == 8, "Offset64 has wrong size"); @@ -55,12 +68,13 @@ static_assert(sizeof(Offset64<>) == 8, "Offset64 has wrong size"); inline void EndianCheck() { int endiantest = 1; // If this fails, see FLATBUFFERS_LITTLEENDIAN above. - FLATBUFFERS_ASSERT(*reinterpret_cast(&endiantest) == + FLATBUFFERS_ASSERT(*reinterpret_cast(&endiantest) == FLATBUFFERS_LITTLEENDIAN); (void)endiantest; } -template FLATBUFFERS_CONSTEXPR size_t AlignOf() { +template +FLATBUFFERS_CONSTEXPR size_t AlignOf() { // clang-format off #ifdef _MSC_VER return __alignof(T); @@ -76,8 +90,8 @@ template FLATBUFFERS_CONSTEXPR size_t AlignOf() { // Lexicographically compare two strings (possibly containing nulls), and // return true if the first is less than the second. -static inline bool StringLessThan(const char *a_data, uoffset_t a_size, - const char *b_data, uoffset_t b_size) { +static inline bool StringLessThan(const char* a_data, uoffset_t a_size, + const char* b_data, uoffset_t b_size) { const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size)); return cmp == 0 ? a_size < b_size : cmp < 0; } @@ -90,42 +104,43 @@ static inline bool StringLessThan(const char *a_data, uoffset_t a_size, // return type like this. // The typedef is for the convenience of callers of this function // (avoiding the need for a trailing return decltype) -template struct IndirectHelper { +template +struct IndirectHelper { typedef T return_type; typedef T mutable_return_type; static const size_t element_stride = sizeof(T); - static return_type Read(const uint8_t *p, const size_t i) { - return EndianScalar((reinterpret_cast(p))[i]); + static return_type Read(const uint8_t* p, const size_t i) { + return EndianScalar((reinterpret_cast(p))[i]); } - static mutable_return_type Read(uint8_t *p, const size_t i) { + static mutable_return_type Read(uint8_t* p, const size_t i) { return reinterpret_cast( - Read(const_cast(p), i)); + Read(const_cast(p), i)); } }; // For vector of Offsets. -template class OffsetT> +template class OffsetT> struct IndirectHelper> { - typedef const T *return_type; - typedef T *mutable_return_type; + typedef const T* return_type; + typedef T* mutable_return_type; typedef typename OffsetT::offset_type offset_type; static const offset_type element_stride = sizeof(offset_type); - static return_type Read(const uint8_t *const p, const offset_type i) { + static return_type Read(const uint8_t* const p, const offset_type i) { // Offsets are relative to themselves, so first update the pointer to // point to the offset location. - const uint8_t *const offset_location = p + i * element_stride; + const uint8_t* const offset_location = p + i * element_stride; // Then read the scalar value of the offset (which may be 32 or 64-bits) and // then determine the relative location from the offset location. return reinterpret_cast( offset_location + ReadScalar(offset_location)); } - static mutable_return_type Read(uint8_t *const p, const offset_type i) { + static mutable_return_type Read(uint8_t* const p, const offset_type i) { // Offsets are relative to themselves, so first update the pointer to // point to the offset location. - uint8_t *const offset_location = p + i * element_stride; + uint8_t* const offset_location = p + i * element_stride; // Then read the scalar value of the offset (which may be 32 or 64-bits) and // then determine the relative location from the offset location. @@ -135,16 +150,26 @@ struct IndirectHelper> { }; // For vector of structs. -template struct IndirectHelper { - typedef const T *return_type; - typedef T *mutable_return_type; - static const size_t element_stride = sizeof(T); - - static return_type Read(const uint8_t *const p, const size_t i) { +template +struct IndirectHelper< + T, typename std::enable_if< + !std::is_scalar::type>::value && + !is_specialisation_of_Offset::value && + !is_specialisation_of_Offset64::value>::type> { + private: + typedef typename std::remove_pointer::type>::type + pointee_type; + + public: + typedef const pointee_type* return_type; + typedef pointee_type* mutable_return_type; + static const size_t element_stride = sizeof(pointee_type); + + static return_type Read(const uint8_t* const p, const size_t i) { // Structs are stored inline, relative to the first struct pointer. return reinterpret_cast(p + i * element_stride); } - static mutable_return_type Read(uint8_t *const p, const size_t i) { + static mutable_return_type Read(uint8_t* const p, const size_t i) { // Structs are stored inline, relative to the first struct pointer. return reinterpret_cast(p + i * element_stride); } @@ -157,14 +182,14 @@ template struct IndirectHelper { /// This function is UNDEFINED for FlatBuffers whose schema does not include /// a file_identifier (likely points at padding or the start of a the root /// vtable). -inline const char *GetBufferIdentifier(const void *buf, +inline const char* GetBufferIdentifier(const void* buf, bool size_prefixed = false) { - return reinterpret_cast(buf) + + return reinterpret_cast(buf) + ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t)); } // Helper to see if the identifier in a buffer has the expected value. -inline bool BufferHasIdentifier(const void *buf, const char *identifier, +inline bool BufferHasIdentifier(const void* buf, const char* identifier, bool size_prefixed = false) { return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier, flatbuffers::kFileIdentifierLength) == 0; @@ -172,26 +197,27 @@ inline bool BufferHasIdentifier(const void *buf, const char *identifier, /// @cond FLATBUFFERS_INTERNAL // Helpers to get a typed pointer to the root object contained in the buffer. -template T *GetMutableRoot(void *buf) { +template +T* GetMutableRoot(void* buf) { if (!buf) return nullptr; EndianCheck(); - return reinterpret_cast( - reinterpret_cast(buf) + - EndianScalar(*reinterpret_cast(buf))); + return reinterpret_cast(reinterpret_cast(buf) + + EndianScalar(*reinterpret_cast(buf))); } -template -T *GetMutableSizePrefixedRoot(void *buf) { - return GetMutableRoot(reinterpret_cast(buf) + sizeof(SizeT)); +template +T* GetMutableSizePrefixedRoot(void* buf) { + return GetMutableRoot(reinterpret_cast(buf) + sizeof(SizeT)); } -template const T *GetRoot(const void *buf) { - return GetMutableRoot(const_cast(buf)); +template +const T* GetRoot(const void* buf) { + return GetMutableRoot(const_cast(buf)); } -template -const T *GetSizePrefixedRoot(const void *buf) { - return GetRoot(reinterpret_cast(buf) + sizeof(SizeT)); +template +const T* GetSizePrefixedRoot(const void* buf) { + return GetRoot(reinterpret_cast(buf) + sizeof(SizeT)); } } // namespace flatbuffers diff --git a/third_party/flatbuffers/include/flatbuffers/buffer_ref.h b/third_party/flatbuffers/include/flatbuffers/buffer_ref.h index f70941fc64d..746903eb972 100644 --- a/third_party/flatbuffers/include/flatbuffers/buffer_ref.h +++ b/third_party/flatbuffers/include/flatbuffers/buffer_ref.h @@ -27,23 +27,24 @@ namespace flatbuffers { // A BufferRef does not own its buffer. struct BufferRefBase {}; // for std::is_base_of -template struct BufferRef : BufferRefBase { +template +struct BufferRef : BufferRefBase { BufferRef() : buf(nullptr), len(0), must_free(false) {} - BufferRef(uint8_t *_buf, uoffset_t _len) + BufferRef(uint8_t* _buf, uoffset_t _len) : buf(_buf), len(_len), must_free(false) {} ~BufferRef() { if (must_free) free(buf); } - const T *GetRoot() const { return flatbuffers::GetRoot(buf); } + const T* GetRoot() const { return flatbuffers::GetRoot(buf); } bool Verify() { Verifier verifier(buf, len); return verifier.VerifyBuffer(nullptr); } - uint8_t *buf; + uint8_t* buf; uoffset_t len; bool must_free; }; diff --git a/third_party/flatbuffers/include/flatbuffers/code_generator.h b/third_party/flatbuffers/include/flatbuffers/code_generator.h index 2971e556eec..cc4df7f1c8b 100644 --- a/third_party/flatbuffers/include/flatbuffers/code_generator.h +++ b/third_party/flatbuffers/include/flatbuffers/code_generator.h @@ -45,13 +45,13 @@ class CodeGenerator { // Generate code from the provided `parser`. // // DEPRECATED: prefer using the other overload of GenerateCode for bfbs. - virtual Status GenerateCode(const Parser &parser, const std::string &path, - const std::string &filename) = 0; + virtual Status GenerateCode(const Parser& parser, const std::string& path, + const std::string& filename) = 0; // Generate code from the provided `parser` and place it in the output. - virtual Status GenerateCodeString(const Parser &parser, - const std::string &filename, - std::string &output) { + virtual Status GenerateCodeString(const Parser& parser, + const std::string& filename, + std::string& output) { (void)parser; (void)filename; (void)output; @@ -60,18 +60,18 @@ class CodeGenerator { // Generate code from the provided `buffer` of given `length`. The buffer is a // serialized reflection.fbs. - virtual Status GenerateCode(const uint8_t *buffer, int64_t length, - const CodeGenOptions &options) = 0; + virtual Status GenerateCode(const uint8_t* buffer, int64_t length, + const CodeGenOptions& options) = 0; - virtual Status GenerateMakeRule(const Parser &parser, const std::string &path, - const std::string &filename, - std::string &output) = 0; + virtual Status GenerateMakeRule(const Parser& parser, const std::string& path, + const std::string& filename, + std::string& output) = 0; - virtual Status GenerateGrpcCode(const Parser &parser, const std::string &path, - const std::string &filename) = 0; + virtual Status GenerateGrpcCode(const Parser& parser, const std::string& path, + const std::string& filename) = 0; - virtual Status GenerateRootFile(const Parser &parser, - const std::string &path) = 0; + virtual Status GenerateRootFile(const Parser& parser, + const std::string& path) = 0; virtual bool IsSchemaOnly() const = 0; @@ -88,8 +88,8 @@ class CodeGenerator { private: // Copying is not supported. - CodeGenerator(const CodeGenerator &) = delete; - CodeGenerator &operator=(const CodeGenerator &) = delete; + CodeGenerator(const CodeGenerator&) = delete; + CodeGenerator& operator=(const CodeGenerator&) = delete; }; } // namespace flatbuffers diff --git a/third_party/flatbuffers/include/flatbuffers/code_generators.h b/third_party/flatbuffers/include/flatbuffers/code_generators.h index fc030d43943..d284ac5a683 100644 --- a/third_party/flatbuffers/include/flatbuffers/code_generators.h +++ b/third_party/flatbuffers/include/flatbuffers/code_generators.h @@ -51,11 +51,11 @@ class CodeWriter { // Associates a key with a value. All subsequent calls to operator+=, where // the specified key is contained in {{ and }} delimiters will be replaced by // the given value. - void SetValue(const std::string &key, const std::string &value) { + void SetValue(const std::string& key, const std::string& value) { value_map_[key] = value; } - std::string GetValue(const std::string &key) const { + std::string GetValue(const std::string& key) const { const auto it = value_map_.find(key); return it == value_map_.end() ? "" : it->second; } @@ -76,7 +76,7 @@ class CodeWriter { if (cur_ident_lvl_) cur_ident_lvl_--; } - void SetPadding(const std::string &padding) { pad_ = padding; } + void SetPadding(const std::string& padding) { pad_ = padding; } private: std::map value_map_; @@ -86,24 +86,24 @@ class CodeWriter { bool ignore_ident_; // Add ident padding (tab or space) based on ident level - void AppendIdent(std::stringstream &stream); + void AppendIdent(std::stringstream& stream); }; class BaseGenerator { public: virtual bool generate() = 0; - static std::string NamespaceDir(const Parser &parser, const std::string &path, - const Namespace &ns, + static std::string NamespaceDir(const Parser& parser, const std::string& path, + const Namespace& ns, const bool dasherize = false); - std::string GeneratedFileName(const std::string &path, - const std::string &file_name, - const IDLOptions &options) const; + std::string GeneratedFileName(const std::string& path, + const std::string& file_name, + const IDLOptions& options) const; protected: - BaseGenerator(const Parser &parser, const std::string &path, - const std::string &file_name, std::string qualifying_start, + BaseGenerator(const Parser& parser, const std::string& path, + const std::string& file_name, std::string qualifying_start, std::string qualifying_separator, std::string default_extension) : parser_(parser), path_(path), @@ -114,84 +114,84 @@ class BaseGenerator { virtual ~BaseGenerator() {} // No copy/assign. - BaseGenerator &operator=(const BaseGenerator &); - BaseGenerator(const BaseGenerator &); + BaseGenerator& operator=(const BaseGenerator&); + BaseGenerator(const BaseGenerator&); - std::string NamespaceDir(const Namespace &ns, + std::string NamespaceDir(const Namespace& ns, const bool dasherize = false) const; - static const char *FlatBuffersGeneratedWarning(); + static const char* FlatBuffersGeneratedWarning(); - static std::string FullNamespace(const char *separator, const Namespace &ns); + static std::string FullNamespace(const char* separator, const Namespace& ns); - static std::string LastNamespacePart(const Namespace &ns); + static std::string LastNamespacePart(const Namespace& ns); // tracks the current namespace for early exit in WrapInNameSpace // c++, java and csharp returns a different namespace from // the following default (no early exit, always fully qualify), // which works for js and php - virtual const Namespace *CurrentNameSpace() const { return nullptr; } + virtual const Namespace* CurrentNameSpace() const { return nullptr; } // Ensure that a type is prefixed with its namespace even within // its own namespace to avoid conflict between generated method // names and similarly named classes or structs - std::string WrapInNameSpace(const Namespace *ns, - const std::string &name) const; + std::string WrapInNameSpace(const Namespace* ns, + const std::string& name) const; - std::string WrapInNameSpace(const Definition &def, - const std::string &suffix = "") const; + std::string WrapInNameSpace(const Definition& def, + const std::string& suffix = "") const; - std::string GetNameSpace(const Definition &def) const; + std::string GetNameSpace(const Definition& def) const; - const Parser &parser_; - const std::string &path_; - const std::string &file_name_; + const Parser& parser_; + const std::string& path_; + const std::string& file_name_; const std::string qualifying_start_; const std::string qualifying_separator_; const std::string default_extension_; }; struct CommentConfig { - const char *first_line; - const char *content_line_prefix; - const char *last_line; + const char* first_line; + const char* content_line_prefix; + const char* last_line; }; -extern void GenComment(const std::vector &dc, - std::string *code_ptr, const CommentConfig *config, - const char *prefix = ""); +extern void GenComment(const std::vector& dc, + std::string* code_ptr, const CommentConfig* config, + const char* prefix = ""); class FloatConstantGenerator { public: virtual ~FloatConstantGenerator() {} - std::string GenFloatConstant(const FieldDef &field) const; + std::string GenFloatConstant(const FieldDef& field) const; private: - virtual std::string Value(double v, const std::string &src) const = 0; + virtual std::string Value(double v, const std::string& src) const = 0; virtual std::string Inf(double v) const = 0; virtual std::string NaN(double v) const = 0; - virtual std::string Value(float v, const std::string &src) const = 0; + virtual std::string Value(float v, const std::string& src) const = 0; virtual std::string Inf(float v) const = 0; virtual std::string NaN(float v) const = 0; - template - std::string GenFloatConstantImpl(const FieldDef &field) const; + template + std::string GenFloatConstantImpl(const FieldDef& field) const; }; class SimpleFloatConstantGenerator : public FloatConstantGenerator { public: - SimpleFloatConstantGenerator(const char *nan_number, - const char *pos_inf_number, - const char *neg_inf_number); + SimpleFloatConstantGenerator(const char* nan_number, + const char* pos_inf_number, + const char* neg_inf_number); private: std::string Value(double v, - const std::string &src) const FLATBUFFERS_OVERRIDE; + const std::string& src) const FLATBUFFERS_OVERRIDE; std::string Inf(double v) const FLATBUFFERS_OVERRIDE; std::string NaN(double v) const FLATBUFFERS_OVERRIDE; - std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE; + std::string Value(float v, const std::string& src) const FLATBUFFERS_OVERRIDE; std::string Inf(float v) const FLATBUFFERS_OVERRIDE; std::string NaN(float v) const FLATBUFFERS_OVERRIDE; @@ -203,24 +203,24 @@ class SimpleFloatConstantGenerator : public FloatConstantGenerator { // C++, C#, Java like generator. class TypedFloatConstantGenerator : public FloatConstantGenerator { public: - TypedFloatConstantGenerator(const char *double_prefix, - const char *single_prefix, const char *nan_number, - const char *pos_inf_number, - const char *neg_inf_number = ""); + TypedFloatConstantGenerator(const char* double_prefix, + const char* single_prefix, const char* nan_number, + const char* pos_inf_number, + const char* neg_inf_number = ""); private: std::string Value(double v, - const std::string &src) const FLATBUFFERS_OVERRIDE; + const std::string& src) const FLATBUFFERS_OVERRIDE; std::string Inf(double v) const FLATBUFFERS_OVERRIDE; std::string NaN(double v) const FLATBUFFERS_OVERRIDE; - std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE; + std::string Value(float v, const std::string& src) const FLATBUFFERS_OVERRIDE; std::string Inf(float v) const FLATBUFFERS_OVERRIDE; std::string NaN(float v) const FLATBUFFERS_OVERRIDE; - std::string MakeNaN(const std::string &prefix) const; - std::string MakeInf(bool neg, const std::string &prefix) const; + std::string MakeNaN(const std::string& prefix) const; + std::string MakeInf(bool neg, const std::string& prefix) const; const std::string double_prefix_; const std::string single_prefix_; @@ -229,9 +229,9 @@ class TypedFloatConstantGenerator : public FloatConstantGenerator { const std::string neg_inf_number_; }; -std::string JavaCSharpMakeRule(const bool java, const Parser &parser, - const std::string &path, - const std::string &file_name); +std::string JavaCSharpMakeRule(const bool java, const Parser& parser, + const std::string& path, + const std::string& file_name); } // namespace flatbuffers diff --git a/third_party/flatbuffers/include/flatbuffers/default_allocator.h b/third_party/flatbuffers/include/flatbuffers/default_allocator.h index d4724122cb5..d1cab08d743 100644 --- a/third_party/flatbuffers/include/flatbuffers/default_allocator.h +++ b/third_party/flatbuffers/include/flatbuffers/default_allocator.h @@ -25,32 +25,32 @@ namespace flatbuffers { // DefaultAllocator uses new/delete to allocate memory regions class DefaultAllocator : public Allocator { public: - uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE { + uint8_t* allocate(size_t size) FLATBUFFERS_OVERRIDE { return new uint8_t[size]; } - void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE { delete[] p; } + void deallocate(uint8_t* p, size_t) FLATBUFFERS_OVERRIDE { delete[] p; } - static void dealloc(void *p, size_t) { delete[] static_cast(p); } + static void dealloc(void* p, size_t) { delete[] static_cast(p); } }; // These functions allow for a null allocator to mean use the default allocator, // as used by DetachedBuffer and vector_downward below. // This is to avoid having a statically or dynamically allocated default // allocator, or having to move it between the classes that may own it. -inline uint8_t *Allocate(Allocator *allocator, size_t size) { +inline uint8_t* Allocate(Allocator* allocator, size_t size) { return allocator ? allocator->allocate(size) : DefaultAllocator().allocate(size); } -inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) { +inline void Deallocate(Allocator* allocator, uint8_t* p, size_t size) { if (allocator) allocator->deallocate(p, size); else DefaultAllocator().deallocate(p, size); } -inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p, +inline uint8_t* ReallocateDownward(Allocator* allocator, uint8_t* old_p, size_t old_size, size_t new_size, size_t in_use_back, size_t in_use_front) { return allocator ? allocator->reallocate_downward(old_p, old_size, new_size, diff --git a/third_party/flatbuffers/include/flatbuffers/detached_buffer.h b/third_party/flatbuffers/include/flatbuffers/detached_buffer.h index 5e900baeb57..0577a42d969 100644 --- a/third_party/flatbuffers/include/flatbuffers/detached_buffer.h +++ b/third_party/flatbuffers/include/flatbuffers/detached_buffer.h @@ -36,8 +36,8 @@ class DetachedBuffer { cur_(nullptr), size_(0) {} - DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf, - size_t reserved, uint8_t *cur, size_t sz) + DetachedBuffer(Allocator* allocator, bool own_allocator, uint8_t* buf, + size_t reserved, uint8_t* cur, size_t sz) : allocator_(allocator), own_allocator_(own_allocator), buf_(buf), @@ -45,7 +45,7 @@ class DetachedBuffer { cur_(cur), size_(sz) {} - DetachedBuffer(DetachedBuffer &&other) noexcept + DetachedBuffer(DetachedBuffer&& other) noexcept : allocator_(other.allocator_), own_allocator_(other.own_allocator_), buf_(other.buf_), @@ -55,7 +55,7 @@ class DetachedBuffer { other.reset(); } - DetachedBuffer &operator=(DetachedBuffer &&other) noexcept { + DetachedBuffer& operator=(DetachedBuffer&& other) noexcept { if (this == &other) return *this; destroy(); @@ -74,28 +74,35 @@ class DetachedBuffer { ~DetachedBuffer() { destroy(); } - const uint8_t *data() const { return cur_; } + const uint8_t* data() const { return cur_; } - uint8_t *data() { return cur_; } + uint8_t* data() { return cur_; } size_t size() const { return size_; } + uint8_t* begin() { return data(); } + const uint8_t* begin() const { return data(); } + uint8_t* end() { return data() + size(); } + const uint8_t* end() const { return data() + size(); } + // These may change access mode, leave these at end of public section - FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other)); + FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer& other)); FLATBUFFERS_DELETE_FUNC( - DetachedBuffer &operator=(const DetachedBuffer &other)); + DetachedBuffer& operator=(const DetachedBuffer& other)); protected: - Allocator *allocator_; + Allocator* allocator_; bool own_allocator_; - uint8_t *buf_; + uint8_t* buf_; size_t reserved_; - uint8_t *cur_; + uint8_t* cur_; size_t size_; inline void destroy() { if (buf_) Deallocate(allocator_, buf_, reserved_); - if (own_allocator_ && allocator_) { delete allocator_; } + if (own_allocator_ && allocator_) { + delete allocator_; + } reset(); } diff --git a/third_party/flatbuffers/include/flatbuffers/file_manager.h b/third_party/flatbuffers/include/flatbuffers/file_manager.h index 069df5b8842..0941faef662 100644 --- a/third_party/flatbuffers/include/flatbuffers/file_manager.h +++ b/third_party/flatbuffers/include/flatbuffers/file_manager.h @@ -31,16 +31,16 @@ class FileManager { FileManager() = default; virtual ~FileManager() = default; - virtual bool SaveFile(const std::string &absolute_file_name, - const std::string &content) = 0; + virtual bool SaveFile(const std::string& absolute_file_name, + const std::string& content) = 0; - virtual bool LoadFile(const std::string &absolute_file_name, - std::string *buf) = 0; + virtual bool LoadFile(const std::string& absolute_file_name, + std::string* buf) = 0; private: // Copying is not supported. - FileManager(const FileManager &) = delete; - FileManager &operator=(const FileManager &) = delete; + FileManager(const FileManager&) = delete; + FileManager& operator=(const FileManager&) = delete; }; } // namespace flatbuffers diff --git a/third_party/flatbuffers/include/flatbuffers/flatbuffer_builder.h b/third_party/flatbuffers/include/flatbuffers/flatbuffer_builder.h index 9a2d62541bd..9eea6bab0c5 100644 --- a/third_party/flatbuffers/include/flatbuffers/flatbuffer_builder.h +++ b/third_party/flatbuffers/include/flatbuffers/flatbuffer_builder.h @@ -47,21 +47,22 @@ inline voffset_t FieldIndexToOffset(voffset_t field_id) { 2 * sizeof(voffset_t); // Vtable size and Object Size. size_t offset = fixed_fields + field_id * sizeof(voffset_t); FLATBUFFERS_ASSERT(offset < std::numeric_limits::max()); - return static_cast(offset);} + return static_cast(offset); +} -template> -const T *data(const std::vector &v) { +template > +const T* data(const std::vector& v) { // Eventually the returned pointer gets passed down to memcpy, so // we need it to be non-null to avoid undefined behavior. static uint8_t t; - return v.empty() ? reinterpret_cast(&t) : &v.front(); + return v.empty() ? reinterpret_cast(&t) : &v.front(); } -template> -T *data(std::vector &v) { +template > +T* data(std::vector& v) { // Eventually the returned pointer gets passed down to memcpy, so // we need it to be non-null to avoid undefined behavior. static uint8_t t; - return v.empty() ? reinterpret_cast(&t) : &v.front(); + return v.empty() ? reinterpret_cast(&t) : &v.front(); } /// @addtogroup flatbuffers_cpp_api @@ -73,7 +74,8 @@ T *data(std::vector &v) { /// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/ /// `CreateVector` functions. Do this is depth-first order to build up a tree to /// the root. `Finish()` wraps up the buffer ready for transport. -template class FlatBufferBuilderImpl { +template +class FlatBufferBuilderImpl { public: // This switches the size type of the builder, based on if its 64-bit aware // (uoffset64_t) or not (uoffset_t). @@ -92,7 +94,7 @@ template class FlatBufferBuilderImpl { /// types with custom alignment AND you wish to read the buffer in-place /// directly after creation. explicit FlatBufferBuilderImpl( - size_t initial_size = 1024, Allocator *allocator = nullptr, + size_t initial_size = 1024, Allocator* allocator = nullptr, bool own_allocator = false, size_t buffer_minalign = AlignOf()) : buf_(initial_size, allocator, own_allocator, buffer_minalign, @@ -111,7 +113,7 @@ template class FlatBufferBuilderImpl { } /// @brief Move constructor for FlatBufferBuilder. - FlatBufferBuilderImpl(FlatBufferBuilderImpl &&other) noexcept + FlatBufferBuilderImpl(FlatBufferBuilderImpl&& other) noexcept : buf_(1024, nullptr, false, AlignOf(), static_cast(Is64Aware ? FLATBUFFERS_MAX_64_BUFFER_SIZE : FLATBUFFERS_MAX_BUFFER_SIZE)), @@ -132,14 +134,14 @@ template class FlatBufferBuilderImpl { } /// @brief Move assignment operator for FlatBufferBuilder. - FlatBufferBuilderImpl &operator=(FlatBufferBuilderImpl &&other) noexcept { + FlatBufferBuilderImpl& operator=(FlatBufferBuilderImpl&& other) noexcept { // Move construct a temporary and swap idiom FlatBufferBuilderImpl temp(std::move(other)); Swap(temp); return *this; } - void Swap(FlatBufferBuilderImpl &other) { + void Swap(FlatBufferBuilderImpl& other) { using std::swap; buf_.swap(other.buf_); swap(num_field_loc, other.num_field_loc); @@ -181,7 +183,7 @@ template class FlatBufferBuilderImpl { /// @brief The current size of the serialized buffer relative to the end of /// the 32-bit region. /// @return Returns an `uoffset_t` with the current size of the buffer. - template + template // Only enable this method for the 64-bit builder, as only that builder is // concerned with the 32/64-bit boundary, and should be the one to bare any // run time costs. @@ -194,7 +196,7 @@ template class FlatBufferBuilderImpl { return static_cast(GetSize() - length_of_64_bit_region_); } - template + template // Only enable this method for the 32-bit builder. typename std::enable_if::type GetSizeRelative32BitRegion() const { @@ -204,7 +206,7 @@ template class FlatBufferBuilderImpl { /// @brief Get the serialized buffer (after you call `Finish()`). /// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the /// buffer. - uint8_t *GetBufferPointer() const { + uint8_t* GetBufferPointer() const { Finished(); return buf_.data(); } @@ -219,7 +221,7 @@ template class FlatBufferBuilderImpl { /// @brief Get a pointer to an unfinished buffer. /// @return Returns a `uint8_t` pointer to the unfinished buffer. - uint8_t *GetCurrentBufferPointer() const { return buf_.data(); } + uint8_t* GetCurrentBufferPointer() const { return buf_.data(); } /// @brief Get the released DetachedBuffer. /// @return A `DetachedBuffer` that owns the buffer and its allocator. @@ -239,7 +241,7 @@ template class FlatBufferBuilderImpl { /// the serialized `FlatBuffer`. /// @remark If the allocator is owned, it gets deleted when the destructor is /// called. - uint8_t *ReleaseRaw(size_t &size, size_t &offset) { + uint8_t* ReleaseRaw(size_t& size, size_t& offset) { Finished(); uint8_t* raw = buf_.release_raw(size, offset); Clear(); @@ -290,22 +292,23 @@ template class FlatBufferBuilderImpl { buf_.fill(PaddingBytes(buf_.size(), elem_size)); } - void PushFlatBuffer(const uint8_t *bytes, size_t size) { + void PushFlatBuffer(const uint8_t* bytes, size_t size) { PushBytes(bytes, size); finished = true; } - void PushBytes(const uint8_t *bytes, size_t size) { buf_.push(bytes, size); } + void PushBytes(const uint8_t* bytes, size_t size) { buf_.push(bytes, size); } void PopBytes(size_t amount) { buf_.pop(amount); } - template void AssertScalarT() { + template + void AssertScalarT() { // The code assumes power of 2 sizes and endian-swap-ability. static_assert(flatbuffers::is_scalar::value, "T must be a scalar type"); } // Write a single aligned scalar to the buffer - template + template ReturnT PushElement(T element) { AssertScalarT(); Align(sizeof(T)); @@ -313,7 +316,7 @@ template class FlatBufferBuilderImpl { return CalculateOffset(); } - template class OffsetT = Offset> + template class OffsetT = Offset> uoffset_t PushElement(OffsetT off) { // Special case for offsets: see ReferTo below. return PushElement(ReferTo(off.o)); @@ -322,34 +325,41 @@ template class FlatBufferBuilderImpl { // When writing fields, we track where they are, so we can create correct // vtables later. void TrackField(voffset_t field, uoffset_t off) { - FieldLoc fl = { off, field }; + FieldLoc fl = {off, field}; buf_.scratch_push_small(fl); num_field_loc++; - if (field > max_voffset_) { max_voffset_ = field; } + if (field > max_voffset_) { + max_voffset_ = field; + } } // Like PushElement, but additionally tracks the field this represents. - template void AddElement(voffset_t field, T e, T def) { + template + void AddElement(voffset_t field, T e, T def) { // We don't serialize values equal to the default. if (IsTheSameAs(e, def) && !force_defaults_) return; TrackField(field, PushElement(e)); } - template void AddElement(voffset_t field, T e) { + template + void AddElement(voffset_t field, T e) { TrackField(field, PushElement(e)); } - template void AddOffset(voffset_t field, Offset off) { + template + void AddOffset(voffset_t field, Offset off) { if (off.IsNull()) return; // Don't store. AddElement(field, ReferTo(off.o), static_cast(0)); } - template void AddOffset(voffset_t field, Offset64 off) { + template + void AddOffset(voffset_t field, Offset64 off) { if (off.IsNull()) return; // Don't store. AddElement(field, ReferTo(off.o), static_cast(0)); } - template void AddStruct(voffset_t field, const T *structptr) { + template + void AddStruct(voffset_t field, const T* structptr) { if (!structptr) return; // Default, don't store. Align(AlignOf()); buf_.push_small(*structptr); @@ -379,12 +389,14 @@ template class FlatBufferBuilderImpl { return ReferTo(off, GetSize()); } - template T ReferTo(const T off, const T2 size) { + template + T ReferTo(const T off, const T2 size) { FLATBUFFERS_ASSERT(off && off <= size); return size - off + static_cast(sizeof(T)); } - template T ReferTo(const T off, const T size) { + template + T ReferTo(const T off, const T size) { FLATBUFFERS_ASSERT(off && off <= size); return size - off + static_cast(sizeof(T)); } @@ -440,7 +452,7 @@ template class FlatBufferBuilderImpl { // Write the offsets into the table for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc); it < buf_.scratch_end(); it += sizeof(FieldLoc)) { - auto field_location = reinterpret_cast(it); + auto field_location = reinterpret_cast(it); const voffset_t pos = static_cast(vtable_offset_loc - field_location->off); // If this asserts, it means you've set a field twice. @@ -449,7 +461,7 @@ template class FlatBufferBuilderImpl { WriteScalar(buf_.data() + field_location->id, pos); } ClearOffsets(); - auto vt1 = reinterpret_cast(buf_.data()); + auto vt1 = reinterpret_cast(buf_.data()); auto vt1_size = ReadScalar(vt1); auto vt_use = GetSizeRelative32BitRegion(); // See if we already have generated a vtable with this exact same @@ -457,8 +469,8 @@ template class FlatBufferBuilderImpl { if (dedup_vtables_) { for (auto it = buf_.scratch_data(); it < buf_.scratch_end(); it += sizeof(uoffset_t)) { - auto vt_offset_ptr = reinterpret_cast(it); - auto vt2 = reinterpret_cast(buf_.data_at(*vt_offset_ptr)); + auto vt_offset_ptr = reinterpret_cast(it); + auto vt2 = reinterpret_cast(buf_.data_at(*vt_offset_ptr)); auto vt2_size = ReadScalar(vt2); if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue; vt_use = *vt_offset_ptr; @@ -489,8 +501,9 @@ template class FlatBufferBuilderImpl { // This checks a required field has been set in a given table that has // just been constructed. - template void Required(Offset table, voffset_t field) { - auto table_ptr = reinterpret_cast(buf_.data_at(table.o)); + template + void Required(Offset table, voffset_t field) { + auto table_ptr = reinterpret_cast(buf_.data_at(table.o)); bool ok = table_ptr->GetOptionalFieldOffset(field) != 0; // If this fails, the caller will show what field needs to be set. FLATBUFFERS_ASSERT(ok); @@ -520,7 +533,8 @@ template class FlatBufferBuilderImpl { // Aligns such than when "len" bytes are written, an object of type `AlignT` // can be written after it (forward in the buffer) without padding. - template void PreAlign(size_t len) { + template + void PreAlign(size_t len) { AssertScalarT(); PreAlign(len, AlignOf()); } @@ -530,8 +544,8 @@ template class FlatBufferBuilderImpl { /// @param[in] str A const char pointer to the data to be stored as a string. /// @param[in] len The number of bytes that should be stored from `str`. /// @return Returns the offset in the buffer where the string starts. - template class OffsetT = Offset> - OffsetT CreateString(const char *str, size_t len) { + template