init
This commit is contained in:
commit
af3ad67081
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.idea
|
||||
test.*
|
11
Makefile
Normal file
11
Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
|
||||
|
||||
.PHONY: proto
|
||||
proto:
|
||||
@protoc -I. --go_out=paths=source_relative:. ./*.proto
|
||||
|
||||
|
||||
.PHONY: proto-test
|
||||
proto-test:
|
||||
@protoc -I. --go_out=paths=source_relative:. tests/pb/*.proto
|
189
field_filter.extensions.go
Normal file
189
field_filter.extensions.go
Normal file
@ -0,0 +1,189 @@
|
||||
package protofilters
|
||||
|
||||
|
||||
|
||||
func New(filters ...*FieldFilter) *FieldsFilter {
|
||||
out := make(map[string]*Filter)
|
||||
for _, v := range filters {
|
||||
if v == nil {
|
||||
continue
|
||||
}
|
||||
out[v.Field] = v.Filter
|
||||
}
|
||||
return &FieldsFilter{Filters: out}
|
||||
}
|
||||
|
||||
func StringEquals(s string) *Filter {
|
||||
return newStringFilter(&StringFilter{
|
||||
Condition: &StringFilter_Equals{
|
||||
Equals: s,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func StringNotEquals(s string) *Filter {
|
||||
return newStringFilter(&StringFilter{
|
||||
Condition: &StringFilter_Equals{
|
||||
Equals: s,
|
||||
},
|
||||
Not: true,
|
||||
})
|
||||
}
|
||||
|
||||
func StringNotIEquals(s string) *Filter {
|
||||
return newStringFilter(&StringFilter{
|
||||
Condition: &StringFilter_Equals{
|
||||
Equals: s,
|
||||
},
|
||||
CaseInsensitive: true,
|
||||
Not: true,
|
||||
})
|
||||
}
|
||||
|
||||
func StringIEquals(s string) *Filter {
|
||||
return newStringFilter(&StringFilter{
|
||||
Condition: &StringFilter_Equals{
|
||||
Equals: s,
|
||||
},
|
||||
CaseInsensitive: true,
|
||||
})
|
||||
}
|
||||
|
||||
func StringRegex(s string) *Filter {
|
||||
return newStringFilter(
|
||||
&StringFilter{
|
||||
Condition: &StringFilter_Regex{
|
||||
Regex: s,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func StringNotRegex(s string) *Filter {
|
||||
return newStringFilter(
|
||||
&StringFilter{
|
||||
Condition: &StringFilter_Regex{
|
||||
Regex: s,
|
||||
},
|
||||
Not: true,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func newStringFilter(f *StringFilter) *Filter {
|
||||
return &Filter{
|
||||
Match: &Filter_String_{
|
||||
String_: f,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func StringIN(s ...string) *Filter {
|
||||
return newStringFilter(
|
||||
&StringFilter{
|
||||
Condition: &StringFilter_In_{
|
||||
In: &StringFilter_In{
|
||||
Values: s,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func StringNotIN(s ...string) *Filter {
|
||||
return newStringFilter(
|
||||
&StringFilter{
|
||||
Condition: &StringFilter_In_{
|
||||
In: &StringFilter_In{
|
||||
Values: s,
|
||||
},
|
||||
},
|
||||
Not: true,
|
||||
})
|
||||
}
|
||||
|
||||
func newNumberFilter(f *NumberFilter) *Filter {
|
||||
return &Filter{
|
||||
Match: &Filter_Number{
|
||||
Number: f,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NumberEquals(n float64) *Filter {
|
||||
return newNumberFilter(
|
||||
&NumberFilter{
|
||||
Condition: &NumberFilter_Equals{
|
||||
Equals: n,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func NumberNotEquals(n float64) *Filter {
|
||||
return newNumberFilter(
|
||||
&NumberFilter{
|
||||
Condition: &NumberFilter_Equals{
|
||||
Equals: n,
|
||||
},
|
||||
Not: true,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func NumberIN(n ...float64) *Filter {
|
||||
return newNumberFilter(
|
||||
&NumberFilter{
|
||||
Condition: &NumberFilter_In_{
|
||||
In: &NumberFilter_In{
|
||||
Values: n,
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func NumberNotIN(n ...float64) *Filter {
|
||||
return newNumberFilter(
|
||||
&NumberFilter{
|
||||
Condition: &NumberFilter_In_{
|
||||
In: &NumberFilter_In{
|
||||
Values: n,
|
||||
},
|
||||
},
|
||||
Not: true,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
func True() *Filter {
|
||||
return NewBoolFilter(&BoolFilter{Equals: true})
|
||||
}
|
||||
|
||||
func False() *Filter {
|
||||
return NewBoolFilter(&BoolFilter{Equals: false})
|
||||
}
|
||||
|
||||
func NewBoolFilter(f *BoolFilter) *Filter {
|
||||
return &Filter{
|
||||
Match: &Filter_Bool{
|
||||
Bool: f,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func Null() *Filter {
|
||||
return NewNullFilter(&NullFilter{Not: false})
|
||||
}
|
||||
|
||||
func NotNull() *Filter {
|
||||
return NewNullFilter(&NullFilter{Not: true})
|
||||
}
|
||||
|
||||
func NewNullFilter(f *NullFilter) *Filter {
|
||||
return &Filter{
|
||||
Match: &Filter_Null{
|
||||
Null: f,
|
||||
},
|
||||
}
|
||||
}
|
915
field_filter.pb.go
Normal file
915
field_filter.pb.go
Normal file
@ -0,0 +1,915 @@
|
||||
// Copyright 2021 Linka Cloud All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Linka Cloud nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.17.1
|
||||
// source: field_filter.proto
|
||||
|
||||
package protofilters
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
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)
|
||||
)
|
||||
|
||||
type FieldsFilter struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The set of field mask paths.
|
||||
Filters map[string]*Filter `protobuf:"bytes,1,rep,name=filters,proto3" json:"filters,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
}
|
||||
|
||||
func (x *FieldsFilter) Reset() {
|
||||
*x = FieldsFilter{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_field_filter_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *FieldsFilter) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*FieldsFilter) ProtoMessage() {}
|
||||
|
||||
func (x *FieldsFilter) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_field_filter_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 FieldsFilter.ProtoReflect.Descriptor instead.
|
||||
func (*FieldsFilter) Descriptor() ([]byte, []int) {
|
||||
return file_field_filter_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *FieldsFilter) GetFilters() map[string]*Filter {
|
||||
if x != nil {
|
||||
return x.Filters
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type FieldFilter struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Field string `protobuf:"bytes,1,opt,name=field,proto3" json:"field,omitempty"`
|
||||
Filter *Filter `protobuf:"bytes,2,opt,name=filter,proto3" json:"filter,omitempty"`
|
||||
}
|
||||
|
||||
func (x *FieldFilter) Reset() {
|
||||
*x = FieldFilter{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_field_filter_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *FieldFilter) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*FieldFilter) ProtoMessage() {}
|
||||
|
||||
func (x *FieldFilter) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_field_filter_proto_msgTypes[1]
|
||||
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 FieldFilter.ProtoReflect.Descriptor instead.
|
||||
func (*FieldFilter) Descriptor() ([]byte, []int) {
|
||||
return file_field_filter_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *FieldFilter) GetField() string {
|
||||
if x != nil {
|
||||
return x.Field
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *FieldFilter) GetFilter() *Filter {
|
||||
if x != nil {
|
||||
return x.Filter
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Filter struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to Match:
|
||||
// *Filter_String_
|
||||
// *Filter_Number
|
||||
// *Filter_Bool
|
||||
// *Filter_Null
|
||||
Match isFilter_Match `protobuf_oneof:"match"`
|
||||
}
|
||||
|
||||
func (x *Filter) Reset() {
|
||||
*x = Filter{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_field_filter_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Filter) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Filter) ProtoMessage() {}
|
||||
|
||||
func (x *Filter) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_field_filter_proto_msgTypes[2]
|
||||
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 Filter.ProtoReflect.Descriptor instead.
|
||||
func (*Filter) Descriptor() ([]byte, []int) {
|
||||
return file_field_filter_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (m *Filter) GetMatch() isFilter_Match {
|
||||
if m != nil {
|
||||
return m.Match
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Filter) GetString_() *StringFilter {
|
||||
if x, ok := x.GetMatch().(*Filter_String_); ok {
|
||||
return x.String_
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Filter) GetNumber() *NumberFilter {
|
||||
if x, ok := x.GetMatch().(*Filter_Number); ok {
|
||||
return x.Number
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Filter) GetBool() *BoolFilter {
|
||||
if x, ok := x.GetMatch().(*Filter_Bool); ok {
|
||||
return x.Bool
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Filter) GetNull() *NullFilter {
|
||||
if x, ok := x.GetMatch().(*Filter_Null); ok {
|
||||
return x.Null
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isFilter_Match interface {
|
||||
isFilter_Match()
|
||||
}
|
||||
|
||||
type Filter_String_ struct {
|
||||
String_ *StringFilter `protobuf:"bytes,1,opt,name=string,proto3,oneof"`
|
||||
}
|
||||
|
||||
type Filter_Number struct {
|
||||
Number *NumberFilter `protobuf:"bytes,2,opt,name=number,proto3,oneof"`
|
||||
}
|
||||
|
||||
type Filter_Bool struct {
|
||||
Bool *BoolFilter `protobuf:"bytes,3,opt,name=bool,proto3,oneof"`
|
||||
}
|
||||
|
||||
type Filter_Null struct {
|
||||
Null *NullFilter `protobuf:"bytes,4,opt,name=null,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*Filter_String_) isFilter_Match() {}
|
||||
|
||||
func (*Filter_Number) isFilter_Match() {}
|
||||
|
||||
func (*Filter_Bool) isFilter_Match() {}
|
||||
|
||||
func (*Filter_Null) isFilter_Match() {}
|
||||
|
||||
type StringFilter struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to Condition:
|
||||
// *StringFilter_Equals
|
||||
// *StringFilter_Regex
|
||||
// *StringFilter_In_
|
||||
Condition isStringFilter_Condition `protobuf_oneof:"condition"`
|
||||
Not bool `protobuf:"varint,4,opt,name=not,proto3" json:"not,omitempty"`
|
||||
CaseInsensitive bool `protobuf:"varint,5,opt,name=case_insensitive,json=caseInsensitive,proto3" json:"case_insensitive,omitempty"`
|
||||
}
|
||||
|
||||
func (x *StringFilter) Reset() {
|
||||
*x = StringFilter{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_field_filter_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *StringFilter) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*StringFilter) ProtoMessage() {}
|
||||
|
||||
func (x *StringFilter) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_field_filter_proto_msgTypes[3]
|
||||
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 StringFilter.ProtoReflect.Descriptor instead.
|
||||
func (*StringFilter) Descriptor() ([]byte, []int) {
|
||||
return file_field_filter_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (m *StringFilter) GetCondition() isStringFilter_Condition {
|
||||
if m != nil {
|
||||
return m.Condition
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *StringFilter) GetEquals() string {
|
||||
if x, ok := x.GetCondition().(*StringFilter_Equals); ok {
|
||||
return x.Equals
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *StringFilter) GetRegex() string {
|
||||
if x, ok := x.GetCondition().(*StringFilter_Regex); ok {
|
||||
return x.Regex
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *StringFilter) GetIn() *StringFilter_In {
|
||||
if x, ok := x.GetCondition().(*StringFilter_In_); ok {
|
||||
return x.In
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *StringFilter) GetNot() bool {
|
||||
if x != nil {
|
||||
return x.Not
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *StringFilter) GetCaseInsensitive() bool {
|
||||
if x != nil {
|
||||
return x.CaseInsensitive
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type isStringFilter_Condition interface {
|
||||
isStringFilter_Condition()
|
||||
}
|
||||
|
||||
type StringFilter_Equals struct {
|
||||
Equals string `protobuf:"bytes,1,opt,name=equals,proto3,oneof"`
|
||||
}
|
||||
|
||||
type StringFilter_Regex struct {
|
||||
Regex string `protobuf:"bytes,2,opt,name=regex,proto3,oneof"`
|
||||
}
|
||||
|
||||
type StringFilter_In_ struct {
|
||||
In *StringFilter_In `protobuf:"bytes,3,opt,name=in,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*StringFilter_Equals) isStringFilter_Condition() {}
|
||||
|
||||
func (*StringFilter_Regex) isStringFilter_Condition() {}
|
||||
|
||||
func (*StringFilter_In_) isStringFilter_Condition() {}
|
||||
|
||||
type NumberFilter struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to Condition:
|
||||
// *NumberFilter_Equals
|
||||
// *NumberFilter_In_
|
||||
Condition isNumberFilter_Condition `protobuf_oneof:"condition"`
|
||||
Not bool `protobuf:"varint,4,opt,name=not,proto3" json:"not,omitempty"`
|
||||
}
|
||||
|
||||
func (x *NumberFilter) Reset() {
|
||||
*x = NumberFilter{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_field_filter_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *NumberFilter) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*NumberFilter) ProtoMessage() {}
|
||||
|
||||
func (x *NumberFilter) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_field_filter_proto_msgTypes[4]
|
||||
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 NumberFilter.ProtoReflect.Descriptor instead.
|
||||
func (*NumberFilter) Descriptor() ([]byte, []int) {
|
||||
return file_field_filter_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (m *NumberFilter) GetCondition() isNumberFilter_Condition {
|
||||
if m != nil {
|
||||
return m.Condition
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NumberFilter) GetEquals() float64 {
|
||||
if x, ok := x.GetCondition().(*NumberFilter_Equals); ok {
|
||||
return x.Equals
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NumberFilter) GetIn() *NumberFilter_In {
|
||||
if x, ok := x.GetCondition().(*NumberFilter_In_); ok {
|
||||
return x.In
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NumberFilter) GetNot() bool {
|
||||
if x != nil {
|
||||
return x.Not
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type isNumberFilter_Condition interface {
|
||||
isNumberFilter_Condition()
|
||||
}
|
||||
|
||||
type NumberFilter_Equals struct {
|
||||
Equals float64 `protobuf:"fixed64,1,opt,name=equals,proto3,oneof"`
|
||||
}
|
||||
|
||||
type NumberFilter_In_ struct {
|
||||
In *NumberFilter_In `protobuf:"bytes,2,opt,name=in,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*NumberFilter_Equals) isNumberFilter_Condition() {}
|
||||
|
||||
func (*NumberFilter_In_) isNumberFilter_Condition() {}
|
||||
|
||||
type NullFilter struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Not bool `protobuf:"varint,1,opt,name=not,proto3" json:"not,omitempty"`
|
||||
}
|
||||
|
||||
func (x *NullFilter) Reset() {
|
||||
*x = NullFilter{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_field_filter_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *NullFilter) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*NullFilter) ProtoMessage() {}
|
||||
|
||||
func (x *NullFilter) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_field_filter_proto_msgTypes[5]
|
||||
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 NullFilter.ProtoReflect.Descriptor instead.
|
||||
func (*NullFilter) Descriptor() ([]byte, []int) {
|
||||
return file_field_filter_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *NullFilter) GetNot() bool {
|
||||
if x != nil {
|
||||
return x.Not
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type BoolFilter struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Equals bool `protobuf:"varint,1,opt,name=equals,proto3" json:"equals,omitempty"`
|
||||
}
|
||||
|
||||
func (x *BoolFilter) Reset() {
|
||||
*x = BoolFilter{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_field_filter_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *BoolFilter) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*BoolFilter) ProtoMessage() {}
|
||||
|
||||
func (x *BoolFilter) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_field_filter_proto_msgTypes[6]
|
||||
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 BoolFilter.ProtoReflect.Descriptor instead.
|
||||
func (*BoolFilter) Descriptor() ([]byte, []int) {
|
||||
return file_field_filter_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *BoolFilter) GetEquals() bool {
|
||||
if x != nil {
|
||||
return x.Equals
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type StringFilter_In struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Values []string `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"`
|
||||
}
|
||||
|
||||
func (x *StringFilter_In) Reset() {
|
||||
*x = StringFilter_In{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_field_filter_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *StringFilter_In) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*StringFilter_In) ProtoMessage() {}
|
||||
|
||||
func (x *StringFilter_In) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_field_filter_proto_msgTypes[8]
|
||||
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 StringFilter_In.ProtoReflect.Descriptor instead.
|
||||
func (*StringFilter_In) Descriptor() ([]byte, []int) {
|
||||
return file_field_filter_proto_rawDescGZIP(), []int{3, 0}
|
||||
}
|
||||
|
||||
func (x *StringFilter_In) GetValues() []string {
|
||||
if x != nil {
|
||||
return x.Values
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NumberFilter_In struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Values []float64 `protobuf:"fixed64,1,rep,packed,name=values,proto3" json:"values,omitempty"`
|
||||
}
|
||||
|
||||
func (x *NumberFilter_In) Reset() {
|
||||
*x = NumberFilter_In{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_field_filter_proto_msgTypes[9]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *NumberFilter_In) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*NumberFilter_In) ProtoMessage() {}
|
||||
|
||||
func (x *NumberFilter_In) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_field_filter_proto_msgTypes[9]
|
||||
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 NumberFilter_In.ProtoReflect.Descriptor instead.
|
||||
func (*NumberFilter_In) Descriptor() ([]byte, []int) {
|
||||
return file_field_filter_proto_rawDescGZIP(), []int{4, 0}
|
||||
}
|
||||
|
||||
func (x *NumberFilter_In) GetValues() []float64 {
|
||||
if x != nil {
|
||||
return x.Values
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_field_filter_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_field_filter_proto_rawDesc = []byte{
|
||||
0x0a, 0x12, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x18, 0x6c, 0x69, 0x6e, 0x6b, 0x61, 0x2e, 0x63, 0x6c, 0x6f, 0x75,
|
||||
0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0xbb,
|
||||
0x01, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12,
|
||||
0x4d, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x33, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x61, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x46, 0x69, 0x65, 0x6c,
|
||||
0x64, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73,
|
||||
0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x1a, 0x5c,
|
||||
0x0a, 0x0c, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
|
||||
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
|
||||
0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x20, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x61, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65,
|
||||
0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x5d, 0x0a, 0x0b,
|
||||
0x46, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x66,
|
||||
0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c,
|
||||
0x64, 0x12, 0x38, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x20, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x61, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x46, 0x69, 0x6c,
|
||||
0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x8d, 0x02, 0x0a, 0x06,
|
||||
0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x61, 0x2e, 0x63,
|
||||
0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72,
|
||||
0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x48, 0x00,
|
||||
0x52, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x40, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62,
|
||||
0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x61,
|
||||
0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x66, 0x69, 0x6c, 0x74,
|
||||
0x65, 0x72, 0x73, 0x2e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72,
|
||||
0x48, 0x00, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x04, 0x62, 0x6f,
|
||||
0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x61,
|
||||
0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x66, 0x69, 0x6c, 0x74,
|
||||
0x65, 0x72, 0x73, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x48, 0x00,
|
||||
0x52, 0x04, 0x62, 0x6f, 0x6f, 0x6c, 0x12, 0x3a, 0x0a, 0x04, 0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x61, 0x2e, 0x63, 0x6c, 0x6f,
|
||||
0x75, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e,
|
||||
0x4e, 0x75, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x75,
|
||||
0x6c, 0x6c, 0x42, 0x07, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x22, 0xe5, 0x01, 0x0a, 0x0c,
|
||||
0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x06,
|
||||
0x65, 0x71, 0x75, 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06,
|
||||
0x65, 0x71, 0x75, 0x61, 0x6c, 0x73, 0x12, 0x16, 0x0a, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x12, 0x3b,
|
||||
0x0a, 0x02, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x6c, 0x69, 0x6e,
|
||||
0x6b, 0x61, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x66, 0x69,
|
||||
0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x6c, 0x74,
|
||||
0x65, 0x72, 0x2e, 0x49, 0x6e, 0x48, 0x00, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6e,
|
||||
0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6e, 0x6f, 0x74, 0x12, 0x29, 0x0a,
|
||||
0x10, 0x63, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76,
|
||||
0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x63, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73,
|
||||
0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x1a, 0x1c, 0x0a, 0x02, 0x49, 0x6e, 0x12, 0x16,
|
||||
0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06,
|
||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x0b, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x22, 0xa2, 0x01, 0x0a, 0x0c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x46, 0x69,
|
||||
0x6c, 0x74, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x06, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x06, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73, 0x12, 0x3b,
|
||||
0x0a, 0x02, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x6c, 0x69, 0x6e,
|
||||
0x6b, 0x61, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x66, 0x69,
|
||||
0x6c, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74,
|
||||
0x65, 0x72, 0x2e, 0x49, 0x6e, 0x48, 0x00, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6e,
|
||||
0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6e, 0x6f, 0x74, 0x1a, 0x1c, 0x0a,
|
||||
0x02, 0x49, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20,
|
||||
0x03, 0x28, 0x01, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x0b, 0x0a, 0x09, 0x63,
|
||||
0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1e, 0x0a, 0x0a, 0x4e, 0x75, 0x6c, 0x6c,
|
||||
0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6e, 0x6f, 0x74, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x03, 0x6e, 0x6f, 0x74, 0x22, 0x24, 0x0a, 0x0a, 0x42, 0x6f, 0x6f, 0x6c,
|
||||
0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73, 0x42, 0x2f,
|
||||
0x50, 0x01, 0x5a, 0x28, 0x67, 0x6f, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x61, 0x2e, 0x63, 0x6c, 0x6f,
|
||||
0x75, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x3b,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0xf8, 0x01, 0x01, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_field_filter_proto_rawDescOnce sync.Once
|
||||
file_field_filter_proto_rawDescData = file_field_filter_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_field_filter_proto_rawDescGZIP() []byte {
|
||||
file_field_filter_proto_rawDescOnce.Do(func() {
|
||||
file_field_filter_proto_rawDescData = protoimpl.X.CompressGZIP(file_field_filter_proto_rawDescData)
|
||||
})
|
||||
return file_field_filter_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_field_filter_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
|
||||
var file_field_filter_proto_goTypes = []interface{}{
|
||||
(*FieldsFilter)(nil), // 0: linka.cloud.protofilters.FieldsFilter
|
||||
(*FieldFilter)(nil), // 1: linka.cloud.protofilters.FieldFilter
|
||||
(*Filter)(nil), // 2: linka.cloud.protofilters.Filter
|
||||
(*StringFilter)(nil), // 3: linka.cloud.protofilters.StringFilter
|
||||
(*NumberFilter)(nil), // 4: linka.cloud.protofilters.NumberFilter
|
||||
(*NullFilter)(nil), // 5: linka.cloud.protofilters.NullFilter
|
||||
(*BoolFilter)(nil), // 6: linka.cloud.protofilters.BoolFilter
|
||||
nil, // 7: linka.cloud.protofilters.FieldsFilter.FiltersEntry
|
||||
(*StringFilter_In)(nil), // 8: linka.cloud.protofilters.StringFilter.In
|
||||
(*NumberFilter_In)(nil), // 9: linka.cloud.protofilters.NumberFilter.In
|
||||
}
|
||||
var file_field_filter_proto_depIdxs = []int32{
|
||||
7, // 0: linka.cloud.protofilters.FieldsFilter.filters:type_name -> linka.cloud.protofilters.FieldsFilter.FiltersEntry
|
||||
2, // 1: linka.cloud.protofilters.FieldFilter.filter:type_name -> linka.cloud.protofilters.Filter
|
||||
3, // 2: linka.cloud.protofilters.Filter.string:type_name -> linka.cloud.protofilters.StringFilter
|
||||
4, // 3: linka.cloud.protofilters.Filter.number:type_name -> linka.cloud.protofilters.NumberFilter
|
||||
6, // 4: linka.cloud.protofilters.Filter.bool:type_name -> linka.cloud.protofilters.BoolFilter
|
||||
5, // 5: linka.cloud.protofilters.Filter.null:type_name -> linka.cloud.protofilters.NullFilter
|
||||
8, // 6: linka.cloud.protofilters.StringFilter.in:type_name -> linka.cloud.protofilters.StringFilter.In
|
||||
9, // 7: linka.cloud.protofilters.NumberFilter.in:type_name -> linka.cloud.protofilters.NumberFilter.In
|
||||
2, // 8: linka.cloud.protofilters.FieldsFilter.FiltersEntry.value:type_name -> linka.cloud.protofilters.Filter
|
||||
9, // [9:9] is the sub-list for method output_type
|
||||
9, // [9:9] is the sub-list for method input_type
|
||||
9, // [9:9] is the sub-list for extension type_name
|
||||
9, // [9:9] is the sub-list for extension extendee
|
||||
0, // [0:9] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_field_filter_proto_init() }
|
||||
func file_field_filter_proto_init() {
|
||||
if File_field_filter_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_field_filter_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*FieldsFilter); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_field_filter_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*FieldFilter); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_field_filter_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Filter); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_field_filter_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*StringFilter); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_field_filter_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*NumberFilter); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_field_filter_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*NullFilter); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_field_filter_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*BoolFilter); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_field_filter_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*StringFilter_In); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_field_filter_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*NumberFilter_In); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
file_field_filter_proto_msgTypes[2].OneofWrappers = []interface{}{
|
||||
(*Filter_String_)(nil),
|
||||
(*Filter_Number)(nil),
|
||||
(*Filter_Bool)(nil),
|
||||
(*Filter_Null)(nil),
|
||||
}
|
||||
file_field_filter_proto_msgTypes[3].OneofWrappers = []interface{}{
|
||||
(*StringFilter_Equals)(nil),
|
||||
(*StringFilter_Regex)(nil),
|
||||
(*StringFilter_In_)(nil),
|
||||
}
|
||||
file_field_filter_proto_msgTypes[4].OneofWrappers = []interface{}{
|
||||
(*NumberFilter_Equals)(nil),
|
||||
(*NumberFilter_In_)(nil),
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_field_filter_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 10,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_field_filter_proto_goTypes,
|
||||
DependencyIndexes: file_field_filter_proto_depIdxs,
|
||||
MessageInfos: file_field_filter_proto_msgTypes,
|
||||
}.Build()
|
||||
File_field_filter_proto = out.File
|
||||
file_field_filter_proto_rawDesc = nil
|
||||
file_field_filter_proto_goTypes = nil
|
||||
file_field_filter_proto_depIdxs = nil
|
||||
}
|
88
field_filter.proto
Normal file
88
field_filter.proto
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright 2021 Linka Cloud All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Linka Cloud nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package linka.cloud.protofilters;
|
||||
|
||||
//option csharp_namespace = "LinkaCloud.ProtoDynamic.WellKnownTypes";
|
||||
//option java_package = "cloud.linka.protodynamic";
|
||||
//option java_outer_classname = "FieldFilterProto";
|
||||
option java_multiple_files = true;
|
||||
//option objc_class_prefix = "GPB";
|
||||
option go_package = "go.linka.cloud/protofilters;protofilters";
|
||||
option cc_enable_arenas = true;
|
||||
|
||||
|
||||
message FieldsFilter {
|
||||
// The set of field mask paths.
|
||||
map<string, Filter> filters = 1;
|
||||
}
|
||||
|
||||
message FieldFilter {
|
||||
string field = 1;
|
||||
Filter filter = 2;
|
||||
}
|
||||
|
||||
message Filter {
|
||||
oneof match {
|
||||
StringFilter string = 1;
|
||||
NumberFilter number = 2;
|
||||
BoolFilter bool = 3;
|
||||
NullFilter null = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message StringFilter {
|
||||
message In {
|
||||
repeated string values = 1;
|
||||
}
|
||||
oneof condition {
|
||||
string equals = 1;
|
||||
string regex = 2;
|
||||
In in = 3;
|
||||
}
|
||||
bool not = 4;
|
||||
bool case_insensitive = 5;
|
||||
}
|
||||
message NumberFilter {
|
||||
message In {
|
||||
repeated double values = 1;
|
||||
}
|
||||
oneof condition {
|
||||
double equals = 1;
|
||||
In in = 2;
|
||||
}
|
||||
bool not = 4;
|
||||
}
|
||||
message NullFilter {
|
||||
bool not = 1;
|
||||
}
|
||||
message BoolFilter {
|
||||
bool equals = 1;
|
||||
}
|
9
go.mod
Normal file
9
go.mod
Normal file
@ -0,0 +1,9 @@
|
||||
module go.linka.cloud/protofilters
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/stretchr/testify v1.3.0
|
||||
google.golang.org/protobuf v1.26.0
|
||||
)
|
21
go.sum
Normal file
21
go.sum
Normal file
@ -0,0 +1,21 @@
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
268
matcher/matcher.go
Normal file
268
matcher/matcher.go
Normal file
@ -0,0 +1,268 @@
|
||||
package matcher
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
pref "google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
||||
pf "go.linka.cloud/protofilters"
|
||||
)
|
||||
|
||||
type Matcher interface {
|
||||
Match(m proto.Message, f *pf.FieldsFilter) (bool, error)
|
||||
MatchFilters(m proto.Message, fs ...*pf.FieldFilter) (bool, error)
|
||||
}
|
||||
|
||||
type CachingMatcher interface {
|
||||
Matcher
|
||||
ResetCache()
|
||||
}
|
||||
|
||||
var defaultMatcher CachingMatcher = &matcher{cache: make(map[string]pref.FieldDescriptor)}
|
||||
|
||||
func Match(m proto.Message, f *pf.FieldsFilter) (bool, error) {
|
||||
return defaultMatcher.Match(m, f)
|
||||
}
|
||||
|
||||
func MatchFilters(m proto.Message, fs ...*pf.FieldFilter) (bool, error) {
|
||||
return defaultMatcher.MatchFilters(m, fs...)
|
||||
}
|
||||
|
||||
type matcher struct {
|
||||
mu sync.RWMutex
|
||||
cache map[string]pref.FieldDescriptor
|
||||
}
|
||||
|
||||
func (x *matcher) Match(m proto.Message, f *pf.FieldsFilter) (bool, error) {
|
||||
if m == nil {
|
||||
return false, errors.New("message is null")
|
||||
}
|
||||
if f == nil {
|
||||
return true, nil
|
||||
}
|
||||
for path, filter := range f.Filters {
|
||||
fd, err := x.lookup(m, path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
ok, err := match(m, fd, filter)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (x *matcher) MatchFilters(m proto.Message, fs ...*pf.FieldFilter) (bool, error) {
|
||||
f := pf.New(fs...)
|
||||
return x.Match(m, f)
|
||||
}
|
||||
|
||||
func (x *matcher) ResetCache() {
|
||||
x.mu.Lock()
|
||||
x.cache = make(map[string]pref.FieldDescriptor)
|
||||
x.mu.Unlock()
|
||||
}
|
||||
|
||||
func (x *matcher) lookup(m proto.Message, path string) (pref.FieldDescriptor, error) {
|
||||
if x.cache == nil {
|
||||
x.mu.Lock()
|
||||
x.cache = make(map[string]pref.FieldDescriptor)
|
||||
x.mu.Unlock()
|
||||
}
|
||||
key := fmt.Sprintf("%s.%s", m.ProtoReflect().Descriptor().FullName(), path)
|
||||
x.mu.RLock()
|
||||
fd, ok := x.cache[key]
|
||||
x.mu.RUnlock()
|
||||
if ok {
|
||||
return fd, nil
|
||||
}
|
||||
md0 := m.ProtoReflect().Descriptor()
|
||||
md := md0
|
||||
fd, ok = rangeFields(path, func(field string) (pref.FieldDescriptor, bool) {
|
||||
// Search the field within the message.
|
||||
if md == nil {
|
||||
return nil, false // not within a message
|
||||
}
|
||||
fd := md.Fields().ByName(pref.Name(field))
|
||||
// The real field name of a group is the message name.
|
||||
if fd == nil {
|
||||
gd := md.Fields().ByName(pref.Name(strings.ToLower(field)))
|
||||
if gd != nil && gd.Kind() == pref.GroupKind && string(gd.Message().Name()) == field {
|
||||
fd = gd
|
||||
}
|
||||
} else if fd.Kind() == pref.GroupKind && string(fd.Message().Name()) != field {
|
||||
fd = nil
|
||||
}
|
||||
if fd == nil {
|
||||
return nil, false // message does not have this field
|
||||
}
|
||||
// Identify the next message to search within.
|
||||
md = fd.Message() // may be nil
|
||||
|
||||
// Repeated fields are only allowed at the last postion.
|
||||
if fd.IsList() || fd.IsMap() {
|
||||
md = nil
|
||||
}
|
||||
|
||||
return fd, true
|
||||
})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s does not contain '%s'", md0.FullName(), path)
|
||||
}
|
||||
x.mu.Lock()
|
||||
x.cache[key] = fd
|
||||
x.mu.Unlock()
|
||||
return fd, nil
|
||||
}
|
||||
|
||||
func match(m proto.Message, fd pref.FieldDescriptor, f *pf.Filter) (bool, error) {
|
||||
switch f.GetMatch().(type) {
|
||||
case *pf.Filter_String_:
|
||||
return matchString(m, fd, f)
|
||||
case *pf.Filter_Number:
|
||||
return matchNumber(m, fd, f)
|
||||
case *pf.Filter_Bool:
|
||||
return matchBool(m, fd, f)
|
||||
case *pf.Filter_Null:
|
||||
return matchNull(m, fd, f)
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func matchNull(m proto.Message, fd pref.FieldDescriptor, f *pf.Filter) (bool, error) {
|
||||
var match bool
|
||||
switch fd.Kind() {
|
||||
case pref.MessageKind:
|
||||
match = !m.ProtoReflect().Has(fd)
|
||||
case pref.GroupKind:
|
||||
match = m.ProtoReflect().Get(fd).List().Len() == 0
|
||||
default:
|
||||
return false, fmt.Errorf("cannot use null filter on %s", fd.Kind().String())
|
||||
}
|
||||
if f.GetNull().GetNot() {
|
||||
return !match, nil
|
||||
}
|
||||
return match, nil
|
||||
}
|
||||
|
||||
func matchBool(m proto.Message, fd pref.FieldDescriptor, f *pf.Filter) (bool, error) {
|
||||
if fd.Kind() != pref.BoolKind {
|
||||
return false, fmt.Errorf("cannot use bool filter on %s", fd.Kind().String())
|
||||
}
|
||||
return m.ProtoReflect().Get(fd).Bool() == f.GetBool().GetEquals(), nil
|
||||
}
|
||||
|
||||
func matchString(m proto.Message, fd pref.FieldDescriptor, f *pf.Filter) (bool, error) {
|
||||
if fd.Kind() != pref.StringKind && fd.Kind() != pref.EnumKind {
|
||||
return false, fmt.Errorf("cannot use string filter on %s", fd.Kind().String())
|
||||
}
|
||||
insensitive := f.GetString_().GetCaseInsensitive()
|
||||
rval := m.ProtoReflect().Get(fd)
|
||||
value := rval.String()
|
||||
if fd.Kind() == pref.EnumKind {
|
||||
e := fd.Enum().Values().ByNumber(rval.Enum())
|
||||
if e == nil {
|
||||
return false, nil
|
||||
}
|
||||
value = string(e.Name())
|
||||
}
|
||||
var match bool
|
||||
switch f.GetString_().GetCondition().(type) {
|
||||
case *pf.StringFilter_Equals:
|
||||
if insensitive {
|
||||
match = strings.ToLower(f.GetString_().GetEquals()) == strings.ToLower(value)
|
||||
} else {
|
||||
match = value == f.GetString_().GetEquals()
|
||||
}
|
||||
case *pf.StringFilter_Regex:
|
||||
reg, err := regexp.Compile(f.GetString_().GetRegex())
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
match = reg.MatchString(value)
|
||||
case *pf.StringFilter_In_:
|
||||
lookup:
|
||||
for _, v := range f.GetString_().GetIn().GetValues() {
|
||||
if (insensitive && strings.ToLower(v) == strings.ToLower(value)) || v == value {
|
||||
match = true
|
||||
break lookup
|
||||
}
|
||||
}
|
||||
}
|
||||
if f.GetString_().GetNot() {
|
||||
return !match, nil
|
||||
}
|
||||
return match, nil
|
||||
}
|
||||
|
||||
func matchNumber(m proto.Message, fd pref.FieldDescriptor, f *pf.Filter) (bool, error) {
|
||||
rval := m.ProtoReflect().Get(fd)
|
||||
var val float64
|
||||
switch fd.Kind() {
|
||||
case pref.Int32Kind,
|
||||
pref.Sint32Kind,
|
||||
pref.Int64Kind,
|
||||
pref.Sint64Kind,
|
||||
pref.Sfixed32Kind,
|
||||
pref.Fixed32Kind,
|
||||
pref.Sfixed64Kind,
|
||||
pref.Fixed64Kind:
|
||||
val = float64(rval.Int())
|
||||
case pref.Uint32Kind, pref.Uint64Kind:
|
||||
val = float64(rval.Uint())
|
||||
case pref.FloatKind, pref.DoubleKind:
|
||||
val = rval.Float()
|
||||
case pref.EnumKind:
|
||||
val = float64(rval.Enum())
|
||||
default:
|
||||
return false, fmt.Errorf("cannot use number filter on %s", fd.Kind().String())
|
||||
}
|
||||
var match bool
|
||||
switch f.GetNumber().GetCondition().(type) {
|
||||
case *pf.NumberFilter_Equals:
|
||||
match = val == f.GetNumber().GetEquals()
|
||||
case *pf.NumberFilter_In_:
|
||||
lookup:
|
||||
for _, v := range f.GetNumber().GetIn().GetValues() {
|
||||
if val == v {
|
||||
match = true
|
||||
break lookup
|
||||
}
|
||||
}
|
||||
}
|
||||
if f.GetNumber().GetNot() {
|
||||
return !match, nil
|
||||
}
|
||||
return match, nil
|
||||
}
|
||||
|
||||
// rangeFields is like strings.Split(path, "."), but avoids allocations by
|
||||
// iterating over each field in place and calling a iterator function.
|
||||
func rangeFields(path string, f func(field string) (pref.FieldDescriptor, bool)) (pref.FieldDescriptor, bool) {
|
||||
for {
|
||||
var field string
|
||||
if i := strings.IndexByte(path, '.'); i >= 0 {
|
||||
field, path = path[:i], path[i:]
|
||||
} else {
|
||||
field, path = path, ""
|
||||
}
|
||||
v, ok := f(field)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if len(path) == 0 {
|
||||
return v, true
|
||||
}
|
||||
path = strings.TrimPrefix(path, ".")
|
||||
}
|
||||
}
|
||||
|
85
matcher/matcher_test.go
Normal file
85
matcher/matcher_test.go
Normal file
@ -0,0 +1,85 @@
|
||||
package matcher
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
pf "go.linka.cloud/protofilters"
|
||||
test "go.linka.cloud/protofilters/tests/pb"
|
||||
)
|
||||
|
||||
func TestFieldFilter(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
m := &test.Test{StringField: "ok"}
|
||||
ok, err := Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"noop": pf.StringEquals("ok"),
|
||||
}})
|
||||
assert.Error(err)
|
||||
assert.False(ok)
|
||||
ok, err = Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"messageField": pf.Null(),
|
||||
}})
|
||||
assert.Error(err)
|
||||
assert.False(ok)
|
||||
assert.True(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"string_field": pf.StringEquals("ok"),
|
||||
}}))
|
||||
assert.True(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"string_field": pf.StringIN("other", "ok"),
|
||||
}}))
|
||||
assert.False(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"string_field": pf.StringIN("other", "noop"),
|
||||
}}))
|
||||
assert.True(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"string_field": pf.StringNotIN(),
|
||||
"enum_field": pf.StringIN("NONE"),
|
||||
}}))
|
||||
assert.False(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"string_field": pf.StringNotRegex(`[a-z](.+)`),
|
||||
}}))
|
||||
m.EnumField = test.Test_Type(42)
|
||||
assert.False(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"enum_field": pf.StringIN("OTHER"),
|
||||
}}))
|
||||
assert.True(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"message_field": pf.Null(),
|
||||
}}))
|
||||
m.MessageField = m
|
||||
assert.False(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"message_field": pf.Null(),
|
||||
}}))
|
||||
ok, err = Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"message_field.string_field.message_field": pf.Null(),
|
||||
}})
|
||||
assert.Error(err)
|
||||
assert.False(ok)
|
||||
assert.False(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"message_field.message_field.message_field": pf.Null(),
|
||||
}}))
|
||||
assert.True(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"message_field.message_field.message_field.string_field": pf.StringIN("ok"),
|
||||
}}))
|
||||
|
||||
assert.False(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"enum_field": pf.StringIN("OTHER"),
|
||||
}}))
|
||||
|
||||
m.NumberField = 42
|
||||
assert.False(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"number_field": pf.NumberEquals(0),
|
||||
}}))
|
||||
assert.True(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"number_field": pf.NumberEquals(42),
|
||||
}}))
|
||||
assert.False(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"number_field": pf.NumberIN(0, 22),
|
||||
}}))
|
||||
assert.True(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"enum_field": pf.NumberIN(0, 42),
|
||||
}}))
|
||||
assert.False(Match(m, &pf.FieldsFilter{Filters: map[string]*pf.Filter{
|
||||
"enum_field": pf.NumberNotIN(0, 42),
|
||||
}}))
|
||||
|
||||
}
|
44
tests/gen/gen.go
Normal file
44
tests/gen/gen.go
Normal file
@ -0,0 +1,44 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protodesc"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
|
||||
test "go.linka.cloud/protofilters/tests/pb"
|
||||
)
|
||||
|
||||
func Gen() {
|
||||
t := &test.Test{StringField: "whatever..."}
|
||||
tf, err := os.Create("test.bin")
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
defer tf.Close()
|
||||
a, err := anypb.New(t)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
b, err := proto.Marshal(a)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
if _, err := tf.Write(b); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
tdf, err := os.Create("test.file-descriptor.bin")
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
defer tdf.Close()
|
||||
b, err = proto.Marshal(protodesc.ToFileDescriptorProto(t.ProtoReflect().Descriptor().ParentFile()))
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
if _, err := tdf.Write(b); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
}
|
60
tests/main.go
Normal file
60
tests/main.go
Normal file
@ -0,0 +1,60 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protodesc"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
"google.golang.org/protobuf/types/dynamicpb"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
|
||||
ff "go.linka.cloud/protofilters"
|
||||
"go.linka.cloud/protofilters/matcher"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// gen.Gen()
|
||||
b, err := ioutil.ReadFile("test.file-descriptor.bin")
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
var fdp descriptorpb.FileDescriptorProto
|
||||
if err := proto.Unmarshal(b, &fdp); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
fd, err := protodesc.NewFile(&fdp, protoregistry.GlobalFiles)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
// protodesc.NewFile(d.)
|
||||
d := dynamicpb.NewMessage(fd.Messages().Get(0))
|
||||
b, err = ioutil.ReadFile("test.bin")
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
a := anypb.Any{}
|
||||
if err := proto.Unmarshal(b, &a); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
if err := anypb.UnmarshalTo(&a, d, proto.UnmarshalOptions{}); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
logrus.Infof("%+v", d)
|
||||
logrus.Info(d.ProtoReflect().Descriptor().FullName())
|
||||
filter := &ff.FieldFilter{
|
||||
Field: "string_field",
|
||||
// Filter: ff.StringRegex(".*....*"),
|
||||
Filter: ff.StringIN("", "whatever..."),
|
||||
}
|
||||
ok, err := matcher.MatchFilters(d, filter)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
if !ok {
|
||||
logrus.Fatal("reg ex not found")
|
||||
}
|
||||
logrus.Infof("%v match %v", d, filter)
|
||||
}
|
Loading…
Reference in New Issue
Block a user