filter.go 1.68 KB
Newer Older
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
1 2 3
package query

import (
4
	"bytes"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
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
	"fmt"
	"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 {
36 37
	Op    Op
	Value []byte
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
38 39 40 41 42
}

func (f FilterValueCompare) Filter(e Entry) bool {
	switch f.Op {
	case Equal:
43
		return bytes.Equal(f.Value, e.Value)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
44
	case NotEqual:
45
		return !bytes.Equal(f.Value, e.Value)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
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
	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)
}