// Code generated by protoc-gen-go. DO NOT EDIT.
// source: test_platform/service_version.proto

package test_platform

import (
	fmt "fmt"
	proto "github.com/golang/protobuf/proto"
	math "math"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package

// 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 {
	Global               int64    `protobuf:"varint,1,opt,name=global,proto3" json:"global,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *ServiceVersion) Reset()         { *m = ServiceVersion{} }
func (m *ServiceVersion) String() string { return proto.CompactTextString(m) }
func (*ServiceVersion) ProtoMessage()    {}
func (*ServiceVersion) Descriptor() ([]byte, []int) {
	return fileDescriptor_418c2109a1e5e267, []int{0}
}

func (m *ServiceVersion) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_ServiceVersion.Unmarshal(m, b)
}
func (m *ServiceVersion) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_ServiceVersion.Marshal(b, m, deterministic)
}
func (m *ServiceVersion) XXX_Merge(src proto.Message) {
	xxx_messageInfo_ServiceVersion.Merge(m, src)
}
func (m *ServiceVersion) XXX_Size() int {
	return xxx_messageInfo_ServiceVersion.Size(m)
}
func (m *ServiceVersion) XXX_DiscardUnknown() {
	xxx_messageInfo_ServiceVersion.DiscardUnknown(m)
}

var xxx_messageInfo_ServiceVersion proto.InternalMessageInfo

func (m *ServiceVersion) GetGlobal() int64 {
	if m != nil {
		return m.Global
	}
	return 0
}

func init() {
	proto.RegisterType((*ServiceVersion)(nil), "test_platform.ServiceVersion")
}

func init() {
	proto.RegisterFile("test_platform/service_version.proto", fileDescriptor_418c2109a1e5e267)
}

var fileDescriptor_418c2109a1e5e267 = []byte{
	// 138 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2e, 0x49, 0x2d, 0x2e,
	0x89, 0x2f, 0xc8, 0x49, 0x2c, 0x49, 0xcb, 0x2f, 0xca, 0xd5, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c,
	0x4e, 0x8d, 0x2f, 0x4b, 0x2d, 0x2a, 0xce, 0xcc, 0xcf, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17,
	0xe2, 0x45, 0x51, 0xa4, 0xa4, 0xc1, 0xc5, 0x17, 0x0c, 0x51, 0x17, 0x06, 0x51, 0x26, 0x24, 0xc6,
	0xc5, 0x96, 0x9e, 0x93, 0x9f, 0x94, 0x98, 0x23, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x1c, 0x04, 0xe5,
	0x39, 0x59, 0x46, 0x99, 0xa7, 0xe7, 0xeb, 0x25, 0x67, 0x14, 0xe5, 0xe7, 0x66, 0x96, 0xe6, 0xea,
	0xe5, 0x17, 0xa5, 0xeb, 0xc3, 0x38, 0xf9, 0xc5, 0xfa, 0x99, 0x79, 0x69, 0x45, 0x89, 0xfa, 0x60,
	0x2b, 0xf4, 0xd3, 0xf3, 0xf5, 0x51, 0x2c, 0x49, 0x62, 0x03, 0x8b, 0x1b, 0x03, 0x02, 0x00, 0x00,
	0xff, 0xff, 0x49, 0x07, 0x71, 0x02, 0xa1, 0x00, 0x00, 0x00,
}
