// Copyright 2020 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.27.1
// 	protoc        v3.17.1
// source: test_platform/service_version.proto

package test_platform

import (
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	reflect "reflect"
	sync "sync"
)

const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

// ServiceVersion denotes the version of services (e.g. the skylab CLI) that
// can trigger Test Platform's Buildbucket builders (e.g. cros_test_platform
// and dut_leaser). It is used to ensure that users keep their local versions
// of such services up-to-date.
type ServiceVersion struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	SkylabTool    int64 `protobuf:"varint,2,opt,name=skylab_tool,json=skylabTool,proto3" json:"skylab_tool,omitempty"`
	CrosfleetTool int64 `protobuf:"varint,3,opt,name=crosfleet_tool,json=crosfleetTool,proto3" json:"crosfleet_tool,omitempty"`
}

func (x *ServiceVersion) Reset() {
	*x = ServiceVersion{}
	if protoimpl.UnsafeEnabled {
		mi := &file_test_platform_service_version_proto_msgTypes[0]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *ServiceVersion) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*ServiceVersion) ProtoMessage() {}

func (x *ServiceVersion) ProtoReflect() protoreflect.Message {
	mi := &file_test_platform_service_version_proto_msgTypes[0]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use ServiceVersion.ProtoReflect.Descriptor instead.
func (*ServiceVersion) Descriptor() ([]byte, []int) {
	return file_test_platform_service_version_proto_rawDescGZIP(), []int{0}
}

func (x *ServiceVersion) GetSkylabTool() int64 {
	if x != nil {
		return x.SkylabTool
	}
	return 0
}

func (x *ServiceVersion) GetCrosfleetTool() int64 {
	if x != nil {
		return x.CrosfleetTool
	}
	return 0
}

var File_test_platform_service_version_proto protoreflect.FileDescriptor

var file_test_platform_service_version_proto_rawDesc = []byte{
	0x0a, 0x23, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f,
	0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e,
	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x6c, 0x61, 0x74,
	0x66, 0x6f, 0x72, 0x6d, 0x22, 0x66, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x56,
	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6b, 0x79, 0x6c, 0x61, 0x62,
	0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x73, 0x6b, 0x79,
	0x6c, 0x61, 0x62, 0x54, 0x6f, 0x6f, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x72, 0x6f, 0x73, 0x66,
	0x6c, 0x65, 0x65, 0x74, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52,
	0x0d, 0x63, 0x72, 0x6f, 0x73, 0x66, 0x6c, 0x65, 0x65, 0x74, 0x54, 0x6f, 0x6f, 0x6c, 0x4a, 0x04,
	0x08, 0x01, 0x10, 0x02, 0x52, 0x06, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x42, 0x39, 0x5a, 0x37,
	0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
	0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x6f, 0x73, 0x2f, 0x69, 0x6e, 0x66, 0x72, 0x61,
	0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x70,
	0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}

var (
	file_test_platform_service_version_proto_rawDescOnce sync.Once
	file_test_platform_service_version_proto_rawDescData = file_test_platform_service_version_proto_rawDesc
)

func file_test_platform_service_version_proto_rawDescGZIP() []byte {
	file_test_platform_service_version_proto_rawDescOnce.Do(func() {
		file_test_platform_service_version_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_platform_service_version_proto_rawDescData)
	})
	return file_test_platform_service_version_proto_rawDescData
}

var file_test_platform_service_version_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_test_platform_service_version_proto_goTypes = []interface{}{
	(*ServiceVersion)(nil), // 0: test_platform.ServiceVersion
}
var file_test_platform_service_version_proto_depIdxs = []int32{
	0, // [0:0] is the sub-list for method output_type
	0, // [0:0] is the sub-list for method input_type
	0, // [0:0] is the sub-list for extension type_name
	0, // [0:0] is the sub-list for extension extendee
	0, // [0:0] is the sub-list for field type_name
}

func init() { file_test_platform_service_version_proto_init() }
func file_test_platform_service_version_proto_init() {
	if File_test_platform_service_version_proto != nil {
		return
	}
	if !protoimpl.UnsafeEnabled {
		file_test_platform_service_version_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*ServiceVersion); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			RawDescriptor: file_test_platform_service_version_proto_rawDesc,
			NumEnums:      0,
			NumMessages:   1,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_test_platform_service_version_proto_goTypes,
		DependencyIndexes: file_test_platform_service_version_proto_depIdxs,
		MessageInfos:      file_test_platform_service_version_proto_msgTypes,
	}.Build()
	File_test_platform_service_version_proto = out.File
	file_test_platform_service_version_proto_rawDesc = nil
	file_test_platform_service_version_proto_goTypes = nil
	file_test_platform_service_version_proto_depIdxs = nil
}
