// Copyright 2014 Cognitect. 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. goog.provide("com.cognitect.transit.handlers"); goog.require("com.cognitect.transit.util"); goog.require("com.cognitect.transit.types"); goog.require("goog.math.Long"); goog.scope(function () { var handlers = com.cognitect.transit.handlers, util = com.cognitect.transit.util, types = com.cognitect.transit.types, Long = goog.math.Long; handlers.ctorGuid = 0; /** * @const * @type {string} */ handlers.ctorGuidProperty = "transit$guid$" + util.randomUUID(); handlers.typeTag = function (ctor) { if (ctor == null) { return "null"; } else if (ctor === String) { return "string"; } else if (ctor === Boolean) { return "boolean"; } else if (ctor === Number) { return "number"; } else if (ctor === Array) { return "array"; } else if (ctor === Object) { return "map"; } else { var tag = ctor[handlers.ctorGuidProperty]; if (tag == null) { if (typeof Object.defineProperty != "undefined") { tag = ++handlers.ctorGuid; Object.defineProperty(ctor, handlers.ctorGuidProperty, { value: tag, enumerable: false }); } else { ctor[handlers.ctorGuidProperty] = tag = ++handlers.ctorGuid; } } return tag; } }; handlers.constructor = function (x) { if (x == null) { return null; } else { return x.constructor; } }; handlers.padZeros = function (n, m) { var s = n.toString(); for (var i = s.length; i < m; i++) { s = "0" + s; } return s; }; handlers.stringableKeys = function (m) { var stringable = false, ks = util.objectKeys(m); for (var i = 0; i < ks.length; i++) { } return true; }; /** * @constructor */ handlers.NilHandler = function Transit$NilHandler() { }; handlers.NilHandler.prototype.tag = function (v) { return "_"; }; handlers.NilHandler.prototype.rep = function (v) { return null; }; handlers.NilHandler.prototype.stringRep = function (v) { return "null"; }; /** * @constructor */ handlers.StringHandler = function Transit$StringHandler() { }; handlers.StringHandler.prototype.tag = function (v) { return "s"; }; handlers.StringHandler.prototype.rep = function (v) { return v; }; handlers.StringHandler.prototype.stringRep = function (v) { return v; }; /** * @constructor */ handlers.NumberHandler = function Transit$NumberHandler() { }; handlers.NumberHandler.prototype.tag = function (v) { return "i"; }; handlers.NumberHandler.prototype.rep = function (v) { return v; }; handlers.NumberHandler.prototype.stringRep = function (v) { return v.toString(); }; /** * @constructor */ handlers.IntegerHandler = function Transit$IntegerHandler() { }; handlers.IntegerHandler.prototype.tag = function (v) { return "i"; }; handlers.IntegerHandler.prototype.rep = function (v) { return v.toString(); }; handlers.IntegerHandler.prototype.stringRep = function (v) { return v.toString(); }; /** * @constructor */ handlers.BooleanHandler = function Transit$BooleanHandler() { }; handlers.BooleanHandler.prototype.tag = function (v) { return "?"; }; handlers.BooleanHandler.prototype.rep = function (v) { return v; }; handlers.BooleanHandler.prototype.stringRep = function (v) { return v.toString(); }; /** * @constructor */ handlers.ArrayHandler = function Transit$ArrayHandler() { }; handlers.ArrayHandler.prototype.tag = function (v) { return "array"; }; handlers.ArrayHandler.prototype.rep = function (v) { return v; }; handlers.ArrayHandler.prototype.stringRep = function (v) { return null; }; /** * @constructor */ handlers.MapHandler = function Transit$MapHandler() { }; handlers.MapHandler.prototype.tag = function (v) { return "map"; }; handlers.MapHandler.prototype.rep = function (v) { return v; }; handlers.MapHandler.prototype.stringRep = function (v) { return null; }; /** * @constructor */ handlers.VerboseDateHandler = function Transit$VerboseDateHandler() { }; handlers.VerboseDateHandler.prototype.tag = function (v) { return "t"; }; handlers.VerboseDateHandler.prototype.rep = function (v) { return v.getUTCFullYear() + "-" + handlers.padZeros(v.getUTCMonth() + 1, 2) + "-" + handlers.padZeros(v.getUTCDate(), 2) + "T" + handlers.padZeros(v.getUTCHours(), 2) + ":" + handlers.padZeros(v.getUTCMinutes(), 2) + ":" + handlers.padZeros(v.getUTCSeconds(), 2) + "." + handlers.padZeros(v.getUTCMilliseconds(), 3) + "Z"; }; handlers.VerboseDateHandler.prototype.stringRep = function (v, h) { return h.rep(v); }; /** * @constructor */ handlers.DateHandler = function Transit$DateHandler() { }; handlers.DateHandler.prototype.tag = function (v) { return "m"; }; handlers.DateHandler.prototype.rep = function (v) { return v.valueOf(); }; handlers.DateHandler.prototype.stringRep = function (v) { return v.valueOf().toString(); }; handlers.DateHandler.prototype.getVerboseHandler = function (v) { return new handlers.VerboseDateHandler(); }; /** * @constructor */ handlers.UUIDHandler = function Transit$UUIDHandler() { }; handlers.UUIDHandler.prototype.tag = function (v) { return "u"; }; handlers.UUIDHandler.prototype.rep = function (v) { return v.toString(); }; handlers.UUIDHandler.prototype.stringRep = function (v) { return v.toString(); }; /** * @constructor */ handlers.KeywordHandler = function Transit$KeywordHandler() { }; handlers.KeywordHandler.prototype.tag = function (v) { return ":"; }; handlers.KeywordHandler.prototype.rep = function (v) { return v._name; }; // NOTE: should be fqn handlers.KeywordHandler.prototype.stringRep = function (v, h) { return h.rep(v); }; /** * @constructor */ handlers.SymbolHandler = function Transit$SymbolHandler() { }; handlers.SymbolHandler.prototype.tag = function (v) { return "$"; }; handlers.SymbolHandler.prototype.rep = function (v) { return v._name; }; // NOTE: should be str handlers.SymbolHandler.prototype.stringRep = function (v, h) { return h.rep(v); }; /** * @constructor */ handlers.TaggedHandler = function Transit$TaggedHandler() { }; handlers.TaggedHandler.prototype.tag = function (v) { return v.tag; }; handlers.TaggedHandler.prototype.rep = function (v) { return v.rep; }; handlers.TaggedHandler.prototype.stringRep = function (v, h) { return null; }; /** * @constructor */ handlers.TransitSetHandler = function Transit$TransitSetHandler() { }; handlers.TransitSetHandler.prototype.tag = function (v) { return "set"; }; handlers.TransitSetHandler.prototype.rep = function (v) { var arr = []; v.forEach(function (key, set) { arr.push(key); }); return types.taggedValue("array", arr); }; handlers.TransitSetHandler.prototype.stringRep = function (v, h) { return null; }; /** * @constructor */ handlers.TransitArrayMapHandler = function Transit$ArrayMapHandler() { }; handlers.TransitArrayMapHandler.prototype.tag = function (v) { return "map"; }; handlers.TransitArrayMapHandler.prototype.rep = function (v) { return v; }; handlers.TransitArrayMapHandler.prototype.stringRep = function (v, h) { return null; }; /** * @constructor */ handlers.TransitMapHandler = function Transit$MapHandler() { }; handlers.TransitMapHandler.prototype.tag = function (v) { return "map"; }; handlers.TransitMapHandler.prototype.rep = function (v) { return v; }; handlers.TransitMapHandler.prototype.stringRep = function (v, h) { return null; }; /** * @constructor */ handlers.BufferHandler = function Transit$BufferHandler() { }; handlers.BufferHandler.prototype.tag = function (v) { return "b"; }; handlers.BufferHandler.prototype.rep = function (v) { return v.toString("base64"); }; handlers.BufferHandler.prototype.stringRep = function (v, h) { return null; }; /** * @constructor */ handlers.Uint8ArrayHandler = function Transit$Uint8ArrayHandler() { }; handlers.Uint8ArrayHandler.prototype.tag = function (v) { return "b"; }; handlers.Uint8ArrayHandler.prototype.rep = function (v) { return util.Uint8ToBase64(v); }; handlers.Uint8ArrayHandler.prototype.stringRep = function (v, h) { return null; }; handlers.defaultHandlers = function (hs) { hs.set(null, new handlers.NilHandler()); hs.set(String, new handlers.StringHandler()); hs.set(Number, new handlers.NumberHandler()); hs.set(Long, new handlers.IntegerHandler()); hs.set(Boolean, new handlers.BooleanHandler()); hs.set(Array, new handlers.ArrayHandler()); hs.set(Object, new handlers.MapHandler()); hs.set(Date, new handlers.DateHandler()); hs.set(types.UUID, new handlers.UUIDHandler()); hs.set(types.Keyword, new handlers.KeywordHandler()); hs.set(types.Symbol, new handlers.SymbolHandler()); hs.set(types.TaggedValue, new handlers.TaggedHandler()); hs.set(types.TransitSet, new handlers.TransitSetHandler()); hs.set(types.TransitArrayMap, new handlers.TransitArrayMapHandler()); hs.set(types.TransitMap, new handlers.TransitMapHandler()); if (typeof Buffer != "undefined") { hs.set(Buffer, new handlers.BufferHandler()); } if (typeof Uint8Array != "undefined") { hs.set(Uint8Array, new handlers.Uint8ArrayHandler()); } return hs; }; /** * @constructor */ handlers.Handlers = function Transit$Handlers() { this.handlers = {}; handlers.defaultHandlers(this); }; handlers.Handlers.prototype.get = function (ctor) { var h = null; if (typeof ctor === "string") { h = this.handlers[ctor]; } else { h = this.handlers[handlers.typeTag(ctor)]; } if (h != null) { return h; } else { return this.handlers["default"]; } }; handlers.Handlers.prototype["get"] = handlers.Handlers.prototype.get; handlers.validTag = function (tag) { switch (tag) { case "null": case "string": case "boolean": case "number": case "array": case "map": return false; break; } return true; }; handlers.Handlers.prototype.set = function (ctor, handler) { if (typeof ctor === "string" && handlers.validTag(ctor)) { this.handlers[ctor] = handler; } else { this.handlers[handlers.typeTag(ctor)] = handler; } }; });