// 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/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)
