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

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

#include <algorithm>

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

namespace cobalt {
namespace loader {

void protobuf_ShutdownFile_installation_5fstore_2eproto() {
  delete Installation::default_instance_;
  delete InstallationStore::default_instance_;
}

#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
void protobuf_AddDesc_installation_5fstore_2eproto_impl() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

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

#endif
  Installation::default_instance_ = new Installation();
  InstallationStore::default_instance_ = new InstallationStore();
  Installation::default_instance_->InitAsDefaultInstance();
  InstallationStore::default_instance_->InitAsDefaultInstance();
  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_installation_5fstore_2eproto);
}

#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AddDesc_installation_5fstore_2eproto_once_);
void protobuf_AddDesc_installation_5fstore_2eproto() {
  ::google::protobuf::GoogleOnceInit(&protobuf_AddDesc_installation_5fstore_2eproto_once_,
                 &protobuf_AddDesc_installation_5fstore_2eproto_impl);
}
#else
// Force AddDescriptors() to be called at static initialization time.
struct StaticDescriptorInitializer_installation_5fstore_2eproto {
  StaticDescriptorInitializer_installation_5fstore_2eproto() {
    protobuf_AddDesc_installation_5fstore_2eproto();
  }
} static_descriptor_initializer_installation_5fstore_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 Installation::kIsSuccessfulFieldNumber;
const int Installation::kNumTriesLeftFieldNumber;
const int Installation::kPriorityFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

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

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

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

void Installation::SharedCtor() {
    _is_default_instance_ = false;
  _cached_size_ = 0;
  is_successful_ = false;
  num_tries_left_ = 0;
  priority_ = 0;
}

Installation::~Installation() {
  // @@protoc_insertion_point(destructor:cobalt.loader.Installation)
  SharedDtor();
}

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

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

Installation* Installation::default_instance_ = NULL;

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

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

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

  ZR_(is_successful_, priority_);

#undef ZR_HELPER_
#undef ZR_

}

bool Installation::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.loader.Installation)
  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 bool is_successful = 1;
      case 1: {
        if (tag == 8) {
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                 input, &is_successful_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(16)) goto parse_num_tries_left;
        break;
      }

      // optional int32 num_tries_left = 2;
      case 2: {
        if (tag == 16) {
         parse_num_tries_left:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &num_tries_left_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(24)) goto parse_priority;
        break;
      }

      // optional int32 priority = 3;
      case 3: {
        if (tag == 24) {
         parse_priority:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &priority_)));

        } 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.loader.Installation)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:cobalt.loader.Installation)
  return false;
#undef DO_
}

void Installation::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:cobalt.loader.Installation)
  // optional bool is_successful = 1;
  if (this->is_successful() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->is_successful(), output);
  }

  // optional int32 num_tries_left = 2;
  if (this->num_tries_left() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->num_tries_left(), output);
  }

  // optional int32 priority = 3;
  if (this->priority() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->priority(), output);
  }

  // @@protoc_insertion_point(serialize_end:cobalt.loader.Installation)
}

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

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

  // optional int32 num_tries_left = 2;
  if (this->num_tries_left() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int32Size(
        this->num_tries_left());
  }

  // optional int32 priority = 3;
  if (this->priority() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int32Size(
        this->priority());
  }

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

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

void Installation::MergeFrom(const Installation& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:cobalt.loader.Installation)
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  if (from.is_successful() != 0) {
    set_is_successful(from.is_successful());
  }
  if (from.num_tries_left() != 0) {
    set_num_tries_left(from.num_tries_left());
  }
  if (from.priority() != 0) {
    set_priority(from.priority());
  }
}

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

bool Installation::IsInitialized() const {

  return true;
}

void Installation::Swap(Installation* other) {
  if (other == this) return;
  InternalSwap(other);
}
void Installation::InternalSwap(Installation* other) {
  std::swap(is_successful_, other->is_successful_);
  std::swap(num_tries_left_, other->num_tries_left_);
  std::swap(priority_, other->priority_);
  _unknown_fields_.Swap(&other->_unknown_fields_);
  std::swap(_cached_size_, other->_cached_size_);
}

::std::string Installation::GetTypeName() const {
  return "cobalt.loader.Installation";
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// Installation

// optional bool is_successful = 1;
void Installation::clear_is_successful() {
  is_successful_ = false;
}
 bool Installation::is_successful() const {
  // @@protoc_insertion_point(field_get:cobalt.loader.Installation.is_successful)
  return is_successful_;
}
 void Installation::set_is_successful(bool value) {
  
  is_successful_ = value;
  // @@protoc_insertion_point(field_set:cobalt.loader.Installation.is_successful)
}

// optional int32 num_tries_left = 2;
void Installation::clear_num_tries_left() {
  num_tries_left_ = 0;
}
 ::google::protobuf::int32 Installation::num_tries_left() const {
  // @@protoc_insertion_point(field_get:cobalt.loader.Installation.num_tries_left)
  return num_tries_left_;
}
 void Installation::set_num_tries_left(::google::protobuf::int32 value) {
  
  num_tries_left_ = value;
  // @@protoc_insertion_point(field_set:cobalt.loader.Installation.num_tries_left)
}

// optional int32 priority = 3;
void Installation::clear_priority() {
  priority_ = 0;
}
 ::google::protobuf::int32 Installation::priority() const {
  // @@protoc_insertion_point(field_get:cobalt.loader.Installation.priority)
  return priority_;
}
 void Installation::set_priority(::google::protobuf::int32 value) {
  
  priority_ = value;
  // @@protoc_insertion_point(field_set:cobalt.loader.Installation.priority)
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

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

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int InstallationStore::kInstallationsFieldNumber;
const int InstallationStore::kRollForwardToInstallationFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

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

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

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

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

InstallationStore::~InstallationStore() {
  // @@protoc_insertion_point(destructor:cobalt.loader.InstallationStore)
  SharedDtor();
}

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

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

InstallationStore* InstallationStore::default_instance_ = NULL;

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

void InstallationStore::Clear() {
// @@protoc_insertion_point(message_clear_start:cobalt.loader.InstallationStore)
  roll_forward_to_installation_ = 0;
  installations_.Clear();
}

bool InstallationStore::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.loader.InstallationStore)
  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.loader.Installation installations = 1;
      case 1: {
        if (tag == 10) {
          DO_(input->IncrementRecursionDepth());
         parse_loop_installations:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
                input, add_installations()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(10)) goto parse_loop_installations;
        input->UnsafeDecrementRecursionDepth();
        if (input->ExpectTag(16)) goto parse_roll_forward_to_installation;
        break;
      }

      // optional int32 roll_forward_to_installation = 2;
      case 2: {
        if (tag == 16) {
         parse_roll_forward_to_installation:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &roll_forward_to_installation_)));

        } 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.loader.InstallationStore)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:cobalt.loader.InstallationStore)
  return false;
#undef DO_
}

void InstallationStore::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:cobalt.loader.InstallationStore)
  // repeated .cobalt.loader.Installation installations = 1;
  for (unsigned int i = 0, n = this->installations_size(); i < n; i++) {
    ::google::protobuf::internal::WireFormatLite::WriteMessage(
      1, this->installations(i), output);
  }

  // optional int32 roll_forward_to_installation = 2;
  if (this->roll_forward_to_installation() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->roll_forward_to_installation(), output);
  }

  // @@protoc_insertion_point(serialize_end:cobalt.loader.InstallationStore)
}

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

  // optional int32 roll_forward_to_installation = 2;
  if (this->roll_forward_to_installation() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int32Size(
        this->roll_forward_to_installation());
  }

  // repeated .cobalt.loader.Installation installations = 1;
  total_size += 1 * this->installations_size();
  for (int i = 0; i < this->installations_size(); i++) {
    total_size +=
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        this->installations(i));
  }

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

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

void InstallationStore::MergeFrom(const InstallationStore& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:cobalt.loader.InstallationStore)
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  installations_.MergeFrom(from.installations_);
  if (from.roll_forward_to_installation() != 0) {
    set_roll_forward_to_installation(from.roll_forward_to_installation());
  }
}

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

bool InstallationStore::IsInitialized() const {

  return true;
}

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

::std::string InstallationStore::GetTypeName() const {
  return "cobalt.loader.InstallationStore";
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// InstallationStore

// repeated .cobalt.loader.Installation installations = 1;
int InstallationStore::installations_size() const {
  return installations_.size();
}
void InstallationStore::clear_installations() {
  installations_.Clear();
}
const ::cobalt::loader::Installation& InstallationStore::installations(int index) const {
  // @@protoc_insertion_point(field_get:cobalt.loader.InstallationStore.installations)
  return installations_.Get(index);
}
::cobalt::loader::Installation* InstallationStore::mutable_installations(int index) {
  // @@protoc_insertion_point(field_mutable:cobalt.loader.InstallationStore.installations)
  return installations_.Mutable(index);
}
::cobalt::loader::Installation* InstallationStore::add_installations() {
  // @@protoc_insertion_point(field_add:cobalt.loader.InstallationStore.installations)
  return installations_.Add();
}
::google::protobuf::RepeatedPtrField< ::cobalt::loader::Installation >*
InstallationStore::mutable_installations() {
  // @@protoc_insertion_point(field_mutable_list:cobalt.loader.InstallationStore.installations)
  return &installations_;
}
const ::google::protobuf::RepeatedPtrField< ::cobalt::loader::Installation >&
InstallationStore::installations() const {
  // @@protoc_insertion_point(field_list:cobalt.loader.InstallationStore.installations)
  return installations_;
}

// optional int32 roll_forward_to_installation = 2;
void InstallationStore::clear_roll_forward_to_installation() {
  roll_forward_to_installation_ = 0;
}
 ::google::protobuf::int32 InstallationStore::roll_forward_to_installation() const {
  // @@protoc_insertion_point(field_get:cobalt.loader.InstallationStore.roll_forward_to_installation)
  return roll_forward_to_installation_;
}
 void InstallationStore::set_roll_forward_to_installation(::google::protobuf::int32 value) {
  
  roll_forward_to_installation_ = value;
  // @@protoc_insertion_point(field_set:cobalt.loader.InstallationStore.roll_forward_to_installation)
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

// @@protoc_insertion_point(namespace_scope)

}  // namespace loader
}  // namespace cobalt

// @@protoc_insertion_point(global_scope)
