// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: storage.proto

#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
#include "storage.pb.h"

#include <algorithm>

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/port.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
// @@protoc_insertion_point(includes)

namespace cobalt {
namespace storage {

void protobuf_ShutdownFile_storage_2eproto() {
  delete Cookie::default_instance_;
  delete LocalStorageEntry::default_instance_;
  delete LocalStorage::default_instance_;
  delete Storage::default_instance_;
}

#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
void protobuf_AddDesc_storage_2eproto_impl() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

#else
void protobuf_AddDesc_storage_2eproto() {
  static bool already_here = false;
  if (already_here) return;
  already_here = true;
  GOOGLE_PROTOBUF_VERIFY_VERSION;

#endif
  Cookie::default_instance_ = new Cookie();
  LocalStorageEntry::default_instance_ = new LocalStorageEntry();
  LocalStorage::default_instance_ = new LocalStorage();
  Storage::default_instance_ = new Storage();
  Cookie::default_instance_->InitAsDefaultInstance();
  LocalStorageEntry::default_instance_->InitAsDefaultInstance();
  LocalStorage::default_instance_->InitAsDefaultInstance();
  Storage::default_instance_->InitAsDefaultInstance();
  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_storage_2eproto);
}

#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AddDesc_storage_2eproto_once_);
void protobuf_AddDesc_storage_2eproto() {
  ::google::protobuf::GoogleOnceInit(&protobuf_AddDesc_storage_2eproto_once_,
                 &protobuf_AddDesc_storage_2eproto_impl);
}
#else
// Force AddDescriptors() to be called at static initialization time.
struct StaticDescriptorInitializer_storage_2eproto {
  StaticDescriptorInitializer_storage_2eproto() {
    protobuf_AddDesc_storage_2eproto();
  }
} static_descriptor_initializer_storage_2eproto_;
#endif

namespace {

static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
GOOGLE_ATTRIBUTE_NOINLINE static void MergeFromFail(int line) {
  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
}

}  // namespace


// ===================================================================

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int Cookie::kNameFieldNumber;
const int Cookie::kValueFieldNumber;
const int Cookie::kDomainFieldNumber;
const int Cookie::kPathFieldNumber;
const int Cookie::kCreationTimeUsFieldNumber;
const int Cookie::kExpirationTimeUsFieldNumber;
const int Cookie::kLastAccessTimeUsFieldNumber;
const int Cookie::kSecureFieldNumber;
const int Cookie::kHttpOnlyFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

Cookie::Cookie()
  : ::google::protobuf::MessageLite(), _arena_ptr_(NULL) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:cobalt.storage.Cookie)
}

void Cookie::InitAsDefaultInstance() {
  _is_default_instance_ = true;
}

Cookie::Cookie(const Cookie& from)
  : ::google::protobuf::MessageLite(),
    _arena_ptr_(NULL) {
  SharedCtor();
  MergeFrom(from);
  // @@protoc_insertion_point(copy_constructor:cobalt.storage.Cookie)
}

void Cookie::SharedCtor() {
    _is_default_instance_ = false;
  ::google::protobuf::internal::GetEmptyString();
  _cached_size_ = 0;
  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  domain_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  path_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  creation_time_us_ = GOOGLE_LONGLONG(0);
  expiration_time_us_ = GOOGLE_LONGLONG(0);
  last_access_time_us_ = GOOGLE_LONGLONG(0);
  secure_ = false;
  http_only_ = false;
}

Cookie::~Cookie() {
  // @@protoc_insertion_point(destructor:cobalt.storage.Cookie)
  SharedDtor();
}

void Cookie::SharedDtor() {
  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  domain_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  path_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  if (this != &default_instance()) {
  #else
  if (this != default_instance_) {
  #endif
  }
}

void Cookie::SetCachedSize(int size) const {
  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const Cookie& Cookie::default_instance() {
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  protobuf_AddDesc_storage_2eproto();
#else
  if (default_instance_ == NULL) protobuf_AddDesc_storage_2eproto();
#endif
  return *default_instance_;
}

Cookie* Cookie::default_instance_ = NULL;

Cookie* Cookie::New(::google::protobuf::Arena* arena) const {
  Cookie* n = new Cookie;
  if (arena != NULL) {
    arena->Own(n);
  }
  return n;
}

void Cookie::Clear() {
// @@protoc_insertion_point(message_clear_start:cobalt.storage.Cookie)
#if defined(__clang__)
#define ZR_HELPER_(f) \
  _Pragma("clang diagnostic push") \
  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
  __builtin_offsetof(Cookie, f) \
  _Pragma("clang diagnostic pop")
#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
  &reinterpret_cast<Cookie*>(16)->f)
#endif

#define ZR_(first, last) do {\
  ::memset(&first, 0,\
           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)

  ZR_(creation_time_us_, secure_);
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  domain_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  path_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  http_only_ = false;

#undef ZR_HELPER_
#undef ZR_

}

bool Cookie::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:cobalt.storage.Cookie)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // optional string name = 1;
      case 1: {
        if (tag == 10) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_name()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->name().data(), this->name().length(),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "cobalt.storage.Cookie.name"));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(18)) goto parse_value;
        break;
      }

      // optional string value = 2;
      case 2: {
        if (tag == 18) {
         parse_value:
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_value()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->value().data(), this->value().length(),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "cobalt.storage.Cookie.value"));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(26)) goto parse_domain;
        break;
      }

      // optional string domain = 3;
      case 3: {
        if (tag == 26) {
         parse_domain:
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_domain()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->domain().data(), this->domain().length(),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "cobalt.storage.Cookie.domain"));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(34)) goto parse_path;
        break;
      }

      // optional string path = 4;
      case 4: {
        if (tag == 34) {
         parse_path:
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_path()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->path().data(), this->path().length(),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "cobalt.storage.Cookie.path"));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(40)) goto parse_creation_time_us;
        break;
      }

      // optional int64 creation_time_us = 5;
      case 5: {
        if (tag == 40) {
         parse_creation_time_us:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
                 input, &creation_time_us_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(48)) goto parse_expiration_time_us;
        break;
      }

      // optional int64 expiration_time_us = 6;
      case 6: {
        if (tag == 48) {
         parse_expiration_time_us:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
                 input, &expiration_time_us_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(56)) goto parse_last_access_time_us;
        break;
      }

      // optional int64 last_access_time_us = 7;
      case 7: {
        if (tag == 56) {
         parse_last_access_time_us:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
                 input, &last_access_time_us_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(64)) goto parse_secure;
        break;
      }

      // optional bool secure = 8;
      case 8: {
        if (tag == 64) {
         parse_secure:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                 input, &secure_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(72)) goto parse_http_only;
        break;
      }

      // optional bool http_only = 9;
      case 9: {
        if (tag == 72) {
         parse_http_only:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                 input, &http_only_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:cobalt.storage.Cookie)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:cobalt.storage.Cookie)
  return false;
#undef DO_
}

void Cookie::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:cobalt.storage.Cookie)
  // optional string name = 1;
  if (this->name().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->name().data(), this->name().length(),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "cobalt.storage.Cookie.name");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      1, this->name(), output);
  }

  // optional string value = 2;
  if (this->value().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->value().data(), this->value().length(),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "cobalt.storage.Cookie.value");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      2, this->value(), output);
  }

  // optional string domain = 3;
  if (this->domain().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->domain().data(), this->domain().length(),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "cobalt.storage.Cookie.domain");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      3, this->domain(), output);
  }

  // optional string path = 4;
  if (this->path().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->path().data(), this->path().length(),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "cobalt.storage.Cookie.path");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      4, this->path(), output);
  }

  // optional int64 creation_time_us = 5;
  if (this->creation_time_us() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt64(5, this->creation_time_us(), output);
  }

  // optional int64 expiration_time_us = 6;
  if (this->expiration_time_us() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt64(6, this->expiration_time_us(), output);
  }

  // optional int64 last_access_time_us = 7;
  if (this->last_access_time_us() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt64(7, this->last_access_time_us(), output);
  }

  // optional bool secure = 8;
  if (this->secure() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteBool(8, this->secure(), output);
  }

  // optional bool http_only = 9;
  if (this->http_only() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteBool(9, this->http_only(), output);
  }

  // @@protoc_insertion_point(serialize_end:cobalt.storage.Cookie)
}

int Cookie::ByteSize() const {
// @@protoc_insertion_point(message_byte_size_start:cobalt.storage.Cookie)
  int total_size = 0;

  // optional string name = 1;
  if (this->name().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->name());
  }

  // optional string value = 2;
  if (this->value().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->value());
  }

  // optional string domain = 3;
  if (this->domain().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->domain());
  }

  // optional string path = 4;
  if (this->path().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->path());
  }

  // optional int64 creation_time_us = 5;
  if (this->creation_time_us() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int64Size(
        this->creation_time_us());
  }

  // optional int64 expiration_time_us = 6;
  if (this->expiration_time_us() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int64Size(
        this->expiration_time_us());
  }

  // optional int64 last_access_time_us = 7;
  if (this->last_access_time_us() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int64Size(
        this->last_access_time_us());
  }

  // optional bool secure = 8;
  if (this->secure() != 0) {
    total_size += 1 + 1;
  }

  // optional bool http_only = 9;
  if (this->http_only() != 0) {
    total_size += 1 + 1;
  }

  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = total_size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
  return total_size;
}

void Cookie::CheckTypeAndMergeFrom(
    const ::google::protobuf::MessageLite& from) {
  MergeFrom(*::google::protobuf::down_cast<const Cookie*>(&from));
}

void Cookie::MergeFrom(const Cookie& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:cobalt.storage.Cookie)
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  if (from.name().size() > 0) {

    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
  }
  if (from.value().size() > 0) {

    value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_);
  }
  if (from.domain().size() > 0) {

    domain_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.domain_);
  }
  if (from.path().size() > 0) {

    path_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.path_);
  }
  if (from.creation_time_us() != 0) {
    set_creation_time_us(from.creation_time_us());
  }
  if (from.expiration_time_us() != 0) {
    set_expiration_time_us(from.expiration_time_us());
  }
  if (from.last_access_time_us() != 0) {
    set_last_access_time_us(from.last_access_time_us());
  }
  if (from.secure() != 0) {
    set_secure(from.secure());
  }
  if (from.http_only() != 0) {
    set_http_only(from.http_only());
  }
}

void Cookie::CopyFrom(const Cookie& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:cobalt.storage.Cookie)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool Cookie::IsInitialized() const {

  return true;
}

void Cookie::Swap(Cookie* other) {
  if (other == this) return;
  InternalSwap(other);
}
void Cookie::InternalSwap(Cookie* other) {
  name_.Swap(&other->name_);
  value_.Swap(&other->value_);
  domain_.Swap(&other->domain_);
  path_.Swap(&other->path_);
  std::swap(creation_time_us_, other->creation_time_us_);
  std::swap(expiration_time_us_, other->expiration_time_us_);
  std::swap(last_access_time_us_, other->last_access_time_us_);
  std::swap(secure_, other->secure_);
  std::swap(http_only_, other->http_only_);
  _unknown_fields_.Swap(&other->_unknown_fields_);
  std::swap(_cached_size_, other->_cached_size_);
}

::std::string Cookie::GetTypeName() const {
  return "cobalt.storage.Cookie";
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// Cookie

// optional string name = 1;
void Cookie::clear_name() {
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& Cookie::name() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.name)
  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Cookie::set_name(const ::std::string& value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:cobalt.storage.Cookie.name)
}
 void Cookie::set_name(const char* value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:cobalt.storage.Cookie.name)
}
 void Cookie::set_name(const char* value, size_t size) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:cobalt.storage.Cookie.name)
}
 ::std::string* Cookie::mutable_name() {
  
  // @@protoc_insertion_point(field_mutable:cobalt.storage.Cookie.name)
  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* Cookie::release_name() {
  // @@protoc_insertion_point(field_release:cobalt.storage.Cookie.name)
  
  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Cookie::set_allocated_name(::std::string* name) {
  if (name != NULL) {
    
  } else {
    
  }
  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
  // @@protoc_insertion_point(field_set_allocated:cobalt.storage.Cookie.name)
}

// optional string value = 2;
void Cookie::clear_value() {
  value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& Cookie::value() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.value)
  return value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Cookie::set_value(const ::std::string& value) {
  
  value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:cobalt.storage.Cookie.value)
}
 void Cookie::set_value(const char* value) {
  
  value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:cobalt.storage.Cookie.value)
}
 void Cookie::set_value(const char* value, size_t size) {
  
  value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:cobalt.storage.Cookie.value)
}
 ::std::string* Cookie::mutable_value() {
  
  // @@protoc_insertion_point(field_mutable:cobalt.storage.Cookie.value)
  return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* Cookie::release_value() {
  // @@protoc_insertion_point(field_release:cobalt.storage.Cookie.value)
  
  return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Cookie::set_allocated_value(::std::string* value) {
  if (value != NULL) {
    
  } else {
    
  }
  value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set_allocated:cobalt.storage.Cookie.value)
}

// optional string domain = 3;
void Cookie::clear_domain() {
  domain_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& Cookie::domain() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.domain)
  return domain_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Cookie::set_domain(const ::std::string& value) {
  
  domain_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:cobalt.storage.Cookie.domain)
}
 void Cookie::set_domain(const char* value) {
  
  domain_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:cobalt.storage.Cookie.domain)
}
 void Cookie::set_domain(const char* value, size_t size) {
  
  domain_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:cobalt.storage.Cookie.domain)
}
 ::std::string* Cookie::mutable_domain() {
  
  // @@protoc_insertion_point(field_mutable:cobalt.storage.Cookie.domain)
  return domain_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* Cookie::release_domain() {
  // @@protoc_insertion_point(field_release:cobalt.storage.Cookie.domain)
  
  return domain_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Cookie::set_allocated_domain(::std::string* domain) {
  if (domain != NULL) {
    
  } else {
    
  }
  domain_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), domain);
  // @@protoc_insertion_point(field_set_allocated:cobalt.storage.Cookie.domain)
}

// optional string path = 4;
void Cookie::clear_path() {
  path_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& Cookie::path() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.path)
  return path_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Cookie::set_path(const ::std::string& value) {
  
  path_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:cobalt.storage.Cookie.path)
}
 void Cookie::set_path(const char* value) {
  
  path_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:cobalt.storage.Cookie.path)
}
 void Cookie::set_path(const char* value, size_t size) {
  
  path_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:cobalt.storage.Cookie.path)
}
 ::std::string* Cookie::mutable_path() {
  
  // @@protoc_insertion_point(field_mutable:cobalt.storage.Cookie.path)
  return path_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* Cookie::release_path() {
  // @@protoc_insertion_point(field_release:cobalt.storage.Cookie.path)
  
  return path_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Cookie::set_allocated_path(::std::string* path) {
  if (path != NULL) {
    
  } else {
    
  }
  path_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), path);
  // @@protoc_insertion_point(field_set_allocated:cobalt.storage.Cookie.path)
}

// optional int64 creation_time_us = 5;
void Cookie::clear_creation_time_us() {
  creation_time_us_ = GOOGLE_LONGLONG(0);
}
 ::google::protobuf::int64 Cookie::creation_time_us() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.creation_time_us)
  return creation_time_us_;
}
 void Cookie::set_creation_time_us(::google::protobuf::int64 value) {
  
  creation_time_us_ = value;
  // @@protoc_insertion_point(field_set:cobalt.storage.Cookie.creation_time_us)
}

// optional int64 expiration_time_us = 6;
void Cookie::clear_expiration_time_us() {
  expiration_time_us_ = GOOGLE_LONGLONG(0);
}
 ::google::protobuf::int64 Cookie::expiration_time_us() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.expiration_time_us)
  return expiration_time_us_;
}
 void Cookie::set_expiration_time_us(::google::protobuf::int64 value) {
  
  expiration_time_us_ = value;
  // @@protoc_insertion_point(field_set:cobalt.storage.Cookie.expiration_time_us)
}

// optional int64 last_access_time_us = 7;
void Cookie::clear_last_access_time_us() {
  last_access_time_us_ = GOOGLE_LONGLONG(0);
}
 ::google::protobuf::int64 Cookie::last_access_time_us() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.last_access_time_us)
  return last_access_time_us_;
}
 void Cookie::set_last_access_time_us(::google::protobuf::int64 value) {
  
  last_access_time_us_ = value;
  // @@protoc_insertion_point(field_set:cobalt.storage.Cookie.last_access_time_us)
}

// optional bool secure = 8;
void Cookie::clear_secure() {
  secure_ = false;
}
 bool Cookie::secure() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.secure)
  return secure_;
}
 void Cookie::set_secure(bool value) {
  
  secure_ = value;
  // @@protoc_insertion_point(field_set:cobalt.storage.Cookie.secure)
}

// optional bool http_only = 9;
void Cookie::clear_http_only() {
  http_only_ = false;
}
 bool Cookie::http_only() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.http_only)
  return http_only_;
}
 void Cookie::set_http_only(bool value) {
  
  http_only_ = value;
  // @@protoc_insertion_point(field_set:cobalt.storage.Cookie.http_only)
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

// ===================================================================

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int LocalStorageEntry::kKeyFieldNumber;
const int LocalStorageEntry::kValueFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

LocalStorageEntry::LocalStorageEntry()
  : ::google::protobuf::MessageLite(), _arena_ptr_(NULL) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:cobalt.storage.LocalStorageEntry)
}

void LocalStorageEntry::InitAsDefaultInstance() {
  _is_default_instance_ = true;
}

LocalStorageEntry::LocalStorageEntry(const LocalStorageEntry& from)
  : ::google::protobuf::MessageLite(),
    _arena_ptr_(NULL) {
  SharedCtor();
  MergeFrom(from);
  // @@protoc_insertion_point(copy_constructor:cobalt.storage.LocalStorageEntry)
}

void LocalStorageEntry::SharedCtor() {
    _is_default_instance_ = false;
  ::google::protobuf::internal::GetEmptyString();
  _cached_size_ = 0;
  key_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}

LocalStorageEntry::~LocalStorageEntry() {
  // @@protoc_insertion_point(destructor:cobalt.storage.LocalStorageEntry)
  SharedDtor();
}

void LocalStorageEntry::SharedDtor() {
  key_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  if (this != &default_instance()) {
  #else
  if (this != default_instance_) {
  #endif
  }
}

void LocalStorageEntry::SetCachedSize(int size) const {
  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const LocalStorageEntry& LocalStorageEntry::default_instance() {
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  protobuf_AddDesc_storage_2eproto();
#else
  if (default_instance_ == NULL) protobuf_AddDesc_storage_2eproto();
#endif
  return *default_instance_;
}

LocalStorageEntry* LocalStorageEntry::default_instance_ = NULL;

LocalStorageEntry* LocalStorageEntry::New(::google::protobuf::Arena* arena) const {
  LocalStorageEntry* n = new LocalStorageEntry;
  if (arena != NULL) {
    arena->Own(n);
  }
  return n;
}

void LocalStorageEntry::Clear() {
// @@protoc_insertion_point(message_clear_start:cobalt.storage.LocalStorageEntry)
  key_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}

bool LocalStorageEntry::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:cobalt.storage.LocalStorageEntry)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // optional string key = 1;
      case 1: {
        if (tag == 10) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_key()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->key().data(), this->key().length(),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "cobalt.storage.LocalStorageEntry.key"));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(18)) goto parse_value;
        break;
      }

      // optional string value = 2;
      case 2: {
        if (tag == 18) {
         parse_value:
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_value()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->value().data(), this->value().length(),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "cobalt.storage.LocalStorageEntry.value"));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:cobalt.storage.LocalStorageEntry)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:cobalt.storage.LocalStorageEntry)
  return false;
#undef DO_
}

void LocalStorageEntry::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:cobalt.storage.LocalStorageEntry)
  // optional string key = 1;
  if (this->key().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->key().data(), this->key().length(),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "cobalt.storage.LocalStorageEntry.key");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      1, this->key(), output);
  }

  // optional string value = 2;
  if (this->value().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->value().data(), this->value().length(),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "cobalt.storage.LocalStorageEntry.value");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      2, this->value(), output);
  }

  // @@protoc_insertion_point(serialize_end:cobalt.storage.LocalStorageEntry)
}

int LocalStorageEntry::ByteSize() const {
// @@protoc_insertion_point(message_byte_size_start:cobalt.storage.LocalStorageEntry)
  int total_size = 0;

  // optional string key = 1;
  if (this->key().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->key());
  }

  // optional string value = 2;
  if (this->value().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->value());
  }

  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = total_size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
  return total_size;
}

void LocalStorageEntry::CheckTypeAndMergeFrom(
    const ::google::protobuf::MessageLite& from) {
  MergeFrom(*::google::protobuf::down_cast<const LocalStorageEntry*>(&from));
}

void LocalStorageEntry::MergeFrom(const LocalStorageEntry& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:cobalt.storage.LocalStorageEntry)
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  if (from.key().size() > 0) {

    key_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.key_);
  }
  if (from.value().size() > 0) {

    value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_);
  }
}

void LocalStorageEntry::CopyFrom(const LocalStorageEntry& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:cobalt.storage.LocalStorageEntry)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool LocalStorageEntry::IsInitialized() const {

  return true;
}

void LocalStorageEntry::Swap(LocalStorageEntry* other) {
  if (other == this) return;
  InternalSwap(other);
}
void LocalStorageEntry::InternalSwap(LocalStorageEntry* other) {
  key_.Swap(&other->key_);
  value_.Swap(&other->value_);
  _unknown_fields_.Swap(&other->_unknown_fields_);
  std::swap(_cached_size_, other->_cached_size_);
}

::std::string LocalStorageEntry::GetTypeName() const {
  return "cobalt.storage.LocalStorageEntry";
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// LocalStorageEntry

// optional string key = 1;
void LocalStorageEntry::clear_key() {
  key_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& LocalStorageEntry::key() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.LocalStorageEntry.key)
  return key_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void LocalStorageEntry::set_key(const ::std::string& value) {
  
  key_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:cobalt.storage.LocalStorageEntry.key)
}
 void LocalStorageEntry::set_key(const char* value) {
  
  key_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:cobalt.storage.LocalStorageEntry.key)
}
 void LocalStorageEntry::set_key(const char* value, size_t size) {
  
  key_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:cobalt.storage.LocalStorageEntry.key)
}
 ::std::string* LocalStorageEntry::mutable_key() {
  
  // @@protoc_insertion_point(field_mutable:cobalt.storage.LocalStorageEntry.key)
  return key_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* LocalStorageEntry::release_key() {
  // @@protoc_insertion_point(field_release:cobalt.storage.LocalStorageEntry.key)
  
  return key_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void LocalStorageEntry::set_allocated_key(::std::string* key) {
  if (key != NULL) {
    
  } else {
    
  }
  key_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), key);
  // @@protoc_insertion_point(field_set_allocated:cobalt.storage.LocalStorageEntry.key)
}

// optional string value = 2;
void LocalStorageEntry::clear_value() {
  value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& LocalStorageEntry::value() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.LocalStorageEntry.value)
  return value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void LocalStorageEntry::set_value(const ::std::string& value) {
  
  value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:cobalt.storage.LocalStorageEntry.value)
}
 void LocalStorageEntry::set_value(const char* value) {
  
  value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:cobalt.storage.LocalStorageEntry.value)
}
 void LocalStorageEntry::set_value(const char* value, size_t size) {
  
  value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:cobalt.storage.LocalStorageEntry.value)
}
 ::std::string* LocalStorageEntry::mutable_value() {
  
  // @@protoc_insertion_point(field_mutable:cobalt.storage.LocalStorageEntry.value)
  return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* LocalStorageEntry::release_value() {
  // @@protoc_insertion_point(field_release:cobalt.storage.LocalStorageEntry.value)
  
  return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void LocalStorageEntry::set_allocated_value(::std::string* value) {
  if (value != NULL) {
    
  } else {
    
  }
  value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set_allocated:cobalt.storage.LocalStorageEntry.value)
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

// ===================================================================

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int LocalStorage::kIdFieldNumber;
const int LocalStorage::kLocalStorageEntriesFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

LocalStorage::LocalStorage()
  : ::google::protobuf::MessageLite(), _arena_ptr_(NULL) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:cobalt.storage.LocalStorage)
}

void LocalStorage::InitAsDefaultInstance() {
  _is_default_instance_ = true;
}

LocalStorage::LocalStorage(const LocalStorage& from)
  : ::google::protobuf::MessageLite(),
    _arena_ptr_(NULL) {
  SharedCtor();
  MergeFrom(from);
  // @@protoc_insertion_point(copy_constructor:cobalt.storage.LocalStorage)
}

void LocalStorage::SharedCtor() {
    _is_default_instance_ = false;
  ::google::protobuf::internal::GetEmptyString();
  _cached_size_ = 0;
  id_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}

LocalStorage::~LocalStorage() {
  // @@protoc_insertion_point(destructor:cobalt.storage.LocalStorage)
  SharedDtor();
}

void LocalStorage::SharedDtor() {
  id_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  if (this != &default_instance()) {
  #else
  if (this != default_instance_) {
  #endif
  }
}

void LocalStorage::SetCachedSize(int size) const {
  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const LocalStorage& LocalStorage::default_instance() {
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  protobuf_AddDesc_storage_2eproto();
#else
  if (default_instance_ == NULL) protobuf_AddDesc_storage_2eproto();
#endif
  return *default_instance_;
}

LocalStorage* LocalStorage::default_instance_ = NULL;

LocalStorage* LocalStorage::New(::google::protobuf::Arena* arena) const {
  LocalStorage* n = new LocalStorage;
  if (arena != NULL) {
    arena->Own(n);
  }
  return n;
}

void LocalStorage::Clear() {
// @@protoc_insertion_point(message_clear_start:cobalt.storage.LocalStorage)
  id_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  local_storage_entries_.Clear();
}

bool LocalStorage::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:cobalt.storage.LocalStorage)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // optional string id = 1;
      case 1: {
        if (tag == 10) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_id()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->id().data(), this->id().length(),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "cobalt.storage.LocalStorage.id"));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(18)) goto parse_local_storage_entries;
        break;
      }

      // repeated .cobalt.storage.LocalStorageEntry local_storage_entries = 2;
      case 2: {
        if (tag == 18) {
         parse_local_storage_entries:
          DO_(input->IncrementRecursionDepth());
         parse_loop_local_storage_entries:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
                input, add_local_storage_entries()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(18)) goto parse_loop_local_storage_entries;
        input->UnsafeDecrementRecursionDepth();
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:cobalt.storage.LocalStorage)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:cobalt.storage.LocalStorage)
  return false;
#undef DO_
}

void LocalStorage::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:cobalt.storage.LocalStorage)
  // optional string id = 1;
  if (this->id().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->id().data(), this->id().length(),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "cobalt.storage.LocalStorage.id");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      1, this->id(), output);
  }

  // repeated .cobalt.storage.LocalStorageEntry local_storage_entries = 2;
  for (unsigned int i = 0, n = this->local_storage_entries_size(); i < n; i++) {
    ::google::protobuf::internal::WireFormatLite::WriteMessage(
      2, this->local_storage_entries(i), output);
  }

  // @@protoc_insertion_point(serialize_end:cobalt.storage.LocalStorage)
}

int LocalStorage::ByteSize() const {
// @@protoc_insertion_point(message_byte_size_start:cobalt.storage.LocalStorage)
  int total_size = 0;

  // optional string id = 1;
  if (this->id().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->id());
  }

  // repeated .cobalt.storage.LocalStorageEntry local_storage_entries = 2;
  total_size += 1 * this->local_storage_entries_size();
  for (int i = 0; i < this->local_storage_entries_size(); i++) {
    total_size +=
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        this->local_storage_entries(i));
  }

  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = total_size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
  return total_size;
}

void LocalStorage::CheckTypeAndMergeFrom(
    const ::google::protobuf::MessageLite& from) {
  MergeFrom(*::google::protobuf::down_cast<const LocalStorage*>(&from));
}

void LocalStorage::MergeFrom(const LocalStorage& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:cobalt.storage.LocalStorage)
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  local_storage_entries_.MergeFrom(from.local_storage_entries_);
  if (from.id().size() > 0) {

    id_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.id_);
  }
}

void LocalStorage::CopyFrom(const LocalStorage& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:cobalt.storage.LocalStorage)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool LocalStorage::IsInitialized() const {

  return true;
}

void LocalStorage::Swap(LocalStorage* other) {
  if (other == this) return;
  InternalSwap(other);
}
void LocalStorage::InternalSwap(LocalStorage* other) {
  id_.Swap(&other->id_);
  local_storage_entries_.UnsafeArenaSwap(&other->local_storage_entries_);
  _unknown_fields_.Swap(&other->_unknown_fields_);
  std::swap(_cached_size_, other->_cached_size_);
}

::std::string LocalStorage::GetTypeName() const {
  return "cobalt.storage.LocalStorage";
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// LocalStorage

// optional string id = 1;
void LocalStorage::clear_id() {
  id_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& LocalStorage::id() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.LocalStorage.id)
  return id_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void LocalStorage::set_id(const ::std::string& value) {
  
  id_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:cobalt.storage.LocalStorage.id)
}
 void LocalStorage::set_id(const char* value) {
  
  id_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:cobalt.storage.LocalStorage.id)
}
 void LocalStorage::set_id(const char* value, size_t size) {
  
  id_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:cobalt.storage.LocalStorage.id)
}
 ::std::string* LocalStorage::mutable_id() {
  
  // @@protoc_insertion_point(field_mutable:cobalt.storage.LocalStorage.id)
  return id_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* LocalStorage::release_id() {
  // @@protoc_insertion_point(field_release:cobalt.storage.LocalStorage.id)
  
  return id_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void LocalStorage::set_allocated_id(::std::string* id) {
  if (id != NULL) {
    
  } else {
    
  }
  id_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), id);
  // @@protoc_insertion_point(field_set_allocated:cobalt.storage.LocalStorage.id)
}

// repeated .cobalt.storage.LocalStorageEntry local_storage_entries = 2;
int LocalStorage::local_storage_entries_size() const {
  return local_storage_entries_.size();
}
void LocalStorage::clear_local_storage_entries() {
  local_storage_entries_.Clear();
}
const ::cobalt::storage::LocalStorageEntry& LocalStorage::local_storage_entries(int index) const {
  // @@protoc_insertion_point(field_get:cobalt.storage.LocalStorage.local_storage_entries)
  return local_storage_entries_.Get(index);
}
::cobalt::storage::LocalStorageEntry* LocalStorage::mutable_local_storage_entries(int index) {
  // @@protoc_insertion_point(field_mutable:cobalt.storage.LocalStorage.local_storage_entries)
  return local_storage_entries_.Mutable(index);
}
::cobalt::storage::LocalStorageEntry* LocalStorage::add_local_storage_entries() {
  // @@protoc_insertion_point(field_add:cobalt.storage.LocalStorage.local_storage_entries)
  return local_storage_entries_.Add();
}
::google::protobuf::RepeatedPtrField< ::cobalt::storage::LocalStorageEntry >*
LocalStorage::mutable_local_storage_entries() {
  // @@protoc_insertion_point(field_mutable_list:cobalt.storage.LocalStorage.local_storage_entries)
  return &local_storage_entries_;
}
const ::google::protobuf::RepeatedPtrField< ::cobalt::storage::LocalStorageEntry >&
LocalStorage::local_storage_entries() const {
  // @@protoc_insertion_point(field_list:cobalt.storage.LocalStorage.local_storage_entries)
  return local_storage_entries_;
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

// ===================================================================

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int Storage::kCookiesFieldNumber;
const int Storage::kLocalStoragesFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

Storage::Storage()
  : ::google::protobuf::MessageLite(), _arena_ptr_(NULL) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:cobalt.storage.Storage)
}

void Storage::InitAsDefaultInstance() {
  _is_default_instance_ = true;
}

Storage::Storage(const Storage& from)
  : ::google::protobuf::MessageLite(),
    _arena_ptr_(NULL) {
  SharedCtor();
  MergeFrom(from);
  // @@protoc_insertion_point(copy_constructor:cobalt.storage.Storage)
}

void Storage::SharedCtor() {
    _is_default_instance_ = false;
  _cached_size_ = 0;
}

Storage::~Storage() {
  // @@protoc_insertion_point(destructor:cobalt.storage.Storage)
  SharedDtor();
}

void Storage::SharedDtor() {
  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  if (this != &default_instance()) {
  #else
  if (this != default_instance_) {
  #endif
  }
}

void Storage::SetCachedSize(int size) const {
  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const Storage& Storage::default_instance() {
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  protobuf_AddDesc_storage_2eproto();
#else
  if (default_instance_ == NULL) protobuf_AddDesc_storage_2eproto();
#endif
  return *default_instance_;
}

Storage* Storage::default_instance_ = NULL;

Storage* Storage::New(::google::protobuf::Arena* arena) const {
  Storage* n = new Storage;
  if (arena != NULL) {
    arena->Own(n);
  }
  return n;
}

void Storage::Clear() {
// @@protoc_insertion_point(message_clear_start:cobalt.storage.Storage)
  cookies_.Clear();
  local_storages_.Clear();
}

bool Storage::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:cobalt.storage.Storage)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // repeated .cobalt.storage.Cookie cookies = 1;
      case 1: {
        if (tag == 10) {
          DO_(input->IncrementRecursionDepth());
         parse_loop_cookies:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
                input, add_cookies()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(10)) goto parse_loop_cookies;
        if (input->ExpectTag(18)) goto parse_loop_local_storages;
        input->UnsafeDecrementRecursionDepth();
        break;
      }

      // repeated .cobalt.storage.LocalStorage local_storages = 2;
      case 2: {
        if (tag == 18) {
          DO_(input->IncrementRecursionDepth());
         parse_loop_local_storages:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
                input, add_local_storages()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(18)) goto parse_loop_local_storages;
        input->UnsafeDecrementRecursionDepth();
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:cobalt.storage.Storage)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:cobalt.storage.Storage)
  return false;
#undef DO_
}

void Storage::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:cobalt.storage.Storage)
  // repeated .cobalt.storage.Cookie cookies = 1;
  for (unsigned int i = 0, n = this->cookies_size(); i < n; i++) {
    ::google::protobuf::internal::WireFormatLite::WriteMessage(
      1, this->cookies(i), output);
  }

  // repeated .cobalt.storage.LocalStorage local_storages = 2;
  for (unsigned int i = 0, n = this->local_storages_size(); i < n; i++) {
    ::google::protobuf::internal::WireFormatLite::WriteMessage(
      2, this->local_storages(i), output);
  }

  // @@protoc_insertion_point(serialize_end:cobalt.storage.Storage)
}

int Storage::ByteSize() const {
// @@protoc_insertion_point(message_byte_size_start:cobalt.storage.Storage)
  int total_size = 0;

  // repeated .cobalt.storage.Cookie cookies = 1;
  total_size += 1 * this->cookies_size();
  for (int i = 0; i < this->cookies_size(); i++) {
    total_size +=
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        this->cookies(i));
  }

  // repeated .cobalt.storage.LocalStorage local_storages = 2;
  total_size += 1 * this->local_storages_size();
  for (int i = 0; i < this->local_storages_size(); i++) {
    total_size +=
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        this->local_storages(i));
  }

  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = total_size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
  return total_size;
}

void Storage::CheckTypeAndMergeFrom(
    const ::google::protobuf::MessageLite& from) {
  MergeFrom(*::google::protobuf::down_cast<const Storage*>(&from));
}

void Storage::MergeFrom(const Storage& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:cobalt.storage.Storage)
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  cookies_.MergeFrom(from.cookies_);
  local_storages_.MergeFrom(from.local_storages_);
}

void Storage::CopyFrom(const Storage& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:cobalt.storage.Storage)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool Storage::IsInitialized() const {

  return true;
}

void Storage::Swap(Storage* other) {
  if (other == this) return;
  InternalSwap(other);
}
void Storage::InternalSwap(Storage* other) {
  cookies_.UnsafeArenaSwap(&other->cookies_);
  local_storages_.UnsafeArenaSwap(&other->local_storages_);
  _unknown_fields_.Swap(&other->_unknown_fields_);
  std::swap(_cached_size_, other->_cached_size_);
}

::std::string Storage::GetTypeName() const {
  return "cobalt.storage.Storage";
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// Storage

// repeated .cobalt.storage.Cookie cookies = 1;
int Storage::cookies_size() const {
  return cookies_.size();
}
void Storage::clear_cookies() {
  cookies_.Clear();
}
const ::cobalt::storage::Cookie& Storage::cookies(int index) const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Storage.cookies)
  return cookies_.Get(index);
}
::cobalt::storage::Cookie* Storage::mutable_cookies(int index) {
  // @@protoc_insertion_point(field_mutable:cobalt.storage.Storage.cookies)
  return cookies_.Mutable(index);
}
::cobalt::storage::Cookie* Storage::add_cookies() {
  // @@protoc_insertion_point(field_add:cobalt.storage.Storage.cookies)
  return cookies_.Add();
}
::google::protobuf::RepeatedPtrField< ::cobalt::storage::Cookie >*
Storage::mutable_cookies() {
  // @@protoc_insertion_point(field_mutable_list:cobalt.storage.Storage.cookies)
  return &cookies_;
}
const ::google::protobuf::RepeatedPtrField< ::cobalt::storage::Cookie >&
Storage::cookies() const {
  // @@protoc_insertion_point(field_list:cobalt.storage.Storage.cookies)
  return cookies_;
}

// repeated .cobalt.storage.LocalStorage local_storages = 2;
int Storage::local_storages_size() const {
  return local_storages_.size();
}
void Storage::clear_local_storages() {
  local_storages_.Clear();
}
const ::cobalt::storage::LocalStorage& Storage::local_storages(int index) const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Storage.local_storages)
  return local_storages_.Get(index);
}
::cobalt::storage::LocalStorage* Storage::mutable_local_storages(int index) {
  // @@protoc_insertion_point(field_mutable:cobalt.storage.Storage.local_storages)
  return local_storages_.Mutable(index);
}
::cobalt::storage::LocalStorage* Storage::add_local_storages() {
  // @@protoc_insertion_point(field_add:cobalt.storage.Storage.local_storages)
  return local_storages_.Add();
}
::google::protobuf::RepeatedPtrField< ::cobalt::storage::LocalStorage >*
Storage::mutable_local_storages() {
  // @@protoc_insertion_point(field_mutable_list:cobalt.storage.Storage.local_storages)
  return &local_storages_;
}
const ::google::protobuf::RepeatedPtrField< ::cobalt::storage::LocalStorage >&
Storage::local_storages() const {
  // @@protoc_insertion_point(field_list:cobalt.storage.Storage.local_storages)
  return local_storages_;
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

// @@protoc_insertion_point(namespace_scope)

}  // namespace storage
}  // namespace cobalt

// @@protoc_insertion_point(global_scope)
