--- /dev/null
+var ProtoBuf = require("protobufjs"),\r
+ ByteBuffer = ProtoBuf.ByteBuffer, // ProtoBuf.js uses and also exposes ByteBuffer.js\r
+ Long = ProtoBuf.Long; // as well as Long.js (not used in this example)\r
+\r
+// Option 1: Loading the .proto file directly\r
+var builder = ProtoBuf.loadProtoFile("./json.proto"), // Creates the Builder\r
+ JS = builder.build("js"); // Returns just the 'js' namespace if that's all we need\r
+\r
+// Option 2: Loading the .json file generated through 'proto2js json.proto > json.json'\r
+var root = ProtoBuf.loadJsonFile("./json.json").build(), // Here we make the Builder return the root namespace\r
+ JS = root.js; // then we reference 'js' inside. Both is possible.\r
+\r
+// Option 3: Loading the module generated through 'proto2js json.proto -commonjs=js > json.js'\r
+var JS = require("./json.js"); // Returns what is specified with -commonjs[=XX] (omitted=root)\r
+\r
+// `JS` now contains the js namespace from json.proto: Value, Array and Object\r
+\r
+// This is how we use these classes:\r
+\r
+/**\r
+ * Converts a JSON-like structure to JS-Namespace values.\r
+ * @param {*} val JSON\r
+ * @returns {!JS.Value} JS-Namespace value\r
+ * @inner\r
+ */\r
+function _protoify(val) {\r
+ switch (typeof val) {\r
+ case 'number':\r
+ if (val%1 === 0 && val >= (0x80000000|0) && val <= (0x7fffffff|0))\r
+ return new JS.Value(val); // sets the first field declared in .js.Value\r
+ else\r
+ return new JS.Value(null, val); // sets the second field\r
+ case 'string':\r
+ return new JS.Value({ 'string': val }); // uses object notation instead\r
+ case 'boolean':\r
+ return new JS.Value({ 'boolean': val });\r
+ case 'object':\r
+ if (val === null)\r
+ return new JS.Value({ 'null': true });\r
+ if (Object.prototype.toString.call(val) === "[object Array]") {\r
+ var arr = new JS.Array();\r
+ for (var i=0; i<val.length; ++i)\r
+ arr['values'][i] = _protoify(val[i]);\r
+ return new JS.Value({ 'array': arr });\r
+ }\r
+ var obj = new JS.Object();\r
+ for (var key in val)\r
+ if (val.hasOwnProperty(key))\r
+ obj['keys'].push(_protoify(key)),\r
+ obj['values'].push(_protoify(val[key]));\r
+ return new JS.Value({ 'object': obj });\r
+ case 'undefined':\r
+ return new JS.Value(); // undefined\r
+ default:\r
+ throw Error("Unsupported type: "+(typeof val)); // symbol, function\r
+ }\r
+}\r
+\r
+/**\r
+ * Converts JS-Namespace values to JSON.\r
+ * @param {!JS.Value} value JS value\r
+ * @returns {*} JSON\r
+ * @inner\r
+ */\r
+function _jsonify(value) {\r
+ if (value.type === null)\r
+ return undefined;\r
+ switch (value.type) {\r
+ case 'null':\r
+ return null;\r
+ case 'array':\r
+ return (function() {\r
+ var values = value['array']['values'],\r
+ i = 0,\r
+ k = values.length,\r
+ arr = new Array(k);\r
+ for (; i<k; ++i)\r
+ arr[i] = _jsonify(values[i]);\r
+ return arr;\r
+ })();\r
+ case 'object':\r
+ return (function() {\r
+ var keys = value['object']['keys'],\r
+ values = value['object']['values'],\r
+ i = 0,\r
+ k = keys.length,\r
+ obj = {};\r
+ for (; i<k; ++i)\r
+ obj[keys[i]['string'] /* is a JS.Value, here always a string */] = _jsonify(values[i]);\r
+ return obj;\r
+ })();\r
+ default:\r
+ return value[value.type];\r
+ }\r
+}\r
+\r
+// And this is how we actually encode and decode them:\r
+\r
+/**\r
+ * A temporary Buffer to speed up encoding.\r
+ * @type {!ByteBuffer}\r
+ * @inner\r
+ */\r
+var tempBuffer = ByteBuffer.allocate(1024);\r
+\r
+/**\r
+ * Converts a JSON structure to a Buffer.\r
+ * @param {*} json JSON\r
+ * @returns {!Buffer|!ArrayBuffer}\r
+ * @expose\r
+ */\r
+module.exports = function(json) {\r
+ return _protoify(json) // Returns the root JS.Value\r
+ .encode(tempBuffer).flip() // Encodes it to a ByteBuffer, here: reusing tempBuffer forever\r
+ // The non-tempBuffer alternative is just doing .encode()\r
+ .toBuffer(); // Converts it to a Buffer. In the browser, this returns an ArrayBuffer. To return an\r
+ // ArrayBuffer explicitly both under node.js and in the browser, use .toArrayBuffer().\r
+ // Performance note: This just returns a slice on the ByteBuffer's backing .buffer\r
+};\r
+\r
+/**\r
+ * Converts a Buffer to a JSON structure.\r
+ * @param {!Buffer|!ArrayBuffer} proto Buffer\r
+ * @returns {*} JSON\r
+ * @expose\r
+ */\r
+module.exports.parse = function(proto) {\r
+ return _jsonify( // Processes JS-namespace objects\r
+ JS.Value.decode(proto) // Decodes the JS.Value from a ByteBuffer, a Buffer, an ArrayBuffer, an Uint8Array, ...\r
+ );\r
+};\r
+\r
+/**\r
+ * Performs maintenance.\r
+ * @expose\r
+ */\r
+module.exports.performMaintenance = function() {\r
+ if (tempBuffer.capacity() > 2048)\r
+ tempBuffer = ByteBuffer.allocate(1024);\r
+ // In case this module is running inside of a daemon, we'd just call this\r
+ // method every now and then to discard the tempBuffer if it becomes too\r
+ // large. This is just an example on how to reuse ByteBuffers effectively.\r
+ // You may consider something like this for the performance benefit, which\r
+ // is decreasing the memory allocation footprint of your app.\r
+};\r
+\r
+// Have a nice day!\r