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

#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
#include "cobalt/storage/store/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/stubs/starboard_poem.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_cobalt_2fstorage_2fstore_2fstorage_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_cobalt_2fstorage_2fstore_2fstorage_2eproto_impl() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

#else
void protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_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_cobalt_2fstorage_2fstore_2fstorage_2eproto);
}

#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto_once_);
void protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto() {
  ::google::protobuf::GoogleOnceInit(&protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto_once_,
                 &protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto_impl);
}
#else
// Force AddDescriptors() to be called at static initialization time.
struct StaticDescriptorInitializer_cobalt_2fstorage_2fstore_2fstorage_2eproto {
  StaticDescriptorInitializer_cobalt_2fstorage_2fstore_2fstorage_2eproto() {
    protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto();
  }
} static_descriptor_initializer_cobalt_2fstorage_2fstore_2fstorage_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_cobalt_2fstorage_2fstore_2fstorage_2eproto();
#else
  if (default_instance_ == NULL) protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_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_cobalt_2fstorage_2fstore_2fstorage_2eproto();
#else
  if (default_instance_ == NULL) protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_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::kSerializedOriginFieldNumber;
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;
  serialized_origin_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}

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

void LocalStorage::SharedDtor() {
  serialized_origin_.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_cobalt_2fstorage_2fstore_2fstorage_2eproto();
#else
  if (default_instance_ == NULL) protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_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)
  serialized_origin_.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 serialized_origin = 1;
      case 1: {
        if (tag == 10) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_serialized_origin()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->serialized_origin().data(), this->serialized_origin().length(),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "cobalt.storage.LocalStorage.serialized_origin"));
        } 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 serialized_origin = 1;
  if (this->serialized_origin().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->serialized_origin().data(), this->serialized_origin().length(),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "cobalt.storage.LocalStorage.serialized_origin");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      1, this->serialized_origin(), 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 serialized_origin = 1;
  if (this->serialized_origin().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->serialized_origin());
  }

  // 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.serialized_origin().size() > 0) {

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

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) {
  serialized_origin_.Swap(&other->serialized_origin_);
  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 serialized_origin = 1;
void LocalStorage::clear_serialized_origin() {
  serialized_origin_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& LocalStorage::serialized_origin() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.LocalStorage.serialized_origin)
  return serialized_origin_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void LocalStorage::set_serialized_origin(const ::std::string& value) {
  
  serialized_origin_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:cobalt.storage.LocalStorage.serialized_origin)
}
 void LocalStorage::set_serialized_origin(const char* value) {
  
  serialized_origin_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:cobalt.storage.LocalStorage.serialized_origin)
}
 void LocalStorage::set_serialized_origin(const char* value, size_t size) {
  
  serialized_origin_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:cobalt.storage.LocalStorage.serialized_origin)
}
 ::std::string* LocalStorage::mutable_serialized_origin() {
  
  // @@protoc_insertion_point(field_mutable:cobalt.storage.LocalStorage.serialized_origin)
  return serialized_origin_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* LocalStorage::release_serialized_origin() {
  // @@protoc_insertion_point(field_release:cobalt.storage.LocalStorage.serialized_origin)
  
  return serialized_origin_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void LocalStorage::set_allocated_serialized_origin(::std::string* serialized_origin) {
  if (serialized_origin != NULL) {
    
  } else {
    
  }
  serialized_origin_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), serialized_origin);
  // @@protoc_insertion_point(field_set_allocated:cobalt.storage.LocalStorage.serialized_origin)
}

// 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_cobalt_2fstorage_2fstore_2fstorage_2eproto();
#else
  if (default_instance_ == NULL) protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_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)
