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

#ifndef PROTOBUF_cobalt_2fstorage_2fstore_2fstorage_2eproto__INCLUDED
#define PROTOBUF_cobalt_2fstorage_2fstore_2fstorage_2eproto__INCLUDED

#include <string>

#include <google/protobuf/stubs/common.h>

#if GOOGLE_PROTOBUF_VERSION < 3000000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers.  Please update
#error your headers.
#endif
#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers.  Please
#error regenerate this file with a newer version of protoc.
#endif

#include <google/protobuf/arena.h>
#include <google/protobuf/arenastring.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/repeated_field.h>
// @@protoc_insertion_point(includes)

namespace cobalt {
namespace storage {

// Internal implementation detail -- do not call these.
void protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto();
void protobuf_AssignDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto();
void protobuf_ShutdownFile_cobalt_2fstorage_2fstore_2fstorage_2eproto();

class Cookie;
class LocalStorage;
class LocalStorageEntry;
class Storage;

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

class Cookie : public ::google::protobuf::MessageLite {
 public:
  Cookie();
  virtual ~Cookie();

  Cookie(const Cookie& from);

  inline Cookie& operator=(const Cookie& from) {
    CopyFrom(from);
    return *this;
  }

  static const Cookie& default_instance();

#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  // Returns the internal default instance pointer. This function can
  // return NULL thus should not be used by the user. This is intended
  // for Protobuf internal code. Please use default_instance() declared
  // above instead.
  static inline const Cookie* internal_default_instance() {
    return default_instance_;
  }
#endif

  GOOGLE_ATTRIBUTE_NOINLINE void Swap(Cookie* other);

  // implements Message ----------------------------------------------

  inline Cookie* New() const { return New(NULL); }

  Cookie* New(::google::protobuf::Arena* arena) const;
  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
  void CopyFrom(const Cookie& from);
  void MergeFrom(const Cookie& from);
  void Clear();
  bool IsInitialized() const;

  int ByteSize() const;
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input);
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const;
  void DiscardUnknownFields();
  int GetCachedSize() const { return _cached_size_; }

 private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const;
  void InternalSwap(Cookie* other);

 private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return _arena_ptr_;
  }
  inline ::google::protobuf::Arena* MaybeArenaPtr() const {
    return _arena_ptr_;
  }

 public:
  ::std::string GetTypeName() const;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // optional string name = 1;
  void clear_name();
  static const int kNameFieldNumber = 1;
  const ::std::string& name() const;
  void set_name(const ::std::string& value);
  void set_name(const char* value);
  void set_name(const char* value, size_t size);
  ::std::string* mutable_name();
  ::std::string* release_name();
  void set_allocated_name(::std::string* name);

  // optional string value = 2;
  void clear_value();
  static const int kValueFieldNumber = 2;
  const ::std::string& value() const;
  void set_value(const ::std::string& value);
  void set_value(const char* value);
  void set_value(const char* value, size_t size);
  ::std::string* mutable_value();
  ::std::string* release_value();
  void set_allocated_value(::std::string* value);

  // optional string domain = 3;
  void clear_domain();
  static const int kDomainFieldNumber = 3;
  const ::std::string& domain() const;
  void set_domain(const ::std::string& value);
  void set_domain(const char* value);
  void set_domain(const char* value, size_t size);
  ::std::string* mutable_domain();
  ::std::string* release_domain();
  void set_allocated_domain(::std::string* domain);

  // optional string path = 4;
  void clear_path();
  static const int kPathFieldNumber = 4;
  const ::std::string& path() const;
  void set_path(const ::std::string& value);
  void set_path(const char* value);
  void set_path(const char* value, size_t size);
  ::std::string* mutable_path();
  ::std::string* release_path();
  void set_allocated_path(::std::string* path);

  // optional int64 creation_time_us = 5;
  void clear_creation_time_us();
  static const int kCreationTimeUsFieldNumber = 5;
  ::google::protobuf::int64 creation_time_us() const;
  void set_creation_time_us(::google::protobuf::int64 value);

  // optional int64 expiration_time_us = 6;
  void clear_expiration_time_us();
  static const int kExpirationTimeUsFieldNumber = 6;
  ::google::protobuf::int64 expiration_time_us() const;
  void set_expiration_time_us(::google::protobuf::int64 value);

  // optional int64 last_access_time_us = 7;
  void clear_last_access_time_us();
  static const int kLastAccessTimeUsFieldNumber = 7;
  ::google::protobuf::int64 last_access_time_us() const;
  void set_last_access_time_us(::google::protobuf::int64 value);

  // optional bool secure = 8;
  void clear_secure();
  static const int kSecureFieldNumber = 8;
  bool secure() const;
  void set_secure(bool value);

  // optional bool http_only = 9;
  void clear_http_only();
  static const int kHttpOnlyFieldNumber = 9;
  bool http_only() const;
  void set_http_only(bool value);

  // @@protoc_insertion_point(class_scope:cobalt.storage.Cookie)
 private:
  ::google::protobuf::internal::ArenaStringPtr _unknown_fields_;
  ::google::protobuf::Arena* _arena_ptr_;

  bool _is_default_instance_;
  ::google::protobuf::internal::ArenaStringPtr name_;
  ::google::protobuf::internal::ArenaStringPtr value_;
  ::google::protobuf::internal::ArenaStringPtr domain_;
  ::google::protobuf::internal::ArenaStringPtr path_;
  ::google::protobuf::int64 creation_time_us_;
  ::google::protobuf::int64 expiration_time_us_;
  ::google::protobuf::int64 last_access_time_us_;
  bool secure_;
  bool http_only_;
  mutable int _cached_size_;
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  friend void
  protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto_impl();
#else
  friend void protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto();
#endif
  friend void protobuf_AssignDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto();
  friend void
  protobuf_ShutdownFile_cobalt_2fstorage_2fstore_2fstorage_2eproto();

  void InitAsDefaultInstance();
  static Cookie* default_instance_;
};
// -------------------------------------------------------------------

class LocalStorageEntry : public ::google::protobuf::MessageLite {
 public:
  LocalStorageEntry();
  virtual ~LocalStorageEntry();

  LocalStorageEntry(const LocalStorageEntry& from);

  inline LocalStorageEntry& operator=(const LocalStorageEntry& from) {
    CopyFrom(from);
    return *this;
  }

  static const LocalStorageEntry& default_instance();

#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  // Returns the internal default instance pointer. This function can
  // return NULL thus should not be used by the user. This is intended
  // for Protobuf internal code. Please use default_instance() declared
  // above instead.
  static inline const LocalStorageEntry* internal_default_instance() {
    return default_instance_;
  }
#endif

  GOOGLE_ATTRIBUTE_NOINLINE void Swap(LocalStorageEntry* other);

  // implements Message ----------------------------------------------

  inline LocalStorageEntry* New() const { return New(NULL); }

  LocalStorageEntry* New(::google::protobuf::Arena* arena) const;
  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
  void CopyFrom(const LocalStorageEntry& from);
  void MergeFrom(const LocalStorageEntry& from);
  void Clear();
  bool IsInitialized() const;

  int ByteSize() const;
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input);
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const;
  void DiscardUnknownFields();
  int GetCachedSize() const { return _cached_size_; }

 private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const;
  void InternalSwap(LocalStorageEntry* other);

 private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return _arena_ptr_;
  }
  inline ::google::protobuf::Arena* MaybeArenaPtr() const {
    return _arena_ptr_;
  }

 public:
  ::std::string GetTypeName() const;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // optional string key = 1;
  void clear_key();
  static const int kKeyFieldNumber = 1;
  const ::std::string& key() const;
  void set_key(const ::std::string& value);
  void set_key(const char* value);
  void set_key(const char* value, size_t size);
  ::std::string* mutable_key();
  ::std::string* release_key();
  void set_allocated_key(::std::string* key);

  // optional string value = 2;
  void clear_value();
  static const int kValueFieldNumber = 2;
  const ::std::string& value() const;
  void set_value(const ::std::string& value);
  void set_value(const char* value);
  void set_value(const char* value, size_t size);
  ::std::string* mutable_value();
  ::std::string* release_value();
  void set_allocated_value(::std::string* value);

  // @@protoc_insertion_point(class_scope:cobalt.storage.LocalStorageEntry)
 private:
  ::google::protobuf::internal::ArenaStringPtr _unknown_fields_;
  ::google::protobuf::Arena* _arena_ptr_;

  bool _is_default_instance_;
  ::google::protobuf::internal::ArenaStringPtr key_;
  ::google::protobuf::internal::ArenaStringPtr value_;
  mutable int _cached_size_;
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  friend void
  protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto_impl();
#else
  friend void protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto();
#endif
  friend void protobuf_AssignDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto();
  friend void
  protobuf_ShutdownFile_cobalt_2fstorage_2fstore_2fstorage_2eproto();

  void InitAsDefaultInstance();
  static LocalStorageEntry* default_instance_;
};
// -------------------------------------------------------------------

class LocalStorage : public ::google::protobuf::MessageLite {
 public:
  LocalStorage();
  virtual ~LocalStorage();

  LocalStorage(const LocalStorage& from);

  inline LocalStorage& operator=(const LocalStorage& from) {
    CopyFrom(from);
    return *this;
  }

  static const LocalStorage& default_instance();

#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  // Returns the internal default instance pointer. This function can
  // return NULL thus should not be used by the user. This is intended
  // for Protobuf internal code. Please use default_instance() declared
  // above instead.
  static inline const LocalStorage* internal_default_instance() {
    return default_instance_;
  }
#endif

  GOOGLE_ATTRIBUTE_NOINLINE void Swap(LocalStorage* other);

  // implements Message ----------------------------------------------

  inline LocalStorage* New() const { return New(NULL); }

  LocalStorage* New(::google::protobuf::Arena* arena) const;
  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
  void CopyFrom(const LocalStorage& from);
  void MergeFrom(const LocalStorage& from);
  void Clear();
  bool IsInitialized() const;

  int ByteSize() const;
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input);
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const;
  void DiscardUnknownFields();
  int GetCachedSize() const { return _cached_size_; }

 private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const;
  void InternalSwap(LocalStorage* other);

 private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return _arena_ptr_;
  }
  inline ::google::protobuf::Arena* MaybeArenaPtr() const {
    return _arena_ptr_;
  }

 public:
  ::std::string GetTypeName() const;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // optional string serialized_origin = 1;
  void clear_serialized_origin();
  static const int kSerializedOriginFieldNumber = 1;
  const ::std::string& serialized_origin() const;
  void set_serialized_origin(const ::std::string& value);
  void set_serialized_origin(const char* value);
  void set_serialized_origin(const char* value, size_t size);
  ::std::string* mutable_serialized_origin();
  ::std::string* release_serialized_origin();
  void set_allocated_serialized_origin(::std::string* serialized_origin);

  // repeated .cobalt.storage.LocalStorageEntry local_storage_entries = 2;
  int local_storage_entries_size() const;
  void clear_local_storage_entries();
  static const int kLocalStorageEntriesFieldNumber = 2;
  const ::cobalt::storage::LocalStorageEntry& local_storage_entries(
      int index) const;
  ::cobalt::storage::LocalStorageEntry* mutable_local_storage_entries(
      int index);
  ::cobalt::storage::LocalStorageEntry* add_local_storage_entries();
  ::google::protobuf::RepeatedPtrField< ::cobalt::storage::LocalStorageEntry>*
  mutable_local_storage_entries();
  const ::google::protobuf::RepeatedPtrField<
      ::cobalt::storage::LocalStorageEntry>&
  local_storage_entries() const;

  // @@protoc_insertion_point(class_scope:cobalt.storage.LocalStorage)
 private:
  ::google::protobuf::internal::ArenaStringPtr _unknown_fields_;
  ::google::protobuf::Arena* _arena_ptr_;

  bool _is_default_instance_;
  ::google::protobuf::internal::ArenaStringPtr serialized_origin_;
  ::google::protobuf::RepeatedPtrField< ::cobalt::storage::LocalStorageEntry>
      local_storage_entries_;
  mutable int _cached_size_;
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  friend void
  protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto_impl();
#else
  friend void protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto();
#endif
  friend void protobuf_AssignDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto();
  friend void
  protobuf_ShutdownFile_cobalt_2fstorage_2fstore_2fstorage_2eproto();

  void InitAsDefaultInstance();
  static LocalStorage* default_instance_;
};
// -------------------------------------------------------------------

class Storage : public ::google::protobuf::MessageLite {
 public:
  Storage();
  virtual ~Storage();

  Storage(const Storage& from);

  inline Storage& operator=(const Storage& from) {
    CopyFrom(from);
    return *this;
  }

  static const Storage& default_instance();

#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  // Returns the internal default instance pointer. This function can
  // return NULL thus should not be used by the user. This is intended
  // for Protobuf internal code. Please use default_instance() declared
  // above instead.
  static inline const Storage* internal_default_instance() {
    return default_instance_;
  }
#endif

  GOOGLE_ATTRIBUTE_NOINLINE void Swap(Storage* other);

  // implements Message ----------------------------------------------

  inline Storage* New() const { return New(NULL); }

  Storage* New(::google::protobuf::Arena* arena) const;
  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
  void CopyFrom(const Storage& from);
  void MergeFrom(const Storage& from);
  void Clear();
  bool IsInitialized() const;

  int ByteSize() const;
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input);
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const;
  void DiscardUnknownFields();
  int GetCachedSize() const { return _cached_size_; }

 private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const;
  void InternalSwap(Storage* other);

 private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return _arena_ptr_;
  }
  inline ::google::protobuf::Arena* MaybeArenaPtr() const {
    return _arena_ptr_;
  }

 public:
  ::std::string GetTypeName() const;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // repeated .cobalt.storage.Cookie cookies = 1;
  int cookies_size() const;
  void clear_cookies();
  static const int kCookiesFieldNumber = 1;
  const ::cobalt::storage::Cookie& cookies(int index) const;
  ::cobalt::storage::Cookie* mutable_cookies(int index);
  ::cobalt::storage::Cookie* add_cookies();
  ::google::protobuf::RepeatedPtrField< ::cobalt::storage::Cookie>*
  mutable_cookies();
  const ::google::protobuf::RepeatedPtrField< ::cobalt::storage::Cookie>&
  cookies() const;

  // repeated .cobalt.storage.LocalStorage local_storages = 2;
  int local_storages_size() const;
  void clear_local_storages();
  static const int kLocalStoragesFieldNumber = 2;
  const ::cobalt::storage::LocalStorage& local_storages(int index) const;
  ::cobalt::storage::LocalStorage* mutable_local_storages(int index);
  ::cobalt::storage::LocalStorage* add_local_storages();
  ::google::protobuf::RepeatedPtrField< ::cobalt::storage::LocalStorage>*
  mutable_local_storages();
  const ::google::protobuf::RepeatedPtrField< ::cobalt::storage::LocalStorage>&
  local_storages() const;

  // @@protoc_insertion_point(class_scope:cobalt.storage.Storage)
 private:
  ::google::protobuf::internal::ArenaStringPtr _unknown_fields_;
  ::google::protobuf::Arena* _arena_ptr_;

  bool _is_default_instance_;
  ::google::protobuf::RepeatedPtrField< ::cobalt::storage::Cookie> cookies_;
  ::google::protobuf::RepeatedPtrField< ::cobalt::storage::LocalStorage>
      local_storages_;
  mutable int _cached_size_;
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  friend void
  protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto_impl();
#else
  friend void protobuf_AddDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto();
#endif
  friend void protobuf_AssignDesc_cobalt_2fstorage_2fstore_2fstorage_2eproto();
  friend void
  protobuf_ShutdownFile_cobalt_2fstorage_2fstore_2fstorage_2eproto();

  void InitAsDefaultInstance();
  static Storage* default_instance_;
};
// ===================================================================


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

#if !PROTOBUF_INLINE_NOT_IN_HEADERS
// Cookie

// optional string name = 1;
inline void Cookie::clear_name() {
  name_.ClearToEmptyNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Cookie::name() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.name)
  return name_.GetNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void Cookie::set_name(const ::std::string& value) {
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
                   value);
  // @@protoc_insertion_point(field_set:cobalt.storage.Cookie.name)
}
inline 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)
}
inline 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)
}
inline ::std::string* Cookie::mutable_name() {
  // @@protoc_insertion_point(field_mutable:cobalt.storage.Cookie.name)
  return name_.MutableNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Cookie::release_name() {
  // @@protoc_insertion_point(field_release:cobalt.storage.Cookie.name)

  return name_.ReleaseNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline 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;
inline void Cookie::clear_value() {
  value_.ClearToEmptyNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Cookie::value() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.value)
  return value_.GetNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void Cookie::set_value(const ::std::string& value) {
  value_.SetNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:cobalt.storage.Cookie.value)
}
inline 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)
}
inline 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)
}
inline ::std::string* Cookie::mutable_value() {
  // @@protoc_insertion_point(field_mutable:cobalt.storage.Cookie.value)
  return value_.MutableNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Cookie::release_value() {
  // @@protoc_insertion_point(field_release:cobalt.storage.Cookie.value)

  return value_.ReleaseNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline 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;
inline void Cookie::clear_domain() {
  domain_.ClearToEmptyNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Cookie::domain() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.domain)
  return domain_.GetNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void Cookie::set_domain(const ::std::string& value) {
  domain_.SetNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:cobalt.storage.Cookie.domain)
}
inline 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)
}
inline 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)
}
inline ::std::string* Cookie::mutable_domain() {
  // @@protoc_insertion_point(field_mutable:cobalt.storage.Cookie.domain)
  return domain_.MutableNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Cookie::release_domain() {
  // @@protoc_insertion_point(field_release:cobalt.storage.Cookie.domain)

  return domain_.ReleaseNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline 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;
inline void Cookie::clear_path() {
  path_.ClearToEmptyNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Cookie::path() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.path)
  return path_.GetNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void Cookie::set_path(const ::std::string& value) {
  path_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
                   value);
  // @@protoc_insertion_point(field_set:cobalt.storage.Cookie.path)
}
inline 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)
}
inline 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)
}
inline ::std::string* Cookie::mutable_path() {
  // @@protoc_insertion_point(field_mutable:cobalt.storage.Cookie.path)
  return path_.MutableNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Cookie::release_path() {
  // @@protoc_insertion_point(field_release:cobalt.storage.Cookie.path)

  return path_.ReleaseNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline 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;
inline void Cookie::clear_creation_time_us() {
  creation_time_us_ = GOOGLE_LONGLONG(0);
}
inline ::google::protobuf::int64 Cookie::creation_time_us() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.creation_time_us)
  return creation_time_us_;
}
inline 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;
inline void Cookie::clear_expiration_time_us() {
  expiration_time_us_ = GOOGLE_LONGLONG(0);
}
inline ::google::protobuf::int64 Cookie::expiration_time_us() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.expiration_time_us)
  return expiration_time_us_;
}
inline 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;
inline void Cookie::clear_last_access_time_us() {
  last_access_time_us_ = GOOGLE_LONGLONG(0);
}
inline ::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_;
}
inline 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;
inline void Cookie::clear_secure() { secure_ = false; }
inline bool Cookie::secure() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Cookie.secure)
  return secure_;
}
inline void Cookie::set_secure(bool value) {
  secure_ = value;
  // @@protoc_insertion_point(field_set:cobalt.storage.Cookie.secure)
}

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

// -------------------------------------------------------------------

// LocalStorageEntry

// optional string key = 1;
inline void LocalStorageEntry::clear_key() {
  key_.ClearToEmptyNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& LocalStorageEntry::key() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.LocalStorageEntry.key)
  return key_.GetNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void LocalStorageEntry::set_key(const ::std::string& value) {
  key_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
                  value);
  // @@protoc_insertion_point(field_set:cobalt.storage.LocalStorageEntry.key)
}
inline 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)
}
inline 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)
}
inline ::std::string* LocalStorageEntry::mutable_key() {
  // @@protoc_insertion_point(field_mutable:cobalt.storage.LocalStorageEntry.key)
  return key_.MutableNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* LocalStorageEntry::release_key() {
  // @@protoc_insertion_point(field_release:cobalt.storage.LocalStorageEntry.key)

  return key_.ReleaseNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline 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;
inline void LocalStorageEntry::clear_value() {
  value_.ClearToEmptyNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& LocalStorageEntry::value() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.LocalStorageEntry.value)
  return value_.GetNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void LocalStorageEntry::set_value(const ::std::string& value) {
  value_.SetNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:cobalt.storage.LocalStorageEntry.value)
}
inline 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)
}
inline 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)
}
inline ::std::string* LocalStorageEntry::mutable_value() {
  // @@protoc_insertion_point(field_mutable:cobalt.storage.LocalStorageEntry.value)
  return value_.MutableNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* LocalStorageEntry::release_value() {
  // @@protoc_insertion_point(field_release:cobalt.storage.LocalStorageEntry.value)

  return value_.ReleaseNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline 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)
}

// -------------------------------------------------------------------

// LocalStorage

// optional string serialized_origin = 1;
inline void LocalStorage::clear_serialized_origin() {
  serialized_origin_.ClearToEmptyNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline 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());
}
inline 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)
}
inline 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)
}
inline 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)
}
inline ::std::string* LocalStorage::mutable_serialized_origin() {
  // @@protoc_insertion_point(field_mutable:cobalt.storage.LocalStorage.serialized_origin)
  return serialized_origin_.MutableNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* LocalStorage::release_serialized_origin() {
  // @@protoc_insertion_point(field_release:cobalt.storage.LocalStorage.serialized_origin)

  return serialized_origin_.ReleaseNoArena(
      &::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline 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;
inline int LocalStorage::local_storage_entries_size() const {
  return local_storage_entries_.size();
}
inline void LocalStorage::clear_local_storage_entries() {
  local_storage_entries_.Clear();
}
inline 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);
}
inline ::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);
}
inline ::cobalt::storage::LocalStorageEntry*
LocalStorage::add_local_storage_entries() {
  // @@protoc_insertion_point(field_add:cobalt.storage.LocalStorage.local_storage_entries)
  return local_storage_entries_.Add();
}
inline ::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_;
}
inline 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_;
}

// -------------------------------------------------------------------

// Storage

// repeated .cobalt.storage.Cookie cookies = 1;
inline int Storage::cookies_size() const { return cookies_.size(); }
inline void Storage::clear_cookies() { cookies_.Clear(); }
inline const ::cobalt::storage::Cookie& Storage::cookies(int index) const {
  // @@protoc_insertion_point(field_get:cobalt.storage.Storage.cookies)
  return cookies_.Get(index);
}
inline ::cobalt::storage::Cookie* Storage::mutable_cookies(int index) {
  // @@protoc_insertion_point(field_mutable:cobalt.storage.Storage.cookies)
  return cookies_.Mutable(index);
}
inline ::cobalt::storage::Cookie* Storage::add_cookies() {
  // @@protoc_insertion_point(field_add:cobalt.storage.Storage.cookies)
  return cookies_.Add();
}
inline ::google::protobuf::RepeatedPtrField< ::cobalt::storage::Cookie>*
Storage::mutable_cookies() {
  // @@protoc_insertion_point(field_mutable_list:cobalt.storage.Storage.cookies)
  return &cookies_;
}
inline 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;
inline int Storage::local_storages_size() const {
  return local_storages_.size();
}
inline void Storage::clear_local_storages() { local_storages_.Clear(); }
inline 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);
}
inline ::cobalt::storage::LocalStorage* Storage::mutable_local_storages(
    int index) {
  // @@protoc_insertion_point(field_mutable:cobalt.storage.Storage.local_storages)
  return local_storages_.Mutable(index);
}
inline ::cobalt::storage::LocalStorage* Storage::add_local_storages() {
  // @@protoc_insertion_point(field_add:cobalt.storage.Storage.local_storages)
  return local_storages_.Add();
}
inline ::google::protobuf::RepeatedPtrField< ::cobalt::storage::LocalStorage>*
Storage::mutable_local_storages() {
  // @@protoc_insertion_point(field_mutable_list:cobalt.storage.Storage.local_storages)
  return &local_storages_;
}
inline 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)

#endif  // PROTOBUF_cobalt_2fstorage_2fstore_2fstorage_2eproto__INCLUDED
