// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.36.10
// 	protoc        v5.27.1
// source: cel/expr/explain.proto

package expr

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

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)
)

// Deprecated: Marked as deprecated in cel/expr/explain.proto.
type Explain struct {
	state         protoimpl.MessageState `protogen:"open.v1"`
	Values        []*Value               `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"`
	ExprSteps     []*Explain_ExprStep    `protobuf:"bytes,2,rep,name=expr_steps,json=exprSteps,proto3" json:"expr_steps,omitempty"`
	unknownFields protoimpl.UnknownFields
	sizeCache     protoimpl.SizeCache
}

func (x *Explain) Reset() {
	*x = Explain{}
	mi := &file_cel_expr_explain_proto_msgTypes[0]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

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

func (*Explain) ProtoMessage() {}

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

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

func (x *Explain) GetValues() []*Value {
	if x != nil {
		return x.Values
	}
	return nil
}

func (x *Explain) GetExprSteps() []*Explain_ExprStep {
	if x != nil {
		return x.ExprSteps
	}
	return nil
}

type Explain_ExprStep struct {
	state         protoimpl.MessageState `protogen:"open.v1"`
	Id            int64                  `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
	ValueIndex    int32                  `protobuf:"varint,2,opt,name=value_index,json=valueIndex,proto3" json:"value_index,omitempty"`
	unknownFields protoimpl.UnknownFields
	sizeCache     protoimpl.SizeCache
}

func (x *Explain_ExprStep) Reset() {
	*x = Explain_ExprStep{}
	mi := &file_cel_expr_explain_proto_msgTypes[1]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

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

func (*Explain_ExprStep) ProtoMessage() {}

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

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

func (x *Explain_ExprStep) GetId() int64 {
	if x != nil {
		return x.Id
	}
	return 0
}

func (x *Explain_ExprStep) GetValueIndex() int32 {
	if x != nil {
		return x.ValueIndex
	}
	return 0
}

var File_cel_expr_explain_proto protoreflect.FileDescriptor

const file_cel_expr_explain_proto_rawDesc = "" +
	"\n" +
	"\x16cel/expr/explain.proto\x12\bcel.expr\x1a\x14cel/expr/value.proto\"\xae\x01\n" +
	"\aExplain\x12'\n" +
	"\x06values\x18\x01 \x03(\v2\x0f.cel.expr.ValueR\x06values\x129\n" +
	"\n" +
	"expr_steps\x18\x02 \x03(\v2\x1a.cel.expr.Explain.ExprStepR\texprSteps\x1a;\n" +
	"\bExprStep\x12\x0e\n" +
	"\x02id\x18\x01 \x01(\x03R\x02id\x12\x1f\n" +
	"\vvalue_index\x18\x02 \x01(\x05R\n" +
	"valueIndex:\x02\x18\x01B/\n" +
	"\fdev.cel.exprB\fExplainProtoP\x01Z\fcel.dev/expr\xf8\x01\x01b\x06proto3"

var (
	file_cel_expr_explain_proto_rawDescOnce sync.Once
	file_cel_expr_explain_proto_rawDescData []byte
)

func file_cel_expr_explain_proto_rawDescGZIP() []byte {
	file_cel_expr_explain_proto_rawDescOnce.Do(func() {
		file_cel_expr_explain_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_cel_expr_explain_proto_rawDesc), len(file_cel_expr_explain_proto_rawDesc)))
	})
	return file_cel_expr_explain_proto_rawDescData
}

var file_cel_expr_explain_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_cel_expr_explain_proto_goTypes = []any{
	(*Explain)(nil),          // 0: cel.expr.Explain
	(*Explain_ExprStep)(nil), // 1: cel.expr.Explain.ExprStep
	(*Value)(nil),            // 2: cel.expr.Value
}
var file_cel_expr_explain_proto_depIdxs = []int32{
	2, // 0: cel.expr.Explain.values:type_name -> cel.expr.Value
	1, // 1: cel.expr.Explain.expr_steps:type_name -> cel.expr.Explain.ExprStep
	2, // [2:2] is the sub-list for method output_type
	2, // [2:2] is the sub-list for method input_type
	2, // [2:2] is the sub-list for extension type_name
	2, // [2:2] is the sub-list for extension extendee
	0, // [0:2] is the sub-list for field type_name
}

func init() { file_cel_expr_explain_proto_init() }
func file_cel_expr_explain_proto_init() {
	if File_cel_expr_explain_proto != nil {
		return
	}
	file_cel_expr_value_proto_init()
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			RawDescriptor: unsafe.Slice(unsafe.StringData(file_cel_expr_explain_proto_rawDesc), len(file_cel_expr_explain_proto_rawDesc)),
			NumEnums:      0,
			NumMessages:   2,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_cel_expr_explain_proto_goTypes,
		DependencyIndexes: file_cel_expr_explain_proto_depIdxs,
		MessageInfos:      file_cel_expr_explain_proto_msgTypes,
	}.Build()
	File_cel_expr_explain_proto = out.File
	file_cel_expr_explain_proto_goTypes = nil
	file_cel_expr_explain_proto_depIdxs = nil
}
