1package query 2 3import ( 4 "bytes" 5 "sort" 6 "strings" 7) 8 9// Order is an object used to order objects 10type Order interface { 11 Compare(a, b Entry) int 12} 13 14// OrderByFunction orders the results based on the result of the given function. 15type OrderByFunction func(a, b Entry) int 16 17func (o OrderByFunction) Compare(a, b Entry) int { 18 return o(a, b) 19} 20 21func (OrderByFunction) String() string { 22 return "FN" 23} 24 25// OrderByValue is used to signal to datastores they should apply internal 26// orderings. 27type OrderByValue struct{} 28 29func (o OrderByValue) Compare(a, b Entry) int { 30 return bytes.Compare(a.Value, b.Value) 31} 32 33func (OrderByValue) String() string { 34 return "VALUE" 35} 36 37// OrderByValueDescending is used to signal to datastores they 38// should apply internal orderings. 39type OrderByValueDescending struct{} 40 41func (o OrderByValueDescending) Compare(a, b Entry) int { 42 return -bytes.Compare(a.Value, b.Value) 43} 44 45func (OrderByValueDescending) String() string { 46 return "desc(VALUE)" 47} 48 49// OrderByKey 50type OrderByKey struct{} 51 52func (o OrderByKey) Compare(a, b Entry) int { 53 return strings.Compare(a.Key, b.Key) 54} 55 56func (OrderByKey) String() string { 57 return "KEY" 58} 59 60// OrderByKeyDescending 61type OrderByKeyDescending struct{} 62 63func (o OrderByKeyDescending) Compare(a, b Entry) int { 64 return -strings.Compare(a.Key, b.Key) 65} 66 67func (OrderByKeyDescending) String() string { 68 return "desc(KEY)" 69} 70 71// Less returns true if a comes before b with the requested orderings. 72func Less(orders []Order, a, b Entry) bool { 73 for _, cmp := range orders { 74 switch cmp.Compare(a, b) { 75 case 0: 76 case -1: 77 return true 78 case 1: 79 return false 80 } 81 } 82 83 // This gives us a *stable* sort for free. We don't care 84 // preserving the order from the underlying datastore 85 // because it's undefined. 86 return a.Key < b.Key 87} 88 89// Sort sorts the given entries using the given orders. 90func Sort(orders []Order, entries []Entry) { 91 sort.Slice(entries, func(i int, j int) bool { 92 return Less(orders, entries[i], entries[j]) 93 }) 94} 95