Path: blob/trunk/third_party/closure/goog/proto2/pbliteserializer.js
2868 views
// Copyright 2008 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview Protocol Buffer 2 Serializer which serializes messages16* into PB-Lite ("JsPbLite") format.17*18* PB-Lite format is an array where each index corresponds to the associated tag19* number. For example, a message like so:20*21* message Foo {22* optional int bar = 1;23* optional int baz = 2;24* optional int bop = 4;25* }26*27* would be represented as such:28*29* [, (bar data), (baz data), (nothing), (bop data)]30*31* Note that since the array index is used to represent the tag number, sparsely32* populated messages with tag numbers that are not continuous (and/or are very33* large) will have many (empty) spots and thus, are inefficient.34*35*36*/3738goog.provide('goog.proto2.PbLiteSerializer');3940goog.require('goog.asserts');41goog.require('goog.proto2.FieldDescriptor');42goog.require('goog.proto2.LazyDeserializer');43goog.require('goog.proto2.Serializer');44454647/**48* PB-Lite serializer.49*50* @constructor51* @extends {goog.proto2.LazyDeserializer}52*/53goog.proto2.PbLiteSerializer = function() {};54goog.inherits(goog.proto2.PbLiteSerializer, goog.proto2.LazyDeserializer);555657/**58* If true, fields will be serialized with 0-indexed tags (i.e., the proto59* field with tag id 1 will have index 0 in the array).60* @type {boolean}61* @private62*/63goog.proto2.PbLiteSerializer.prototype.zeroIndexing_ = false;646566/**67* By default, the proto tag with id 1 will have index 1 in the serialized68* array.69*70* If the serializer is set to use zero-indexing, the tag with id 1 will have71* index 0.72*73* @param {boolean} zeroIndexing Whether this serializer should deal with74* 0-indexed protos.75*/76goog.proto2.PbLiteSerializer.prototype.setZeroIndexed = function(zeroIndexing) {77this.zeroIndexing_ = zeroIndexing;78};798081/**82* Serializes a message to a PB-Lite object.83*84* @param {goog.proto2.Message} message The message to be serialized.85* @return {!Array<?>} The serialized form of the message.86* @override87*/88goog.proto2.PbLiteSerializer.prototype.serialize = function(message) {89var descriptor = message.getDescriptor();90var fields = descriptor.getFields();9192var serialized = [];93var zeroIndexing = this.zeroIndexing_;9495// Add the known fields.96for (var i = 0; i < fields.length; i++) {97var field = fields[i];9899if (!message.has(field)) {100continue;101}102103var tag = field.getTag();104var index = zeroIndexing ? tag - 1 : tag;105106if (field.isRepeated()) {107serialized[index] = [];108109for (var j = 0; j < message.countOf(field); j++) {110serialized[index][j] =111this.getSerializedValue(field, message.get(field, j));112}113} else {114serialized[index] = this.getSerializedValue(field, message.get(field));115}116}117118// Add any unknown fields.119message.forEachUnknown(function(tag, value) {120var index = zeroIndexing ? tag - 1 : tag;121serialized[index] = value;122});123124return serialized;125};126127128/** @override */129goog.proto2.PbLiteSerializer.prototype.deserializeField = function(130message, field, value) {131132if (value == null) {133// Since value double-equals null, it may be either null or undefined.134// Ensure we return the same one, since they have different meanings.135// TODO(user): If the field is repeated, this method should probably136// return [] instead of null.137return value;138}139140if (field.isRepeated()) {141var data = [];142143goog.asserts.assert(goog.isArray(value), 'Value must be array: %s', value);144145for (var i = 0; i < value.length; i++) {146data[i] = this.getDeserializedValue(field, value[i]);147}148149return data;150} else {151return this.getDeserializedValue(field, value);152}153};154155156/** @override */157goog.proto2.PbLiteSerializer.prototype.getSerializedValue = function(158field, value) {159if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.BOOL) {160// Booleans are serialized in numeric form.161return value ? 1 : 0;162}163164return goog.proto2.Serializer.prototype.getSerializedValue.apply(165this, arguments);166};167168169/** @override */170goog.proto2.PbLiteSerializer.prototype.getDeserializedValue = function(171field, value) {172173if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.BOOL) {174goog.asserts.assert(175goog.isNumber(value) || goog.isBoolean(value),176'Value is expected to be a number or boolean');177return !!value;178}179180return goog.proto2.Serializer.prototype.getDeserializedValue.apply(181this, arguments);182};183184185/** @override */186goog.proto2.PbLiteSerializer.prototype.deserialize = function(187descriptor, data) {188var toConvert = data;189if (this.zeroIndexing_) {190// Make the data align with tag-IDs (1-indexed) by shifting everything191// up one.192toConvert = [];193for (var key in data) {194toConvert[parseInt(key, 10) + 1] = data[key];195}196}197return goog.proto2.PbLiteSerializer.base(198this, 'deserialize', descriptor, toConvert);199};200201202