// 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\"\220\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\"\320\001\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_UNREACHABL"
  "E\020\003\022\037\n\033REMOTE_LOCATION_UNREACHABLE\020\004\022%\n!"
  "REMOTE_LOCATION_PERMISSION_DENIED\020\005\022\027\n\023E"
  "RROR_DURING_UPLOAD\020\006\022\017\n\013DEVICE_BUSY\020\0072\234\004"
  "\n\037NativeSoftwareManagementService\022Q\n\022Get"
  "SoftwareVersion\022\017.dmi.HardwareID\032*.dmi.G"
  "etSoftwareVersionInformationResponse\022>\n\r"
  "DownloadImage\022\031.dmi.DownloadImageRequest"
  "\032\020.dmi.ImageStatus0\001\0224\n\rActivateImage\022\017."
  "dmi.HardwareID\032\020.dmi.ImageStatus0\001\022;\n\024Re"
  "vertToStandbyImage\022\017.dmi.HardwareID\032\020.dm"
  "i.ImageStatus0\001\022G\n\032UpdateStartupConfigur"
  "ation\022\022.dmi.ConfigRequest\032\023.dmi.ConfigRe"
  "sponse0\001\022\\\n\033GetStartupConfigurationInfo\022"
  "\035.dmi.StartupConfigInfoRequest\032\036.dmi.Sta"
  "rtupConfigInfoResponse\022L\n\017UploadDebugInf"
  "o\022\033.dmi.UploadDebugInfoRequest\032\032.dmi.Upl"
  "oadDebugInfoStatus0\001B;Z9github.com/openc"
  "ord/device-management-interface/v3/go/dm"
  "ib\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, 2529,
};

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:
      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_UNREACHABLE;
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::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>
