--- /dev/null
+/**\r
+ * @alias ProtoBuf.Builder\r
+ * @expose\r
+ */\r
+ProtoBuf.Builder = (function(ProtoBuf, Lang, Reflect) {\r
+ "use strict";\r
+\r
+ /**\r
+ * Constructs a new Builder.\r
+ * @exports ProtoBuf.Builder\r
+ * @class Provides the functionality to build protocol messages.\r
+ * @param {Object.<string,*>=} options Options\r
+ * @constructor\r
+ */\r
+ var Builder = function(options) {\r
+\r
+ /**\r
+ * Namespace.\r
+ * @type {ProtoBuf.Reflect.Namespace}\r
+ * @expose\r
+ */\r
+ this.ns = new Reflect.Namespace(this, null, ""); // Global namespace\r
+\r
+ /**\r
+ * Namespace pointer.\r
+ * @type {ProtoBuf.Reflect.T}\r
+ * @expose\r
+ */\r
+ this.ptr = this.ns;\r
+\r
+ /**\r
+ * Resolved flag.\r
+ * @type {boolean}\r
+ * @expose\r
+ */\r
+ this.resolved = false;\r
+\r
+ /**\r
+ * The current building result.\r
+ * @type {Object.<string,ProtoBuf.Builder.Message|Object>|null}\r
+ * @expose\r
+ */\r
+ this.result = null;\r
+\r
+ /**\r
+ * Imported files.\r
+ * @type {Array.<string>}\r
+ * @expose\r
+ */\r
+ this.files = {};\r
+\r
+ /**\r
+ * Import root override.\r
+ * @type {?string}\r
+ * @expose\r
+ */\r
+ this.importRoot = null;\r
+\r
+ /**\r
+ * Options.\r
+ * @type {!Object.<string, *>}\r
+ * @expose\r
+ */\r
+ this.options = options || {};\r
+ };\r
+\r
+ /**\r
+ * @alias ProtoBuf.Builder.prototype\r
+ * @inner\r
+ */\r
+ var BuilderPrototype = Builder.prototype;\r
+\r
+ // ----- Definition tests -----\r
+\r
+ /**\r
+ * Tests if a definition most likely describes a message.\r
+ * @param {!Object} def\r
+ * @returns {boolean}\r
+ * @expose\r
+ */\r
+ Builder.isMessage = function(def) {\r
+ // Messages require a string name\r
+ if (typeof def["name"] !== 'string')\r
+ return false;\r
+ // Messages do not contain values (enum) or rpc methods (service)\r
+ if (typeof def["values"] !== 'undefined' || typeof def["rpc"] !== 'undefined')\r
+ return false;\r
+ return true;\r
+ };\r
+\r
+ /**\r
+ * Tests if a definition most likely describes a message field.\r
+ * @param {!Object} def\r
+ * @returns {boolean}\r
+ * @expose\r
+ */\r
+ Builder.isMessageField = function(def) {\r
+ // Message fields require a string rule, name and type and an id\r
+ if (typeof def["rule"] !== 'string' || typeof def["name"] !== 'string' || typeof def["type"] !== 'string' || typeof def["id"] === 'undefined')\r
+ return false;\r
+ return true;\r
+ };\r
+\r
+ /**\r
+ * Tests if a definition most likely describes an enum.\r
+ * @param {!Object} def\r
+ * @returns {boolean}\r
+ * @expose\r
+ */\r
+ Builder.isEnum = function(def) {\r
+ // Enums require a string name\r
+ if (typeof def["name"] !== 'string')\r
+ return false;\r
+ // Enums require at least one value\r
+ if (typeof def["values"] === 'undefined' || !Array.isArray(def["values"]) || def["values"].length === 0)\r
+ return false;\r
+ return true;\r
+ };\r
+\r
+ /**\r
+ * Tests if a definition most likely describes a service.\r
+ * @param {!Object} def\r
+ * @returns {boolean}\r
+ * @expose\r
+ */\r
+ Builder.isService = function(def) {\r
+ // Services require a string name and an rpc object\r
+ if (typeof def["name"] !== 'string' || typeof def["rpc"] !== 'object' || !def["rpc"])\r
+ return false;\r
+ return true;\r
+ };\r
+\r
+ /**\r
+ * Tests if a definition most likely describes an extended message\r
+ * @param {!Object} def\r
+ * @returns {boolean}\r
+ * @expose\r
+ */\r
+ Builder.isExtend = function(def) {\r
+ // Extends rquire a string ref\r
+ if (typeof def["ref"] !== 'string')\r
+ return false;\r
+ return true;\r
+ };\r
+\r
+ // ----- Building -----\r
+\r
+ /**\r
+ * Resets the pointer to the root namespace.\r
+ * @returns {!ProtoBuf.Builder} this\r
+ * @expose\r
+ */\r
+ BuilderPrototype.reset = function() {\r
+ this.ptr = this.ns;\r
+ return this;\r
+ };\r
+\r
+ /**\r
+ * Defines a namespace on top of the current pointer position and places the pointer on it.\r
+ * @param {string} namespace\r
+ * @return {!ProtoBuf.Builder} this\r
+ * @expose\r
+ */\r
+ BuilderPrototype.define = function(namespace) {\r
+ if (typeof namespace !== 'string' || !Lang.TYPEREF.test(namespace))\r
+ throw Error("illegal namespace: "+namespace);\r
+ namespace.split(".").forEach(function(part) {\r
+ var ns = this.ptr.getChild(part);\r
+ if (ns === null) // Keep existing\r
+ this.ptr.addChild(ns = new Reflect.Namespace(this, this.ptr, part));\r
+ this.ptr = ns;\r
+ }, this);\r
+ return this;\r
+ };\r
+\r
+ /**\r
+ * Creates the specified definitions at the current pointer position.\r
+ * @param {!Array.<!Object>} defs Messages, enums or services to create\r
+ * @returns {!ProtoBuf.Builder} this\r
+ * @throws {Error} If a message definition is invalid\r
+ * @expose\r
+ */\r
+ BuilderPrototype.create = function(defs) {\r
+ if (!defs)\r
+ return this; // Nothing to create\r
+ if (!Array.isArray(defs))\r
+ defs = [defs];\r
+ else {\r
+ if (defs.length === 0)\r
+ return this;\r
+ defs = defs.slice();\r
+ }\r
+\r
+ // It's quite hard to keep track of scopes and memory here, so let's do this iteratively.\r
+ var stack = [defs];\r
+ while (stack.length > 0) {\r
+ defs = stack.pop();\r
+\r
+ if (!Array.isArray(defs)) // Stack always contains entire namespaces\r
+ throw Error("not a valid namespace: "+JSON.stringify(defs));\r
+\r
+ while (defs.length > 0) {\r
+ var def = defs.shift(); // Namespaces always contain an array of messages, enums and services\r
+\r
+ if (Builder.isMessage(def)) {\r
+ var obj = new Reflect.Message(this, this.ptr, def["name"], def["options"], def["isGroup"], def["syntax"]);\r
+\r
+ // Create OneOfs\r
+ var oneofs = {};\r
+ if (def["oneofs"])\r
+ Object.keys(def["oneofs"]).forEach(function(name) {\r
+ obj.addChild(oneofs[name] = new Reflect.Message.OneOf(this, obj, name));\r
+ }, this);\r
+\r
+ // Create fields\r
+ if (def["fields"])\r
+ def["fields"].forEach(function(fld) {\r
+ if (obj.getChild(fld["id"]|0) !== null)\r
+ throw Error("duplicate or invalid field id in "+obj.name+": "+fld['id']);\r
+ if (fld["options"] && typeof fld["options"] !== 'object')\r
+ throw Error("illegal field options in "+obj.name+"#"+fld["name"]);\r
+ var oneof = null;\r
+ if (typeof fld["oneof"] === 'string' && !(oneof = oneofs[fld["oneof"]]))\r
+ throw Error("illegal oneof in "+obj.name+"#"+fld["name"]+": "+fld["oneof"]);\r
+ fld = new Reflect.Message.Field(this, obj, fld["rule"], fld["keytype"], fld["type"], fld["name"], fld["id"], fld["options"], oneof, def["syntax"]);\r
+ if (oneof)\r
+ oneof.fields.push(fld);\r
+ obj.addChild(fld);\r
+ }, this);\r
+\r
+ // Push children to stack\r
+ var subObj = [];\r
+ if (def["enums"])\r
+ def["enums"].forEach(function(enm) {\r
+ subObj.push(enm);\r
+ });\r
+ if (def["messages"])\r
+ def["messages"].forEach(function(msg) {\r
+ subObj.push(msg);\r
+ });\r
+ if (def["services"])\r
+ def["services"].forEach(function(svc) {\r
+ subObj.push(svc);\r
+ });\r
+\r
+ // Set extension ranges\r
+ if (def["extensions"]) {\r
+ if (typeof def["extensions"][0] === 'number') // pre 5.0.1\r
+ obj.extensions = [ def["extensions"] ];\r
+ else\r
+ obj.extensions = def["extensions"];\r
+ }\r
+\r
+ // Create on top of current namespace\r
+ this.ptr.addChild(obj);\r
+ if (subObj.length > 0) {\r
+ stack.push(defs); // Push the current level back\r
+ defs = subObj; // Continue processing sub level\r
+ subObj = null;\r
+ this.ptr = obj; // And move the pointer to this namespace\r
+ obj = null;\r
+ continue;\r
+ }\r
+ subObj = null;\r
+\r
+ } else if (Builder.isEnum(def)) {\r
+\r
+ obj = new Reflect.Enum(this, this.ptr, def["name"], def["options"], def["syntax"]);\r
+ def["values"].forEach(function(val) {\r
+ obj.addChild(new Reflect.Enum.Value(this, obj, val["name"], val["id"]));\r
+ }, this);\r
+ this.ptr.addChild(obj);\r
+\r
+ } else if (Builder.isService(def)) {\r
+\r
+ obj = new Reflect.Service(this, this.ptr, def["name"], def["options"]);\r
+ Object.keys(def["rpc"]).forEach(function(name) {\r
+ var mtd = def["rpc"][name];\r
+ obj.addChild(new Reflect.Service.RPCMethod(this, obj, name, mtd["request"], mtd["response"], !!mtd["request_stream"], !!mtd["response_stream"], mtd["options"]));\r
+ }, this);\r
+ this.ptr.addChild(obj);\r
+\r
+ } else if (Builder.isExtend(def)) {\r
+\r
+ obj = this.ptr.resolve(def["ref"], true);\r
+ if (obj) {\r
+ def["fields"].forEach(function(fld) {\r
+ if (obj.getChild(fld['id']|0) !== null)\r
+ throw Error("duplicate extended field id in "+obj.name+": "+fld['id']);\r
+ // Check if field id is allowed to be extended\r
+ if (obj.extensions) {\r
+ var valid = false;\r
+ obj.extensions.forEach(function(range) {\r
+ if (fld["id"] >= range[0] && fld["id"] <= range[1])\r
+ valid = true;\r
+ });\r
+ if (!valid)\r
+ throw Error("illegal extended field id in "+obj.name+": "+fld['id']+" (not within valid ranges)");\r
+ }\r
+ // Convert extension field names to camel case notation if the override is set\r
+ var name = fld["name"];\r
+ if (this.options['convertFieldsToCamelCase'])\r
+ name = ProtoBuf.Util.toCamelCase(name);\r
+ // see #161: Extensions use their fully qualified name as their runtime key and...\r
+ var field = new Reflect.Message.ExtensionField(this, obj, fld["rule"], fld["type"], this.ptr.fqn()+'.'+name, fld["id"], fld["options"]);\r
+ // ...are added on top of the current namespace as an extension which is used for\r
+ // resolving their type later on (the extension always keeps the original name to\r
+ // prevent naming collisions)\r
+ var ext = new Reflect.Extension(this, this.ptr, fld["name"], field);\r
+ field.extension = ext;\r
+ this.ptr.addChild(ext);\r
+ obj.addChild(field);\r
+ }, this);\r
+\r
+ } else if (!/\.?google\.protobuf\./.test(def["ref"])) // Silently skip internal extensions\r
+ throw Error("extended message "+def["ref"]+" is not defined");\r
+\r
+ } else\r
+ throw Error("not a valid definition: "+JSON.stringify(def));\r
+\r
+ def = null;\r
+ obj = null;\r
+ }\r
+ // Break goes here\r
+ defs = null;\r
+ this.ptr = this.ptr.parent; // Namespace done, continue at parent\r
+ }\r
+ this.resolved = false; // Require re-resolve\r
+ this.result = null; // Require re-build\r
+ return this;\r
+ };\r
+\r
+ /**\r
+ * Propagates syntax to all children.\r
+ * @param {!Object} parent\r
+ * @inner\r
+ */\r
+ function propagateSyntax(parent) {\r
+ if (parent['messages']) {\r
+ parent['messages'].forEach(function(child) {\r
+ child["syntax"] = parent["syntax"];\r
+ propagateSyntax(child);\r
+ });\r
+ }\r
+ if (parent['enums']) {\r
+ parent['enums'].forEach(function(child) {\r
+ child["syntax"] = parent["syntax"];\r
+ });\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Imports another definition into this builder.\r
+ * @param {Object.<string,*>} json Parsed import\r
+ * @param {(string|{root: string, file: string})=} filename Imported file name\r
+ * @returns {!ProtoBuf.Builder} this\r
+ * @throws {Error} If the definition or file cannot be imported\r
+ * @expose\r
+ */\r
+ BuilderPrototype["import"] = function(json, filename) {\r
+ var delim = '/';\r
+\r
+ // Make sure to skip duplicate imports\r
+\r
+ if (typeof filename === 'string') {\r
+\r
+ if (ProtoBuf.Util.IS_NODE)\r
+ filename = require("path")['resolve'](filename);\r
+ if (this.files[filename] === true)\r
+ return this.reset();\r
+ this.files[filename] = true;\r
+\r
+ } else if (typeof filename === 'object') { // Object with root, file.\r
+\r
+ var root = filename.root;\r
+ if (ProtoBuf.Util.IS_NODE)\r
+ root = require("path")['resolve'](root);\r
+ if (root.indexOf("\\") >= 0 || filename.file.indexOf("\\") >= 0)\r
+ delim = '\\';\r
+ var fname;\r
+ if (ProtoBuf.Util.IS_NODE)\r
+ fname = require("path")['join'](root, filename.file);\r
+ else\r
+ fname = root + delim + filename.file;\r
+ if (this.files[fname] === true)\r
+ return this.reset();\r
+ this.files[fname] = true;\r
+ }\r
+\r
+ // Import imports\r
+\r
+ if (json['imports'] && json['imports'].length > 0) {\r
+ var importRoot,\r
+ resetRoot = false;\r
+\r
+ if (typeof filename === 'object') { // If an import root is specified, override\r
+\r
+ this.importRoot = filename["root"]; resetRoot = true; // ... and reset afterwards\r
+ importRoot = this.importRoot;\r
+ filename = filename["file"];\r
+ if (importRoot.indexOf("\\") >= 0 || filename.indexOf("\\") >= 0)\r
+ delim = '\\';\r
+\r
+ } else if (typeof filename === 'string') {\r
+\r
+ if (this.importRoot) // If import root is overridden, use it\r
+ importRoot = this.importRoot;\r
+ else { // Otherwise compute from filename\r
+ if (filename.indexOf("/") >= 0) { // Unix\r
+ importRoot = filename.replace(/\/[^\/]*$/, "");\r
+ if (/* /file.proto */ importRoot === "")\r
+ importRoot = "/";\r
+ } else if (filename.indexOf("\\") >= 0) { // Windows\r
+ importRoot = filename.replace(/\\[^\\]*$/, "");\r
+ delim = '\\';\r
+ } else\r
+ importRoot = ".";\r
+ }\r
+\r
+ } else\r
+ importRoot = null;\r
+\r
+ for (var i=0; i<json['imports'].length; i++) {\r
+ if (typeof json['imports'][i] === 'string') { // Import file\r
+ if (!importRoot)\r
+ throw Error("cannot determine import root");\r
+ var importFilename = json['imports'][i];\r
+ if (importFilename === "google/protobuf/descriptor.proto")\r
+ continue; // Not needed and therefore not used\r
+ if (ProtoBuf.Util.IS_NODE)\r
+ importFilename = require("path")['join'](importRoot, importFilename);\r
+ else\r
+ importFilename = importRoot + delim + importFilename;\r
+ if (this.files[importFilename] === true)\r
+ continue; // Already imported\r
+ if (/\.proto$/i.test(importFilename) && !ProtoBuf.DotProto) // If this is a light build\r
+ importFilename = importFilename.replace(/\.proto$/, ".json"); // always load the JSON file\r
+ var contents = ProtoBuf.Util.fetch(importFilename);\r
+ if (contents === null)\r
+ throw Error("failed to import '"+importFilename+"' in '"+filename+"': file not found");\r
+ if (/\.json$/i.test(importFilename)) // Always possible\r
+ this["import"](JSON.parse(contents+""), importFilename); // May throw\r
+ else\r
+ this["import"](ProtoBuf.DotProto.Parser.parse(contents), importFilename); // May throw\r
+ } else // Import structure\r
+ if (!filename)\r
+ this["import"](json['imports'][i]);\r
+ else if (/\.(\w+)$/.test(filename)) // With extension: Append _importN to the name portion to make it unique\r
+ this["import"](json['imports'][i], filename.replace(/^(.+)\.(\w+)$/, function($0, $1, $2) { return $1+"_import"+i+"."+$2; }));\r
+ else // Without extension: Append _importN to make it unique\r
+ this["import"](json['imports'][i], filename+"_import"+i);\r
+ }\r
+ if (resetRoot) // Reset import root override when all imports are done\r
+ this.importRoot = null;\r
+ }\r
+\r
+ // Import structures\r
+\r
+ if (json['package'])\r
+ this.define(json['package']);\r
+ if (json['syntax'])\r
+ propagateSyntax(json);\r
+ var base = this.ptr;\r
+ if (json['options'])\r
+ Object.keys(json['options']).forEach(function(key) {\r
+ base.options[key] = json['options'][key];\r
+ });\r
+ if (json['messages'])\r
+ this.create(json['messages']),\r
+ this.ptr = base;\r
+ if (json['enums'])\r
+ this.create(json['enums']),\r
+ this.ptr = base;\r
+ if (json['services'])\r
+ this.create(json['services']),\r
+ this.ptr = base;\r
+ if (json['extends'])\r
+ this.create(json['extends']);\r
+\r
+ return this.reset();\r
+ };\r
+\r
+ /**\r
+ * Resolves all namespace objects.\r
+ * @throws {Error} If a type cannot be resolved\r
+ * @returns {!ProtoBuf.Builder} this\r
+ * @expose\r
+ */\r
+ BuilderPrototype.resolveAll = function() {\r
+ // Resolve all reflected objects\r
+ var res;\r
+ if (this.ptr == null || typeof this.ptr.type === 'object')\r
+ return this; // Done (already resolved)\r
+\r
+ if (this.ptr instanceof Reflect.Namespace) { // Resolve children\r
+\r
+ this.ptr.children.forEach(function(child) {\r
+ this.ptr = child;\r
+ this.resolveAll();\r
+ }, this);\r
+\r
+ } else if (this.ptr instanceof Reflect.Message.Field) { // Resolve type\r
+\r
+ if (!Lang.TYPE.test(this.ptr.type)) {\r
+ if (!Lang.TYPEREF.test(this.ptr.type))\r
+ throw Error("illegal type reference in "+this.ptr.toString(true)+": "+this.ptr.type);\r
+ res = (this.ptr instanceof Reflect.Message.ExtensionField ? this.ptr.extension.parent : this.ptr.parent).resolve(this.ptr.type, true);\r
+ if (!res)\r
+ throw Error("unresolvable type reference in "+this.ptr.toString(true)+": "+this.ptr.type);\r
+ this.ptr.resolvedType = res;\r
+ if (res instanceof Reflect.Enum) {\r
+ this.ptr.type = ProtoBuf.TYPES["enum"];\r
+ if (this.ptr.syntax === 'proto3' && res.syntax !== 'proto3')\r
+ throw Error("proto3 message cannot reference proto2 enum");\r
+ }\r
+ else if (res instanceof Reflect.Message)\r
+ this.ptr.type = res.isGroup ? ProtoBuf.TYPES["group"] : ProtoBuf.TYPES["message"];\r
+ else\r
+ throw Error("illegal type reference in "+this.ptr.toString(true)+": "+this.ptr.type);\r
+ } else\r
+ this.ptr.type = ProtoBuf.TYPES[this.ptr.type];\r
+\r
+ // If it's a map field, also resolve the key type. The key type can be only a numeric, string, or bool type\r
+ // (i.e., no enums or messages), so we don't need to resolve against the current namespace.\r
+ if (this.ptr.map) {\r
+ if (!Lang.TYPE.test(this.ptr.keyType))\r
+ throw Error("illegal key type for map field in "+this.ptr.toString(true)+": "+this.ptr.keyType);\r
+ this.ptr.keyType = ProtoBuf.TYPES[this.ptr.keyType];\r
+ }\r
+\r
+ // If it's a repeated and packable field then proto3 mandates it should be packed by\r
+ // default\r
+ if (\r
+ this.ptr.syntax === 'proto3' &&\r
+ this.ptr.repeated && this.ptr.options.packed === undefined &&\r
+ ProtoBuf.PACKABLE_WIRE_TYPES.indexOf(this.ptr.type.wireType) !== -1\r
+ ) {\r
+ this.ptr.options.packed = true;\r
+ }\r
+\r
+ } else if (this.ptr instanceof ProtoBuf.Reflect.Service.Method) {\r
+\r
+ if (this.ptr instanceof ProtoBuf.Reflect.Service.RPCMethod) {\r
+ res = this.ptr.parent.resolve(this.ptr.requestName, true);\r
+ if (!res || !(res instanceof ProtoBuf.Reflect.Message))\r
+ throw Error("Illegal type reference in "+this.ptr.toString(true)+": "+this.ptr.requestName);\r
+ this.ptr.resolvedRequestType = res;\r
+ res = this.ptr.parent.resolve(this.ptr.responseName, true);\r
+ if (!res || !(res instanceof ProtoBuf.Reflect.Message))\r
+ throw Error("Illegal type reference in "+this.ptr.toString(true)+": "+this.ptr.responseName);\r
+ this.ptr.resolvedResponseType = res;\r
+ } else // Should not happen as nothing else is implemented\r
+ throw Error("illegal service type in "+this.ptr.toString(true));\r
+\r
+ } else if (\r
+ !(this.ptr instanceof ProtoBuf.Reflect.Message.OneOf) && // Not built\r
+ !(this.ptr instanceof ProtoBuf.Reflect.Extension) && // Not built\r
+ !(this.ptr instanceof ProtoBuf.Reflect.Enum.Value) // Built in enum\r
+ )\r
+ throw Error("illegal object in namespace: "+typeof(this.ptr)+": "+this.ptr);\r
+\r
+ return this.reset();\r
+ };\r
+\r
+ /**\r
+ * Builds the protocol. This will first try to resolve all definitions and, if this has been successful,\r
+ * return the built package.\r
+ * @param {(string|Array.<string>)=} path Specifies what to return. If omitted, the entire namespace will be returned.\r
+ * @returns {!ProtoBuf.Builder.Message|!Object.<string,*>}\r
+ * @throws {Error} If a type could not be resolved\r
+ * @expose\r
+ */\r
+ BuilderPrototype.build = function(path) {\r
+ this.reset();\r
+ if (!this.resolved)\r
+ this.resolveAll(),\r
+ this.resolved = true,\r
+ this.result = null; // Require re-build\r
+ if (this.result === null) // (Re-)Build\r
+ this.result = this.ns.build();\r
+ if (!path)\r
+ return this.result;\r
+ var part = typeof path === 'string' ? path.split(".") : path,\r
+ ptr = this.result; // Build namespace pointer (no hasChild etc.)\r
+ for (var i=0; i<part.length; i++)\r
+ if (ptr[part[i]])\r
+ ptr = ptr[part[i]];\r
+ else {\r
+ ptr = null;\r
+ break;\r
+ }\r
+ return ptr;\r
+ };\r
+\r
+ /**\r
+ * Similar to {@link ProtoBuf.Builder#build}, but looks up the internal reflection descriptor.\r
+ * @param {string=} path Specifies what to return. If omitted, the entire namespace wiil be returned.\r
+ * @param {boolean=} excludeNonNamespace Excludes non-namespace types like fields, defaults to `false`\r
+ * @returns {?ProtoBuf.Reflect.T} Reflection descriptor or `null` if not found\r
+ */\r
+ BuilderPrototype.lookup = function(path, excludeNonNamespace) {\r
+ return path ? this.ns.resolve(path, excludeNonNamespace) : this.ns;\r
+ };\r
+\r
+ /**\r
+ * Returns a string representation of this object.\r
+ * @return {string} String representation as of "Builder"\r
+ * @expose\r
+ */\r
+ BuilderPrototype.toString = function() {\r
+ return "Builder";\r
+ };\r
+\r
+ // ----- Base classes -----\r
+ // Exist for the sole purpose of being able to "... instanceof ProtoBuf.Builder.Message" etc.\r
+\r
+ /**\r
+ * @alias ProtoBuf.Builder.Message\r
+ */\r
+ Builder.Message = function() {};\r
+\r
+ /**\r
+ * @alias ProtoBuf.Builder.Enum\r
+ */\r
+ Builder.Enum = function() {};\r
+\r
+ /**\r
+ * @alias ProtoBuf.Builder.Message\r
+ */\r
+ Builder.Service = function() {};\r
+\r
+ return Builder;\r
+\r
+})(ProtoBuf, ProtoBuf.Lang, ProtoBuf.Reflect);\r