/*eslint-disable*/
/**
 * @fileoverview
 * @enhanceable
 * @public
 */
// GENERATED CODE -- DO NOT EDIT!

var jspb = require('google-protobuf');
var goog = jspb;
var global = Function('return this')();

goog.exportSymbol('proto.Outer', null, global);
goog.exportSymbol('proto.Test', null, global);
goog.exportSymbol('proto.Test.Enum', null, global);
goog.exportSymbol('proto.Test.Inner', null, global);
goog.exportSymbol('proto.Test.Inner.InnerInner', null, global);

/**
 * Generated by JsPbCodeGenerator.
 * @param {Array=} opt_data Optional initial data array, typically from a
 * server response, or constructed directly in Javascript. The array is used
 * in place and becomes part of the constructed object. It is not cloned.
 * If no data is provided, the constructed object will be empty, but still
 * valid.
 * @extends {jspb.Message}
 * @constructor
 */
proto.Test = function(opt_data) {
  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.Test, jspb.Message);
if (goog.DEBUG && !COMPILED) {
  proto.Test.displayName = 'proto.Test';
}


if (jspb.Message.GENERATE_TO_OBJECT) {
/**
 * Creates an object representation of this proto suitable for use in Soy templates.
 * Field names that are reserved in JavaScript and will be renamed to pb_name.
 * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
 * For the list of reserved names please see:
 *     com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
 * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
 *     for transitional soy proto support: http://goto/soy-param-migration
 * @return {!Object}
 */
proto.Test.prototype.toObject = function(opt_includeInstance) {
  return proto.Test.toObject(opt_includeInstance, this);
};


/**
 * Static version of the {@see toObject} method.
 * @param {boolean|undefined} includeInstance Whether to include the JSPB
 *     instance for transitional soy proto support:
 *     http://goto/soy-param-migration
 * @param {!proto.Test} msg The msg instance to transform.
 * @return {!Object}
 */
proto.Test.toObject = function(includeInstance, msg) {
  var f, obj = {
    string: jspb.Message.getFieldWithDefault(msg, 1, ""),
    uint32: jspb.Message.getFieldWithDefault(msg, 2, 0),
    inner: (f = msg.getInner()) && proto.Test.Inner.toObject(includeInstance, f),
    pb_float: +jspb.Message.getFieldWithDefault(msg, 4, 0.0)
  };

  if (includeInstance) {
    obj.$jspbMessageInstance = msg;
  }
  return obj;
};
}


/**
 * Deserializes binary data (in protobuf wire format).
 * @param {jspb.ByteSource} bytes The bytes to deserialize.
 * @return {!proto.Test}
 */
proto.Test.deserializeBinary = function(bytes) {
  var reader = new jspb.BinaryReader(bytes);
  var msg = new proto.Test;
  return proto.Test.deserializeBinaryFromReader(msg, reader);
};


/**
 * Deserializes binary data (in protobuf wire format) from the
 * given reader into the given message object.
 * @param {!proto.Test} msg The message object to deserialize into.
 * @param {!jspb.BinaryReader} reader The BinaryReader to use.
 * @return {!proto.Test}
 */
proto.Test.deserializeBinaryFromReader = function(msg, reader) {
  while (reader.nextField()) {
    if (reader.isEndGroup()) {
      break;
    }
    var field = reader.getFieldNumber();
    switch (field) {
    case 1:
      var value = /** @type {string} */ (reader.readString());
      msg.setString(value);
      break;
    case 2:
      var value = /** @type {number} */ (reader.readUint32());
      msg.setUint32(value);
      break;
    case 3:
      var value = new proto.Test.Inner;
      reader.readMessage(value,proto.Test.Inner.deserializeBinaryFromReader);
      msg.setInner(value);
      break;
    case 4:
      var value = /** @type {number} */ (reader.readFloat());
      msg.setFloat(value);
      break;
    default:
      reader.skipField();
      break;
    }
  }
  return msg;
};


/**
 * Serializes the message to binary data (in protobuf wire format).
 * @return {!Uint8Array}
 */
proto.Test.prototype.serializeBinary = function() {
  var writer = new jspb.BinaryWriter();
  proto.Test.serializeBinaryToWriter(this, writer);
  return writer.getResultBuffer();
};


/**
 * Serializes the given message to binary data (in protobuf wire
 * format), writing to the given BinaryWriter.
 * @param {!proto.Test} message
 * @param {!jspb.BinaryWriter} writer
 */
proto.Test.serializeBinaryToWriter = function(message, writer) {
  var f = undefined;
  f = message.getString();
  if (f.length > 0) {
    writer.writeString(
      1,
      f
    );
  }
  f = message.getUint32();
  if (f !== 0) {
    writer.writeUint32(
      2,
      f
    );
  }
  f = message.getInner();
  if (f != null) {
    writer.writeMessage(
      3,
      f,
      proto.Test.Inner.serializeBinaryToWriter
    );
  }
  f = message.getFloat();
  if (f !== 0.0) {
    writer.writeFloat(
      4,
      f
    );
  }
};


/**
 * @enum {number}
 */
proto.Test.Enum = {
  ONE: 0,
  TWO: 1,
  THREE: 2,
  FOUR: 3,
  FIVE: 4
};


/**
 * Generated by JsPbCodeGenerator.
 * @param {Array=} opt_data Optional initial data array, typically from a
 * server response, or constructed directly in Javascript. The array is used
 * in place and becomes part of the constructed object. It is not cloned.
 * If no data is provided, the constructed object will be empty, but still
 * valid.
 * @extends {jspb.Message}
 * @constructor
 */
proto.Test.Inner = function(opt_data) {
  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.Test.Inner, jspb.Message);
if (goog.DEBUG && !COMPILED) {
  proto.Test.Inner.displayName = 'proto.Test.Inner';
}


if (jspb.Message.GENERATE_TO_OBJECT) {
/**
 * Creates an object representation of this proto suitable for use in Soy templates.
 * Field names that are reserved in JavaScript and will be renamed to pb_name.
 * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
 * For the list of reserved names please see:
 *     com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
 * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
 *     for transitional soy proto support: http://goto/soy-param-migration
 * @return {!Object}
 */
proto.Test.Inner.prototype.toObject = function(opt_includeInstance) {
  return proto.Test.Inner.toObject(opt_includeInstance, this);
};


/**
 * Static version of the {@see toObject} method.
 * @param {boolean|undefined} includeInstance Whether to include the JSPB
 *     instance for transitional soy proto support:
 *     http://goto/soy-param-migration
 * @param {!proto.Test.Inner} msg The msg instance to transform.
 * @return {!Object}
 */
proto.Test.Inner.toObject = function(includeInstance, msg) {
  var f, obj = {
    int32: jspb.Message.getFieldWithDefault(msg, 1, 0),
    innerinner: (f = msg.getInnerinner()) && proto.Test.Inner.InnerInner.toObject(includeInstance, f),
    outer: (f = msg.getOuter()) && proto.Outer.toObject(includeInstance, f)
  };

  if (includeInstance) {
    obj.$jspbMessageInstance = msg;
  }
  return obj;
};
}


/**
 * Deserializes binary data (in protobuf wire format).
 * @param {jspb.ByteSource} bytes The bytes to deserialize.
 * @return {!proto.Test.Inner}
 */
proto.Test.Inner.deserializeBinary = function(bytes) {
  var reader = new jspb.BinaryReader(bytes);
  var msg = new proto.Test.Inner;
  return proto.Test.Inner.deserializeBinaryFromReader(msg, reader);
};


/**
 * Deserializes binary data (in protobuf wire format) from the
 * given reader into the given message object.
 * @param {!proto.Test.Inner} msg The message object to deserialize into.
 * @param {!jspb.BinaryReader} reader The BinaryReader to use.
 * @return {!proto.Test.Inner}
 */
proto.Test.Inner.deserializeBinaryFromReader = function(msg, reader) {
  while (reader.nextField()) {
    if (reader.isEndGroup()) {
      break;
    }
    var field = reader.getFieldNumber();
    switch (field) {
    case 1:
      var value = /** @type {number} */ (reader.readInt32());
      msg.setInt32(value);
      break;
    case 2:
      var value = new proto.Test.Inner.InnerInner;
      reader.readMessage(value,proto.Test.Inner.InnerInner.deserializeBinaryFromReader);
      msg.setInnerinner(value);
      break;
    case 3:
      var value = new proto.Outer;
      reader.readMessage(value,proto.Outer.deserializeBinaryFromReader);
      msg.setOuter(value);
      break;
    default:
      reader.skipField();
      break;
    }
  }
  return msg;
};


/**
 * Serializes the message to binary data (in protobuf wire format).
 * @return {!Uint8Array}
 */
proto.Test.Inner.prototype.serializeBinary = function() {
  var writer = new jspb.BinaryWriter();
  proto.Test.Inner.serializeBinaryToWriter(this, writer);
  return writer.getResultBuffer();
};


/**
 * Serializes the given message to binary data (in protobuf wire
 * format), writing to the given BinaryWriter.
 * @param {!proto.Test.Inner} message
 * @param {!jspb.BinaryWriter} writer
 */
proto.Test.Inner.serializeBinaryToWriter = function(message, writer) {
  var f = undefined;
  f = message.getInt32();
  if (f !== 0) {
    writer.writeInt32(
      1,
      f
    );
  }
  f = message.getInnerinner();
  if (f != null) {
    writer.writeMessage(
      2,
      f,
      proto.Test.Inner.InnerInner.serializeBinaryToWriter
    );
  }
  f = message.getOuter();
  if (f != null) {
    writer.writeMessage(
      3,
      f,
      proto.Outer.serializeBinaryToWriter
    );
  }
};



/**
 * Generated by JsPbCodeGenerator.
 * @param {Array=} opt_data Optional initial data array, typically from a
 * server response, or constructed directly in Javascript. The array is used
 * in place and becomes part of the constructed object. It is not cloned.
 * If no data is provided, the constructed object will be empty, but still
 * valid.
 * @extends {jspb.Message}
 * @constructor
 */
proto.Test.Inner.InnerInner = function(opt_data) {
  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.Test.Inner.InnerInner, jspb.Message);
if (goog.DEBUG && !COMPILED) {
  proto.Test.Inner.InnerInner.displayName = 'proto.Test.Inner.InnerInner';
}


if (jspb.Message.GENERATE_TO_OBJECT) {
/**
 * Creates an object representation of this proto suitable for use in Soy templates.
 * Field names that are reserved in JavaScript and will be renamed to pb_name.
 * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
 * For the list of reserved names please see:
 *     com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
 * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
 *     for transitional soy proto support: http://goto/soy-param-migration
 * @return {!Object}
 */
proto.Test.Inner.InnerInner.prototype.toObject = function(opt_includeInstance) {
  return proto.Test.Inner.InnerInner.toObject(opt_includeInstance, this);
};


/**
 * Static version of the {@see toObject} method.
 * @param {boolean|undefined} includeInstance Whether to include the JSPB
 *     instance for transitional soy proto support:
 *     http://goto/soy-param-migration
 * @param {!proto.Test.Inner.InnerInner} msg The msg instance to transform.
 * @return {!Object}
 */
proto.Test.Inner.InnerInner.toObject = function(includeInstance, msg) {
  var f, obj = {
    pb_long: jspb.Message.getFieldWithDefault(msg, 1, 0),
    pb_enum: jspb.Message.getFieldWithDefault(msg, 2, 0),
    sint32: jspb.Message.getFieldWithDefault(msg, 3, 0)
  };

  if (includeInstance) {
    obj.$jspbMessageInstance = msg;
  }
  return obj;
};
}


/**
 * Deserializes binary data (in protobuf wire format).
 * @param {jspb.ByteSource} bytes The bytes to deserialize.
 * @return {!proto.Test.Inner.InnerInner}
 */
proto.Test.Inner.InnerInner.deserializeBinary = function(bytes) {
  var reader = new jspb.BinaryReader(bytes);
  var msg = new proto.Test.Inner.InnerInner;
  return proto.Test.Inner.InnerInner.deserializeBinaryFromReader(msg, reader);
};


/**
 * Deserializes binary data (in protobuf wire format) from the
 * given reader into the given message object.
 * @param {!proto.Test.Inner.InnerInner} msg The message object to deserialize into.
 * @param {!jspb.BinaryReader} reader The BinaryReader to use.
 * @return {!proto.Test.Inner.InnerInner}
 */
proto.Test.Inner.InnerInner.deserializeBinaryFromReader = function(msg, reader) {
  while (reader.nextField()) {
    if (reader.isEndGroup()) {
      break;
    }
    var field = reader.getFieldNumber();
    switch (field) {
    case 1:
      var value = /** @type {number} */ (reader.readInt64());
      msg.setLong(value);
      break;
    case 2:
      var value = /** @type {!proto.Test.Enum} */ (reader.readEnum());
      msg.setEnum(value);
      break;
    case 3:
      var value = /** @type {number} */ (reader.readSint32());
      msg.setSint32(value);
      break;
    default:
      reader.skipField();
      break;
    }
  }
  return msg;
};


/**
 * Serializes the message to binary data (in protobuf wire format).
 * @return {!Uint8Array}
 */
proto.Test.Inner.InnerInner.prototype.serializeBinary = function() {
  var writer = new jspb.BinaryWriter();
  proto.Test.Inner.InnerInner.serializeBinaryToWriter(this, writer);
  return writer.getResultBuffer();
};


/**
 * Serializes the given message to binary data (in protobuf wire
 * format), writing to the given BinaryWriter.
 * @param {!proto.Test.Inner.InnerInner} message
 * @param {!jspb.BinaryWriter} writer
 */
proto.Test.Inner.InnerInner.serializeBinaryToWriter = function(message, writer) {
  var f = undefined;
  f = message.getLong();
  if (f !== 0) {
    writer.writeInt64(
      1,
      f
    );
  }
  f = message.getEnum();
  if (f !== 0.0) {
    writer.writeEnum(
      2,
      f
    );
  }
  f = message.getSint32();
  if (f !== 0) {
    writer.writeSint32(
      3,
      f
    );
  }
};


/**
 * optional int64 long = 1;
 * @return {number}
 */
proto.Test.Inner.InnerInner.prototype.getLong = function() {
  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
};


/** @param {number} value */
proto.Test.Inner.InnerInner.prototype.setLong = function(value) {
  jspb.Message.setField(this, 1, value);
};


/**
 * optional Enum enum = 2;
 * @return {!proto.Test.Enum}
 */
proto.Test.Inner.InnerInner.prototype.getEnum = function() {
  return /** @type {!proto.Test.Enum} */ (jspb.Message.getFieldWithDefault(this, 2, 0));
};


/** @param {!proto.Test.Enum} value */
proto.Test.Inner.InnerInner.prototype.setEnum = function(value) {
  jspb.Message.setField(this, 2, value);
};


/**
 * optional sint32 sint32 = 3;
 * @return {number}
 */
proto.Test.Inner.InnerInner.prototype.getSint32 = function() {
  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0));
};


/** @param {number} value */
proto.Test.Inner.InnerInner.prototype.setSint32 = function(value) {
  jspb.Message.setField(this, 3, value);
};


/**
 * optional int32 int32 = 1;
 * @return {number}
 */
proto.Test.Inner.prototype.getInt32 = function() {
  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
};


/** @param {number} value */
proto.Test.Inner.prototype.setInt32 = function(value) {
  jspb.Message.setField(this, 1, value);
};


/**
 * optional InnerInner innerInner = 2;
 * @return {?proto.Test.Inner.InnerInner}
 */
proto.Test.Inner.prototype.getInnerinner = function() {
  return /** @type{?proto.Test.Inner.InnerInner} */ (
    jspb.Message.getWrapperField(this, proto.Test.Inner.InnerInner, 2));
};


/** @param {?proto.Test.Inner.InnerInner|undefined} value */
proto.Test.Inner.prototype.setInnerinner = function(value) {
  jspb.Message.setWrapperField(this, 2, value);
};


proto.Test.Inner.prototype.clearInnerinner = function() {
  this.setInnerinner(undefined);
};


/**
 * Returns whether this field is set.
 * @return {!boolean}
 */
proto.Test.Inner.prototype.hasInnerinner = function() {
  return jspb.Message.getField(this, 2) != null;
};


/**
 * optional Outer outer = 3;
 * @return {?proto.Outer}
 */
proto.Test.Inner.prototype.getOuter = function() {
  return /** @type{?proto.Outer} */ (
    jspb.Message.getWrapperField(this, proto.Outer, 3));
};


/** @param {?proto.Outer|undefined} value */
proto.Test.Inner.prototype.setOuter = function(value) {
  jspb.Message.setWrapperField(this, 3, value);
};


proto.Test.Inner.prototype.clearOuter = function() {
  this.setOuter(undefined);
};


/**
 * Returns whether this field is set.
 * @return {!boolean}
 */
proto.Test.Inner.prototype.hasOuter = function() {
  return jspb.Message.getField(this, 3) != null;
};


/**
 * optional string string = 1;
 * @return {string}
 */
proto.Test.prototype.getString = function() {
  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
};


/** @param {string} value */
proto.Test.prototype.setString = function(value) {
  jspb.Message.setField(this, 1, value);
};


/**
 * optional uint32 uint32 = 2;
 * @return {number}
 */
proto.Test.prototype.getUint32 = function() {
  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));
};


/** @param {number} value */
proto.Test.prototype.setUint32 = function(value) {
  jspb.Message.setField(this, 2, value);
};


/**
 * optional Inner inner = 3;
 * @return {?proto.Test.Inner}
 */
proto.Test.prototype.getInner = function() {
  return /** @type{?proto.Test.Inner} */ (
    jspb.Message.getWrapperField(this, proto.Test.Inner, 3));
};


/** @param {?proto.Test.Inner|undefined} value */
proto.Test.prototype.setInner = function(value) {
  jspb.Message.setWrapperField(this, 3, value);
};


proto.Test.prototype.clearInner = function() {
  this.setInner(undefined);
};


/**
 * Returns whether this field is set.
 * @return {!boolean}
 */
proto.Test.prototype.hasInner = function() {
  return jspb.Message.getField(this, 3) != null;
};


/**
 * optional float float = 4;
 * @return {number}
 */
proto.Test.prototype.getFloat = function() {
  return /** @type {number} */ (+jspb.Message.getFieldWithDefault(this, 4, 0.0));
};


/** @param {number} value */
proto.Test.prototype.setFloat = function(value) {
  jspb.Message.setField(this, 4, value);
};



/**
 * Generated by JsPbCodeGenerator.
 * @param {Array=} opt_data Optional initial data array, typically from a
 * server response, or constructed directly in Javascript. The array is used
 * in place and becomes part of the constructed object. It is not cloned.
 * If no data is provided, the constructed object will be empty, but still
 * valid.
 * @extends {jspb.Message}
 * @constructor
 */
proto.Outer = function(opt_data) {
  jspb.Message.initialize(this, opt_data, 0, -1, proto.Outer.repeatedFields_, null);
};
goog.inherits(proto.Outer, jspb.Message);
if (goog.DEBUG && !COMPILED) {
  proto.Outer.displayName = 'proto.Outer';
}
/**
 * List of repeated fields within this message type.
 * @private {!Array<number>}
 * @const
 */
proto.Outer.repeatedFields_ = [1];



if (jspb.Message.GENERATE_TO_OBJECT) {
/**
 * Creates an object representation of this proto suitable for use in Soy templates.
 * Field names that are reserved in JavaScript and will be renamed to pb_name.
 * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
 * For the list of reserved names please see:
 *     com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
 * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
 *     for transitional soy proto support: http://goto/soy-param-migration
 * @return {!Object}
 */
proto.Outer.prototype.toObject = function(opt_includeInstance) {
  return proto.Outer.toObject(opt_includeInstance, this);
};


/**
 * Static version of the {@see toObject} method.
 * @param {boolean|undefined} includeInstance Whether to include the JSPB
 *     instance for transitional soy proto support:
 *     http://goto/soy-param-migration
 * @param {!proto.Outer} msg The msg instance to transform.
 * @return {!Object}
 */
proto.Outer.toObject = function(includeInstance, msg) {
  var f, obj = {
    boolList: jspb.Message.getField(msg, 1),
    pb_double: +jspb.Message.getFieldWithDefault(msg, 2, 0.0)
  };

  if (includeInstance) {
    obj.$jspbMessageInstance = msg;
  }
  return obj;
};
}


/**
 * Deserializes binary data (in protobuf wire format).
 * @param {jspb.ByteSource} bytes The bytes to deserialize.
 * @return {!proto.Outer}
 */
proto.Outer.deserializeBinary = function(bytes) {
  var reader = new jspb.BinaryReader(bytes);
  var msg = new proto.Outer;
  return proto.Outer.deserializeBinaryFromReader(msg, reader);
};


/**
 * Deserializes binary data (in protobuf wire format) from the
 * given reader into the given message object.
 * @param {!proto.Outer} msg The message object to deserialize into.
 * @param {!jspb.BinaryReader} reader The BinaryReader to use.
 * @return {!proto.Outer}
 */
proto.Outer.deserializeBinaryFromReader = function(msg, reader) {
  while (reader.nextField()) {
    if (reader.isEndGroup()) {
      break;
    }
    var field = reader.getFieldNumber();
    switch (field) {
    case 1:
      var value = /** @type {!Array.<boolean>} */ (reader.readPackedBool());
      msg.setBoolList(value);
      break;
    case 2:
      var value = /** @type {number} */ (reader.readDouble());
      msg.setDouble(value);
      break;
    default:
      reader.skipField();
      break;
    }
  }
  return msg;
};


/**
 * Serializes the message to binary data (in protobuf wire format).
 * @return {!Uint8Array}
 */
proto.Outer.prototype.serializeBinary = function() {
  var writer = new jspb.BinaryWriter();
  proto.Outer.serializeBinaryToWriter(this, writer);
  return writer.getResultBuffer();
};


/**
 * Serializes the given message to binary data (in protobuf wire
 * format), writing to the given BinaryWriter.
 * @param {!proto.Outer} message
 * @param {!jspb.BinaryWriter} writer
 */
proto.Outer.serializeBinaryToWriter = function(message, writer) {
  var f = undefined;
  f = message.getBoolList();
  if (f.length > 0) {
    writer.writePackedBool(
      1,
      f
    );
  }
  f = message.getDouble();
  if (f !== 0.0) {
    writer.writeDouble(
      2,
      f
    );
  }
};


/**
 * repeated bool bool = 1;
 * Note that Boolean fields may be set to 0/1 when serialized from a Java server.
 * You should avoid comparisons like {@code val === true/false} in those cases.
 * If you change this array by adding, removing or replacing elements, or if you
 * replace the array itself, then you must call the setter to update it.
 * @return {!Array.<boolean>}
 */
proto.Outer.prototype.getBoolList = function() {
  return /** @type {!Array.<boolean>} */ (jspb.Message.getField(this, 1));
};


/** @param {!Array.<boolean>} value */
proto.Outer.prototype.setBoolList = function(value) {
  jspb.Message.setField(this, 1, value || []);
};


/**
 * @param {!boolean} value
 * @param {number=} opt_index
 */
proto.Outer.prototype.addBool = function(value, opt_index) {
  jspb.Message.addToRepeatedField(this, 1, value, opt_index);
};


proto.Outer.prototype.clearBoolList = function() {
  this.setBoolList([]);
};


/**
 * optional double double = 2;
 * @return {number}
 */
proto.Outer.prototype.getDouble = function() {
  return /** @type {number} */ (+jspb.Message.getFieldWithDefault(this, 2, 0.0));
};


/** @param {number} value */
proto.Outer.prototype.setDouble = function(value) {
  jspb.Message.setField(this, 2, value);
};


goog.object.extend(exports, proto);
