filter.go 1.79 KB
Newer Older
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
package query

import (
	"fmt"
	"reflect"
	"strings"
)

// Filter is an object that tests ResultEntries
type Filter interface {
	// Filter returns whether an entry passes the filter
	Filter(e Entry) bool
}

// Op is a comparison operator
type Op string

var (
	Equal              = Op("==")
	NotEqual           = Op("!=")
	GreaterThan        = Op(">")
	GreaterThanOrEqual = Op(">=")
	LessThan           = Op("<")
	LessThanOrEqual    = Op("<=")
)

// FilterValueCompare is used to signal to datastores they
// should apply internal comparisons. unfortunately, there
// is no way to apply comparisons* to interface{} types in
// Go, so if the datastore doesnt have a special way to
// handle these comparisons, you must provided the
// TypedFilter to actually do filtering.
//
// [*] other than == and !=, which use reflect.DeepEqual.
type FilterValueCompare struct {
	Op          Op
	Value       interface{}
	TypedFilter Filter
}

func (f FilterValueCompare) Filter(e Entry) bool {
	if f.TypedFilter != nil {
		return f.TypedFilter.Filter(e)
	}

	switch f.Op {
	case Equal:
		return reflect.DeepEqual(f.Value, e.Value)
	case NotEqual:
		return !reflect.DeepEqual(f.Value, e.Value)
	default:
		panic(fmt.Errorf("cannot apply op '%s' to interface{}.", f.Op))
	}
}

type FilterKeyCompare struct {
	Op  Op
	Key string
}

func (f FilterKeyCompare) Filter(e Entry) bool {
	switch f.Op {
	case Equal:
		return e.Key == f.Key
	case NotEqual:
		return e.Key != f.Key
	case GreaterThan:
		return e.Key > f.Key
	case GreaterThanOrEqual:
		return e.Key >= f.Key
	case LessThan:
		return e.Key < f.Key
	case LessThanOrEqual:
		return e.Key <= f.Key
	default:
		panic(fmt.Errorf("unknown op '%s'", f.Op))
	}
}

type FilterKeyPrefix struct {
	Prefix string
}

func (f FilterKeyPrefix) Filter(e Entry) bool {
	return strings.HasPrefix(e.Key, f.Prefix)
}