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

#ifndef PROTOBUF_storage_2eproto__INCLUDED
#define PROTOBUF_storage_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/generated_message_util.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
// @@protoc_insertion_point(includes)

namespace cobalt {
namespace storage {

// Internal implementation detail -- do not call these.
void protobuf_AddDesc_storage_2eproto();
void protobuf_AssignDesc_storage_2eproto();
void protobuf_ShutdownFile_storage_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_storage_2eproto_impl();
  #else
  friend void  protobuf_AddDesc_storage_2eproto();
  #endif
  friend void protobuf_AssignDesc_storage_2eproto();
  friend void protobuf_ShutdownFile_storage_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_storage_2eproto_impl();
  #else
  friend void  protobuf_AddDesc_storage_2eproto();
  #endif
  friend void protobuf_AssignDesc_storage_2eproto();
  friend void protobuf_ShutdownFile_storage_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 id = 1;
  void clear_id();
  static const int kIdFieldNumber = 1;
  const ::std::string& id() const;
  void set_id(const ::std::string& value);
  void set_id(const char* value);
  void set_id(const char* value, size_t size);
  ::std::string* mutable_id();
  ::std::string* release_id();
  void set_allocated_id(::std::string* id);

  // 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 id_;
  ::google::protobuf::RepeatedPtrField< ::cobalt::storage::LocalStorageEntry > local_storage_entries_;
  mutable int _cached_size_;
  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  friend void  protobuf_AddDesc_storage_2eproto_impl();
  #else
  friend void  protobuf_AddDesc_storage_2eproto();
  #endif
  friend void protobuf_AssignDesc_storage_2eproto();
  friend void protobuf_ShutdownFile_storage_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_storage_2eproto_impl();
  #else
  friend void  protobuf_AddDesc_storage_2eproto();
  #endif
  friend void protobuf_AssignDesc_storage_2eproto();
  friend void protobuf_ShutdownFile_storage_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 id = 1;
inline void LocalStorage::clear_id() {
  id_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& LocalStorage::id() const {
  // @@protoc_insertion_point(field_get:cobalt.storage.LocalStorage.id)
  return id_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void LocalStorage::set_id(const ::std::string& value) {
  
  id_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:cobalt.storage.LocalStorage.id)
}
inline void LocalStorage::set_id(const char* value) {
  
  id_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:cobalt.storage.LocalStorage.id)
}
inline void LocalStorage::set_id(const char* value, size_t size) {
  
  id_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:cobalt.storage.LocalStorage.id)
}
inline ::std::string* LocalStorage::mutable_id() {
  
  // @@protoc_insertion_point(field_mutable:cobalt.storage.LocalStorage.id)
  return id_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* LocalStorage::release_id() {
  // @@protoc_insertion_point(field_release:cobalt.storage.LocalStorage.id)
  
  return id_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void LocalStorage::set_allocated_id(::std::string* id) {
  if (id != NULL) {
    
  } else {
    
  }
  id_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), id);
  // @@protoc_insertion_point(field_set_allocated:cobalt.storage.LocalStorage.id)
}

// repeated .cobalt.storage.LocalStorageEntry local_storage_entries = 2;
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_storage_2eproto__INCLUDED
