// Copyright 2020 The Chromium OS Authors. All rights reserved.
// 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.25.0-devel
// 	protoc        v3.6.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
}
