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

#include "dmi/sw_management_service.pb.h"

#include <algorithm>

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
// @@protoc_insertion_point(includes)
#include <google/protobuf/port_def.inc>

extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Uuid_dmi_2fhw_2eproto;
extern PROTOBUF_INTERNAL_EXPORT_dmi_2fsw_5fimage_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_ImageVersion_dmi_2fsw_5fimage_2eproto;
extern PROTOBUF_INTERNAL_EXPORT_dmi_2fsw_5fimage_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_ImageInformation_dmi_2fsw_5fimage_2eproto;
extern PROTOBUF_INTERNAL_EXPORT_dmi_2fsw_5fmanagement_5fservice_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_SoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto;
namespace dmi {
class SoftwareVersionInformationDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<SoftwareVersionInformation> _instance;
} _SoftwareVersionInformation_default_instance_;
class GetSoftwareVersionInformationResponseDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<GetSoftwareVersionInformationResponse> _instance;
} _GetSoftwareVersionInformationResponse_default_instance_;
class DownloadImageRequestDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<DownloadImageRequest> _instance;
} _DownloadImageRequest_default_instance_;
class ConfigRequestDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<ConfigRequest> _instance;
} _ConfigRequest_default_instance_;
class ConfigResponseDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<ConfigResponse> _instance;
} _ConfigResponse_default_instance_;
class StartupConfigInfoRequestDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<StartupConfigInfoRequest> _instance;
} _StartupConfigInfoRequest_default_instance_;
class StartupConfigInfoResponseDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<StartupConfigInfoResponse> _instance;
} _StartupConfigInfoResponse_default_instance_;
class UploadDebugInfoRequestDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<UploadDebugInfoRequest> _instance;
} _UploadDebugInfoRequest_default_instance_;
class UploadDebugInfoStatusDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<UploadDebugInfoStatus> _instance;
} _UploadDebugInfoStatus_default_instance_;
}  // namespace dmi
static void InitDefaultsSoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_SoftwareVersionInformation_default_instance_;
    new (ptr) ::dmi::SoftwareVersionInformation();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::SoftwareVersionInformation::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<1> scc_info_SoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsSoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto}, {
      &scc_info_ImageVersion_dmi_2fsw_5fimage_2eproto.base,}};

static void InitDefaultsGetSoftwareVersionInformationResponse_dmi_2fsw_5fmanagement_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_GetSoftwareVersionInformationResponse_default_instance_;
    new (ptr) ::dmi::GetSoftwareVersionInformationResponse();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::GetSoftwareVersionInformationResponse::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<1> scc_info_GetSoftwareVersionInformationResponse_dmi_2fsw_5fmanagement_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsGetSoftwareVersionInformationResponse_dmi_2fsw_5fmanagement_5fservice_2eproto}, {
      &scc_info_SoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto.base,}};

static void InitDefaultsDownloadImageRequest_dmi_2fsw_5fmanagement_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_DownloadImageRequest_default_instance_;
    new (ptr) ::dmi::DownloadImageRequest();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::DownloadImageRequest::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<2> scc_info_DownloadImageRequest_dmi_2fsw_5fmanagement_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsDownloadImageRequest_dmi_2fsw_5fmanagement_5fservice_2eproto}, {
      &scc_info_Uuid_dmi_2fhw_2eproto.base,
      &scc_info_ImageInformation_dmi_2fsw_5fimage_2eproto.base,}};

static void InitDefaultsConfigRequest_dmi_2fsw_5fmanagement_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_ConfigRequest_default_instance_;
    new (ptr) ::dmi::ConfigRequest();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::ConfigRequest::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<1> scc_info_ConfigRequest_dmi_2fsw_5fmanagement_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsConfigRequest_dmi_2fsw_5fmanagement_5fservice_2eproto}, {
      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};

static void InitDefaultsConfigResponse_dmi_2fsw_5fmanagement_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_ConfigResponse_default_instance_;
    new (ptr) ::dmi::ConfigResponse();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::ConfigResponse::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<0> scc_info_ConfigResponse_dmi_2fsw_5fmanagement_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsConfigResponse_dmi_2fsw_5fmanagement_5fservice_2eproto}, {}};

static void InitDefaultsStartupConfigInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_StartupConfigInfoRequest_default_instance_;
    new (ptr) ::dmi::StartupConfigInfoRequest();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::StartupConfigInfoRequest::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<1> scc_info_StartupConfigInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsStartupConfigInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto}, {
      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};

static void InitDefaultsStartupConfigInfoResponse_dmi_2fsw_5fmanagement_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_StartupConfigInfoResponse_default_instance_;
    new (ptr) ::dmi::StartupConfigInfoResponse();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::StartupConfigInfoResponse::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<0> scc_info_StartupConfigInfoResponse_dmi_2fsw_5fmanagement_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsStartupConfigInfoResponse_dmi_2fsw_5fmanagement_5fservice_2eproto}, {}};

static void InitDefaultsUploadDebugInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_UploadDebugInfoRequest_default_instance_;
    new (ptr) ::dmi::UploadDebugInfoRequest();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::UploadDebugInfoRequest::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<1> scc_info_UploadDebugInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsUploadDebugInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto}, {
      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};

static void InitDefaultsUploadDebugInfoStatus_dmi_2fsw_5fmanagement_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_UploadDebugInfoStatus_default_instance_;
    new (ptr) ::dmi::UploadDebugInfoStatus();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::UploadDebugInfoStatus::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<1> scc_info_UploadDebugInfoStatus_dmi_2fsw_5fmanagement_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsUploadDebugInfoStatus_dmi_2fsw_5fmanagement_5fservice_2eproto}, {
      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};

void InitDefaults_dmi_2fsw_5fmanagement_5fservice_2eproto() {
  ::google::protobuf::internal::InitSCC(&scc_info_SoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_GetSoftwareVersionInformationResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_DownloadImageRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_ConfigRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_ConfigResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_StartupConfigInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_StartupConfigInfoResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_UploadDebugInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_UploadDebugInfoStatus_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
}

::google::protobuf::Metadata file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[9];
const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto[5];
constexpr ::google::protobuf::ServiceDescriptor const** file_level_service_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto = nullptr;

const ::google::protobuf::uint32 TableStruct_dmi_2fsw_5fmanagement_5fservice_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::SoftwareVersionInformation, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::SoftwareVersionInformation, active_versions_),
  PROTOBUF_FIELD_OFFSET(::dmi::SoftwareVersionInformation, standby_versions_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::GetSoftwareVersionInformationResponse, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::GetSoftwareVersionInformationResponse, status_),
  PROTOBUF_FIELD_OFFSET(::dmi::GetSoftwareVersionInformationResponse, reason_),
  PROTOBUF_FIELD_OFFSET(::dmi::GetSoftwareVersionInformationResponse, info_),
  PROTOBUF_FIELD_OFFSET(::dmi::GetSoftwareVersionInformationResponse, reason_detail_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::DownloadImageRequest, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::DownloadImageRequest, device_uuid_),
  PROTOBUF_FIELD_OFFSET(::dmi::DownloadImageRequest, image_info_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::ConfigRequest, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::ConfigRequest, device_uuid_),
  PROTOBUF_FIELD_OFFSET(::dmi::ConfigRequest, config_url_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::ConfigResponse, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::ConfigResponse, status_),
  PROTOBUF_FIELD_OFFSET(::dmi::ConfigResponse, reason_),
  PROTOBUF_FIELD_OFFSET(::dmi::ConfigResponse, reason_detail_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoRequest, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoRequest, device_uuid_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoResponse, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoResponse, status_),
  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoResponse, reason_),
  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoResponse, config_url_),
  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoResponse, version_),
  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoResponse, reason_detail_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::UploadDebugInfoRequest, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::UploadDebugInfoRequest, device_uuid_),
  PROTOBUF_FIELD_OFFSET(::dmi::UploadDebugInfoRequest, location_url_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::UploadDebugInfoStatus, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::UploadDebugInfoStatus, device_uuid_),
  PROTOBUF_FIELD_OFFSET(::dmi::UploadDebugInfoStatus, status_),
  PROTOBUF_FIELD_OFFSET(::dmi::UploadDebugInfoStatus, percent_uploaded_),
  PROTOBUF_FIELD_OFFSET(::dmi::UploadDebugInfoStatus, reason_),
  PROTOBUF_FIELD_OFFSET(::dmi::UploadDebugInfoStatus, location_url_),
  PROTOBUF_FIELD_OFFSET(::dmi::UploadDebugInfoStatus, file_name_),
};
static const ::google::protobuf::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
  { 0, -1, sizeof(::dmi::SoftwareVersionInformation)},
  { 7, -1, sizeof(::dmi::GetSoftwareVersionInformationResponse)},
  { 16, -1, sizeof(::dmi::DownloadImageRequest)},
  { 23, -1, sizeof(::dmi::ConfigRequest)},
  { 30, -1, sizeof(::dmi::ConfigResponse)},
  { 38, -1, sizeof(::dmi::StartupConfigInfoRequest)},
  { 44, -1, sizeof(::dmi::StartupConfigInfoResponse)},
  { 54, -1, sizeof(::dmi::UploadDebugInfoRequest)},
  { 61, -1, sizeof(::dmi::UploadDebugInfoStatus)},
};

static ::google::protobuf::Message const * const file_default_instances[] = {
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_SoftwareVersionInformation_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_GetSoftwareVersionInformationResponse_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_DownloadImageRequest_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ConfigRequest_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ConfigResponse_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_StartupConfigInfoRequest_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_StartupConfigInfoResponse_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_UploadDebugInfoRequest_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_UploadDebugInfoStatus_default_instance_),
};

::google::protobuf::internal::AssignDescriptorsTable assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto = {
  {}, AddDescriptors_dmi_2fsw_5fmanagement_5fservice_2eproto, "dmi/sw_management_service.proto", schemas,
  file_default_instances, TableStruct_dmi_2fsw_5fmanagement_5fservice_2eproto::offsets,
  file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto, 9, file_level_enum_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto, file_level_service_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto,
};

const char descriptor_table_protodef_dmi_2fsw_5fmanagement_5fservice_2eproto[] =
  "\n\037dmi/sw_management_service.proto\022\003dmi\032\021"
  "dmi/commons.proto\032\014dmi/hw.proto\032\022dmi/sw_"
  "image.proto\"u\n\032SoftwareVersionInformatio"
  "n\022*\n\017active_versions\030\001 \003(\0132\021.dmi.ImageVe"
  "rsion\022+\n\020standby_versions\030\002 \003(\0132\021.dmi.Im"
  "ageVersion\"\255\002\n%GetSoftwareVersionInforma"
  "tionResponse\022\033\n\006status\030\001 \001(\0162\013.dmi.Statu"
  "s\022A\n\006reason\030\002 \001(\01621.dmi.GetSoftwareVersi"
  "onInformationResponse.Reason\022-\n\004info\030\003 \001"
  "(\0132\037.dmi.SoftwareVersionInformation\022\025\n\rr"
  "eason_detail\030\004 \001(\t\"^\n\006Reason\022\024\n\020UNDEFINE"
  "D_REASON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INTERN"
  "AL_ERROR\020\002\022\026\n\022DEVICE_UNREACHABLE\020\003\"a\n\024Do"
  "wnloadImageRequest\022\036\n\013device_uuid\030\001 \001(\0132"
  "\t.dmi.Uuid\022)\n\nimage_info\030\002 \001(\0132\025.dmi.Ima"
  "geInformation\"C\n\rConfigRequest\022\036\n\013device"
  "_uuid\030\001 \001(\0132\t.dmi.Uuid\022\022\n\nconfig_url\030\002 \001"
  "(\t\"\243\002\n\016ConfigResponse\022\033\n\006status\030\001 \001(\0162\013."
  "dmi.Status\022*\n\006reason\030\002 \001(\0162\032.dmi.ConfigR"
  "esponse.Reason\022\025\n\rreason_detail\030\003 \001(\t\"\260\001"
  "\n\006Reason\022\024\n\020UNDEFINED_REASON\020\000\022\022\n\016UNKNOW"
  "N_DEVICE\020\001\022\022\n\016INTERNAL_ERROR\020\002\022\031\n\025ERROR_"
  "FETCHING_CONFIG\020\003\022\022\n\016INVALID_CONFIG\020\004\022!\n"
  "\035OPERATION_ALREADY_IN_PROGRESS\020\005\022\026\n\022DEVI"
  "CE_UNREACHABLE\020\006\":\n\030StartupConfigInfoReq"
  "uest\022\036\n\013device_uuid\030\001 \001(\0132\t.dmi.Uuid\"\213\002\n"
  "\031StartupConfigInfoResponse\022\033\n\006status\030\001 \001"
  "(\0162\013.dmi.Status\0225\n\006reason\030\002 \001(\0162%.dmi.St"
  "artupConfigInfoResponse.Reason\022\022\n\nconfig"
  "_url\030\003 \001(\t\022\017\n\007version\030\004 \001(\t\022\025\n\rreason_de"
  "tail\030\005 \001(\t\"^\n\006Reason\022\024\n\020UNDEFINED_REASON"
  "\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INTERNAL_ERROR"
  "\020\002\022\026\n\022DEVICE_UNREACHABLE\020\003\"N\n\026UploadDebu"
  "gInfoRequest\022\036\n\013device_uuid\030\001 \001(\0132\t.dmi."
  "Uuid\022\024\n\014location_url\030\003 \001(\t\"\346\004\n\025UploadDeb"
  "ugInfoStatus\022\036\n\013device_uuid\030\001 \001(\0132\t.dmi."
  "Uuid\0227\n\006status\030\002 \001(\0162\'.dmi.UploadDebugIn"
  "foStatus.UploadStatus\022\030\n\020percent_uploade"
  "d\030\003 \001(\005\0221\n\006reason\030\004 \001(\0162!.dmi.UploadDebu"
  "gInfoStatus.Reason\022\024\n\014location_url\030\005 \001(\t"
  "\022\021\n\tfile_name\030\006 \001(\t\"U\n\014UploadStatus\022\033\n\027U"
  "NDEFINED_UPLOAD_STATUS\020\000\022\014\n\010COMPLETE\020\001\022\017"
  "\n\013IN_PROGRESS\020\002\022\t\n\005ERROR\020\003\"\246\002\n\006Reason\022\024\n"
  "\020UNDEFINED_REASON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022"
  "\022\n\016INTERNAL_ERROR\020\002\022\030\n\024DEVICE_NOT_REACHA"
  "BLE\020\003\022\037\n\033REMOTE_LOCATION_UNREACHABLE\020\004\022%"
  "\n!REMOTE_LOCATION_PERMISSION_DENIED\020\005\022\027\n"
  "\023ERROR_DURING_UPLOAD\020\006\022\017\n\013DEVICE_BUSY\020\007\022"
  "\024\n\020ERROR_IN_REQUEST\020\010\022\031\n\025DEVICE_IN_WRONG"
  "_STATE\020\t\022!\n\035OPERATION_ALREADY_IN_PROGRES"
  "S\020\n2\234\004\n\037NativeSoftwareManagementService\022"
  "Q\n\022GetSoftwareVersion\022\017.dmi.HardwareID\032*"
  ".dmi.GetSoftwareVersionInformationRespon"
  "se\022>\n\rDownloadImage\022\031.dmi.DownloadImageR"
  "equest\032\020.dmi.ImageStatus0\001\0224\n\rActivateIm"
  "age\022\017.dmi.HardwareID\032\020.dmi.ImageStatus0\001"
  "\022;\n\024RevertToStandbyImage\022\017.dmi.HardwareI"
  "D\032\020.dmi.ImageStatus0\001\022G\n\032UpdateStartupCo"
  "nfiguration\022\022.dmi.ConfigRequest\032\023.dmi.Co"
  "nfigResponse0\001\022\\\n\033GetStartupConfiguratio"
  "nInfo\022\035.dmi.StartupConfigInfoRequest\032\036.d"
  "mi.StartupConfigInfoResponse\022L\n\017UploadDe"
  "bugInfo\022\033.dmi.UploadDebugInfoRequest\032\032.d"
  "mi.UploadDebugInfoStatus0\001B;Z9github.com"
  "/opencord/device-management-interface/v3"
  "/go/dmib\006proto3"
  ;
::google::protobuf::internal::DescriptorTable descriptor_table_dmi_2fsw_5fmanagement_5fservice_2eproto = {
  false, InitDefaults_dmi_2fsw_5fmanagement_5fservice_2eproto, 
  descriptor_table_protodef_dmi_2fsw_5fmanagement_5fservice_2eproto,
  "dmi/sw_management_service.proto", &assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto, 2615,
};

void AddDescriptors_dmi_2fsw_5fmanagement_5fservice_2eproto() {
  static constexpr ::google::protobuf::internal::InitFunc deps[3] =
  {
    ::AddDescriptors_dmi_2fcommons_2eproto,
    ::AddDescriptors_dmi_2fhw_2eproto,
    ::AddDescriptors_dmi_2fsw_5fimage_2eproto,
  };
 ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmi_2fsw_5fmanagement_5fservice_2eproto, deps, 3);
}

// Force running AddDescriptors() at dynamic initialization time.
static bool dynamic_init_dummy_dmi_2fsw_5fmanagement_5fservice_2eproto = []() { AddDescriptors_dmi_2fsw_5fmanagement_5fservice_2eproto(); return true; }();
namespace dmi {
const ::google::protobuf::EnumDescriptor* GetSoftwareVersionInformationResponse_Reason_descriptor() {
  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
  return file_level_enum_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto[0];
}
bool GetSoftwareVersionInformationResponse_Reason_IsValid(int value) {
  switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
      return true;
    default:
      return false;
  }
}

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse::UNDEFINED_REASON;
const GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse::UNKNOWN_DEVICE;
const GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse::INTERNAL_ERROR;
const GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse::DEVICE_UNREACHABLE;
const GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse::Reason_MIN;
const GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse::Reason_MAX;
const int GetSoftwareVersionInformationResponse::Reason_ARRAYSIZE;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
const ::google::protobuf::EnumDescriptor* ConfigResponse_Reason_descriptor() {
  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
  return file_level_enum_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto[1];
}
bool ConfigResponse_Reason_IsValid(int value) {
  switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
      return true;
    default:
      return false;
  }
}

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const ConfigResponse_Reason ConfigResponse::UNDEFINED_REASON;
const ConfigResponse_Reason ConfigResponse::UNKNOWN_DEVICE;
const ConfigResponse_Reason ConfigResponse::INTERNAL_ERROR;
const ConfigResponse_Reason ConfigResponse::ERROR_FETCHING_CONFIG;
const ConfigResponse_Reason ConfigResponse::INVALID_CONFIG;
const ConfigResponse_Reason ConfigResponse::OPERATION_ALREADY_IN_PROGRESS;
const ConfigResponse_Reason ConfigResponse::DEVICE_UNREACHABLE;
const ConfigResponse_Reason ConfigResponse::Reason_MIN;
const ConfigResponse_Reason ConfigResponse::Reason_MAX;
const int ConfigResponse::Reason_ARRAYSIZE;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
const ::google::protobuf::EnumDescriptor* StartupConfigInfoResponse_Reason_descriptor() {
  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
  return file_level_enum_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto[2];
}
bool StartupConfigInfoResponse_Reason_IsValid(int value) {
  switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
      return true;
    default:
      return false;
  }
}

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const StartupConfigInfoResponse_Reason StartupConfigInfoResponse::UNDEFINED_REASON;
const StartupConfigInfoResponse_Reason StartupConfigInfoResponse::UNKNOWN_DEVICE;
const StartupConfigInfoResponse_Reason StartupConfigInfoResponse::INTERNAL_ERROR;
const StartupConfigInfoResponse_Reason StartupConfigInfoResponse::DEVICE_UNREACHABLE;
const StartupConfigInfoResponse_Reason StartupConfigInfoResponse::Reason_MIN;
const StartupConfigInfoResponse_Reason StartupConfigInfoResponse::Reason_MAX;
const int StartupConfigInfoResponse::Reason_ARRAYSIZE;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
const ::google::protobuf::EnumDescriptor* UploadDebugInfoStatus_UploadStatus_descriptor() {
  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
  return file_level_enum_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto[3];
}
bool UploadDebugInfoStatus_UploadStatus_IsValid(int value) {
  switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
      return true;
    default:
      return false;
  }
}

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const UploadDebugInfoStatus_UploadStatus UploadDebugInfoStatus::UNDEFINED_UPLOAD_STATUS;
const UploadDebugInfoStatus_UploadStatus UploadDebugInfoStatus::COMPLETE;
const UploadDebugInfoStatus_UploadStatus UploadDebugInfoStatus::IN_PROGRESS;
const UploadDebugInfoStatus_UploadStatus UploadDebugInfoStatus::ERROR;
const UploadDebugInfoStatus_UploadStatus UploadDebugInfoStatus::UploadStatus_MIN;
const UploadDebugInfoStatus_UploadStatus UploadDebugInfoStatus::UploadStatus_MAX;
const int UploadDebugInfoStatus::UploadStatus_ARRAYSIZE;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
const ::google::protobuf::EnumDescriptor* UploadDebugInfoStatus_Reason_descriptor() {
  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
  return file_level_enum_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto[4];
}
bool UploadDebugInfoStatus_Reason_IsValid(int value) {
  switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
    case 10:
      return true;
    default:
      return false;
  }
}

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const UploadDebugInfoStatus_Reason UploadDebugInfoStatus::UNDEFINED_REASON;
const UploadDebugInfoStatus_Reason UploadDebugInfoStatus::UNKNOWN_DEVICE;
const UploadDebugInfoStatus_Reason UploadDebugInfoStatus::INTERNAL_ERROR;
const UploadDebugInfoStatus_Reason UploadDebugInfoStatus::DEVICE_NOT_REACHABLE;
const UploadDebugInfoStatus_Reason UploadDebugInfoStatus::REMOTE_LOCATION_UNREACHABLE;
const UploadDebugInfoStatus_Reason UploadDebugInfoStatus::REMOTE_LOCATION_PERMISSION_DENIED;
const UploadDebugInfoStatus_Reason UploadDebugInfoStatus::ERROR_DURING_UPLOAD;
const UploadDebugInfoStatus_Reason UploadDebugInfoStatus::DEVICE_BUSY;
const UploadDebugInfoStatus_Reason UploadDebugInfoStatus::ERROR_IN_REQUEST;
const UploadDebugInfoStatus_Reason UploadDebugInfoStatus::DEVICE_IN_WRONG_STATE;
const UploadDebugInfoStatus_Reason UploadDebugInfoStatus::OPERATION_ALREADY_IN_PROGRESS;
const UploadDebugInfoStatus_Reason UploadDebugInfoStatus::Reason_MIN;
const UploadDebugInfoStatus_Reason UploadDebugInfoStatus::Reason_MAX;
const int UploadDebugInfoStatus::Reason_ARRAYSIZE;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

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

void SoftwareVersionInformation::InitAsDefaultInstance() {
}
class SoftwareVersionInformation::HasBitSetters {
 public:
};

void SoftwareVersionInformation::clear_active_versions() {
  active_versions_.Clear();
}
void SoftwareVersionInformation::clear_standby_versions() {
  standby_versions_.Clear();
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int SoftwareVersionInformation::kActiveVersionsFieldNumber;
const int SoftwareVersionInformation::kStandbyVersionsFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

SoftwareVersionInformation::SoftwareVersionInformation()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.SoftwareVersionInformation)
}
SoftwareVersionInformation::SoftwareVersionInformation(const SoftwareVersionInformation& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr),
      active_versions_(from.active_versions_),
      standby_versions_(from.standby_versions_) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  // @@protoc_insertion_point(copy_constructor:dmi.SoftwareVersionInformation)
}

void SoftwareVersionInformation::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_SoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
}

SoftwareVersionInformation::~SoftwareVersionInformation() {
  // @@protoc_insertion_point(destructor:dmi.SoftwareVersionInformation)
  SharedDtor();
}

void SoftwareVersionInformation::SharedDtor() {
}

void SoftwareVersionInformation::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const SoftwareVersionInformation& SoftwareVersionInformation::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_SoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  return *internal_default_instance();
}


void SoftwareVersionInformation::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.SoftwareVersionInformation)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  active_versions_.Clear();
  standby_versions_.Clear();
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* SoftwareVersionInformation::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<SoftwareVersionInformation*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // repeated .dmi.ImageVersion active_versions = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
        do {
          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
          parser_till_end = ::dmi::ImageVersion::_InternalParse;
          object = msg->add_active_versions();
          if (size > end - ptr) goto len_delim_till_end;
          ptr += size;
          GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
              {parser_till_end, object}, ptr - size, ptr));
          if (ptr >= end) break;
        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 10 && (ptr += 1));
        break;
      }
      // repeated .dmi.ImageVersion standby_versions = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
        do {
          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
          parser_till_end = ::dmi::ImageVersion::_InternalParse;
          object = msg->add_standby_versions();
          if (size > end - ptr) goto len_delim_till_end;
          ptr += size;
          GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
              {parser_till_end, object}, ptr - size, ptr));
          if (ptr >= end) break;
        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 18 && (ptr += 1));
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool SoftwareVersionInformation::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.SoftwareVersionInformation)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // repeated .dmi.ImageVersion active_versions = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
                input, add_active_versions()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // repeated .dmi.ImageVersion standby_versions = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
                input, add_standby_versions()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.SoftwareVersionInformation)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.SoftwareVersionInformation)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void SoftwareVersionInformation::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.SoftwareVersionInformation)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // repeated .dmi.ImageVersion active_versions = 1;
  for (unsigned int i = 0,
      n = static_cast<unsigned int>(this->active_versions_size()); i < n; i++) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      1,
      this->active_versions(static_cast<int>(i)),
      output);
  }

  // repeated .dmi.ImageVersion standby_versions = 2;
  for (unsigned int i = 0,
      n = static_cast<unsigned int>(this->standby_versions_size()); i < n; i++) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      2,
      this->standby_versions(static_cast<int>(i)),
      output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.SoftwareVersionInformation)
}

::google::protobuf::uint8* SoftwareVersionInformation::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.SoftwareVersionInformation)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // repeated .dmi.ImageVersion active_versions = 1;
  for (unsigned int i = 0,
      n = static_cast<unsigned int>(this->active_versions_size()); i < n; i++) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        1, this->active_versions(static_cast<int>(i)), target);
  }

  // repeated .dmi.ImageVersion standby_versions = 2;
  for (unsigned int i = 0,
      n = static_cast<unsigned int>(this->standby_versions_size()); i < n; i++) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        2, this->standby_versions(static_cast<int>(i)), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.SoftwareVersionInformation)
  return target;
}

size_t SoftwareVersionInformation::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.SoftwareVersionInformation)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // repeated .dmi.ImageVersion active_versions = 1;
  {
    unsigned int count = static_cast<unsigned int>(this->active_versions_size());
    total_size += 1UL * count;
    for (unsigned int i = 0; i < count; i++) {
      total_size +=
        ::google::protobuf::internal::WireFormatLite::MessageSize(
          this->active_versions(static_cast<int>(i)));
    }
  }

  // repeated .dmi.ImageVersion standby_versions = 2;
  {
    unsigned int count = static_cast<unsigned int>(this->standby_versions_size());
    total_size += 1UL * count;
    for (unsigned int i = 0; i < count; i++) {
      total_size +=
        ::google::protobuf::internal::WireFormatLite::MessageSize(
          this->standby_versions(static_cast<int>(i)));
    }
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void SoftwareVersionInformation::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.SoftwareVersionInformation)
  GOOGLE_DCHECK_NE(&from, this);
  const SoftwareVersionInformation* source =
      ::google::protobuf::DynamicCastToGenerated<SoftwareVersionInformation>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.SoftwareVersionInformation)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.SoftwareVersionInformation)
    MergeFrom(*source);
  }
}

void SoftwareVersionInformation::MergeFrom(const SoftwareVersionInformation& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.SoftwareVersionInformation)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  active_versions_.MergeFrom(from.active_versions_);
  standby_versions_.MergeFrom(from.standby_versions_);
}

void SoftwareVersionInformation::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.SoftwareVersionInformation)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

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

bool SoftwareVersionInformation::IsInitialized() const {
  return true;
}

void SoftwareVersionInformation::Swap(SoftwareVersionInformation* other) {
  if (other == this) return;
  InternalSwap(other);
}
void SoftwareVersionInformation::InternalSwap(SoftwareVersionInformation* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  CastToBase(&active_versions_)->InternalSwap(CastToBase(&other->active_versions_));
  CastToBase(&standby_versions_)->InternalSwap(CastToBase(&other->standby_versions_));
}

::google::protobuf::Metadata SoftwareVersionInformation::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
}


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

void GetSoftwareVersionInformationResponse::InitAsDefaultInstance() {
  ::dmi::_GetSoftwareVersionInformationResponse_default_instance_._instance.get_mutable()->info_ = const_cast< ::dmi::SoftwareVersionInformation*>(
      ::dmi::SoftwareVersionInformation::internal_default_instance());
}
class GetSoftwareVersionInformationResponse::HasBitSetters {
 public:
  static const ::dmi::SoftwareVersionInformation& info(const GetSoftwareVersionInformationResponse* msg);
};

const ::dmi::SoftwareVersionInformation&
GetSoftwareVersionInformationResponse::HasBitSetters::info(const GetSoftwareVersionInformationResponse* msg) {
  return *msg->info_;
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int GetSoftwareVersionInformationResponse::kStatusFieldNumber;
const int GetSoftwareVersionInformationResponse::kReasonFieldNumber;
const int GetSoftwareVersionInformationResponse::kInfoFieldNumber;
const int GetSoftwareVersionInformationResponse::kReasonDetailFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

GetSoftwareVersionInformationResponse::GetSoftwareVersionInformationResponse()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.GetSoftwareVersionInformationResponse)
}
GetSoftwareVersionInformationResponse::GetSoftwareVersionInformationResponse(const GetSoftwareVersionInformationResponse& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (from.reason_detail().size() > 0) {
    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
  }
  if (from.has_info()) {
    info_ = new ::dmi::SoftwareVersionInformation(*from.info_);
  } else {
    info_ = nullptr;
  }
  ::memcpy(&status_, &from.status_,
    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
  // @@protoc_insertion_point(copy_constructor:dmi.GetSoftwareVersionInformationResponse)
}

void GetSoftwareVersionInformationResponse::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_GetSoftwareVersionInformationResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  ::memset(&info_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&reason_) -
      reinterpret_cast<char*>(&info_)) + sizeof(reason_));
}

GetSoftwareVersionInformationResponse::~GetSoftwareVersionInformationResponse() {
  // @@protoc_insertion_point(destructor:dmi.GetSoftwareVersionInformationResponse)
  SharedDtor();
}

void GetSoftwareVersionInformationResponse::SharedDtor() {
  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (this != internal_default_instance()) delete info_;
}

void GetSoftwareVersionInformationResponse::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const GetSoftwareVersionInformationResponse& GetSoftwareVersionInformationResponse::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_GetSoftwareVersionInformationResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  return *internal_default_instance();
}


void GetSoftwareVersionInformationResponse::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.GetSoftwareVersionInformationResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (GetArenaNoVirtual() == nullptr && info_ != nullptr) {
    delete info_;
  }
  info_ = nullptr;
  ::memset(&status_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&reason_) -
      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* GetSoftwareVersionInformationResponse::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<GetSoftwareVersionInformationResponse*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.Status status = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_status(static_cast<::dmi::Status>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // .dmi.GetSoftwareVersionInformationResponse.Reason reason = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_reason(static_cast<::dmi::GetSoftwareVersionInformationResponse_Reason>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // .dmi.SoftwareVersionInformation info = 3;
      case 3: {
        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::SoftwareVersionInformation::_InternalParse;
        object = msg->mutable_info();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      // string reason_detail = 4;
      case 4: {
        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        ctx->extra_parse_data().SetFieldName("dmi.GetSoftwareVersionInformationResponse.reason_detail");
        object = msg->mutable_reason_detail();
        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
          goto string_till_end;
        }
        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
        ptr += size;
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
string_till_end:
  static_cast<::std::string*>(object)->clear();
  static_cast<::std::string*>(object)->reserve(size);
  goto len_delim_till_end;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool GetSoftwareVersionInformationResponse::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.GetSoftwareVersionInformationResponse)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.Status status = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_status(static_cast< ::dmi::Status >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.GetSoftwareVersionInformationResponse.Reason reason = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_reason(static_cast< ::dmi::GetSoftwareVersionInformationResponse_Reason >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.SoftwareVersionInformation info = 3;
      case 3: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_info()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // string reason_detail = 4;
      case 4: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_reason_detail()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "dmi.GetSoftwareVersionInformationResponse.reason_detail"));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.GetSoftwareVersionInformationResponse)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.GetSoftwareVersionInformationResponse)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void GetSoftwareVersionInformationResponse::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.GetSoftwareVersionInformationResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      1, this->status(), output);
  }

  // .dmi.GetSoftwareVersionInformationResponse.Reason reason = 2;
  if (this->reason() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      2, this->reason(), output);
  }

  // .dmi.SoftwareVersionInformation info = 3;
  if (this->has_info()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      3, HasBitSetters::info(this), output);
  }

  // string reason_detail = 4;
  if (this->reason_detail().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.GetSoftwareVersionInformationResponse.reason_detail");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      4, this->reason_detail(), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.GetSoftwareVersionInformationResponse)
}

::google::protobuf::uint8* GetSoftwareVersionInformationResponse::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.GetSoftwareVersionInformationResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      1, this->status(), target);
  }

  // .dmi.GetSoftwareVersionInformationResponse.Reason reason = 2;
  if (this->reason() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      2, this->reason(), target);
  }

  // .dmi.SoftwareVersionInformation info = 3;
  if (this->has_info()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        3, HasBitSetters::info(this), target);
  }

  // string reason_detail = 4;
  if (this->reason_detail().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.GetSoftwareVersionInformationResponse.reason_detail");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        4, this->reason_detail(), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.GetSoftwareVersionInformationResponse)
  return target;
}

size_t GetSoftwareVersionInformationResponse::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.GetSoftwareVersionInformationResponse)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // string reason_detail = 4;
  if (this->reason_detail().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->reason_detail());
  }

  // .dmi.SoftwareVersionInformation info = 3;
  if (this->has_info()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *info_);
  }

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
  }

  // .dmi.GetSoftwareVersionInformationResponse.Reason reason = 2;
  if (this->reason() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void GetSoftwareVersionInformationResponse::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.GetSoftwareVersionInformationResponse)
  GOOGLE_DCHECK_NE(&from, this);
  const GetSoftwareVersionInformationResponse* source =
      ::google::protobuf::DynamicCastToGenerated<GetSoftwareVersionInformationResponse>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.GetSoftwareVersionInformationResponse)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.GetSoftwareVersionInformationResponse)
    MergeFrom(*source);
  }
}

void GetSoftwareVersionInformationResponse::MergeFrom(const GetSoftwareVersionInformationResponse& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.GetSoftwareVersionInformationResponse)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.reason_detail().size() > 0) {

    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
  }
  if (from.has_info()) {
    mutable_info()->::dmi::SoftwareVersionInformation::MergeFrom(from.info());
  }
  if (from.status() != 0) {
    set_status(from.status());
  }
  if (from.reason() != 0) {
    set_reason(from.reason());
  }
}

void GetSoftwareVersionInformationResponse::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.GetSoftwareVersionInformationResponse)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

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

bool GetSoftwareVersionInformationResponse::IsInitialized() const {
  return true;
}

void GetSoftwareVersionInformationResponse::Swap(GetSoftwareVersionInformationResponse* other) {
  if (other == this) return;
  InternalSwap(other);
}
void GetSoftwareVersionInformationResponse::InternalSwap(GetSoftwareVersionInformationResponse* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
    GetArenaNoVirtual());
  swap(info_, other->info_);
  swap(status_, other->status_);
  swap(reason_, other->reason_);
}

::google::protobuf::Metadata GetSoftwareVersionInformationResponse::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
}


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

void DownloadImageRequest::InitAsDefaultInstance() {
  ::dmi::_DownloadImageRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
      ::dmi::Uuid::internal_default_instance());
  ::dmi::_DownloadImageRequest_default_instance_._instance.get_mutable()->image_info_ = const_cast< ::dmi::ImageInformation*>(
      ::dmi::ImageInformation::internal_default_instance());
}
class DownloadImageRequest::HasBitSetters {
 public:
  static const ::dmi::Uuid& device_uuid(const DownloadImageRequest* msg);
  static const ::dmi::ImageInformation& image_info(const DownloadImageRequest* msg);
};

const ::dmi::Uuid&
DownloadImageRequest::HasBitSetters::device_uuid(const DownloadImageRequest* msg) {
  return *msg->device_uuid_;
}
const ::dmi::ImageInformation&
DownloadImageRequest::HasBitSetters::image_info(const DownloadImageRequest* msg) {
  return *msg->image_info_;
}
void DownloadImageRequest::clear_device_uuid() {
  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
    delete device_uuid_;
  }
  device_uuid_ = nullptr;
}
void DownloadImageRequest::clear_image_info() {
  if (GetArenaNoVirtual() == nullptr && image_info_ != nullptr) {
    delete image_info_;
  }
  image_info_ = nullptr;
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int DownloadImageRequest::kDeviceUuidFieldNumber;
const int DownloadImageRequest::kImageInfoFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

DownloadImageRequest::DownloadImageRequest()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.DownloadImageRequest)
}
DownloadImageRequest::DownloadImageRequest(const DownloadImageRequest& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  if (from.has_device_uuid()) {
    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
  } else {
    device_uuid_ = nullptr;
  }
  if (from.has_image_info()) {
    image_info_ = new ::dmi::ImageInformation(*from.image_info_);
  } else {
    image_info_ = nullptr;
  }
  // @@protoc_insertion_point(copy_constructor:dmi.DownloadImageRequest)
}

void DownloadImageRequest::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_DownloadImageRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  ::memset(&device_uuid_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&image_info_) -
      reinterpret_cast<char*>(&device_uuid_)) + sizeof(image_info_));
}

DownloadImageRequest::~DownloadImageRequest() {
  // @@protoc_insertion_point(destructor:dmi.DownloadImageRequest)
  SharedDtor();
}

void DownloadImageRequest::SharedDtor() {
  if (this != internal_default_instance()) delete device_uuid_;
  if (this != internal_default_instance()) delete image_info_;
}

void DownloadImageRequest::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const DownloadImageRequest& DownloadImageRequest::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_DownloadImageRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  return *internal_default_instance();
}


void DownloadImageRequest::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.DownloadImageRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
    delete device_uuid_;
  }
  device_uuid_ = nullptr;
  if (GetArenaNoVirtual() == nullptr && image_info_ != nullptr) {
    delete image_info_;
  }
  image_info_ = nullptr;
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* DownloadImageRequest::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<DownloadImageRequest*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.Uuid device_uuid = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::Uuid::_InternalParse;
        object = msg->mutable_device_uuid();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      // .dmi.ImageInformation image_info = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::ImageInformation::_InternalParse;
        object = msg->mutable_image_info();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool DownloadImageRequest::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.DownloadImageRequest)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.Uuid device_uuid = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_device_uuid()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.ImageInformation image_info = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_image_info()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.DownloadImageRequest)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.DownloadImageRequest)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void DownloadImageRequest::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.DownloadImageRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      1, HasBitSetters::device_uuid(this), output);
  }

  // .dmi.ImageInformation image_info = 2;
  if (this->has_image_info()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      2, HasBitSetters::image_info(this), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.DownloadImageRequest)
}

::google::protobuf::uint8* DownloadImageRequest::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.DownloadImageRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        1, HasBitSetters::device_uuid(this), target);
  }

  // .dmi.ImageInformation image_info = 2;
  if (this->has_image_info()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        2, HasBitSetters::image_info(this), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.DownloadImageRequest)
  return target;
}

size_t DownloadImageRequest::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.DownloadImageRequest)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *device_uuid_);
  }

  // .dmi.ImageInformation image_info = 2;
  if (this->has_image_info()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *image_info_);
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void DownloadImageRequest::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.DownloadImageRequest)
  GOOGLE_DCHECK_NE(&from, this);
  const DownloadImageRequest* source =
      ::google::protobuf::DynamicCastToGenerated<DownloadImageRequest>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.DownloadImageRequest)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.DownloadImageRequest)
    MergeFrom(*source);
  }
}

void DownloadImageRequest::MergeFrom(const DownloadImageRequest& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.DownloadImageRequest)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.has_device_uuid()) {
    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
  }
  if (from.has_image_info()) {
    mutable_image_info()->::dmi::ImageInformation::MergeFrom(from.image_info());
  }
}

void DownloadImageRequest::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.DownloadImageRequest)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

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

bool DownloadImageRequest::IsInitialized() const {
  return true;
}

void DownloadImageRequest::Swap(DownloadImageRequest* other) {
  if (other == this) return;
  InternalSwap(other);
}
void DownloadImageRequest::InternalSwap(DownloadImageRequest* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  swap(device_uuid_, other->device_uuid_);
  swap(image_info_, other->image_info_);
}

::google::protobuf::Metadata DownloadImageRequest::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
}


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

void ConfigRequest::InitAsDefaultInstance() {
  ::dmi::_ConfigRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
      ::dmi::Uuid::internal_default_instance());
}
class ConfigRequest::HasBitSetters {
 public:
  static const ::dmi::Uuid& device_uuid(const ConfigRequest* msg);
};

const ::dmi::Uuid&
ConfigRequest::HasBitSetters::device_uuid(const ConfigRequest* msg) {
  return *msg->device_uuid_;
}
void ConfigRequest::clear_device_uuid() {
  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
    delete device_uuid_;
  }
  device_uuid_ = nullptr;
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int ConfigRequest::kDeviceUuidFieldNumber;
const int ConfigRequest::kConfigUrlFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

ConfigRequest::ConfigRequest()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.ConfigRequest)
}
ConfigRequest::ConfigRequest(const ConfigRequest& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  config_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (from.config_url().size() > 0) {
    config_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.config_url_);
  }
  if (from.has_device_uuid()) {
    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
  } else {
    device_uuid_ = nullptr;
  }
  // @@protoc_insertion_point(copy_constructor:dmi.ConfigRequest)
}

void ConfigRequest::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_ConfigRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  config_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  device_uuid_ = nullptr;
}

ConfigRequest::~ConfigRequest() {
  // @@protoc_insertion_point(destructor:dmi.ConfigRequest)
  SharedDtor();
}

void ConfigRequest::SharedDtor() {
  config_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (this != internal_default_instance()) delete device_uuid_;
}

void ConfigRequest::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const ConfigRequest& ConfigRequest::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_ConfigRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  return *internal_default_instance();
}


void ConfigRequest::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.ConfigRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  config_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
    delete device_uuid_;
  }
  device_uuid_ = nullptr;
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* ConfigRequest::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<ConfigRequest*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.Uuid device_uuid = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::Uuid::_InternalParse;
        object = msg->mutable_device_uuid();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      // string config_url = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        ctx->extra_parse_data().SetFieldName("dmi.ConfigRequest.config_url");
        object = msg->mutable_config_url();
        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
          goto string_till_end;
        }
        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
        ptr += size;
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
string_till_end:
  static_cast<::std::string*>(object)->clear();
  static_cast<::std::string*>(object)->reserve(size);
  goto len_delim_till_end;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool ConfigRequest::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.ConfigRequest)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.Uuid device_uuid = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_device_uuid()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // string config_url = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_config_url()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->config_url().data(), static_cast<int>(this->config_url().length()),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "dmi.ConfigRequest.config_url"));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.ConfigRequest)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.ConfigRequest)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void ConfigRequest::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.ConfigRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      1, HasBitSetters::device_uuid(this), output);
  }

  // string config_url = 2;
  if (this->config_url().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->config_url().data(), static_cast<int>(this->config_url().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.ConfigRequest.config_url");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      2, this->config_url(), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.ConfigRequest)
}

::google::protobuf::uint8* ConfigRequest::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.ConfigRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        1, HasBitSetters::device_uuid(this), target);
  }

  // string config_url = 2;
  if (this->config_url().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->config_url().data(), static_cast<int>(this->config_url().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.ConfigRequest.config_url");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        2, this->config_url(), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.ConfigRequest)
  return target;
}

size_t ConfigRequest::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.ConfigRequest)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // string config_url = 2;
  if (this->config_url().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->config_url());
  }

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *device_uuid_);
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void ConfigRequest::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.ConfigRequest)
  GOOGLE_DCHECK_NE(&from, this);
  const ConfigRequest* source =
      ::google::protobuf::DynamicCastToGenerated<ConfigRequest>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ConfigRequest)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ConfigRequest)
    MergeFrom(*source);
  }
}

void ConfigRequest::MergeFrom(const ConfigRequest& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ConfigRequest)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.config_url().size() > 0) {

    config_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.config_url_);
  }
  if (from.has_device_uuid()) {
    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
  }
}

void ConfigRequest::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.ConfigRequest)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

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

bool ConfigRequest::IsInitialized() const {
  return true;
}

void ConfigRequest::Swap(ConfigRequest* other) {
  if (other == this) return;
  InternalSwap(other);
}
void ConfigRequest::InternalSwap(ConfigRequest* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  config_url_.Swap(&other->config_url_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
    GetArenaNoVirtual());
  swap(device_uuid_, other->device_uuid_);
}

::google::protobuf::Metadata ConfigRequest::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
}


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

void ConfigResponse::InitAsDefaultInstance() {
}
class ConfigResponse::HasBitSetters {
 public:
};

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int ConfigResponse::kStatusFieldNumber;
const int ConfigResponse::kReasonFieldNumber;
const int ConfigResponse::kReasonDetailFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

ConfigResponse::ConfigResponse()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.ConfigResponse)
}
ConfigResponse::ConfigResponse(const ConfigResponse& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (from.reason_detail().size() > 0) {
    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
  }
  ::memcpy(&status_, &from.status_,
    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
  // @@protoc_insertion_point(copy_constructor:dmi.ConfigResponse)
}

void ConfigResponse::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_ConfigResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  ::memset(&status_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&reason_) -
      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
}

ConfigResponse::~ConfigResponse() {
  // @@protoc_insertion_point(destructor:dmi.ConfigResponse)
  SharedDtor();
}

void ConfigResponse::SharedDtor() {
  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}

void ConfigResponse::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const ConfigResponse& ConfigResponse::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_ConfigResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  return *internal_default_instance();
}


void ConfigResponse::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.ConfigResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  ::memset(&status_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&reason_) -
      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* ConfigResponse::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<ConfigResponse*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.Status status = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_status(static_cast<::dmi::Status>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // .dmi.ConfigResponse.Reason reason = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_reason(static_cast<::dmi::ConfigResponse_Reason>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // string reason_detail = 3;
      case 3: {
        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        ctx->extra_parse_data().SetFieldName("dmi.ConfigResponse.reason_detail");
        object = msg->mutable_reason_detail();
        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
          goto string_till_end;
        }
        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
        ptr += size;
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
string_till_end:
  static_cast<::std::string*>(object)->clear();
  static_cast<::std::string*>(object)->reserve(size);
  goto len_delim_till_end;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool ConfigResponse::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.ConfigResponse)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.Status status = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_status(static_cast< ::dmi::Status >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.ConfigResponse.Reason reason = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_reason(static_cast< ::dmi::ConfigResponse_Reason >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // string reason_detail = 3;
      case 3: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_reason_detail()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "dmi.ConfigResponse.reason_detail"));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.ConfigResponse)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.ConfigResponse)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void ConfigResponse::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.ConfigResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      1, this->status(), output);
  }

  // .dmi.ConfigResponse.Reason reason = 2;
  if (this->reason() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      2, this->reason(), output);
  }

  // string reason_detail = 3;
  if (this->reason_detail().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.ConfigResponse.reason_detail");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      3, this->reason_detail(), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.ConfigResponse)
}

::google::protobuf::uint8* ConfigResponse::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.ConfigResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      1, this->status(), target);
  }

  // .dmi.ConfigResponse.Reason reason = 2;
  if (this->reason() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      2, this->reason(), target);
  }

  // string reason_detail = 3;
  if (this->reason_detail().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.ConfigResponse.reason_detail");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        3, this->reason_detail(), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.ConfigResponse)
  return target;
}

size_t ConfigResponse::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.ConfigResponse)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // string reason_detail = 3;
  if (this->reason_detail().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->reason_detail());
  }

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
  }

  // .dmi.ConfigResponse.Reason reason = 2;
  if (this->reason() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void ConfigResponse::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.ConfigResponse)
  GOOGLE_DCHECK_NE(&from, this);
  const ConfigResponse* source =
      ::google::protobuf::DynamicCastToGenerated<ConfigResponse>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ConfigResponse)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ConfigResponse)
    MergeFrom(*source);
  }
}

void ConfigResponse::MergeFrom(const ConfigResponse& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ConfigResponse)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.reason_detail().size() > 0) {

    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
  }
  if (from.status() != 0) {
    set_status(from.status());
  }
  if (from.reason() != 0) {
    set_reason(from.reason());
  }
}

void ConfigResponse::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.ConfigResponse)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

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

bool ConfigResponse::IsInitialized() const {
  return true;
}

void ConfigResponse::Swap(ConfigResponse* other) {
  if (other == this) return;
  InternalSwap(other);
}
void ConfigResponse::InternalSwap(ConfigResponse* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
    GetArenaNoVirtual());
  swap(status_, other->status_);
  swap(reason_, other->reason_);
}

::google::protobuf::Metadata ConfigResponse::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
}


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

void StartupConfigInfoRequest::InitAsDefaultInstance() {
  ::dmi::_StartupConfigInfoRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
      ::dmi::Uuid::internal_default_instance());
}
class StartupConfigInfoRequest::HasBitSetters {
 public:
  static const ::dmi::Uuid& device_uuid(const StartupConfigInfoRequest* msg);
};

const ::dmi::Uuid&
StartupConfigInfoRequest::HasBitSetters::device_uuid(const StartupConfigInfoRequest* msg) {
  return *msg->device_uuid_;
}
void StartupConfigInfoRequest::clear_device_uuid() {
  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
    delete device_uuid_;
  }
  device_uuid_ = nullptr;
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int StartupConfigInfoRequest::kDeviceUuidFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

StartupConfigInfoRequest::StartupConfigInfoRequest()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.StartupConfigInfoRequest)
}
StartupConfigInfoRequest::StartupConfigInfoRequest(const StartupConfigInfoRequest& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  if (from.has_device_uuid()) {
    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
  } else {
    device_uuid_ = nullptr;
  }
  // @@protoc_insertion_point(copy_constructor:dmi.StartupConfigInfoRequest)
}

void StartupConfigInfoRequest::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_StartupConfigInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  device_uuid_ = nullptr;
}

StartupConfigInfoRequest::~StartupConfigInfoRequest() {
  // @@protoc_insertion_point(destructor:dmi.StartupConfigInfoRequest)
  SharedDtor();
}

void StartupConfigInfoRequest::SharedDtor() {
  if (this != internal_default_instance()) delete device_uuid_;
}

void StartupConfigInfoRequest::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const StartupConfigInfoRequest& StartupConfigInfoRequest::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_StartupConfigInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  return *internal_default_instance();
}


void StartupConfigInfoRequest::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.StartupConfigInfoRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
    delete device_uuid_;
  }
  device_uuid_ = nullptr;
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* StartupConfigInfoRequest::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<StartupConfigInfoRequest*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.Uuid device_uuid = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::Uuid::_InternalParse;
        object = msg->mutable_device_uuid();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool StartupConfigInfoRequest::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.StartupConfigInfoRequest)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.Uuid device_uuid = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_device_uuid()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.StartupConfigInfoRequest)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.StartupConfigInfoRequest)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void StartupConfigInfoRequest::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.StartupConfigInfoRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      1, HasBitSetters::device_uuid(this), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.StartupConfigInfoRequest)
}

::google::protobuf::uint8* StartupConfigInfoRequest::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.StartupConfigInfoRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        1, HasBitSetters::device_uuid(this), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.StartupConfigInfoRequest)
  return target;
}

size_t StartupConfigInfoRequest::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.StartupConfigInfoRequest)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *device_uuid_);
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void StartupConfigInfoRequest::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.StartupConfigInfoRequest)
  GOOGLE_DCHECK_NE(&from, this);
  const StartupConfigInfoRequest* source =
      ::google::protobuf::DynamicCastToGenerated<StartupConfigInfoRequest>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.StartupConfigInfoRequest)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.StartupConfigInfoRequest)
    MergeFrom(*source);
  }
}

void StartupConfigInfoRequest::MergeFrom(const StartupConfigInfoRequest& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.StartupConfigInfoRequest)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.has_device_uuid()) {
    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
  }
}

void StartupConfigInfoRequest::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.StartupConfigInfoRequest)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

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

bool StartupConfigInfoRequest::IsInitialized() const {
  return true;
}

void StartupConfigInfoRequest::Swap(StartupConfigInfoRequest* other) {
  if (other == this) return;
  InternalSwap(other);
}
void StartupConfigInfoRequest::InternalSwap(StartupConfigInfoRequest* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  swap(device_uuid_, other->device_uuid_);
}

::google::protobuf::Metadata StartupConfigInfoRequest::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
}


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

void StartupConfigInfoResponse::InitAsDefaultInstance() {
}
class StartupConfigInfoResponse::HasBitSetters {
 public:
};

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int StartupConfigInfoResponse::kStatusFieldNumber;
const int StartupConfigInfoResponse::kReasonFieldNumber;
const int StartupConfigInfoResponse::kConfigUrlFieldNumber;
const int StartupConfigInfoResponse::kVersionFieldNumber;
const int StartupConfigInfoResponse::kReasonDetailFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

StartupConfigInfoResponse::StartupConfigInfoResponse()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.StartupConfigInfoResponse)
}
StartupConfigInfoResponse::StartupConfigInfoResponse(const StartupConfigInfoResponse& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  config_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (from.config_url().size() > 0) {
    config_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.config_url_);
  }
  version_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (from.version().size() > 0) {
    version_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.version_);
  }
  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (from.reason_detail().size() > 0) {
    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
  }
  ::memcpy(&status_, &from.status_,
    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
  // @@protoc_insertion_point(copy_constructor:dmi.StartupConfigInfoResponse)
}

void StartupConfigInfoResponse::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_StartupConfigInfoResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  config_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  version_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  ::memset(&status_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&reason_) -
      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
}

StartupConfigInfoResponse::~StartupConfigInfoResponse() {
  // @@protoc_insertion_point(destructor:dmi.StartupConfigInfoResponse)
  SharedDtor();
}

void StartupConfigInfoResponse::SharedDtor() {
  config_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  version_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}

void StartupConfigInfoResponse::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const StartupConfigInfoResponse& StartupConfigInfoResponse::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_StartupConfigInfoResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  return *internal_default_instance();
}


void StartupConfigInfoResponse::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.StartupConfigInfoResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  config_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  ::memset(&status_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&reason_) -
      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* StartupConfigInfoResponse::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<StartupConfigInfoResponse*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.Status status = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_status(static_cast<::dmi::Status>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // .dmi.StartupConfigInfoResponse.Reason reason = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_reason(static_cast<::dmi::StartupConfigInfoResponse_Reason>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // string config_url = 3;
      case 3: {
        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        ctx->extra_parse_data().SetFieldName("dmi.StartupConfigInfoResponse.config_url");
        object = msg->mutable_config_url();
        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
          goto string_till_end;
        }
        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
        ptr += size;
        break;
      }
      // string version = 4;
      case 4: {
        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        ctx->extra_parse_data().SetFieldName("dmi.StartupConfigInfoResponse.version");
        object = msg->mutable_version();
        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
          goto string_till_end;
        }
        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
        ptr += size;
        break;
      }
      // string reason_detail = 5;
      case 5: {
        if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        ctx->extra_parse_data().SetFieldName("dmi.StartupConfigInfoResponse.reason_detail");
        object = msg->mutable_reason_detail();
        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
          goto string_till_end;
        }
        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
        ptr += size;
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
string_till_end:
  static_cast<::std::string*>(object)->clear();
  static_cast<::std::string*>(object)->reserve(size);
  goto len_delim_till_end;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool StartupConfigInfoResponse::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.StartupConfigInfoResponse)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.Status status = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_status(static_cast< ::dmi::Status >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.StartupConfigInfoResponse.Reason reason = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_reason(static_cast< ::dmi::StartupConfigInfoResponse_Reason >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // string config_url = 3;
      case 3: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_config_url()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->config_url().data(), static_cast<int>(this->config_url().length()),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "dmi.StartupConfigInfoResponse.config_url"));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // string version = 4;
      case 4: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_version()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->version().data(), static_cast<int>(this->version().length()),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "dmi.StartupConfigInfoResponse.version"));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // string reason_detail = 5;
      case 5: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (42 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_reason_detail()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "dmi.StartupConfigInfoResponse.reason_detail"));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.StartupConfigInfoResponse)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.StartupConfigInfoResponse)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void StartupConfigInfoResponse::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.StartupConfigInfoResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      1, this->status(), output);
  }

  // .dmi.StartupConfigInfoResponse.Reason reason = 2;
  if (this->reason() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      2, this->reason(), output);
  }

  // string config_url = 3;
  if (this->config_url().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->config_url().data(), static_cast<int>(this->config_url().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.StartupConfigInfoResponse.config_url");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      3, this->config_url(), output);
  }

  // string version = 4;
  if (this->version().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->version().data(), static_cast<int>(this->version().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.StartupConfigInfoResponse.version");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      4, this->version(), output);
  }

  // string reason_detail = 5;
  if (this->reason_detail().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.StartupConfigInfoResponse.reason_detail");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      5, this->reason_detail(), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.StartupConfigInfoResponse)
}

::google::protobuf::uint8* StartupConfigInfoResponse::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.StartupConfigInfoResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      1, this->status(), target);
  }

  // .dmi.StartupConfigInfoResponse.Reason reason = 2;
  if (this->reason() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      2, this->reason(), target);
  }

  // string config_url = 3;
  if (this->config_url().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->config_url().data(), static_cast<int>(this->config_url().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.StartupConfigInfoResponse.config_url");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        3, this->config_url(), target);
  }

  // string version = 4;
  if (this->version().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->version().data(), static_cast<int>(this->version().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.StartupConfigInfoResponse.version");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        4, this->version(), target);
  }

  // string reason_detail = 5;
  if (this->reason_detail().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.StartupConfigInfoResponse.reason_detail");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        5, this->reason_detail(), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.StartupConfigInfoResponse)
  return target;
}

size_t StartupConfigInfoResponse::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.StartupConfigInfoResponse)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // string config_url = 3;
  if (this->config_url().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->config_url());
  }

  // string version = 4;
  if (this->version().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->version());
  }

  // string reason_detail = 5;
  if (this->reason_detail().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->reason_detail());
  }

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
  }

  // .dmi.StartupConfigInfoResponse.Reason reason = 2;
  if (this->reason() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void StartupConfigInfoResponse::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.StartupConfigInfoResponse)
  GOOGLE_DCHECK_NE(&from, this);
  const StartupConfigInfoResponse* source =
      ::google::protobuf::DynamicCastToGenerated<StartupConfigInfoResponse>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.StartupConfigInfoResponse)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.StartupConfigInfoResponse)
    MergeFrom(*source);
  }
}

void StartupConfigInfoResponse::MergeFrom(const StartupConfigInfoResponse& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.StartupConfigInfoResponse)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.config_url().size() > 0) {

    config_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.config_url_);
  }
  if (from.version().size() > 0) {

    version_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.version_);
  }
  if (from.reason_detail().size() > 0) {

    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
  }
  if (from.status() != 0) {
    set_status(from.status());
  }
  if (from.reason() != 0) {
    set_reason(from.reason());
  }
}

void StartupConfigInfoResponse::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.StartupConfigInfoResponse)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

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

bool StartupConfigInfoResponse::IsInitialized() const {
  return true;
}

void StartupConfigInfoResponse::Swap(StartupConfigInfoResponse* other) {
  if (other == this) return;
  InternalSwap(other);
}
void StartupConfigInfoResponse::InternalSwap(StartupConfigInfoResponse* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  config_url_.Swap(&other->config_url_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
    GetArenaNoVirtual());
  version_.Swap(&other->version_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
    GetArenaNoVirtual());
  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
    GetArenaNoVirtual());
  swap(status_, other->status_);
  swap(reason_, other->reason_);
}

::google::protobuf::Metadata StartupConfigInfoResponse::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
}


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

void UploadDebugInfoRequest::InitAsDefaultInstance() {
  ::dmi::_UploadDebugInfoRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
      ::dmi::Uuid::internal_default_instance());
}
class UploadDebugInfoRequest::HasBitSetters {
 public:
  static const ::dmi::Uuid& device_uuid(const UploadDebugInfoRequest* msg);
};

const ::dmi::Uuid&
UploadDebugInfoRequest::HasBitSetters::device_uuid(const UploadDebugInfoRequest* msg) {
  return *msg->device_uuid_;
}
void UploadDebugInfoRequest::clear_device_uuid() {
  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
    delete device_uuid_;
  }
  device_uuid_ = nullptr;
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int UploadDebugInfoRequest::kDeviceUuidFieldNumber;
const int UploadDebugInfoRequest::kLocationUrlFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

UploadDebugInfoRequest::UploadDebugInfoRequest()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.UploadDebugInfoRequest)
}
UploadDebugInfoRequest::UploadDebugInfoRequest(const UploadDebugInfoRequest& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  location_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (from.location_url().size() > 0) {
    location_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.location_url_);
  }
  if (from.has_device_uuid()) {
    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
  } else {
    device_uuid_ = nullptr;
  }
  // @@protoc_insertion_point(copy_constructor:dmi.UploadDebugInfoRequest)
}

void UploadDebugInfoRequest::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_UploadDebugInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  location_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  device_uuid_ = nullptr;
}

UploadDebugInfoRequest::~UploadDebugInfoRequest() {
  // @@protoc_insertion_point(destructor:dmi.UploadDebugInfoRequest)
  SharedDtor();
}

void UploadDebugInfoRequest::SharedDtor() {
  location_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (this != internal_default_instance()) delete device_uuid_;
}

void UploadDebugInfoRequest::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const UploadDebugInfoRequest& UploadDebugInfoRequest::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_UploadDebugInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  return *internal_default_instance();
}


void UploadDebugInfoRequest::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.UploadDebugInfoRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  location_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
    delete device_uuid_;
  }
  device_uuid_ = nullptr;
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* UploadDebugInfoRequest::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<UploadDebugInfoRequest*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.Uuid device_uuid = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::Uuid::_InternalParse;
        object = msg->mutable_device_uuid();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      // string location_url = 3;
      case 3: {
        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        ctx->extra_parse_data().SetFieldName("dmi.UploadDebugInfoRequest.location_url");
        object = msg->mutable_location_url();
        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
          goto string_till_end;
        }
        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
        ptr += size;
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
string_till_end:
  static_cast<::std::string*>(object)->clear();
  static_cast<::std::string*>(object)->reserve(size);
  goto len_delim_till_end;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool UploadDebugInfoRequest::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.UploadDebugInfoRequest)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.Uuid device_uuid = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_device_uuid()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // string location_url = 3;
      case 3: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_location_url()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->location_url().data(), static_cast<int>(this->location_url().length()),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "dmi.UploadDebugInfoRequest.location_url"));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.UploadDebugInfoRequest)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.UploadDebugInfoRequest)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void UploadDebugInfoRequest::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.UploadDebugInfoRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      1, HasBitSetters::device_uuid(this), output);
  }

  // string location_url = 3;
  if (this->location_url().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->location_url().data(), static_cast<int>(this->location_url().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.UploadDebugInfoRequest.location_url");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      3, this->location_url(), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.UploadDebugInfoRequest)
}

::google::protobuf::uint8* UploadDebugInfoRequest::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.UploadDebugInfoRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        1, HasBitSetters::device_uuid(this), target);
  }

  // string location_url = 3;
  if (this->location_url().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->location_url().data(), static_cast<int>(this->location_url().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.UploadDebugInfoRequest.location_url");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        3, this->location_url(), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.UploadDebugInfoRequest)
  return target;
}

size_t UploadDebugInfoRequest::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.UploadDebugInfoRequest)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // string location_url = 3;
  if (this->location_url().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->location_url());
  }

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *device_uuid_);
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void UploadDebugInfoRequest::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.UploadDebugInfoRequest)
  GOOGLE_DCHECK_NE(&from, this);
  const UploadDebugInfoRequest* source =
      ::google::protobuf::DynamicCastToGenerated<UploadDebugInfoRequest>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.UploadDebugInfoRequest)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.UploadDebugInfoRequest)
    MergeFrom(*source);
  }
}

void UploadDebugInfoRequest::MergeFrom(const UploadDebugInfoRequest& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.UploadDebugInfoRequest)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.location_url().size() > 0) {

    location_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.location_url_);
  }
  if (from.has_device_uuid()) {
    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
  }
}

void UploadDebugInfoRequest::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.UploadDebugInfoRequest)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

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

bool UploadDebugInfoRequest::IsInitialized() const {
  return true;
}

void UploadDebugInfoRequest::Swap(UploadDebugInfoRequest* other) {
  if (other == this) return;
  InternalSwap(other);
}
void UploadDebugInfoRequest::InternalSwap(UploadDebugInfoRequest* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  location_url_.Swap(&other->location_url_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
    GetArenaNoVirtual());
  swap(device_uuid_, other->device_uuid_);
}

::google::protobuf::Metadata UploadDebugInfoRequest::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
}


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

void UploadDebugInfoStatus::InitAsDefaultInstance() {
  ::dmi::_UploadDebugInfoStatus_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
      ::dmi::Uuid::internal_default_instance());
}
class UploadDebugInfoStatus::HasBitSetters {
 public:
  static const ::dmi::Uuid& device_uuid(const UploadDebugInfoStatus* msg);
};

const ::dmi::Uuid&
UploadDebugInfoStatus::HasBitSetters::device_uuid(const UploadDebugInfoStatus* msg) {
  return *msg->device_uuid_;
}
void UploadDebugInfoStatus::clear_device_uuid() {
  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
    delete device_uuid_;
  }
  device_uuid_ = nullptr;
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int UploadDebugInfoStatus::kDeviceUuidFieldNumber;
const int UploadDebugInfoStatus::kStatusFieldNumber;
const int UploadDebugInfoStatus::kPercentUploadedFieldNumber;
const int UploadDebugInfoStatus::kReasonFieldNumber;
const int UploadDebugInfoStatus::kLocationUrlFieldNumber;
const int UploadDebugInfoStatus::kFileNameFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

UploadDebugInfoStatus::UploadDebugInfoStatus()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.UploadDebugInfoStatus)
}
UploadDebugInfoStatus::UploadDebugInfoStatus(const UploadDebugInfoStatus& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  location_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (from.location_url().size() > 0) {
    location_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.location_url_);
  }
  file_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (from.file_name().size() > 0) {
    file_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.file_name_);
  }
  if (from.has_device_uuid()) {
    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
  } else {
    device_uuid_ = nullptr;
  }
  ::memcpy(&status_, &from.status_,
    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
  // @@protoc_insertion_point(copy_constructor:dmi.UploadDebugInfoStatus)
}

void UploadDebugInfoStatus::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_UploadDebugInfoStatus_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  location_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  file_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  ::memset(&device_uuid_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&reason_) -
      reinterpret_cast<char*>(&device_uuid_)) + sizeof(reason_));
}

UploadDebugInfoStatus::~UploadDebugInfoStatus() {
  // @@protoc_insertion_point(destructor:dmi.UploadDebugInfoStatus)
  SharedDtor();
}

void UploadDebugInfoStatus::SharedDtor() {
  location_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  file_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (this != internal_default_instance()) delete device_uuid_;
}

void UploadDebugInfoStatus::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const UploadDebugInfoStatus& UploadDebugInfoStatus::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_UploadDebugInfoStatus_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
  return *internal_default_instance();
}


void UploadDebugInfoStatus::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.UploadDebugInfoStatus)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  location_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
    delete device_uuid_;
  }
  device_uuid_ = nullptr;
  ::memset(&status_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&reason_) -
      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* UploadDebugInfoStatus::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<UploadDebugInfoStatus*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.Uuid device_uuid = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::Uuid::_InternalParse;
        object = msg->mutable_device_uuid();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      // .dmi.UploadDebugInfoStatus.UploadStatus status = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_status(static_cast<::dmi::UploadDebugInfoStatus_UploadStatus>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // int32 percent_uploaded = 3;
      case 3: {
        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
        msg->set_percent_uploaded(::google::protobuf::internal::ReadVarint(&ptr));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // .dmi.UploadDebugInfoStatus.Reason reason = 4;
      case 4: {
        if (static_cast<::google::protobuf::uint8>(tag) != 32) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_reason(static_cast<::dmi::UploadDebugInfoStatus_Reason>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // string location_url = 5;
      case 5: {
        if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        ctx->extra_parse_data().SetFieldName("dmi.UploadDebugInfoStatus.location_url");
        object = msg->mutable_location_url();
        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
          goto string_till_end;
        }
        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
        ptr += size;
        break;
      }
      // string file_name = 6;
      case 6: {
        if (static_cast<::google::protobuf::uint8>(tag) != 50) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        ctx->extra_parse_data().SetFieldName("dmi.UploadDebugInfoStatus.file_name");
        object = msg->mutable_file_name();
        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
          goto string_till_end;
        }
        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
        ptr += size;
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
string_till_end:
  static_cast<::std::string*>(object)->clear();
  static_cast<::std::string*>(object)->reserve(size);
  goto len_delim_till_end;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool UploadDebugInfoStatus::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.UploadDebugInfoStatus)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.Uuid device_uuid = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_device_uuid()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.UploadDebugInfoStatus.UploadStatus status = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_status(static_cast< ::dmi::UploadDebugInfoStatus_UploadStatus >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // int32 percent_uploaded = 3;
      case 3: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {

          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &percent_uploaded_)));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.UploadDebugInfoStatus.Reason reason = 4;
      case 4: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (32 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_reason(static_cast< ::dmi::UploadDebugInfoStatus_Reason >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // string location_url = 5;
      case 5: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (42 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_location_url()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->location_url().data(), static_cast<int>(this->location_url().length()),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "dmi.UploadDebugInfoStatus.location_url"));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // string file_name = 6;
      case 6: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (50 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_file_name()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->file_name().data(), static_cast<int>(this->file_name().length()),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "dmi.UploadDebugInfoStatus.file_name"));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.UploadDebugInfoStatus)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.UploadDebugInfoStatus)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void UploadDebugInfoStatus::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.UploadDebugInfoStatus)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      1, HasBitSetters::device_uuid(this), output);
  }

  // .dmi.UploadDebugInfoStatus.UploadStatus status = 2;
  if (this->status() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      2, this->status(), output);
  }

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

  // .dmi.UploadDebugInfoStatus.Reason reason = 4;
  if (this->reason() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      4, this->reason(), output);
  }

  // string location_url = 5;
  if (this->location_url().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->location_url().data(), static_cast<int>(this->location_url().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.UploadDebugInfoStatus.location_url");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      5, this->location_url(), output);
  }

  // string file_name = 6;
  if (this->file_name().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->file_name().data(), static_cast<int>(this->file_name().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.UploadDebugInfoStatus.file_name");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      6, this->file_name(), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.UploadDebugInfoStatus)
}

::google::protobuf::uint8* UploadDebugInfoStatus::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.UploadDebugInfoStatus)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        1, HasBitSetters::device_uuid(this), target);
  }

  // .dmi.UploadDebugInfoStatus.UploadStatus status = 2;
  if (this->status() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      2, this->status(), target);
  }

  // int32 percent_uploaded = 3;
  if (this->percent_uploaded() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->percent_uploaded(), target);
  }

  // .dmi.UploadDebugInfoStatus.Reason reason = 4;
  if (this->reason() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      4, this->reason(), target);
  }

  // string location_url = 5;
  if (this->location_url().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->location_url().data(), static_cast<int>(this->location_url().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.UploadDebugInfoStatus.location_url");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        5, this->location_url(), target);
  }

  // string file_name = 6;
  if (this->file_name().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->file_name().data(), static_cast<int>(this->file_name().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.UploadDebugInfoStatus.file_name");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        6, this->file_name(), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.UploadDebugInfoStatus)
  return target;
}

size_t UploadDebugInfoStatus::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.UploadDebugInfoStatus)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // string location_url = 5;
  if (this->location_url().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->location_url());
  }

  // string file_name = 6;
  if (this->file_name().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->file_name());
  }

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *device_uuid_);
  }

  // .dmi.UploadDebugInfoStatus.UploadStatus status = 2;
  if (this->status() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
  }

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

  // .dmi.UploadDebugInfoStatus.Reason reason = 4;
  if (this->reason() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void UploadDebugInfoStatus::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.UploadDebugInfoStatus)
  GOOGLE_DCHECK_NE(&from, this);
  const UploadDebugInfoStatus* source =
      ::google::protobuf::DynamicCastToGenerated<UploadDebugInfoStatus>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.UploadDebugInfoStatus)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.UploadDebugInfoStatus)
    MergeFrom(*source);
  }
}

void UploadDebugInfoStatus::MergeFrom(const UploadDebugInfoStatus& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.UploadDebugInfoStatus)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.location_url().size() > 0) {

    location_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.location_url_);
  }
  if (from.file_name().size() > 0) {

    file_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.file_name_);
  }
  if (from.has_device_uuid()) {
    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
  }
  if (from.status() != 0) {
    set_status(from.status());
  }
  if (from.percent_uploaded() != 0) {
    set_percent_uploaded(from.percent_uploaded());
  }
  if (from.reason() != 0) {
    set_reason(from.reason());
  }
}

void UploadDebugInfoStatus::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.UploadDebugInfoStatus)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

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

bool UploadDebugInfoStatus::IsInitialized() const {
  return true;
}

void UploadDebugInfoStatus::Swap(UploadDebugInfoStatus* other) {
  if (other == this) return;
  InternalSwap(other);
}
void UploadDebugInfoStatus::InternalSwap(UploadDebugInfoStatus* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  location_url_.Swap(&other->location_url_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
    GetArenaNoVirtual());
  file_name_.Swap(&other->file_name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
    GetArenaNoVirtual());
  swap(device_uuid_, other->device_uuid_);
  swap(status_, other->status_);
  swap(percent_uploaded_, other->percent_uploaded_);
  swap(reason_, other->reason_);
}

::google::protobuf::Metadata UploadDebugInfoStatus::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
}


// @@protoc_insertion_point(namespace_scope)
}  // namespace dmi
namespace google {
namespace protobuf {
template<> PROTOBUF_NOINLINE ::dmi::SoftwareVersionInformation* Arena::CreateMaybeMessage< ::dmi::SoftwareVersionInformation >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::SoftwareVersionInformation >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::GetSoftwareVersionInformationResponse* Arena::CreateMaybeMessage< ::dmi::GetSoftwareVersionInformationResponse >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::GetSoftwareVersionInformationResponse >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::DownloadImageRequest* Arena::CreateMaybeMessage< ::dmi::DownloadImageRequest >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::DownloadImageRequest >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::ConfigRequest* Arena::CreateMaybeMessage< ::dmi::ConfigRequest >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::ConfigRequest >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::ConfigResponse* Arena::CreateMaybeMessage< ::dmi::ConfigResponse >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::ConfigResponse >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::StartupConfigInfoRequest* Arena::CreateMaybeMessage< ::dmi::StartupConfigInfoRequest >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::StartupConfigInfoRequest >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::StartupConfigInfoResponse* Arena::CreateMaybeMessage< ::dmi::StartupConfigInfoResponse >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::StartupConfigInfoResponse >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::UploadDebugInfoRequest* Arena::CreateMaybeMessage< ::dmi::UploadDebugInfoRequest >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::UploadDebugInfoRequest >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::UploadDebugInfoStatus* Arena::CreateMaybeMessage< ::dmi::UploadDebugInfoStatus >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::UploadDebugInfoStatus >(arena);
}
}  // namespace protobuf
}  // namespace google

// @@protoc_insertion_point(global_scope)
#include <google/protobuf/port_undef.inc>
